Re: [PATCH v8 06/14] net: stream: Don't ignore EINVAL on netdev socket connection

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:52AM +0200, Laurent Vivier wrote:
> From: Stefano Brivio 
> 
> Other errors are treated as failure by net_stream_client_init(),
> but if connect() returns EINVAL, we'll fail silently. Remove the
> related exception.

Is this also a bug in net_socket_connect_init()?  Is there an
equivalent bug in dgram.c?

> Signed-off-by: Stefano Brivio 
> [lvivier: applied to net/stream.c]
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Daniel P. Berrangé 
> ---
>  net/stream.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/stream.c b/net/stream.c
> index 0851e90becca..e8afbaca50b6 100644
> --- a/net/stream.c
> +++ b/net/stream.c
> @@ -363,8 +363,7 @@ static int net_stream_client_init(NetClientState *peer,
>  if (errno == EINTR || errno == EWOULDBLOCK) {
>  /* continue */
>  } else if (errno == EINPROGRESS ||
> -   errno == EALREADY ||
> -   errno == EINVAL) {
> +   errno == EALREADY) {
>  break;
>  } else {
>  error_setg_errno(errp, errno, "can't connect socket");

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH v8 11/14] qemu-sockets: move and rename SocketAddress_to_str()

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:57AM +0200, Laurent Vivier wrote:
> Rename SocketAddress_to_str() to socket_uri() and move it to
> util/qemu-sockets.c close to socket_parse().
> 
> socket_uri() generates a string from a SocketAddress while
> socket_parse() generates a SocketAddress from a string.
> 
> Signed-off-by: Laurent Vivier 

Reviewed-by: David Gibson 

> ---
>  include/qemu/sockets.h |  2 +-
>  monitor/hmp-cmds.c | 23 +--
>  util/qemu-sockets.c| 20 
>  3 files changed, 22 insertions(+), 23 deletions(-)
> 
> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
> index 47194b9732f8..e5a06d2e3729 100644
> --- a/include/qemu/sockets.h
> +++ b/include/qemu/sockets.h
> @@ -40,6 +40,7 @@ NetworkAddressFamily inet_netfamily(int family);
>  int unix_listen(const char *path, Error **errp);
>  int unix_connect(const char *path, Error **errp);
>  
> +char *socket_uri(SocketAddress *addr);
>  SocketAddress *socket_parse(const char *str, Error **errp);
>  int socket_connect(SocketAddress *addr, Error **errp);
>  int socket_listen(SocketAddress *addr, int num, Error **errp);
> @@ -123,5 +124,4 @@ SocketAddress *socket_address_flatten(SocketAddressLegacy 
> *addr);
>   * Return 0 on success.
>   */
>  int socket_address_parse_named_fd(SocketAddress *addr, Error **errp);
> -
>  #endif /* QEMU_SOCKETS_H */
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index c6cd6f91dde6..cb35059c2d45 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -197,27 +197,6 @@ void hmp_info_mice(Monitor *mon, const QDict *qdict)
>  qapi_free_MouseInfoList(mice_list);
>  }
>  
> -static char *SocketAddress_to_str(SocketAddress *addr)
> -{
> -switch (addr->type) {
> -case SOCKET_ADDRESS_TYPE_INET:
> -return g_strdup_printf("tcp:%s:%s",
> -   addr->u.inet.host,
> -   addr->u.inet.port);
> -case SOCKET_ADDRESS_TYPE_UNIX:
> -return g_strdup_printf("unix:%s",
> -   addr->u.q_unix.path);
> -case SOCKET_ADDRESS_TYPE_FD:
> -return g_strdup_printf("fd:%s", addr->u.fd.str);
> -case SOCKET_ADDRESS_TYPE_VSOCK:
> -return g_strdup_printf("tcp:%s:%s",
> -   addr->u.vsock.cid,
> -   addr->u.vsock.port);
> -default:
> -return g_strdup("unknown address type");
> -}
> -}
> -
>  void hmp_info_migrate(Monitor *mon, const QDict *qdict)
>  {
>  MigrationInfo *info;
> @@ -380,7 +359,7 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
>  monitor_printf(mon, "socket address: [\n");
>  
>  for (addr = info->socket_address; addr; addr = addr->next) {
> -char *s = SocketAddress_to_str(addr->value);
> +char *s = socket_uri(addr->value);
>  monitor_printf(mon, "\t%s\n", s);
>  g_free(s);
>  }
> diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
> index 83f4bd6fd211..9f6f655fd526 100644
> --- a/util/qemu-sockets.c
> +++ b/util/qemu-sockets.c
> @@ -1077,6 +1077,26 @@ int unix_connect(const char *path, Error **errp)
>  return sock;
>  }
>  
> +char *socket_uri(SocketAddress *addr)
> +{
> +switch (addr->type) {
> +case SOCKET_ADDRESS_TYPE_INET:
> +return g_strdup_printf("tcp:%s:%s",
> +   addr->u.inet.host,
> +   addr->u.inet.port);
> +case SOCKET_ADDRESS_TYPE_UNIX:
> +return g_strdup_printf("unix:%s",
> +   addr->u.q_unix.path);
> +case SOCKET_ADDRESS_TYPE_FD:
> +return g_strdup_printf("fd:%s", addr->u.fd.str);
> +case SOCKET_ADDRESS_TYPE_VSOCK:
> +return g_strdup_printf("tcp:%s:%s",
> +   addr->u.vsock.cid,
> +   addr->u.vsock.port);
> +default:
> +return g_strdup("unknown address type");
> +}
> +}
>  
>  SocketAddress *socket_parse(const char *str, Error **errp)
>  {

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH v8 07/14] net: stream: add unix socket

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:53AM +0200, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Stefano Brivio 
> ---
>  net/stream.c| 108 +---
>  qapi/net.json   |   2 +-
>  qemu-options.hx |   1 +
>  3 files changed, 105 insertions(+), 6 deletions(-)
> 
> diff --git a/net/stream.c b/net/stream.c
> index e8afbaca50b6..0f91ff20df61 100644
> --- a/net/stream.c
> +++ b/net/stream.c
> @@ -235,7 +235,7 @@ static NetStreamState 
> *net_stream_fd_init_stream(NetClientState *peer,
>  static void net_stream_accept(void *opaque)
>  {
>  NetStreamState *s = opaque;
> -struct sockaddr_in saddr;
> +struct sockaddr_storage saddr;
>  socklen_t len;
>  int fd;
>  
> @@ -253,9 +253,27 @@ static void net_stream_accept(void *opaque)
>  s->fd = fd;
>  s->nc.link_down = false;
>  net_stream_connect(s);
> -snprintf(s->nc.info_str, sizeof(s->nc.info_str),
> - "connection from %s:%d",
> - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
> +switch (saddr.ss_family) {
> +case AF_INET: {
> +struct sockaddr_in *saddr_in = (struct sockaddr_in *)
> +
> +snprintf(s->nc.info_str, sizeof(s->nc.info_str),
> + "connection from %s:%d",
> + inet_ntoa(saddr_in->sin_addr), ntohs(saddr_in->sin_port));
> +break;
> +}
> +case AF_UNIX: {
> +struct sockaddr_un saddr_un;
> +
> +len = sizeof(saddr_un);
> +getsockname(s->listen_fd, (struct sockaddr *)_un, );

It seems like there's an asymmetry here in that we've gotten the
connection address outside the switch for inet sockets, but we need an
additional getsockname() for unix sockets.  Am I missing something? 

> +snprintf(s->nc.info_str, sizeof(s->nc.info_str),
> + "connect from %s", saddr_un.sun_path);
> +break;
> +}
> +default:
> +g_assert_not_reached();
> +}
>  }
>  
>  static int net_stream_server_init(NetClientState *peer,
> @@ -295,6 +313,43 @@ static int net_stream_server_init(NetClientState *peer,
>  }
>  break;
>  }
> +case SOCKET_ADDRESS_TYPE_UNIX: {
> +struct sockaddr_un saddr_un;
> +
> +ret = unlink(addr->u.q_unix.path);
> +if (ret < 0 && errno != ENOENT) {
> +error_setg_errno(errp, errno, "failed to unlink socket %s",
> + addr->u.q_unix.path);
> +return -1;
> +}
> +
> +saddr_un.sun_family = PF_UNIX;
> +ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s",
> +   addr->u.q_unix.path);
> +if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) {
> +error_setg(errp, "UNIX socket path '%s' is too long",
> +   addr->u.q_unix.path);
> +error_append_hint(errp, "Path must be less than %zu bytes\n",
> +  sizeof(saddr_un.sun_path));
> +return -1;
> +}
> +
> +fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
> +if (fd < 0) {
> +error_setg_errno(errp, errno, "can't create stream socket");
> +return -1;
> +}
> +qemu_socket_set_nonblock(fd);
> +
> +ret = bind(fd, (struct sockaddr *)_un, sizeof(saddr_un));
> +if (ret < 0) {
> +error_setg_errno(errp, errno, "can't create socket with path: 
> %s",
> + saddr_un.sun_path);
> +closesocket(fd);
> +return -1;
> +}
> +break;
> +}
>  case SOCKET_ADDRESS_TYPE_FD:
>  fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp);
>  if (fd == -1) {
> @@ -380,6 +435,49 @@ static int net_stream_client_init(NetClientState *peer,
> ntohs(saddr_in.sin_port));
>  break;
>  }
> +case SOCKET_ADDRESS_TYPE_UNIX: {
> +struct sockaddr_un saddr_un;
> +
> +saddr_un.sun_family = PF_UNIX;
> +ret = snprintf(saddr_un.sun_path, sizeof(saddr_un.sun_path), "%s",
> +   addr->u.q_unix.path);
> +if (ret < 0 || ret >= sizeof(saddr_un.sun_path)) {
> +error_setg(errp, "UNIX socket path '%s' is too long",
> +   addr->u.q_unix.path);
> +error_append_hint(errp, "Path must be less than %zu bytes\n",
> +  sizeof(saddr_un.sun_path));
> +return -1;
> +}
> +
> +fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
> +if (fd < 0) {
> +error_setg_errno(errp, errno, "can't create stream socket");
> +return -1;
> +}
> +qemu_socket_set_nonblock(fd);
> +
> +connected = 0;
> +for (;;) {
> +ret = connect(fd, (struct sockaddr *)_un, 
> sizeof(saddr_un));
> +if (ret < 0) {
> +if (errno == EINTR || errno == EWOULDBLOCK) {
> + 

Re: [PATCH v8 05/14] qapi: net: add stream and dgram netdevs

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:51AM +0200, Laurent Vivier wrote:
> Copied from socket netdev file and modified to use SocketAddress
> to be able to introduce new features like unix socket.
> 
> "udp" and "mcast" are squashed into dgram netdev, multicast is detected
> according to the IP address type.
> "listen" and "connect" modes are managed by stream netdev. An optional
> parameter "server" defines the mode (server by default)
> 
> The two new types need to be parsed the modern way with -netdev, because
> with the traditional way, the "type" field of netdev structure collides with
> the "type" field of SocketAddress and prevents the correct evaluation of the
> command line option. Moreover the traditional way doesn't allow to use
> the same type (SocketAddress) several times with the -netdev option
> (needed to specify "local" and "remote" addresses).
> 
> The previous commit paved the way for parsing the modern way, but
> omitted one detail: how to pick modern vs. traditional, in
> netdev_is_modern().
> 
> We want to pick based on the value of parameter "type".  But how to
> extract it from the option argument?
> 
> Parsing the option argument, either the modern or the traditional way,
> extracts it for us, but only if parsing succeeds.
> 
> If parsing fails, there is no good option.  No matter which parser we
> pick, it'll be the wrong one for some arguments, and the error
> reporting will be confusing.
> 
> Fortunately, the traditional parser accepts *anything* when called in
> a certain way.  This maximizes our chance to extract the value of
> "type", and in turn minimizes the risk of confusing error reporting.
> 
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Stefano Brivio 
> ---
>  hmp-commands.hx |   2 +-
>  net/clients.h   |   6 +
>  net/dgram.c | 631 
>  net/hub.c   |   2 +
>  net/meson.build |   2 +
>  net/net.c   |  30 ++-
>  net/stream.c| 423 
>  qapi/net.json   |  63 -
>  qemu-options.hx |  12 +
>  9 files changed, 1167 insertions(+), 4 deletions(-)
>  create mode 100644 net/dgram.c
>  create mode 100644 net/stream.c
> 
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 182e639d1498..83e8d45a2a8b 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1276,7 +1276,7 @@ ERST
>  {
>  .name   = "netdev_add",
>  .args_type  = "netdev:O",
> -.params = "[user|tap|socket|vde|bridge|hubport|netmap|vhost-user"
> +.params = 
> "[user|tap|socket|stream|dgram|vde|bridge|hubport|netmap|vhost-user"
>  #ifdef CONFIG_VMNET
>"|vmnet-host|vmnet-shared|vmnet-bridged"
>  #endif
> diff --git a/net/clients.h b/net/clients.h
> index c9157789f2ce..ed8bdfff1e7c 100644
> --- a/net/clients.h
> +++ b/net/clients.h
> @@ -40,6 +40,12 @@ int net_init_hubport(const Netdev *netdev, const char 
> *name,
>  int net_init_socket(const Netdev *netdev, const char *name,
>  NetClientState *peer, Error **errp);
>  
> +int net_init_stream(const Netdev *netdev, const char *name,
> +NetClientState *peer, Error **errp);
> +
> +int net_init_dgram(const Netdev *netdev, const char *name,
> +   NetClientState *peer, Error **errp);
> +
>  int net_init_tap(const Netdev *netdev, const char *name,
>   NetClientState *peer, Error **errp);
>  
> diff --git a/net/dgram.c b/net/dgram.c
> new file mode 100644
> index ..dbe65102d174
> --- /dev/null
> +++ b/net/dgram.c
> @@ -0,0 +1,631 @@
> +/*
> + * QEMU System Emulator
> + *
> + * Copyright (c) 2003-2008 Fabrice Bellard

Shouldn't this have your copyright as well as Fabrice's old one copied
from socket.c?

> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a 
> copy
> + * of this software and associated documentation files (the "Software"), to 
> deal
> + * in the Software without restriction, including without limitation the 
> rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
> FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "net/net.h"
> +#include "clients.h"
> +#include 

Re: [PATCH v8 02/14] net: remove the @errp argument of net_client_inits()

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:48AM +0200, Laurent Vivier wrote:
> The only caller passes _fatal, so use this directly in the function.
> 
> It's what we do for -blockdev, -device, and -object.
> 
> Suggested-by: Markus Armbruster 
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Markus Armbruster 

Reviewed-by: David Gibson 

> ---
>  include/net/net.h |  2 +-
>  net/net.c | 20 +++-
>  softmmu/vl.c  |  2 +-
>  3 files changed, 9 insertions(+), 15 deletions(-)
> 
> diff --git a/include/net/net.h b/include/net/net.h
> index 81d0b21defce..c1c34a58f849 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -222,7 +222,7 @@ extern const char *host_net_devices[];
>  /* from net.c */
>  int net_client_parse(QemuOptsList *opts_list, const char *str);
>  void show_netdevs(void);
> -int net_init_clients(Error **errp);
> +void net_init_clients(void);
>  void net_check_clients(void);
>  void net_cleanup(void);
>  void hmp_host_net_add(Monitor *mon, const QDict *qdict);
> diff --git a/net/net.c b/net/net.c
> index d2288bd3a929..15958f881776 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -1562,27 +1562,21 @@ out:
>  return ret;
>  }
>  
> -int net_init_clients(Error **errp)
> +void net_init_clients(void)
>  {
>  net_change_state_entry =
>  qemu_add_vm_change_state_handler(net_vm_change_state_handler, NULL);
>  
>  QTAILQ_INIT(_clients);
>  
> -if (qemu_opts_foreach(qemu_find_opts("netdev"),
> -  net_init_netdev, NULL, errp)) {
> -return -1;
> -}
> -
> -if (qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL, errp)) 
> {
> -return -1;
> -}
> +qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL,
> +  _fatal);
>  
> -if (qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL, 
> errp)) {
> -return -1;
> -}
> +qemu_opts_foreach(qemu_find_opts("nic"), net_param_nic, NULL,
> +  _fatal);
>  
> -return 0;
> +qemu_opts_foreach(qemu_find_opts("net"), net_init_client, NULL,
> +  _fatal);
>  }
>  
>  int net_client_parse(QemuOptsList *opts_list, const char *optarg)
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index dea4005e4791..1fe8b5c5a120 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -1906,7 +1906,7 @@ static void qemu_create_late_backends(void)
>  qtest_server_init(qtest_chrdev, qtest_log, _fatal);
>  }
>  
> -net_init_clients(_fatal);
> +net_init_clients();
>  
>  object_option_foreach_add(object_create_late);
>  

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH v8 03/14] net: simplify net_client_parse() error management

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:49AM +0200, Laurent Vivier wrote:
> All net_client_parse() callers exit in case of error.
> 
> Move exit(1) to net_client_parse() and remove error checking from
> the callers.
> 
> Suggested-by: Markus Armbruster 
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Markus Armbruster 

Reviewed-by: David Gibson 
> ---
>  include/net/net.h |  2 +-
>  net/net.c |  6 ++
>  softmmu/vl.c  | 12 +++-
>  3 files changed, 6 insertions(+), 14 deletions(-)
> 
> diff --git a/include/net/net.h b/include/net/net.h
> index c1c34a58f849..55023e7e9fa9 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -220,7 +220,7 @@ extern NICInfo nd_table[MAX_NICS];
>  extern const char *host_net_devices[];
>  
>  /* from net.c */
> -int net_client_parse(QemuOptsList *opts_list, const char *str);
> +void net_client_parse(QemuOptsList *opts_list, const char *str);
>  void show_netdevs(void);
>  void net_init_clients(void);
>  void net_check_clients(void);
> diff --git a/net/net.c b/net/net.c
> index 15958f881776..f056e8aebfb2 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -1579,13 +1579,11 @@ void net_init_clients(void)
>_fatal);
>  }
>  
> -int net_client_parse(QemuOptsList *opts_list, const char *optarg)
> +void net_client_parse(QemuOptsList *opts_list, const char *optarg)
>  {
>  if (!qemu_opts_parse_noisily(opts_list, optarg, true)) {
> -return -1;
> +exit(1);
>  }
> -
> -return 0;
>  }
>  
>  /* From FreeBSD */
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 1fe8b5c5a120..55d163475e9e 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2809,21 +2809,15 @@ void qemu_init(int argc, char **argv, char **envp)
>  break;
>  case QEMU_OPTION_netdev:
>  default_net = 0;
> -if (net_client_parse(qemu_find_opts("netdev"), optarg) == 
> -1) {
> -exit(1);
> -}
> +net_client_parse(qemu_find_opts("netdev"), optarg);
>  break;
>  case QEMU_OPTION_nic:
>  default_net = 0;
> -if (net_client_parse(qemu_find_opts("nic"), optarg) == -1) {
> -exit(1);
> -}
> +net_client_parse(qemu_find_opts("nic"), optarg);
>  break;
>  case QEMU_OPTION_net:
>  default_net = 0;
> -if (net_client_parse(qemu_find_opts("net"), optarg) == -1) {
> -exit(1);
> -}
> +net_client_parse(qemu_find_opts("net"), optarg);
>  break;
>  #ifdef CONFIG_LIBISCSI
>  case QEMU_OPTION_iscsi:

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH v8 01/14] net: introduce convert_host_port()

2022-09-13 Thread David Gibson
On Tue, Sep 13, 2022 at 08:39:47AM +0200, Laurent Vivier wrote:
> Signed-off-by: Laurent Vivier 
> Reviewed-by: Stefano Brivio 

Reviewed-by: David Gibson 

Although, if you do respin, an actual commit message would be nice to
have.


> ---
>  include/qemu/sockets.h |  2 ++
>  net/net.c  | 62 ++
>  2 files changed, 34 insertions(+), 30 deletions(-)
> 
> diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
> index 038faa157f59..47194b9732f8 100644
> --- a/include/qemu/sockets.h
> +++ b/include/qemu/sockets.h
> @@ -47,6 +47,8 @@ void socket_listen_cleanup(int fd, Error **errp);
>  int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
>  
>  /* Old, ipv4 only bits.  Don't use for new code. */
> +int convert_host_port(struct sockaddr_in *saddr, const char *host,
> +  const char *port, Error **errp);
>  int parse_host_port(struct sockaddr_in *saddr, const char *str,
>  Error **errp);
>  int socket_init(void);
> diff --git a/net/net.c b/net/net.c
> index 2db160e0634d..d2288bd3a929 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -66,55 +66,57 @@ static QTAILQ_HEAD(, NetClientState) net_clients;
>  /***/
>  /* network device redirectors */
>  
> -int parse_host_port(struct sockaddr_in *saddr, const char *str,
> -Error **errp)
> +int convert_host_port(struct sockaddr_in *saddr, const char *host,
> +  const char *port, Error **errp)
>  {
> -gchar **substrings;
>  struct hostent *he;
> -const char *addr, *p, *r;
> -int port, ret = 0;
> +const char *r;
> +long p;
>  
>  memset(saddr, 0, sizeof(*saddr));
>  
> -substrings = g_strsplit(str, ":", 2);
> -if (!substrings || !substrings[0] || !substrings[1]) {
> -error_setg(errp, "host address '%s' doesn't contain ':' "
> -   "separating host from port", str);
> -ret = -1;
> -goto out;
> -}
> -
> -addr = substrings[0];
> -p = substrings[1];
> -
>  saddr->sin_family = AF_INET;
> -if (addr[0] == '\0') {
> +if (host[0] == '\0') {
>  saddr->sin_addr.s_addr = 0;
>  } else {
> -if (qemu_isdigit(addr[0])) {
> -if (!inet_aton(addr, >sin_addr)) {
> +if (qemu_isdigit(host[0])) {
> +if (!inet_aton(host, >sin_addr)) {
>  error_setg(errp, "host address '%s' is not a valid "
> -   "IPv4 address", addr);
> -ret = -1;
> -goto out;
> +   "IPv4 address", host);
> +return -1;
>  }
>  } else {
> -he = gethostbyname(addr);
> +he = gethostbyname(host);
>  if (he == NULL) {
> -error_setg(errp, "can't resolve host address '%s'", addr);
> -ret = -1;
> -goto out;
> +error_setg(errp, "can't resolve host address '%s'", host);
> +return -1;
>  }
>  saddr->sin_addr = *(struct in_addr *)he->h_addr;
>  }
>  }
> -port = strtol(p, (char **), 0);
> -if (r == p) {
> -error_setg(errp, "port number '%s' is invalid", p);
> +if (qemu_strtol(port, , 0, ) != 0) {
> +error_setg(errp, "port number '%s' is invalid", port);
> +return -1;
> +}
> +saddr->sin_port = htons(p);
> +return 0;
> +}
> +
> +int parse_host_port(struct sockaddr_in *saddr, const char *str,
> +Error **errp)
> +{
> +gchar **substrings;
> +int ret;
> +
> +substrings = g_strsplit(str, ":", 2);
> +if (!substrings || !substrings[0] || !substrings[1]) {
> +error_setg(errp, "host address '%s' doesn't contain ':' "
> +   "separating host from port", str);
>  ret = -1;
>  goto out;
>  }
> -saddr->sin_port = htons(port);
> +
> +ret = convert_host_port(saddr, substrings[0], substrings[1], errp);
>  
>  out:
>  g_strfreev(substrings);

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH] e1000e: set RX desc status with DD flag in a separate operation

2022-09-13 Thread Jason Wang
On Fri, Sep 9, 2022 at 7:20 PM dinghui  wrote:
>
> On 2022/9/9 10:40, Jason Wang wrote:
> > On Sat, Aug 27, 2022 at 12:06 AM Ding Hui  wrote:
> >>
> >> Like commit 034d00d48581 ("e1000: set RX descriptor status in
> >> a separate operation"), there is also same issue in e1000e, which
> >> would cause lost packets or stop sending packets to VM with DPDK.
> >>
> >> Do similar fix in e1000e.
> >>
> >> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/402
> >> Signed-off-by: Ding Hui 
> >> ---
> >>   hw/net/e1000e_core.c | 54 +++-
> >>   1 file changed, 53 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
> >> index 208e3e0d79..b8038e4014 100644
> >> --- a/hw/net/e1000e_core.c
> >> +++ b/hw/net/e1000e_core.c
> >> @@ -1364,6 +1364,58 @@ struct NetRxPkt *pkt, const E1000E_RSSInfo 
> >> *rss_info,
> >>   }
> >>   }
> >>
> >> +static inline void
> >> +e1000e_pci_dma_write_rx_desc(E1000ECore *core, dma_addr_t addr,
> >> + uint8_t *desc, dma_addr_t len)
> >> +{
> >> +PCIDevice *dev = core->owner;
> >> +
> >> +if (e1000e_rx_use_legacy_descriptor(core)) {
> >> +struct e1000_rx_desc *d = (struct e1000_rx_desc *) desc;
> >> +size_t offset = offsetof(struct e1000_rx_desc, status);
> >> +typeof(d->status) status = d->status;
> >> +
> >> +d->status &= ~E1000_RXD_STAT_DD;
> >> +pci_dma_write(dev, addr, desc, len);
> >> +
> >> +if (status & E1000_RXD_STAT_DD) {
> >> +d->status = status;
> >> +pci_dma_write(dev, addr + offset, , sizeof(status));
> >> +}
> >> +} else {
> >> +if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) {
> >> +union e1000_rx_desc_packet_split *d =
> >> +(union e1000_rx_desc_packet_split *) desc;
> >> +size_t offset = offsetof(union e1000_rx_desc_packet_split,
> >> +wb.middle.status_error);
> >> +typeof(d->wb.middle.status_error) status =
> >> +d->wb.middle.status_error;
> >
> > Any reason to use typeof here? Its type is known to be uint32_t?
> >
>
> My intention was using exact type same with struct member status_error,
> which is indeed uint32_t now. If the type of status_error in struct be
> changed in some case, we do not need to change everywhere.
>
> Maybe I worry too much, the struct is related to h/w spec, so it is
> unlikely be changed in the future.
>
> Should I send v2 to use uint32_t directly? I'm also OK with it.

Yes, please.

Thanks

>
> >> +
> >> +d->wb.middle.status_error &= ~E1000_RXD_STAT_DD;
> >> +pci_dma_write(dev, addr, desc, len);
> >> +
> >> +if (status & E1000_RXD_STAT_DD) {
> >> +d->wb.middle.status_error = status;
> >> +pci_dma_write(dev, addr + offset, , 
> >> sizeof(status));
> >> +}
> >> +} else {
> >> +union e1000_rx_desc_extended *d =
> >> +(union e1000_rx_desc_extended *) desc;
> >> +size_t offset = offsetof(union e1000_rx_desc_extended,
> >> +wb.upper.status_error);
> >> +typeof(d->wb.upper.status_error) status = 
> >> d->wb.upper.status_error;
> >
> > So did here.
> >
> > Thanks
> >
> >> +
> >> +d->wb.upper.status_error &= ~E1000_RXD_STAT_DD;
> >> +pci_dma_write(dev, addr, desc, len);
> >> +
> >> +if (status & E1000_RXD_STAT_DD) {
> >> +d->wb.upper.status_error = status;
> >> +pci_dma_write(dev, addr + offset, , 
> >> sizeof(status));
> >> +}
> >> +}
> >> +}
> >> +}
> >> +
> >>   typedef struct e1000e_ba_state_st {
> >>   uint16_t written[MAX_PS_BUFFERS];
> >>   uint8_t cur_idx;
> >> @@ -1600,7 +1652,7 @@ e1000e_write_packet_to_guest(E1000ECore *core, 
> >> struct NetRxPkt *pkt,
> >>
> >>   e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,
> >>  rss_info, do_ps ? ps_hdr_len : 0, 
> >> );
> >> -pci_dma_write(d, base, , core->rx_desc_len);
> >> +e1000e_pci_dma_write_rx_desc(core, base, desc, core->rx_desc_len);
> >>
> >>   e1000e_ring_advance(core, rxi,
> >>   core->rx_desc_len / E1000_MIN_RX_DESC_LEN);
> >> --
> >> 2.17.1
> >>
> >
> >
>
>
> --
> Thanks,
> - Ding Hui
>




Re: [PATCH v5 11/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()

2022-09-13 Thread Jason Wang
On Wed, Sep 14, 2022 at 12:21 PM Xuan Zhuo  wrote:
>
> From: Kangjie Xu 
>
> Introduce vhost_net_virtqueue_restart(), which can restart the
> specific virtqueue when the vhost net started running before.
> If it fails to restart the virtqueue, the device will be stopped.
>
> Here we do not reuse vhost_net_start_one() or vhost_dev_start()
> because they work at queue pair level. The mem table and features
> do not change, so we can call the vhost_virtqueue_start() to
> restart a specific queue.
>
> This patch only considers the case of vhost-kernel, when
> NetClientDriver is NET_CLIENT_DRIVER_TAP.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/net/vhost_net.c  | 53 +
>  include/net/vhost_net.h |  2 ++
>  2 files changed, 55 insertions(+)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 8beecb4d22..d2926e2ed6 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -34,6 +34,7 @@
>  #include "standard-headers/linux/virtio_ring.h"
>  #include "hw/virtio/vhost.h"
>  #include "hw/virtio/virtio-bus.h"
> +#include "linux-headers/linux/vhost.h"
>
>
>  /* Features supported by host kernel. */
> @@ -556,3 +557,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
> NetClientState *nc,
>   net->dev.vqs + idx,
>   net->dev.vq_index + idx);
>  }
> +
> +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
> +int vq_index)
> +{
> +VHostNetState *net = get_vhost_net(nc->peer);
> +const VhostOps *vhost_ops = net->dev.vhost_ops;
> +struct vhost_vring_file file = { };
> +int idx, r;
> +
> +if (!net->dev.started) {
> +return -EBUSY;
> +}
> +
> +/* should only be called after backend is connected */
> +assert(vhost_ops);
> +
> +idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
> +
> +r = vhost_virtqueue_start(>dev,
> +  vdev,
> +  net->dev.vqs + idx,
> +  net->dev.vq_index + idx);
> +if (r < 0) {
> +goto err_start;
> +}
> +
> +if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> +file.index = idx;
> +file.fd = net->backend;
> +r = vhost_net_set_backend(>dev, );
> +if (r < 0) {
> +r = -errno;
> +goto err_start;
> +}
> +}
> +
> +return 0;
> +
> +err_start:
> +error_report("Error when restarting the queue.");
> +
> +if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> +file.fd = VHOST_FILE_UNBIND;
> +file.index = idx;
> +int r = vhost_net_set_backend(>dev, );
> +assert(r >= 0);
> +}
> +
> +vhost_dev_stop(>dev, vdev);
> +
> +return r;
> +}
> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> index 85d85a4957..40b9a40074 100644
> --- a/include/net/vhost_net.h
> +++ b/include/net/vhost_net.h
> @@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
>
>  void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> int vq_index);
> +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
> +int vq_index);
>  #endif
> --
> 2.32.0.3.g01195cf9f
>




Re: [PATCH v5 15/15] vhost: vhost-kernel: enable vq reset feature

2022-09-13 Thread Jason Wang
On Wed, Sep 14, 2022 at 12:21 PM Xuan Zhuo  wrote:
>
> From: Kangjie Xu 
>
> Add virtqueue reset feature for vhost-kernel.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/net/vhost_net.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index d2926e2ed6..53b2fac4f6 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -47,6 +47,7 @@ static const int kernel_feature_bits[] = {
>  VIRTIO_NET_F_MTU,
>  VIRTIO_F_IOMMU_PLATFORM,
>  VIRTIO_F_RING_PACKED,
> +VIRTIO_F_RING_RESET,
>  VIRTIO_NET_F_HASH_REPORT,
>  VHOST_INVALID_FEATURE_BIT
>  };
> --
> 2.32.0.3.g01195cf9f
>




[PATCH v5 14/15] virtio-net: support queue_enable

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Support queue_enable in vhost-kernel scenario. It can be called when
a vq reset operation has been performed and the vq is restared.

It should be noted that we can restart the vq when the vhost has
already started. When launching a new vhost device, the vhost is not
started and all vqs are not initalized until VIRTIO_PCI_COMMON_STATUS
is written. Thus, we should use vhost_started to differentiate the
two cases: vq reset and device start.

Currently it only supports vhost-kernel.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/net/virtio-net.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d774a3e652..7817206596 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -557,6 +557,26 @@ static void virtio_net_queue_reset(VirtIODevice *vdev, 
uint32_t queue_index)
 flush_or_purge_queued_packets(nc);
 }
 
+static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+int r;
+
+if (!nc->peer || !vdev->vhost_started) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+r = vhost_net_virtqueue_restart(vdev, nc, queue_index);
+if (r < 0) {
+error_report("unable to restart vhost net virtqueue: %d, "
+"when resetting the queue", queue_index);
+}
+}
+}
+
 static void virtio_net_reset(VirtIODevice *vdev)
 {
 VirtIONet *n = VIRTIO_NET(vdev);
@@ -3802,6 +3822,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
 vdc->bad_features = virtio_net_bad_features;
 vdc->reset = virtio_net_reset;
 vdc->queue_reset = virtio_net_queue_reset;
+vdc->queue_enable = virtio_net_queue_enable;
 vdc->set_status = virtio_net_set_status;
 vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
 vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
-- 
2.32.0.3.g01195cf9f




[PATCH v5 09/15] vhost: expose vhost_virtqueue_stop()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Expose vhost_virtqueue_stop(), we need to use it when resetting a
virtqueue.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/vhost.c | 8 
 include/hw/virtio/vhost.h | 2 ++
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 7900bc81ab..5407f60226 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1201,10 +1201,10 @@ fail_alloc_desc:
 return r;
 }
 
-static void vhost_virtqueue_stop(struct vhost_dev *dev,
-struct VirtIODevice *vdev,
-struct vhost_virtqueue *vq,
-unsigned idx)
+void vhost_virtqueue_stop(struct vhost_dev *dev,
+  struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq,
+  unsigned idx)
 {
 int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx);
 struct vhost_vring_state state = {
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index b092f57d98..2b168b2269 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -281,6 +281,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t 
iova, int write);
 
 int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
   struct vhost_virtqueue *vq, unsigned idx);
+void vhost_virtqueue_stop(struct vhost_dev *dev, struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq, unsigned idx);
 
 void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
 void vhost_dev_free_inflight(struct vhost_inflight *inflight);
-- 
2.32.0.3.g01195cf9f




[PATCH v5 00/15] Support VIRTIO_F_RING_RESET for virtio-net, vhost-net kernel in virtio pci-modern

2022-09-13 Thread Xuan Zhuo
The virtio queue reset function has already been defined in the virtio spec 1.2.
The relevant virtio spec information is here:

https://github.com/oasis-tcs/virtio-spec/issues/124
https://github.com/oasis-tcs/virtio-spec/issues/139

This patch set is to support this function in QEMU. It consists of several 
parts:
1. Patches 1-7 are the basic interfaces for vq reset in virtio and virtio-pci.
2. Patches 8-11 support vq reset and vq restart for vhost-kernel.
3. Patches 12-14 support vq reset and vq restart for virtio-net.
5. Patch 15 enables the vq reset feature for vhost-kernel.

The process of virtqueue reset can be concluded as:
1. The virtqueue is disabled when VIRTIO_PCI_COMMON_Q_RESET is written.
2. Then the virtqueue can be optionally restarted(re-enabled).

Since this patch set involves multiple modules and seems a bit messy, we 
briefly describe the
calling process for different modes below.
virtio-net:
1. VIRTIO_PCI_COMMON_Q_RESET is written [virtio-pci]
-> virtio_queue_reset() [virtio]
-> virtio_net_queue_reset() [virtio-net]
-> __virtio_queue_reset()
2. VIRTIO_PCI_COMMON_Q_ENABLE is written [virtio-pci]
-> set enabled, reset status of vq.

vhost-kernel:
1. VIRTIO_PCI_COMMON_Q_RESET is written [virtio-pci]
-> virtio_queue_reset() [virtio]
-> virtio_net_queue_reset() [virtio-net]
-> vhost_net_virtqueue_stop() [vhost-net]
-> vhost_net_set_backend() [vhost]
-> vhost_virtqueue_stop()
-> __virtio_queue_reset()
2. VIRTIO_PCI_COMMON_Q_ENABLE is written [virtio-pci]
-> virtio_queue_enable() [virtio]
-> virtio_net_queue_enable() [virtio-net]
-> vhost_net_virtqueue_restart() [vhost-net]
-> vhost_virtqueue_start() [vhost]
-> vhost_net_set_backend()
-> set enabled, reset status of vq.


Test environment and method:
Host: 5.19.0-rc3 (With vq reset support)
Qemu: QEMU emulator version 7.0.50
Guest: 5.19.0-rc3 (With vq reset support)
Test Cmd: ethtool -g eth1; ethtool -G eth1 rx $1 tx $2; ethtool -g eth1;

The drvier can resize the virtio queue, then virtio queue reset function 
should
be triggered.

The default is split mode, modify Qemu virtio-net to add PACKED feature to
test packed mode.

Guest Kernel Patch:

https://lore.kernel.org/bpf/20220801063902.129329-1-xuanz...@linux.alibaba.com/

Host Kernel Patch:

https://lore.kernel.org/bpf/20220825085610.80315-1-kangjie...@linux.alibaba.com/

Looking forward to your review and comments. Thanks.

changelog:

v5:
  1. vhost_net_virtqueue_restart() use -EBUSY replace -ENOTSUP. @Jason
  2. reuse  VHOST_FILE_UNBIND. @Jason

v4:
  1. Add explanation for preventing userspace datapath in virtio-net.
  2. Return error when vhost is not started in vhost_net_virtqueue_restart().
  3. Reset the virtqueue in the device reusing vhost_virtqueue_stop().
  4. Disable queue reset feature for pre-7.2 machine.

v3:
  1. Remove support for vhost-user in this series and refactor the code.
  2. Rename 'vhost_net_virtqueue_stop' to 'vhost_net_virtqueue_reset'.
  3. Make PCI transport ready before device ready when queue_enabled is set to 
true.
  4. Add some comments.

v2:
  1. Add support for vhost-net kernel scenario.
  2. Add a new vhost-user message VHOST_USER_RESET_VRING.
  3. Add migration compatibility for virtqueue reset.

Kangjie Xu (10):
  virtio: introduce virtio_queue_enable()
  virtio: core: vq reset feature negotation support
  virtio-pci: support queue enable
  vhost: expose vhost_virtqueue_start()
  vhost: expose vhost_virtqueue_stop()
  vhost-net: vhost-kernel: introduce vhost_net_virtqueue_reset()
  vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()
  virtio-net: introduce flush_or_purge_queued_packets()
  virtio-net: support queue_enable
  vhost: vhost-kernel: enable vq reset feature

Xuan Zhuo (5):
  virtio: sync relevant definitions with linux
  virtio: introduce __virtio_queue_reset()
  virtio: introduce virtio_queue_reset()
  virtio-pci: support queue reset
  virtio-net: support queue reset

 hw/core/machine.c |  4 +-
 hw/net/vhost_net.c| 79 +++
 hw/net/virtio-net.c   | 56 +++--
 hw/virtio/vhost.c | 16 ++--
 hw/virtio/virtio-pci.c| 16 
 hw/virtio/virtio.c| 62 +++
 include/hw/virtio/vhost.h |  5 ++
 include/hw/virtio/virtio-pci.h|  5 ++
 include/hw/virtio/virtio.h|  8 +-
 include/net/vhost_net.h   |  4 +
 .../standard-headers/linux/virtio_config.h|  5 ++
 include/standard-headers/linux/virtio_pci.h   |  2 +
 12 files changed, 230 insertions(+), 32 deletions(-)

--
2.32.0.3.g01195cf9f




[PATCH v5 13/15] virtio-net: support queue reset

2022-09-13 Thread Xuan Zhuo
virtio-net and vhost-kernel implement queue reset.
Queued packets in the corresponding queue pair are flushed
or purged.

For virtio-net, userspace datapath will be disabled later in
__virtio_queue_reset(). It will set addr of vring to 0 and idx to 0.
Thus, virtio_net_receive() and virtio_net_flush_tx() will not receive
or send packets.

For vhost-net, the datapath will be disabled in vhost_net_virtqueue_reset().

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 
Acked-by: Jason Wang 
---
 hw/net/virtio-net.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 27b59c0ad6..d774a3e652 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -540,6 +540,23 @@ static RxFilterInfo 
*virtio_net_query_rxfilter(NetClientState *nc)
 return info;
 }
 
+static void virtio_net_queue_reset(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+
+if (!nc->peer) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+vhost_net_virtqueue_reset(vdev, nc, queue_index);
+}
+
+flush_or_purge_queued_packets(nc);
+}
+
 static void virtio_net_reset(VirtIODevice *vdev)
 {
 VirtIONet *n = VIRTIO_NET(vdev);
@@ -3784,6 +3801,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
 vdc->set_features = virtio_net_set_features;
 vdc->bad_features = virtio_net_bad_features;
 vdc->reset = virtio_net_reset;
+vdc->queue_reset = virtio_net_queue_reset;
 vdc->set_status = virtio_net_set_status;
 vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
 vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
-- 
2.32.0.3.g01195cf9f




[PATCH v5 11/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce vhost_net_virtqueue_restart(), which can restart the
specific virtqueue when the vhost net started running before.
If it fails to restart the virtqueue, the device will be stopped.

Here we do not reuse vhost_net_start_one() or vhost_dev_start()
because they work at queue pair level. The mem table and features
do not change, so we can call the vhost_virtqueue_start() to
restart a specific queue.

This patch only considers the case of vhost-kernel, when
NetClientDriver is NET_CLIENT_DRIVER_TAP.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
 hw/net/vhost_net.c  | 53 +
 include/net/vhost_net.h |  2 ++
 2 files changed, 55 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 8beecb4d22..d2926e2ed6 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -34,6 +34,7 @@
 #include "standard-headers/linux/virtio_ring.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/virtio-bus.h"
+#include "linux-headers/linux/vhost.h"
 
 
 /* Features supported by host kernel. */
@@ -556,3 +557,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
NetClientState *nc,
  net->dev.vqs + idx,
  net->dev.vq_index + idx);
 }
+
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index)
+{
+VHostNetState *net = get_vhost_net(nc->peer);
+const VhostOps *vhost_ops = net->dev.vhost_ops;
+struct vhost_vring_file file = { };
+int idx, r;
+
+if (!net->dev.started) {
+return -EBUSY;
+}
+
+/* should only be called after backend is connected */
+assert(vhost_ops);
+
+idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
+
+r = vhost_virtqueue_start(>dev,
+  vdev,
+  net->dev.vqs + idx,
+  net->dev.vq_index + idx);
+if (r < 0) {
+goto err_start;
+}
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.index = idx;
+file.fd = net->backend;
+r = vhost_net_set_backend(>dev, );
+if (r < 0) {
+r = -errno;
+goto err_start;
+}
+}
+
+return 0;
+
+err_start:
+error_report("Error when restarting the queue.");
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.fd = VHOST_FILE_UNBIND;
+file.index = idx;
+int r = vhost_net_set_backend(>dev, );
+assert(r >= 0);
+}
+
+vhost_dev_stop(>dev, vdev);
+
+return r;
+}
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 85d85a4957..40b9a40074 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
 
 void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
int vq_index);
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index);
 #endif
-- 
2.32.0.3.g01195cf9f




[PATCH v5 07/15] virtio-pci: support queue enable

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

PCI devices support device specific vq enable.

Based on this function, the driver can re-enable the virtqueue after the
virtqueue is reset.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio-pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 79b9e641dd..a53b5d9f1e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1342,6 +1342,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr 
addr,
proxy->vqs[vdev->queue_sel].used[0]);
 proxy->vqs[vdev->queue_sel].enabled = 1;
 proxy->vqs[vdev->queue_sel].reset = 0;
+virtio_queue_enable(vdev, vdev->queue_sel);
 } else {
 virtio_error(vdev, "wrong value for queue_enable %"PRIx64, val);
 }
-- 
2.32.0.3.g01195cf9f




[PATCH v5 01/15] virtio: sync relevant definitions with linux

2022-09-13 Thread Xuan Zhuo
This is updated using scripts/update-linux-headers.sh.

Added VIRTIO_F_RING_RESET, VIRTIO_PCI_COMMON_Q_RESET. It came from here:
https://github.com/oasis-tcs/virtio-spec/issues/124
https://github.com/oasis-tcs/virtio-spec/issues/139

Add VIRTIO_PCI_COMMON_Q_NDATA, which comes from here:
https://github.com/oasis-tcs/virtio-spec/issues/89

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 
Acked-by: Jason Wang 
---
 include/standard-headers/linux/virtio_config.h | 5 +
 include/standard-headers/linux/virtio_pci.h| 2 ++
 2 files changed, 7 insertions(+)

diff --git a/include/standard-headers/linux/virtio_config.h 
b/include/standard-headers/linux/virtio_config.h
index 7acd8d4abc..47a7eef5e4 100644
--- a/include/standard-headers/linux/virtio_config.h
+++ b/include/standard-headers/linux/virtio_config.h
@@ -96,4 +96,9 @@
  * Does the device support Single Root I/O Virtualization?
  */
 #define VIRTIO_F_SR_IOV37
+
+/*
+ * This feature indicates that the driver can reset a queue individually.
+ */
+#define VIRTIO_F_RING_RESET40
 #endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/include/standard-headers/linux/virtio_pci.h 
b/include/standard-headers/linux/virtio_pci.h
index db7a8e2fcb..be912cfc95 100644
--- a/include/standard-headers/linux/virtio_pci.h
+++ b/include/standard-headers/linux/virtio_pci.h
@@ -202,6 +202,8 @@ struct virtio_pci_cfg_cap {
 #define VIRTIO_PCI_COMMON_Q_AVAILHI44
 #define VIRTIO_PCI_COMMON_Q_USEDLO 48
 #define VIRTIO_PCI_COMMON_Q_USEDHI 52
+#define VIRTIO_PCI_COMMON_Q_NDATA  56
+#define VIRTIO_PCI_COMMON_Q_RESET  58
 
 #endif /* VIRTIO_PCI_NO_MODERN */
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 03/15] virtio: introduce virtio_queue_reset()

2022-09-13 Thread Xuan Zhuo
Introduce a new interface function virtio_queue_reset() to implement
reset for vq.

Add a new callback to VirtioDeviceClass for queue reset operation for
each child device.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio.c | 11 +++
 include/hw/virtio/virtio.h |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 67d54832a9..0e9d41366f 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2039,6 +2039,17 @@ static void __virtio_queue_reset(VirtIODevice *vdev, 
uint32_t i)
 virtio_virtqueue_reset_region_cache(>vq[i]);
 }
 
+void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+
+if (k->queue_reset) {
+k->queue_reset(vdev, queue_index);
+}
+
+__virtio_queue_reset(vdev, queue_index);
+}
+
 void virtio_reset(void *opaque)
 {
 VirtIODevice *vdev = opaque;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index db1c0ddf6b..879394299b 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -130,6 +130,7 @@ struct VirtioDeviceClass {
 void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
 void (*reset)(VirtIODevice *vdev);
 void (*set_status)(VirtIODevice *vdev, uint8_t val);
+void (*queue_reset)(VirtIODevice *vdev, uint32_t queue_index);
 /* For transitional devices, this is a bitmap of features
  * that are only exposed on the legacy interface but not
  * the modern one.
@@ -268,6 +269,7 @@ int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, 
int n,
   MemoryRegion *mr, bool assign);
 int virtio_set_status(VirtIODevice *vdev, uint8_t val);
 void virtio_reset(void *opaque);
+void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index);
 void virtio_update_irq(VirtIODevice *vdev);
 int virtio_set_features(VirtIODevice *vdev, uint64_t val);
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 06/15] virtio-pci: support queue reset

2022-09-13 Thread Xuan Zhuo
PCI devices support vq reset.

Based on this function, the driver can adjust the size of the ring, and
quickly recycle the buffer in the ring.

The migration of the virtio devices will not happen during a reset
operation. This is becuase the global iothread lock is held. Migration
thread also needs the lock. As a result, when migration of virtio
devices starts, the 'reset' status of VirtIOPCIQueue will always be 0.
Thus, we do not need to add it in vmstate_virtio_pci_modern_queue_state.

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 
Acked-by: Jason Wang 
---
 hw/virtio/virtio-pci.c | 15 +++
 include/hw/virtio/virtio-pci.h |  5 +
 2 files changed, 20 insertions(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index a50c5a57d7..79b9e641dd 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1251,6 +1251,9 @@ static uint64_t virtio_pci_common_read(void *opaque, 
hwaddr addr,
 case VIRTIO_PCI_COMMON_Q_USEDHI:
 val = proxy->vqs[vdev->queue_sel].used[1];
 break;
+case VIRTIO_PCI_COMMON_Q_RESET:
+val = proxy->vqs[vdev->queue_sel].reset;
+break;
 default:
 val = 0;
 }
@@ -1338,6 +1341,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr 
addr,
((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 |
proxy->vqs[vdev->queue_sel].used[0]);
 proxy->vqs[vdev->queue_sel].enabled = 1;
+proxy->vqs[vdev->queue_sel].reset = 0;
 } else {
 virtio_error(vdev, "wrong value for queue_enable %"PRIx64, val);
 }
@@ -1360,6 +1364,16 @@ static void virtio_pci_common_write(void *opaque, hwaddr 
addr,
 case VIRTIO_PCI_COMMON_Q_USEDHI:
 proxy->vqs[vdev->queue_sel].used[1] = val;
 break;
+case VIRTIO_PCI_COMMON_Q_RESET:
+if (val == 1) {
+proxy->vqs[vdev->queue_sel].reset = 1;
+
+virtio_queue_reset(vdev, vdev->queue_sel);
+
+proxy->vqs[vdev->queue_sel].reset = 0;
+proxy->vqs[vdev->queue_sel].enabled = 0;
+}
+break;
 default:
 break;
 }
@@ -1954,6 +1968,7 @@ static void virtio_pci_reset(DeviceState *qdev)
 
 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
 proxy->vqs[i].enabled = 0;
+proxy->vqs[i].reset = 0;
 proxy->vqs[i].num = 0;
 proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0;
 proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0;
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index 2446dcd9ae..938799e8f6 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -117,6 +117,11 @@ typedef struct VirtIOPCIRegion {
 typedef struct VirtIOPCIQueue {
   uint16_t num;
   bool enabled;
+  /*
+   * No need to migrate the reset status, because it is always 0
+   * when the migration starts.
+   */
+  bool reset;
   uint32_t desc[2];
   uint32_t avail[2];
   uint32_t used[2];
-- 
2.32.0.3.g01195cf9f




[PATCH v5 15/15] vhost: vhost-kernel: enable vq reset feature

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Add virtqueue reset feature for vhost-kernel.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
 hw/net/vhost_net.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index d2926e2ed6..53b2fac4f6 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -47,6 +47,7 @@ static const int kernel_feature_bits[] = {
 VIRTIO_NET_F_MTU,
 VIRTIO_F_IOMMU_PLATFORM,
 VIRTIO_F_RING_PACKED,
+VIRTIO_F_RING_RESET,
 VIRTIO_NET_F_HASH_REPORT,
 VHOST_INVALID_FEATURE_BIT
 };
-- 
2.32.0.3.g01195cf9f




[PATCH v5 12/15] virtio-net: introduce flush_or_purge_queued_packets()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce the fucntion flush_or_purge_queued_packets(), it will be
used in device reset and virtqueue reset. Therefore, we extract the
common logic as a new function.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/net/virtio-net.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index dd0d056fde..27b59c0ad6 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -118,6 +118,16 @@ static int vq2q(int queue_index)
 return queue_index / 2;
 }
 
+static void flush_or_purge_queued_packets(NetClientState *nc)
+{
+if (!nc->peer) {
+return;
+}
+
+qemu_flush_or_purge_queued_packets(nc->peer, true);
+assert(!virtio_net_get_subqueue(nc)->async_tx.elem);
+}
+
 /* TODO
  * - we could suppress RX interrupt if we were so inclined.
  */
@@ -560,12 +570,7 @@ static void virtio_net_reset(VirtIODevice *vdev)
 
 /* Flush any async TX */
 for (i = 0;  i < n->max_queue_pairs; i++) {
-NetClientState *nc = qemu_get_subqueue(n->nic, i);
-
-if (nc->peer) {
-qemu_flush_or_purge_queued_packets(nc->peer, true);
-assert(!virtio_net_get_subqueue(nc)->async_tx.elem);
-}
+flush_or_purge_queued_packets(qemu_get_subqueue(n->nic, i));
 }
 }
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 08/15] vhost: expose vhost_virtqueue_start()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Expose vhost_virtqueue_start(), we need to use it when restarting a
virtqueue.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/vhost.c | 8 
 include/hw/virtio/vhost.h | 3 +++
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index f758f177bb..7900bc81ab 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1081,10 +1081,10 @@ out:
 return ret;
 }
 
-static int vhost_virtqueue_start(struct vhost_dev *dev,
-struct VirtIODevice *vdev,
-struct vhost_virtqueue *vq,
-unsigned idx)
+int vhost_virtqueue_start(struct vhost_dev *dev,
+  struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq,
+  unsigned idx)
 {
 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
 VirtioBusState *vbus = VIRTIO_BUS(qbus);
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index a346f23d13..b092f57d98 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -279,6 +279,9 @@ int vhost_net_set_backend(struct vhost_dev *hdev,
 
 int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write);
 
+int vhost_virtqueue_start(struct vhost_dev *dev, struct VirtIODevice *vdev,
+  struct vhost_virtqueue *vq, unsigned idx);
+
 void vhost_dev_reset_inflight(struct vhost_inflight *inflight);
 void vhost_dev_free_inflight(struct vhost_inflight *inflight);
 void vhost_dev_save_inflight(struct vhost_inflight *inflight, QEMUFile *f);
-- 
2.32.0.3.g01195cf9f




[PATCH v5 05/15] virtio: core: vq reset feature negotation support

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

A a new command line parameter "queue_reset" is added.

Meanwhile, the vq reset feature is disabled for pre-7.2 machines.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/core/machine.c  | 4 +++-
 include/hw/virtio/virtio.h | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index aa520e74a8..907fa78ff0 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -40,7 +40,9 @@
 #include "hw/virtio/virtio-pci.h"
 #include "qom/object_interfaces.h"
 
-GlobalProperty hw_compat_7_1[] = {};
+GlobalProperty hw_compat_7_1[] = {
+{ "virtio-device", "queue_reset", "false" },
+};
 const size_t hw_compat_7_1_len = G_N_ELEMENTS(hw_compat_7_1);
 
 GlobalProperty hw_compat_7_0[] = {
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 085997d8f3..ed3ecbef80 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -295,7 +295,9 @@ typedef struct VirtIORNGConf VirtIORNGConf;
 DEFINE_PROP_BIT64("iommu_platform", _state, _field, \
   VIRTIO_F_IOMMU_PLATFORM, false), \
 DEFINE_PROP_BIT64("packed", _state, _field, \
-  VIRTIO_F_RING_PACKED, false)
+  VIRTIO_F_RING_PACKED, false), \
+DEFINE_PROP_BIT64("queue_reset", _state, _field, \
+  VIRTIO_F_RING_RESET, true)
 
 hwaddr virtio_queue_get_desc_addr(VirtIODevice *vdev, int n);
 bool virtio_queue_enabled_legacy(VirtIODevice *vdev, int n);
-- 
2.32.0.3.g01195cf9f




[PATCH v5 10/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_reset()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce vhost_virtqueue_reset(), which can reset the specific
virtqueue in the device. Then it will unmap vrings and the desc
of the virtqueue.

Here we do not reuse the vhost_net_stop_one() or vhost_dev_stop(),
because they work at queue pair level. We do not use
vhost_virtqueue_stop() because it may stop the device in the
backend.

This patch only considers the case of vhost-kernel, when
NetClientDriver is NET_CLIENT_DRIVER_TAP.

Furthermore, we do not need net->nc->info->poll() because
it enables userspace datapath and we want to stop all
datapaths for this reset virtqueue here.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/net/vhost_net.c  | 25 +
 include/net/vhost_net.h |  2 ++
 2 files changed, 27 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index d28f8b974b..8beecb4d22 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -531,3 +531,28 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
 
 return vhost_ops->vhost_net_set_mtu(>dev, mtu);
 }
+
+void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
+   int vq_index)
+{
+VHostNetState *net = get_vhost_net(nc->peer);
+const VhostOps *vhost_ops = net->dev.vhost_ops;
+struct vhost_vring_file file = { .fd = -1 };
+int idx;
+
+/* should only be called after backend is connected */
+assert(vhost_ops);
+
+idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.index = idx;
+int r = vhost_net_set_backend(>dev, );
+assert(r >= 0);
+}
+
+vhost_virtqueue_stop(>dev,
+ vdev,
+ net->dev.vqs + idx,
+ net->dev.vq_index + idx);
+}
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 387e913e4e..85d85a4957 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -48,4 +48,6 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
 
 int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
 
+void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
+   int vq_index);
 #endif
-- 
2.32.0.3.g01195cf9f




[PATCH v5 04/15] virtio: introduce virtio_queue_enable()

2022-09-13 Thread Xuan Zhuo
From: Kangjie Xu 

Introduce the interface queue_enable() in VirtioDeviceClass and the
fucntion virtio_queue_enable() in virtio, it can be called when
VIRTIO_PCI_COMMON_Q_ENABLE is written and related virtqueue can be
started. It only supports the devices of virtio 1 or later. The
not-supported devices can only start the virtqueue when DRIVER_OK.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio.c | 14 ++
 include/hw/virtio/virtio.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 0e9d41366f..141f18c633 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2050,6 +2050,20 @@ void virtio_queue_reset(VirtIODevice *vdev, uint32_t 
queue_index)
 __virtio_queue_reset(vdev, queue_index);
 }
 
+void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
+{
+VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+
+if (!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
+error_report("queue_enable is only suppported in devices of virtio "
+ "1.0 or later.");
+}
+
+if (k->queue_enable) {
+k->queue_enable(vdev, queue_index);
+}
+}
+
 void virtio_reset(void *opaque)
 {
 VirtIODevice *vdev = opaque;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 879394299b..085997d8f3 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -131,6 +131,7 @@ struct VirtioDeviceClass {
 void (*reset)(VirtIODevice *vdev);
 void (*set_status)(VirtIODevice *vdev, uint8_t val);
 void (*queue_reset)(VirtIODevice *vdev, uint32_t queue_index);
+void (*queue_enable)(VirtIODevice *vdev, uint32_t queue_index);
 /* For transitional devices, this is a bitmap of features
  * that are only exposed on the legacy interface but not
  * the modern one.
@@ -270,6 +271,7 @@ int virtio_queue_set_host_notifier_mr(VirtIODevice *vdev, 
int n,
 int virtio_set_status(VirtIODevice *vdev, uint8_t val);
 void virtio_reset(void *opaque);
 void virtio_queue_reset(VirtIODevice *vdev, uint32_t queue_index);
+void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index);
 void virtio_update_irq(VirtIODevice *vdev);
 int virtio_set_features(VirtIODevice *vdev, uint64_t val);
 
-- 
2.32.0.3.g01195cf9f




[PATCH v5 02/15] virtio: introduce __virtio_queue_reset()

2022-09-13 Thread Xuan Zhuo
Separate the logic of vq reset. This logic will be called directly
later.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 hw/virtio/virtio.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 5d607aeaa0..67d54832a9 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2019,6 +2019,26 @@ static enum virtio_device_endian 
virtio_current_cpu_endian(void)
 }
 }
 
+static void __virtio_queue_reset(VirtIODevice *vdev, uint32_t i)
+{
+vdev->vq[i].vring.desc = 0;
+vdev->vq[i].vring.avail = 0;
+vdev->vq[i].vring.used = 0;
+vdev->vq[i].last_avail_idx = 0;
+vdev->vq[i].shadow_avail_idx = 0;
+vdev->vq[i].used_idx = 0;
+vdev->vq[i].last_avail_wrap_counter = true;
+vdev->vq[i].shadow_avail_wrap_counter = true;
+vdev->vq[i].used_wrap_counter = true;
+virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR);
+vdev->vq[i].signalled_used = 0;
+vdev->vq[i].signalled_used_valid = false;
+vdev->vq[i].notification = true;
+vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
+vdev->vq[i].inuse = 0;
+virtio_virtqueue_reset_region_cache(>vq[i]);
+}
+
 void virtio_reset(void *opaque)
 {
 VirtIODevice *vdev = opaque;
@@ -2050,22 +2070,7 @@ void virtio_reset(void *opaque)
 virtio_notify_vector(vdev, vdev->config_vector);
 
 for(i = 0; i < VIRTIO_QUEUE_MAX; i++) {
-vdev->vq[i].vring.desc = 0;
-vdev->vq[i].vring.avail = 0;
-vdev->vq[i].vring.used = 0;
-vdev->vq[i].last_avail_idx = 0;
-vdev->vq[i].shadow_avail_idx = 0;
-vdev->vq[i].used_idx = 0;
-vdev->vq[i].last_avail_wrap_counter = true;
-vdev->vq[i].shadow_avail_wrap_counter = true;
-vdev->vq[i].used_wrap_counter = true;
-virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR);
-vdev->vq[i].signalled_used = 0;
-vdev->vq[i].signalled_used_valid = false;
-vdev->vq[i].notification = true;
-vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
-vdev->vq[i].inuse = 0;
-virtio_virtqueue_reset_region_cache(>vq[i]);
+__virtio_queue_reset(vdev, i);
 }
 }
 
-- 
2.32.0.3.g01195cf9f




Re: [PATCH v2 6/6] vhost: vhost-user: enable vq reset feature

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Add virtqueue reset feature for vhost-user.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/net/vhost_net.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 8b80942e7c..ad319faee8 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -74,6 +74,7 @@ static const int user_feature_bits[] = {
  VIRTIO_NET_F_MTU,
  VIRTIO_F_IOMMU_PLATFORM,
  VIRTIO_F_RING_PACKED,
+VIRTIO_F_RING_RESET,
  VIRTIO_NET_F_RSS,
  VIRTIO_NET_F_HASH_REPORT,
  





Re: [PATCH v2 5/6] virtio-net: vhost-user: update queue_reset and queue_enable

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Update virtio_net_queue_reset() and virtio_net_queue_enable()
for vhost-user scenario.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/net/virtio-net.c | 6 --
  1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 6ab796b399..19a2132180 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -550,7 +550,8 @@ static void virtio_net_queue_reset(VirtIODevice *vdev, 
uint32_t queue_index)
  }
  
  if (get_vhost_net(nc->peer) &&

-nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+(nc->peer->info->type == NET_CLIENT_DRIVER_TAP ||
+ nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER)) {
  vhost_net_virtqueue_reset(vdev, nc, queue_index);
  }
  
@@ -568,7 +569,8 @@ static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)

  }
  
  if (get_vhost_net(nc->peer) &&

-nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+(nc->peer->info->type == NET_CLIENT_DRIVER_TAP ||
+ nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER)) {
  r = vhost_net_virtqueue_restart(vdev, nc, queue_index);
  if (r < 0) {
  error_report("unable to restart vhost net virtqueue: %d, "





Re: [PATCH v2 3/6] vhost-net: vhost-user: update vhost_net_virtqueue_reset()

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Update vhost_net_virtqueue_reset() for vhost-user scenario.

In order to reuse some functions, we process the idx for
vhost-user scenario because vhost_get_vq_index behave
differently for vhost-user.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
  hw/net/vhost_net.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index ea896ea75b..25e5665489 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -545,6 +545,9 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
NetClientState *nc,
  assert(vhost_ops);
  
  idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);

+if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
+idx -= net->dev.vq_index;
+}



This looks tricky. Any reason we can't simply use vq_index for both 
vhost-user and vhost-net?


Thanks


  
  if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {

  file.index = idx;





Re: [PATCH v2 2/6] vhost-user: add op to enable or disable a single vring

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

There is only vhost_set_dev_enable op in VhostOps. Thus, we introduce
the interface vhost_set_vring_enable to set the enable status for a
single vring.

Resetting a single vq will rely on this interface.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/virtio/vhost-user.c| 25 ++---
  include/hw/virtio/vhost-backend.h |  3 +++
  2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 794519359b..3f140d5085 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1198,6 +1198,22 @@ static int vhost_user_set_vring_base(struct vhost_dev 
*dev,
  return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
  }
  
+static int vhost_user_set_vring_enable(struct vhost_dev *dev,

+   int index,
+   int enable)
+{
+if (index < dev->vq_index || index >= dev->vq_index + dev->nvqs) {
+return -EINVAL;
+}
+
+struct vhost_vring_state state = {
+.index = index,
+.num   = enable,
+};
+
+return vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, );
+}
+
  static int vhost_user_set_dev_enable(struct vhost_dev *dev, int enable)
  {
  int i;
@@ -1207,13 +1223,7 @@ static int vhost_user_set_dev_enable(struct vhost_dev 
*dev, int enable)
  }
  
  for (i = 0; i < dev->nvqs; ++i) {

-int ret;
-struct vhost_vring_state state = {
-.index = dev->vq_index + i,
-.num   = enable,
-};
-
-ret = vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, );
+int ret = vhost_user_set_vring_enable(dev, dev->vq_index + i, enable);
  if (ret < 0) {
  /*
   * Restoring the previous state is likely infeasible, as well as
@@ -2627,6 +2637,7 @@ const VhostOps user_ops = {
  .vhost_set_owner = vhost_user_set_owner,
  .vhost_reset_device = vhost_user_reset_device,
  .vhost_get_vq_index = vhost_user_get_vq_index,
+.vhost_set_vring_enable = vhost_user_set_vring_enable,
  .vhost_set_dev_enable = vhost_user_set_dev_enable,
  .vhost_requires_shm_log = vhost_user_requires_shm_log,
  .vhost_migration_done = vhost_user_migration_done,
diff --git a/include/hw/virtio/vhost-backend.h 
b/include/hw/virtio/vhost-backend.h
index b49432045f..dad7191bac 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -81,6 +81,8 @@ typedef int (*vhost_set_backend_cap_op)(struct vhost_dev 
*dev);
  typedef int (*vhost_set_owner_op)(struct vhost_dev *dev);
  typedef int (*vhost_reset_device_op)(struct vhost_dev *dev);
  typedef int (*vhost_get_vq_index_op)(struct vhost_dev *dev, int idx);
+typedef int (*vhost_set_vring_enable_op)(struct vhost_dev *dev,
+ int index, int enable);
  typedef int (*vhost_set_dev_enable_op)(struct vhost_dev *dev,
 int enable);
  typedef bool (*vhost_requires_shm_log_op)(struct vhost_dev *dev);
@@ -155,6 +157,7 @@ typedef struct VhostOps {
  vhost_set_owner_op vhost_set_owner;
  vhost_reset_device_op vhost_reset_device;
  vhost_get_vq_index_op vhost_get_vq_index;
+vhost_set_vring_enable_op vhost_set_vring_enable;
  vhost_set_dev_enable_op vhost_set_dev_enable;
  vhost_requires_shm_log_op vhost_requires_shm_log;
  vhost_migration_done_op vhost_migration_done;





Re: [PATCH v2 1/6] net: virtio: rename vhost_set_vring_enable to vhost_set_dev_enable

2022-09-13 Thread Jason Wang



在 2022/9/12 11:10, Kangjie Xu 写道:

Previously, vhost_set_vring_enable will enable/disable all vrings
in a device,



Nit: It would be more clear to say to disable all vrings for a specific 
vhost device.


Since in the case of multiqueue virtio-net, a single virtio-net device 
may have multiple vhost devices.


Thanks



which causes ambiguity. So we rename it to
vhost_set_dev_enable.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
  backends/cryptodev-vhost.c| 12 ++--
  hw/net/vhost_net-stub.c   |  2 +-
  hw/net/vhost_net.c|  8 
  hw/net/virtio-net.c   |  4 ++--
  hw/virtio/vhost-user.c|  4 ++--
  include/hw/virtio/vhost-backend.h |  6 +++---
  include/net/vhost_net.h   |  2 +-
  7 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
index bc13e466b4..b83e939760 100644
--- a/backends/cryptodev-vhost.c
+++ b/backends/cryptodev-vhost.c
@@ -147,9 +147,9 @@ cryptodev_vhost_set_vq_index(CryptoDevBackendVhost *crypto,
  }
  
  static int

-vhost_set_vring_enable(CryptoDevBackendClient *cc,
-CryptoDevBackend *b,
-uint16_t queue, int enable)
+vhost_set_dev_enable(CryptoDevBackendClient *cc,
+ CryptoDevBackend *b,
+ uint16_t queue, int enable)
  {
  CryptoDevBackendVhost *crypto =
 cryptodev_get_vhost(cc, b, queue);
@@ -162,8 +162,8 @@ vhost_set_vring_enable(CryptoDevBackendClient *cc,
  }
  
  vhost_ops = crypto->dev.vhost_ops;

-if (vhost_ops->vhost_set_vring_enable) {
-return vhost_ops->vhost_set_vring_enable(>dev, enable);
+if (vhost_ops->vhost_set_dev_enable) {
+return vhost_ops->vhost_set_dev_enable(>dev, enable);
  }
  
  return 0;

@@ -219,7 +219,7 @@ int cryptodev_vhost_start(VirtIODevice *dev, int 
total_queues)
  
  if (cc->vring_enable) {

  /* restore vring enable state */
-r = vhost_set_vring_enable(cc, b, i, cc->vring_enable);
+r = vhost_set_dev_enable(cc, b, i, cc->vring_enable);
  
  if (r < 0) {

  goto err_start;
diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c
index 89d71cfb8e..ac5f217dc1 100644
--- a/hw/net/vhost_net-stub.c
+++ b/hw/net/vhost_net-stub.c
@@ -92,7 +92,7 @@ VHostNetState *get_vhost_net(NetClientState *nc)
  return 0;
  }
  
-int vhost_set_vring_enable(NetClientState *nc, int enable)

+int vhost_set_dev_enable(NetClientState *nc, int enable)
  {
  return 0;
  }
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 97cdf9280b..ea896ea75b 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -396,7 +396,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
  
  if (peer->vring_enable) {

  /* restore vring enable state */
-r = vhost_set_vring_enable(peer, peer->vring_enable);
+r = vhost_set_dev_enable(peer, peer->vring_enable);
  
  if (r < 0) {

  vhost_net_stop_one(get_vhost_net(peer), dev);
@@ -508,15 +508,15 @@ VHostNetState *get_vhost_net(NetClientState *nc)
  return vhost_net;
  }
  
-int vhost_set_vring_enable(NetClientState *nc, int enable)

+int vhost_set_dev_enable(NetClientState *nc, int enable)
  {
  VHostNetState *net = get_vhost_net(nc);
  const VhostOps *vhost_ops = net->dev.vhost_ops;
  
  nc->vring_enable = enable;
  
-if (vhost_ops && vhost_ops->vhost_set_vring_enable) {

-return vhost_ops->vhost_set_vring_enable(>dev, enable);
+if (vhost_ops && vhost_ops->vhost_set_dev_enable) {
+return vhost_ops->vhost_set_dev_enable(>dev, enable);
  }
  
  return 0;

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 7817206596..6ab796b399 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -696,7 +696,7 @@ static int peer_attach(VirtIONet *n, int index)
  }
  
  if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {

-vhost_set_vring_enable(nc->peer, 1);
+vhost_set_dev_enable(nc->peer, 1);
  }
  
  if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {

@@ -719,7 +719,7 @@ static int peer_detach(VirtIONet *n, int index)
  }
  
  if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {

-vhost_set_vring_enable(nc->peer, 0);
+vhost_set_dev_enable(nc->peer, 0);
  }
  
  if (nc->peer->info->type !=  NET_CLIENT_DRIVER_TAP) {

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index bd24741be8..794519359b 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1198,7 +1198,7 @@ static int vhost_user_set_vring_base(struct vhost_dev 
*dev,
  return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
  }
  
-static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable)

+static int 

Re: [PATCH v4 14/15] virtio-net: support queue_enable

2022-09-13 Thread Jason Wang



在 2022/9/12 01:22, Kangjie Xu 写道:

Support queue_enable in vhost-kernel scenario. It can be called when
a vq reset operation has been performed and the vq is restared.

It should be noted that we can restart the vq when the vhost has
already started. When launching a new vhost device, the vhost is not
started and all vqs are not initalized until VIRTIO_PCI_COMMON_STATUS
is written. Thus, we should use vhost_started to differentiate the
two cases: vq reset and device start.

Currently it only supports vhost-kernel.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 



Acked-by: Jason Wang 



---
  hw/net/virtio-net.c | 21 +
  1 file changed, 21 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d774a3e652..7817206596 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -557,6 +557,26 @@ static void virtio_net_queue_reset(VirtIODevice *vdev, 
uint32_t queue_index)
  flush_or_purge_queued_packets(nc);
  }
  
+static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index)

+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+int r;
+
+if (!nc->peer || !vdev->vhost_started) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+r = vhost_net_virtqueue_restart(vdev, nc, queue_index);
+if (r < 0) {
+error_report("unable to restart vhost net virtqueue: %d, "
+"when resetting the queue", queue_index);
+}
+}
+}
+
  static void virtio_net_reset(VirtIODevice *vdev)
  {
  VirtIONet *n = VIRTIO_NET(vdev);
@@ -3802,6 +3822,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
  vdc->bad_features = virtio_net_bad_features;
  vdc->reset = virtio_net_reset;
  vdc->queue_reset = virtio_net_queue_reset;
+vdc->queue_enable = virtio_net_queue_enable;
  vdc->set_status = virtio_net_set_status;
  vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
  vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;





Re: [PATCH v4 13/15] virtio-net: support queue reset

2022-09-13 Thread Jason Wang



在 2022/9/12 01:22, Kangjie Xu 写道:

From: Xuan Zhuo 

virtio-net and vhost-kernel implement queue reset.
Queued packets in the corresponding queue pair are flushed
or purged.

For virtio-net, userspace datapath will be disabled later in
__virtio_queue_reset(). It will set addr of vring to 0 and idx to 0.
Thus, virtio_net_receive() and virtio_net_flush_tx() will not receive
or send packets.

For vhost-net, the datapath will be disabled in vhost_net_virtqueue_reset().

Signed-off-by: Xuan Zhuo 
Signed-off-by: Kangjie Xu 



Acked-by: Jason Wang 



---
  hw/net/virtio-net.c | 18 ++
  1 file changed, 18 insertions(+)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 27b59c0ad6..d774a3e652 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -540,6 +540,23 @@ static RxFilterInfo 
*virtio_net_query_rxfilter(NetClientState *nc)
  return info;
  }
  
+static void virtio_net_queue_reset(VirtIODevice *vdev, uint32_t queue_index)

+{
+VirtIONet *n = VIRTIO_NET(vdev);
+NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(queue_index));
+
+if (!nc->peer) {
+return;
+}
+
+if (get_vhost_net(nc->peer) &&
+nc->peer->info->type == NET_CLIENT_DRIVER_TAP) {
+vhost_net_virtqueue_reset(vdev, nc, queue_index);
+}
+
+flush_or_purge_queued_packets(nc);
+}
+
  static void virtio_net_reset(VirtIODevice *vdev)
  {
  VirtIONet *n = VIRTIO_NET(vdev);
@@ -3784,6 +3801,7 @@ static void virtio_net_class_init(ObjectClass *klass, 
void *data)
  vdc->set_features = virtio_net_set_features;
  vdc->bad_features = virtio_net_bad_features;
  vdc->reset = virtio_net_reset;
+vdc->queue_reset = virtio_net_queue_reset;
  vdc->set_status = virtio_net_set_status;
  vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
  vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;





Re: [PATCH v4 11/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_restart()

2022-09-13 Thread Jason Wang



在 2022/9/12 01:22, Kangjie Xu 写道:

Introduce vhost_net_virtqueue_restart(), which can restart the
specific virtqueue when the vhost net started running before.
If it fails to restart the virtqueue, the device will be stopped.

Here we do not reuse vhost_net_start_one() or vhost_dev_start()
because they work at queue pair level. The mem table and features
do not change, so we can call the vhost_virtqueue_start() to
restart a specific queue.

This patch only considers the case of vhost-kernel, when
NetClientDriver is NET_CLIENT_DRIVER_TAP.

Signed-off-by: Kangjie Xu 
Signed-off-by: Xuan Zhuo 
---
  hw/net/vhost_net.c  | 52 +
  include/net/vhost_net.h |  2 ++
  2 files changed, 54 insertions(+)

diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 8beecb4d22..1059aa45b4 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -556,3 +556,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, 
NetClientState *nc,
   net->dev.vqs + idx,
   net->dev.vq_index + idx);
  }
+
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index)
+{
+VHostNetState *net = get_vhost_net(nc->peer);
+const VhostOps *vhost_ops = net->dev.vhost_ops;
+struct vhost_vring_file file = { };
+int idx, r;
+
+if (!net->dev.started) {
+return -ENOTSUP;
+}



-EBUSY?



+
+/* should only be called after backend is connected */
+assert(vhost_ops);
+
+idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
+
+r = vhost_virtqueue_start(>dev,
+  vdev,
+  net->dev.vqs + idx,
+  net->dev.vq_index + idx);
+if (r < 0) {
+goto err_start;
+}
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.index = idx;
+file.fd = net->backend;
+r = vhost_net_set_backend(>dev, );
+if (r < 0) {
+r = -errno;
+goto err_start;
+}
+}
+
+return 0;
+
+err_start:
+error_report("Error when restarting the queue.");
+
+if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
+file.fd = -1;



Let's try reuse  VHOST_FILE_UNBIND.

Other looks good.

Thanks



+file.index = idx;
+int r = vhost_net_set_backend(>dev, );
+assert(r >= 0);
+}
+
+vhost_dev_stop(>dev, vdev);
+
+return r;
+}
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 85d85a4957..40b9a40074 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
  
  void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,

 int vq_index);
+int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc,
+int vq_index);
  #endif





Re: [PATCH 2/3] vdpa: load vlan configuration at NIC startup

2022-09-13 Thread Jason Wang
On Fri, Sep 9, 2022 at 4:38 PM Michael S. Tsirkin  wrote:
>
> On Fri, Sep 09, 2022 at 10:01:16AM +0200, Eugenio Perez Martin wrote:
> > On Fri, Sep 9, 2022 at 8:40 AM Jason Wang  wrote:
> > >
> > > On Fri, Sep 9, 2022 at 2:38 PM Jason Wang  wrote:
> > > >
> > > > On Wed, Sep 7, 2022 at 12:36 AM Eugenio Pérez  
> > > > wrote:
> > > > >
> > > > > To have enabled vlans at device startup may happen in the destination 
> > > > > of
> > > > > a live migration, so this configuration must be restored.
> > > > >
> > > > > At this moment the code is not accessible, since SVQ refuses to start 
> > > > > if
> > > > > vlan feature is exposed by the device.
> > > > >
> > > > > Signed-off-by: Eugenio Pérez 
> > > > > ---
> > > > >  net/vhost-vdpa.c | 46 --
> > > > >  1 file changed, 44 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> > > > > index 4bc3fd01a8..ecbfd08eb9 100644
> > > > > --- a/net/vhost-vdpa.c
> > > > > +++ b/net/vhost-vdpa.c
> > > > > @@ -100,6 +100,8 @@ static const uint64_t vdpa_svq_device_features =
> > > > >  BIT_ULL(VIRTIO_NET_F_RSC_EXT) |
> > > > >  BIT_ULL(VIRTIO_NET_F_STANDBY);
> > > > >
> > > > > +#define MAX_VLAN(1 << 12)   /* Per 802.1Q definition */
> > > > > +
> > > > >  VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
> > > > >  {
> > > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > > @@ -423,6 +425,47 @@ static int vhost_vdpa_net_load_mq(VhostVDPAState 
> > > > > *s,
> > > > >  return *s->status != VIRTIO_NET_OK;
> > > > >  }
> > > > >
> > > > > +static int vhost_vdpa_net_load_single_vlan(VhostVDPAState *s,
> > > > > +   const VirtIONet *n,
> > > > > +   uint16_t vid)
> > > > > +{
> > > > > +ssize_t dev_written = vhost_vdpa_net_load_cmd(s, 
> > > > > VIRTIO_NET_CTRL_VLAN,
> > > > > +  
> > > > > VIRTIO_NET_CTRL_VLAN_ADD,
> > > > > +  , sizeof(vid));
> > > > > +if (unlikely(dev_written < 0)) {
> > > > > +return dev_written;
> > > > > +}
> > > > > +
> > > > > +if (unlikely(*s->status != VIRTIO_NET_OK)) {
> > > > > +return -EINVAL;
> > > > > +}
> > > > > +
> > > > > +return 0;
> > > > > +}
> > > > > +
> > > > > +static int vhost_vdpa_net_load_vlan(VhostVDPAState *s,
> > > > > +const VirtIONet *n)
> > > > > +{
> > > > > +uint64_t features = n->parent_obj.guest_features;
> > > > > +
> > > > > +if (!(features & BIT_ULL(VIRTIO_NET_F_CTRL_VLAN))) {
> > > > > +return 0;
> > > > > +}
> > > > > +
> > > > > +for (int i = 0; i < MAX_VLAN >> 5; i++) {
> > > > > +for (int j = 0; n->vlans[i] && j <= 0x1f; j++) {
> > > > > +if (n->vlans[i] & (1U << j)) {
> > > > > +int r = vhost_vdpa_net_load_single_vlan(s, n, (i << 
> > > > > 5) + j);
> > > >
> > > > This seems to cause a lot of latency if the driver has a lot of vlans.
> > > >
> > > > I wonder if it's simply to let all vlan traffic go by disabling
> > > > CTRL_VLAN feature at vDPA layer.
> > >
> >
> > The guest will not be able to recover that vlan configuration.
> >
> > > Another idea is to extend the spec to allow us to accept a bitmap of
> > > the vlan ids via a single command, then we will be fine.
> > >
> >
> > I'm not sure if adding more ways to configure something is the answer,
> > but I'd be ok to implement it.
> >
> > Another idea is to allow the sending of many CVQ commands in parallel.
> > It shouldn't be very hard to achieve using exposed buffers as ring
> > buffers, and it will short down the start of the devices with many
> > features.
>
> This would seem like a reasonable second step.  A first step would be to
> measure the overhead to make sure there's actually a need to optimize
> this.

+1.

Thanks

>
>
> > Thanks!
> >
> > > Thanks
> > >
> > > >
> > > > Thanks
> > > >
> > > > > +if (unlikely(r != 0)) {
> > > > > +return r;
> > > > > +}
> > > > > +}
> > > > > +}
> > > > > +}
> > > > > +
> > > > > +return 0;
> > > > > +}
> > > > > +
> > > > >  static int vhost_vdpa_net_load(NetClientState *nc)
> > > > >  {
> > > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > > @@ -445,8 +488,7 @@ static int vhost_vdpa_net_load(NetClientState *nc)
> > > > >  if (unlikely(r)) {
> > > > >  return r;
> > > > >  }
> > > > > -
> > > > > -return 0;
> > > > > +return vhost_vdpa_net_load_vlan(s, n);
> > > > >  }
> > > > >
> > > > >  static NetClientInfo net_vhost_vdpa_cvq_info = {
> > > > > --
> > > > > 2.31.1
> > > > >
> > >
>




Re: [PATCH 2/3] vdpa: load vlan configuration at NIC startup

2022-09-13 Thread Jason Wang
On Fri, Sep 9, 2022 at 4:02 PM Eugenio Perez Martin  wrote:
>
> On Fri, Sep 9, 2022 at 8:40 AM Jason Wang  wrote:
> >
> > On Fri, Sep 9, 2022 at 2:38 PM Jason Wang  wrote:
> > >
> > > On Wed, Sep 7, 2022 at 12:36 AM Eugenio Pérez  wrote:
> > > >
> > > > To have enabled vlans at device startup may happen in the destination of
> > > > a live migration, so this configuration must be restored.
> > > >
> > > > At this moment the code is not accessible, since SVQ refuses to start if
> > > > vlan feature is exposed by the device.
> > > >
> > > > Signed-off-by: Eugenio Pérez 
> > > > ---
> > > >  net/vhost-vdpa.c | 46 --
> > > >  1 file changed, 44 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> > > > index 4bc3fd01a8..ecbfd08eb9 100644
> > > > --- a/net/vhost-vdpa.c
> > > > +++ b/net/vhost-vdpa.c
> > > > @@ -100,6 +100,8 @@ static const uint64_t vdpa_svq_device_features =
> > > >  BIT_ULL(VIRTIO_NET_F_RSC_EXT) |
> > > >  BIT_ULL(VIRTIO_NET_F_STANDBY);
> > > >
> > > > +#define MAX_VLAN(1 << 12)   /* Per 802.1Q definition */
> > > > +
> > > >  VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
> > > >  {
> > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > @@ -423,6 +425,47 @@ static int vhost_vdpa_net_load_mq(VhostVDPAState 
> > > > *s,
> > > >  return *s->status != VIRTIO_NET_OK;
> > > >  }
> > > >
> > > > +static int vhost_vdpa_net_load_single_vlan(VhostVDPAState *s,
> > > > +   const VirtIONet *n,
> > > > +   uint16_t vid)
> > > > +{
> > > > +ssize_t dev_written = vhost_vdpa_net_load_cmd(s, 
> > > > VIRTIO_NET_CTRL_VLAN,
> > > > +  
> > > > VIRTIO_NET_CTRL_VLAN_ADD,
> > > > +  , sizeof(vid));
> > > > +if (unlikely(dev_written < 0)) {
> > > > +return dev_written;
> > > > +}
> > > > +
> > > > +if (unlikely(*s->status != VIRTIO_NET_OK)) {
> > > > +return -EINVAL;
> > > > +}
> > > > +
> > > > +return 0;
> > > > +}
> > > > +
> > > > +static int vhost_vdpa_net_load_vlan(VhostVDPAState *s,
> > > > +const VirtIONet *n)
> > > > +{
> > > > +uint64_t features = n->parent_obj.guest_features;
> > > > +
> > > > +if (!(features & BIT_ULL(VIRTIO_NET_F_CTRL_VLAN))) {
> > > > +return 0;
> > > > +}
> > > > +
> > > > +for (int i = 0; i < MAX_VLAN >> 5; i++) {
> > > > +for (int j = 0; n->vlans[i] && j <= 0x1f; j++) {
> > > > +if (n->vlans[i] & (1U << j)) {
> > > > +int r = vhost_vdpa_net_load_single_vlan(s, n, (i << 5) 
> > > > + j);
> > >
> > > This seems to cause a lot of latency if the driver has a lot of vlans.
> > >
> > > I wonder if it's simply to let all vlan traffic go by disabling
> > > CTRL_VLAN feature at vDPA layer.
> >
>
> The guest will not be able to recover that vlan configuration.

Spec said it's best effort and we actually don't do this for
vhost-net/user for years and manage to survive.

>
> > Another idea is to extend the spec to allow us to accept a bitmap of
> > the vlan ids via a single command, then we will be fine.
> >
>
> I'm not sure if adding more ways to configure something is the answer,
> but I'd be ok to implement it.
>
> Another idea is to allow the sending of many CVQ commands in parallel.
> It shouldn't be very hard to achieve using exposed buffers as ring
> buffers, and it will short down the start of the devices with many
> features.

In the extreme case, what if guests decide to filter all of the vlans?
It means we need MAX_VLAN commands which may exceeds the size of the
control virtqueue.

Thanks

>
> Thanks!
>
> > Thanks
> >
> > >
> > > Thanks
> > >
> > > > +if (unlikely(r != 0)) {
> > > > +return r;
> > > > +}
> > > > +}
> > > > +}
> > > > +}
> > > > +
> > > > +return 0;
> > > > +}
> > > > +
> > > >  static int vhost_vdpa_net_load(NetClientState *nc)
> > > >  {
> > > >  VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > > > @@ -445,8 +488,7 @@ static int vhost_vdpa_net_load(NetClientState *nc)
> > > >  if (unlikely(r)) {
> > > >  return r;
> > > >  }
> > > > -
> > > > -return 0;
> > > > +return vhost_vdpa_net_load_vlan(s, n);
> > > >  }
> > > >
> > > >  static NetClientInfo net_vhost_vdpa_cvq_info = {
> > > > --
> > > > 2.31.1
> > > >
> >
>




Re: [PATCH v4 10/15] vhost-net: vhost-kernel: introduce vhost_net_virtqueue_reset()

2022-09-13 Thread Jason Wang
On Mon, Sep 12, 2022 at 1:22 AM Kangjie Xu  wrote:
>
> Introduce vhost_virtqueue_reset(), which can reset the specific
> virtqueue in the device. Then it will unmap vrings and the desc
> of the virtqueue.
>
> Here we do not reuse the vhost_net_stop_one() or vhost_dev_stop(),
> because they work at queue pair level. We do not use
> vhost_virtqueue_stop() because it may stop the device in the
> backend.
>
> This patch only considers the case of vhost-kernel, when
> NetClientDriver is NET_CLIENT_DRIVER_TAP.
>
> Furthermore, we do not need net->nc->info->poll() because
> it enables userspace datapath and we want to stop all
> datapaths for this reset virtqueue here.
>
> Signed-off-by: Kangjie Xu 
> Signed-off-by: Xuan Zhuo 

Acked-by: Jason Wang 

> ---
>  hw/net/vhost_net.c  | 25 +
>  include/net/vhost_net.h |  2 ++
>  2 files changed, 27 insertions(+)
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index d28f8b974b..8beecb4d22 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -531,3 +531,28 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t 
> mtu)
>
>  return vhost_ops->vhost_net_set_mtu(>dev, mtu);
>  }
> +
> +void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> +   int vq_index)
> +{
> +VHostNetState *net = get_vhost_net(nc->peer);
> +const VhostOps *vhost_ops = net->dev.vhost_ops;
> +struct vhost_vring_file file = { .fd = -1 };
> +int idx;
> +
> +/* should only be called after backend is connected */
> +assert(vhost_ops);
> +
> +idx = vhost_ops->vhost_get_vq_index(>dev, vq_index);
> +
> +if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) {
> +file.index = idx;
> +int r = vhost_net_set_backend(>dev, );
> +assert(r >= 0);
> +}
> +
> +vhost_virtqueue_stop(>dev,
> + vdev,
> + net->dev.vqs + idx,
> + net->dev.vq_index + idx);
> +}
> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> index 387e913e4e..85d85a4957 100644
> --- a/include/net/vhost_net.h
> +++ b/include/net/vhost_net.h
> @@ -48,4 +48,6 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
>
>  int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
>
> +void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc,
> +   int vq_index);
>  #endif
> --
> 2.32.0
>




[PATCH v4 1/2] x86: return modified setup_data only if read as memory, not as file

2022-09-13 Thread Jason A. Donenfeld
If setup_data is being read into a specific memory location, then
generally the setup_data address parameter is read first, so that the
caller knows where to read it into. In that case, we should return
setup_data containing the absolute addresses that are hard coded and
determined a priori. This is the case when kernels are loaded by BIOS,
for example. In contrast, when setup_data is read as a file, then we
shouldn't modify setup_data, since the absolute address will be wrong by
definition. This is the case when OVMF loads the image.

This allows setup_data to be used like normal, without crashing when EFI
tries to use it.

(As a small development note, strangely, fw_cfg_add_file_callback() was
exported but fw_cfg_add_bytes_callback() wasn't, so this makes that
consistent.)

Cc: Gerd Hoffmann 
Cc: Laurent Vivier 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Peter Maydell 
Cc: Philippe Mathieu-Daudé 
Cc: Richard Henderson 
Suggested-by: Ard Biesheuvel 
Signed-off-by: Jason A. Donenfeld 
---
 hw/i386/x86.c | 37 +++--
 hw/nvram/fw_cfg.c | 12 ++--
 include/hw/nvram/fw_cfg.h | 22 ++
 3 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 050eedc0c8..933bbdd836 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -764,6 +764,18 @@ static bool load_elfboot(const char *kernel_filename,
 return true;
 }
 
+struct setup_data_fixup {
+void *pos;
+hwaddr val;
+uint32_t addr;
+};
+
+static void fixup_setup_data(void *opaque)
+{
+struct setup_data_fixup *fixup = opaque;
+stq_p(fixup->pos, fixup->val);
+}
+
 void x86_load_linux(X86MachineState *x86ms,
 FWCfgState *fw_cfg,
 int acpi_data_size,
@@ -1088,8 +1100,11 @@ void x86_load_linux(X86MachineState *x86ms,
 qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
 }
 
-/* Offset 0x250 is a pointer to the first setup_data link. */
-stq_p(header + 0x250, first_setup_data);
+fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
+sev_load_ctx.kernel_data = (char *)kernel;
+sev_load_ctx.kernel_size = kernel_size;
 
 /*
  * If we're starting an encrypted VM, it will be OVMF based, which uses the
@@ -1099,16 +1114,18 @@ void x86_load_linux(X86MachineState *x86ms,
  * file the user passed in.
  */
 if (!sev_enabled()) {
+struct setup_data_fixup *fixup = g_malloc(sizeof(*fixup));
+
 memcpy(setup, header, MIN(sizeof(header), setup_size));
+/* Offset 0x250 is a pointer to the first setup_data link. */
+fixup->pos = setup + 0x250;
+fixup->val = first_setup_data;
+fixup->addr = real_addr;
+fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_SETUP_ADDR, fixup_setup_data, 
NULL,
+  fixup, >addr, sizeof(fixup->addr), 
true);
+} else {
+fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
 }
-
-fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
-fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
-fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
-sev_load_ctx.kernel_data = (char *)kernel;
-sev_load_ctx.kernel_size = kernel_size;
-
-fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
 fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
 fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
 sev_load_ctx.setup_data = (char *)setup;
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index d605f3f45a..564bda3395 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -692,12 +692,12 @@ static const VMStateDescription vmstate_fw_cfg = {
 }
 };
 
-static void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
-  FWCfgCallback select_cb,
-  FWCfgWriteCallback write_cb,
-  void *callback_opaque,
-  void *data, size_t len,
-  bool read_only)
+void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key,
+   FWCfgCallback select_cb,
+   FWCfgWriteCallback write_cb,
+   void *callback_opaque,
+   void *data, size_t len,
+   bool read_only)
 {
 int arch = !!(key & FW_CFG_ARCH_LOCAL);
 
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 0e7a8bc7af..e4fef393be 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -117,6 +117,28 @@ struct FWCfgMemState {
  */
 void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
 
+/**
+ * fw_cfg_add_bytes_callback:
+ * @s: fw_cfg 

[PATCH v4 2/2] x86: re-enable rng seeding via setup_data

2022-09-13 Thread Jason A. Donenfeld
This reverts 3824e25db1 ("x86: disable rng seeding via setup_data"), but
for 7.2 rather than 7.1, now that modifying setup_data is safe to do.

Cc: Laurent Vivier 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
Cc: Peter Maydell 
Cc: Philippe Mathieu-Daudé 
Cc: Richard Henderson 
Cc: Ard Biesheuvel 
Acked-by: Gerd Hoffmann 
Signed-off-by: Jason A. Donenfeld 
---
 hw/i386/microvm.c | 2 +-
 hw/i386/pc_piix.c | 3 ++-
 hw/i386/pc_q35.c  | 3 ++-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 52cafa003d..7fe8cce03e 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -332,7 +332,7 @@ static void microvm_memory_init(MicrovmMachineState *mms)
 rom_set_fw(fw_cfg);
 
 if (machine->kernel_filename != NULL) {
-x86_load_linux(x86ms, fw_cfg, 0, true, true);
+x86_load_linux(x86ms, fw_cfg, 0, true, false);
 }
 
 if (mms->option_roms) {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 8043a250ad..0b1a79c0fa 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -439,7 +439,6 @@ static void pc_i440fx_7_2_machine_options(MachineClass *m)
 m->alias = "pc";
 m->is_default = true;
 pcmc->default_cpu_version = 1;
-pcmc->legacy_no_rng_seed = true;
 }
 
 DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL,
@@ -447,9 +446,11 @@ DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL,
 
 static void pc_i440fx_7_1_machine_options(MachineClass *m)
 {
+PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
 pc_i440fx_7_2_machine_options(m);
 m->alias = NULL;
 m->is_default = false;
+pcmc->legacy_no_rng_seed = true;
 compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
 compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
 }
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 53eda50e81..a496bd6e74 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -376,7 +376,6 @@ static void pc_q35_7_2_machine_options(MachineClass *m)
 pc_q35_machine_options(m);
 m->alias = "q35";
 pcmc->default_cpu_version = 1;
-pcmc->legacy_no_rng_seed = true;
 }
 
 DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL,
@@ -384,8 +383,10 @@ DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL,
 
 static void pc_q35_7_1_machine_options(MachineClass *m)
 {
+PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
 pc_q35_7_2_machine_options(m);
 m->alias = NULL;
+pcmc->legacy_no_rng_seed = true;
 compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len);
 compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len);
 }
-- 
2.37.3




[PATCH v3 19/20] ppc4xx_sdram: Generalise bank setup

2022-09-13 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 | 93 ++-
 hw/ppc/trace-events   |  1 +
 2 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index e36898a906..79a9efce4b 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);
+}
+}
+
 /*/
 /* DDR SDRAM controller */
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
@@ -445,6 +461,8 @@ static void ppc4xx_sdram_ddr_class_init(ObjectClass *oc, 
void *data)
 
 /*/
 /* DDR2 SDRAM controller */
+#define SDRAM_DDR2_BCR_MASK 0xffe0ffc1
+
 enum {
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
@@ -518,50 +536,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;
-sdram->bank[i].base = sdram_ddr2_base(bcr);
-sdram->bank[i].size = sdram_ddr2_size(bcr);
-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;
@@ -618,6 +592,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:
@@ -641,12 +616,24 @@ static void sdram_ddr2_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 if (!(s->mcopt2 & BIT(27)) && (val & BIT(27))) {
 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 |= BIT(27);
 } else if ((s->mcopt2 & BIT(27)) && !(val & BIT(27))) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr2_unmap_bcr(s);
+for (i 

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

2022-09-13 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  | 321 -
 hw/ppc/ppc4xx_devs.c| 403 -
 hw/ppc/ppc4xx_sdram.c   | 752 
 include/hw/ppc/ppc4xx.h |  34 +-
 5 files changed, 771 insertions(+), 742 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 114c1a1b1c..651263926e 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -10,20 +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 "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 */
@@ -379,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;
@@ -481,317 +471,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
  sdr, _read_sdr, _write_sdr);
 }
 
-/*/
-/* SDRAM controller */
-enum {
-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;
-sdram->bank[i].base = sdram_ddr2_base(bcr);
-sdram->bank[i].size = sdram_ddr2_size(bcr);
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
-sdram_bank_map(>bank[i]);
-}
-}
-
-static void 

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

2022-09-13 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 79a9efce4b..c731012940 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -137,6 +137,8 @@ static void sdram_bank_set_bcr(Ppc4xxSdramBank *bank, 
uint32_t bcr,
 
 /*/
 /* DDR SDRAM controller */
+#define SDRAM_DDR_BCR_MASK 0xFFDEE001
+
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
@@ -195,58 +197,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;
@@ -317,6 +267,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:
@@ -338,12 +289,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)) {
@@ -363,16 +326,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: /* 

[PATCH v3 17/20] ppc4xx_sdram: Use hwaddr for memory bank size

2022-09-13 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 bc28d69a26..242e2f4c6e 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"
@@ -122,11 +121,6 @@ static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 
 /*/
 /* 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;
@@ -170,9 +164,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;
@@ -513,9 +507,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 v3 14/20] ppc440_sdram: Move RAM size check to ppc440_sdram_init

2022-09-13 Thread BALATON Zoltan
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 565bfffc22..f48eba215a 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;
 
@@ -728,18 +728,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 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)
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 v3 13/20] ppc4xx_sdram: Rename functions to prevent name clashes

2022-09-13 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 
---
 hw/ppc/ppc440_uc.c   | 69 ++--
 hw/ppc/ppc4xx_devs.c | 44 ++--
 2 files changed, 57 insertions(+), 56 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index d8a7947196..565bfffc22 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -502,7 +502,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;
 
@@ -547,12 +547,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;
@@ -578,50 +578,51 @@ 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;
-sdram->bank[i].base = sdram_base(bcr);
-sdram->bank[i].size = sdram_size(bcr);
+sdram->bank[i].base = sdram_ddr2_base(bcr);
+sdram->bank[i].size = sdram_ddr2_size(bcr);
 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;
@@ -632,8 +633,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 - SDRAM_R0BAS].size);
 }
 break;
 case SDRAM_CONF1HB:
@@ -674,7 +675,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 return ret;
 }
 
-static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
+static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
 ppc440_sdram_t *sdram = opaque;
 
@@ -700,12 +701,12 @@ static void dcr_write_sdram(void *opaque, int dcrn, 
uint32_t val)
 if (!(sdram->mcopt2 & BIT(27)) && (val & BIT(27))) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_map_bcr(sdram);
+sdram_ddr2_map_bcr(sdram);
 sdram->mcopt2 |= BIT(27);
 } else if ((sdram->mcopt2 & BIT(27)) && !(val & BIT(27))) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_unmap_bcr(sdram);
+sdram_ddr2_unmap_bcr(sdram);
 sdram->mcopt2 &= ~BIT(27);
 }
 break;
@@ -718,7 

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

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

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 5db59d1190..01184e717b 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -561,26 +561,33 @@ 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));
+sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
+sdram->bank[i].base = sdram_base(bcr);
+sdram->bank[i].size = sdram_size(bcr);
 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);
+sdram_bank_map(>bank[i]);
 }
 }
 
-- 
2.30.4




[PATCH v3 15/20] ppc440_sdram: QOM'ify

2022-09-13 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  | 115 +---
 hw/ppc/sam460ex.c   |   7 ++-
 include/hw/ppc/ppc4xx.h |  14 +
 4 files changed, 91 insertions(+), 47 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 f48eba215a..114c1a1b1c 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -483,13 +483,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 {
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
@@ -578,7 +571,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) {
@@ -596,7 +589,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;
 
@@ -611,7 +604,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;
 
@@ -624,7 +617,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) {
@@ -677,7 +670,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:
@@ -719,52 +712,86 @@ 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 v3 18/20] ppc4xx_sdram: Rename local state variable for brevity

2022-09-13 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 242e2f4c6e..e36898a906 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -233,56 +233,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;
@@ -300,78 +300,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 v3 11/20] ppc440_sdram: Get rid of the init RAM hack

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

Signed-off-by: BALATON Zoltan 
---
v2: replace 0x0800 with BIT(27)

 hw/ppc/ppc440.h| 3 +--
 hw/ppc/ppc440_uc.c | 8 ++--
 hw/ppc/sam460ex.c  | 8 +++-
 3 files changed, 10 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 3c442eaecc..b3f56c49b5 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -723,12 +723,11 @@ static void sdram_reset(void *opaque)
 ppc440_sdram_t *sdram = opaque;
 
 sdram->addr = 0;
-sdram->mcopt2 = BIT(27);
+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;
@@ -745,9 +744,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);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index f4c2a693fb..dac329d482 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -345,7 +345,13 @@ 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 */
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x21) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x0800)) {
+error_report("Couldn't enable memory regions");
+exit(1);
+}
 
 /* IIC controllers and devices */
 dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700,
-- 
2.30.4




[PATCH v3 12/20] ppc440_sdram: Rename local variable for readibility

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

Signed-off-by: BALATON Zoltan 
---
 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 b3f56c49b5..d8a7947196 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -729,40 +729,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);
 }
 
 /*/
-- 
2.30.4




[PATCH v3 08/20] ppc4xx_sdram: Drop extra zeros for readability

2022-09-13 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 
---
 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 375834a52b..bfe7b2d3a6 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -49,31 +49,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;
@@ -104,7 +104,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));
@@ -115,7 +115,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));
@@ -136,7 +136,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);
 }
 }
 }
@@ -213,7 +213,7 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 break;
 default:
 /* Avoid gcc warning */
-ret = 0x;
+ret = 0;
 break;
 }
 
@@ -306,18 +306,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 v3 06/20] ppc4xx_sdram: Move size check to ppc4xx_sdram_init()

2022-09-13 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 
---
 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 bf02a71c6d..cdd4e0cb4c 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -271,22 +271,12 @@ 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();
 CPUPPCState *env;
 
-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 2bd5e41140..9b456f1819 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 */
 if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
 ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 7bdcbd6fac..eb3aa97b16 100644
--- 

[PATCH v3 07/20] ppc4xx_sdram: QOM'ify

2022-09-13 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_uc.c  | 22 +
 hw/ppc/ppc440_bamboo.c  | 10 +++--
 hw/ppc/ppc4xx_devs.c| 99 ++---
 include/hw/ppc/ppc4xx.h | 27 +--
 5 files changed, 98 insertions(+), 63 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_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 9b456f1819..6052d3a2e0 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,9 +196,13 @@ 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),
+ _abort);
+ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, _fatal);
+object_unref(OBJECT(dev));
 /* 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, machine->ram);
+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 */
 if (ppc_dcr_write(env->dcr_env, 

[PATCH v3 05/20] ppc440_bamboo: Add missing 4 MiB valid memory size

2022-09-13 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 2aac8a3fe9..2bd5e41140 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 v3 10/20] ppc440_sdram: Implement enable bit in the DDR2 SDRAM

2022-09-13 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 
---
v2: replace 0x0800 with BIT(27)

 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 01184e717b..3c442eaecc 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 */
@@ -484,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;
@@ -581,12 +583,15 @@ static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
 {
 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));
 sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
 sdram->bank[i].base = sdram_base(bcr);
 sdram->bank[i].size = sdram_size(bcr);
 if (enabled && (bcr & 1)) {
+trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
 sdram_bank_map(>bank[i]);
 }
 }
@@ -596,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 {
@@ -605,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;
@@ -636,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;
@@ -680,6 +696,19 @@ 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 & BIT(27)) && (val & BIT(27))) {
+trace_ppc4xx_sdram_enable("enable");
+/* validate all RAM mappings */
+sdram_map_bcr(sdram);
+sdram->mcopt2 |= BIT(27);
+} else if ((sdram->mcopt2 & BIT(27)) && !(val & BIT(27))) {
+trace_ppc4xx_sdram_enable("disable");
+/* invalidate all RAM mappings */
+sdram_unmap_bcr(sdram);
+sdram->mcopt2 &= ~BIT(27);
+}
+break;
 default:
 break;
 }
@@ -694,6 +723,7 @@ static void sdram_reset(void *opaque)
 ppc440_sdram_t *sdram = opaque;
 
 sdram->addr = 0;
+sdram->mcopt2 = BIT(27);
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-- 
2.30.4




[PATCH v3 04/20] ppc4xx: Use Ppc4xxSdramBank in ppc4xx_sdram_banks()

2022-09-13 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 
---
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 e3412c4fcd..2aac8a3fe9 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 */
 if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
 ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 6ab0ad7985..5db59d1190 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -690,8 +690,7 @@ static void sdram_reset(void *opaque)
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion 

[PATCH v3 02/20] ppc4xx: Introduce Ppc4xxSdramBank struct

2022-09-13 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 v3 01/20] ppc440_bamboo: Remove unnecessary memsets

2022-09-13 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 v3 03/20] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-13 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. This is needed when booting a kernel directly from -kernel
without a firmware. Do this from board code accesing normal SDRAM
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 */
+env = >soc.cpu.env;
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
+error_report("Could not enable memory regions");
+exit(1);
+}
+
 /* allocate and load BIOS */
 if (machine->firmware) {
 MemoryRegion *bios = g_new(MemoryRegion, 1);
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..e3412c4fcd 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -211,7 +211,13 @@ 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 */
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
+error_report("couldn't enable memory regions");
+exit(1);
+}
 
 /* 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 db4e29..6ab0ad7985 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -489,8 +489,6 @@ typedef struct ppc440_sdram_t {
 } ppc440_sdram_t;
 
 enum {
-SDRAM0_CFGADDR = 0x10,
-SDRAM0_CFGDATA,
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
 SDRAM_R2BAS,
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 1226ec4aa9..936d6f77fe 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -56,11 +56,6 @@ struct 

[PATCH v3 00/20] ppc4xx_sdram QOMify and clean ups

2022-09-13 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.

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 (20):
  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 readibility
  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

 hw/ppc/meson.build  |   3 +-
 hw/ppc/ppc405.h |   8 +-
 hw/ppc/ppc405_boards.c  |  22 +-
 hw/ppc/ppc405_uc.c  |  33 +-
 hw/ppc/ppc440.h |   4 -
 hw/ppc/ppc440_bamboo.c  |  29 +-
 hw/ppc/ppc440_uc.c  | 267 +--
 hw/ppc/ppc4xx_devs.c| 413 ---
 hw/ppc/ppc4xx_sdram.c   | 723 
 hw/ppc/sam460ex.c   |  48 +--
 hw/ppc/trace-events |   1 +
 include/hw/ppc/ppc4xx.h |  66 +++-
 12 files changed, 847 insertions(+), 770 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_sdram.c

-- 
2.30.4




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

2022-09-13 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.2




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

2022-09-13 Thread Helge Deller
Signed-off-by: Helge Deller 
---
 linux-user/strace.list |  3 +++
 linux-user/syscall.c   | 12 
 2 files changed, 15 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 df018f0e32..e63025a5e3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8721,6 +8721,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));
+#ifdef 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(close_range(arg1, arg2, arg3));
+#endif

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




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

2022-09-13 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.2




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

2022-09-13 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 = 

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

2022-09-13 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..df018f0e32 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)
+_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
+#endif
+#if defined(__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)
+_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(TARGET_NR_pidfd_open)
+case TARGET_NR_pidfd_open:
+return get_errno(pidfd_open(arg1, arg2));
+#endif
+#if 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(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.2




[PULL 00/12] linux-user patches

2022-09-13 Thread Helge Deller
The following changes since commit 621da7789083b80d6f1ff1c0fb499334007b4f51:

  Update version for v7.1.0 release (2022-08-30 09:40:11 -0700)

are available in the Git repository at:

  https://github.com/hdeller/qemu-hppa.git tags/publish1-pull-request

for you to fetch changes up to 192cac33ab6449202d0b44c4d664020b09ce9266:

  linux-user: Add parameters of getrandom() syscall for strace (2022-09-11 
19:58:07 +0200)


linux-user: Add more syscalls, enhance tracing & logging enhancements

- show missing signals in strace output
- add pidfd_open(), pidfd_send_signal(), pidfd_getfd() and close_range()
  syscalls
- add and enhance strace output for clock_gettime64(), chmod(),
  clock_nanosleep(), futex() and getrandom() syscalls
- show failing executable in EXCP_DUMP()
- increase TASK_UNMAPPED_BASE and dump IIR on register dump (on hppa
  target)



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 |  46 
 target/hppa/helper.c |   6 +-
 9 files changed, 251 insertions(+), 59 deletions(-)

--
2.37.2




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

2022-09-13 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.2




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

2022-09-13 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.2




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

2022-09-13 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.2




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

2022-09-13 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.2




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

2022-09-13 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.2




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

2022-09-13 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.2




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

2022-09-13 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.2




Re: [RFC PATCH v2 3/3] hw/peci: add support for EndPointConfig reads

2022-09-13 Thread Peter Delevoryas
On Tue, Sep 13, 2022 at 06:21:49PM +, Titus Rwantare wrote:
> Signed-off-by: Titus Rwantare 
> Reviewed-by: Hao Wu 

Reviewed-by: Peter Delevoryas 

> ---
>  hw/peci/peci-client.c  | 63 ++
>  hw/peci/peci-core.c| 44 +++--
>  include/hw/peci/peci.h | 23 +++
>  3 files changed, 128 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/peci/peci-client.c b/hw/peci/peci-client.c
> index 2aa797b5f6..e54735bb53 100644
> --- a/hw/peci/peci-client.c
> +++ b/hw/peci/peci-client.c
> @@ -23,6 +23,64 @@
>  
>  #define PECI_CLIENT_DEFAULT_TEMP 30
>  
> +/* TODO: move this out into a config */
> +static const PECIEndPointConfig spr_config[] = {
> +{
> +.hdr.msg_type = LOCAL_PCI_CFG,
> +.hdr.addr_type = 0x4,
> +.hdr.bus = 31,
> +.hdr.dev = 0,
> +.hdr.func = 2,
> +.hdr.reg = 0xD4,
> +.data = BIT(31)
> +},
> +{
> +.hdr.msg_type = LOCAL_PCI_CFG,
> +.hdr.addr_type = 0x4,
> +.hdr.bus = 31,
> +.hdr.dev = 0,
> +.hdr.func = 2,
> +.hdr.reg = 0xD0,
> +.data = BIT(31) | BIT(30)
> +},
> +{
> +.hdr.msg_type = LOCAL_PCI_CFG,
> +.hdr.addr_type = 0x4,
> +.hdr.bus = 31,
> +.hdr.dev = 30,
> +.hdr.func = 6,
> +.hdr.reg = 0x84,
> +.data = 0x03FF
> +},
> +{
> +.hdr.msg_type = LOCAL_PCI_CFG,
> +.hdr.addr_type = 0x4,
> +.hdr.bus = 31,
> +.hdr.dev = 30,
> +.hdr.func = 6,
> +.hdr.reg = 0x80,
> +.data = 0x
> +},
> +{
> +.hdr.msg_type = LOCAL_PCI_CFG,
> +.hdr.addr_type = 0x4,
> +.hdr.bus = 31,
> +.hdr.dev = 30,
> +.hdr.func = 6,
> +.hdr.reg = 0x84,
> +.data = 0x03FF
> +},
> +{
> +.hdr.msg_type = LOCAL_PCI_CFG,
> +.hdr.addr_type = 0x4,
> +.hdr.bus = 31,
> +.hdr.dev = 30,
> +.hdr.func = 6,
> +.hdr.reg = 0x80,
> +.data = 0x
> +},
> +};
> +
>  static void peci_client_update_temps(PECIClientDevice *client)
>  {
>  uint8_t temp_cpu = 0;
> @@ -115,7 +173,12 @@ PECIClientDevice *peci_add_client(PECIBus *bus,
>  break;
>  
>  case FAM6_ICELAKE_X:
> +client->revision = 0x40;
> +break;
> +
>  case FAM6_SAPPHIRE_RAPIDS_X:
> +client->endpoint_conf = spr_config;
> +client->num_entries = sizeof(spr_config) / sizeof(spr_config[0]);
>  client->revision = 0x40;
>  client->ucode = 0x8c0004a0;
>  break;
> diff --git a/hw/peci/peci-core.c b/hw/peci/peci-core.c
> index 8210bfa198..0650a03e2d 100644
> --- a/hw/peci/peci-core.c
> +++ b/hw/peci/peci-core.c
> @@ -22,6 +22,47 @@
>  #define PECI_FCS_OK 0
>  #define PECI_FCS_ERR1
>  
> +static PECIEndPointHeader peci_fmt_end_pt_header(PECICmd *pcmd)
> +{
> +uint32_t val = pcmd->rx[7] | (pcmd->rx[8] << 8) | (pcmd->rx[9] << 16) |
> +  (pcmd->rx[10] << 24);
> +
> +PECIEndPointHeader header = {
> +.msg_type = pcmd->rx[1],
> +.addr_type = pcmd->rx[5],
> +.bus = (val >> 20) & 0xFF,
> +.dev = (val >> 15) & 0x1F,
> +.func = (val >> 12) & 0x7,
> +.reg = val & 0xFFF,
> +};
> +
> +return header;
> +}
> +
> +static void peci_rd_endpoint_cfg(PECIClientDevice *client, PECICmd *pcmd)
> +{
> +PECIPkgCfg *resp = (PECIPkgCfg *)pcmd->tx;
> +PECIEndPointHeader req = peci_fmt_end_pt_header(pcmd);
> +PECIEndPointConfig const *c;
> +
> +if (client->endpoint_conf) {
> +for (size_t i = 0; i < client->num_entries; i++) {
> +c = >endpoint_conf[i];
> +
> +if (!memcmp(, >hdr, sizeof(PECIEndPointHeader))) {
> +resp->data = c->data;
> +resp->cc = PECI_DEV_CC_SUCCESS;
> +return;
> +}
> +}
> +}
> +
> +qemu_log_mask(LOG_UNIMP,
> +  "%s: msg_type: 0x%x bus: %u, dev: %u, func: %u, reg: 
> 0x%x\n",
> +  __func__, req.msg_type, req.bus, req.dev, req.func, 
> req.reg);
> +
> +}
> +
>  static void peci_rd_pkg_cfg(PECIClientDevice *client, PECICmd *pcmd)
>  {
>  PECIPkgCfg *resp = (PECIPkgCfg *)pcmd->tx;
> @@ -153,8 +194,7 @@ int peci_handle_cmd(PECIBus *bus, PECICmd *pcmd)
>  break;
>  
>  case PECI_CMD_RD_END_PT_CFG:
> -qemu_log_mask(LOG_UNIMP, "%s: unimplemented CMD_RD_END_PT_CFG\n",
> -  __func__);
> +peci_rd_endpoint_cfg(client, pcmd);
>  break;
>  
>  default:
> diff --git a/include/hw/peci/peci.h b/include/hw/peci/peci.h
> index 1a0abe65cd..3dcfe82245 100644
> --- a/include/hw/peci/peci.h
> +++ b/include/hw/peci/peci.h
> @@ -112,6 +112,26 @@ typedef struct PECITempTarget {
>  uint8_t tjmax;
>  } PECITempTarget;
>  
> +typedef enum PECIEndPointType {
> +LOCAL_PCI_CFG = 3,
> + 

Re: [PATCH v2 00/18] ppc4xx_sdram QOMify and clean ups

2022-09-13 Thread BALATON Zoltan

On Tue, 13 Sep 2022, 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.

v2: address some review comments and try to avoid compile problem with
gcc 12.2 (untested)


Looks like I made a mistake while rebasing this and some patches were 
inadverently squashed. I'll send a v3 correcting this, please disregard 
this one.



Regards,
BALATON Zoltan

BALATON Zoltan (18):
 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 controller
 ppc440_sdram: Rename local variable for readibility
 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

hw/ppc/meson.build  |   3 +-
hw/ppc/ppc405.h |   8 +-
hw/ppc/ppc405_boards.c  |  22 +-
hw/ppc/ppc405_uc.c  |  33 +-
hw/ppc/ppc440.h |   4 -
hw/ppc/ppc440_bamboo.c  |  29 +-
hw/ppc/ppc440_uc.c  | 267 +--
hw/ppc/ppc4xx_devs.c| 413 ---
hw/ppc/ppc4xx_sdram.c   | 723 
hw/ppc/sam460ex.c   |  48 +--
hw/ppc/trace-events |   1 +
include/hw/ppc/ppc4xx.h |  66 +++-
12 files changed, 847 insertions(+), 770 deletions(-)
create mode 100644 hw/ppc/ppc4xx_sdram.c



Re: [RFC PATCH 1/3] hw/peci: add initial support for PECI

2022-09-13 Thread Peter Delevoryas
On Tue, Sep 13, 2022 at 11:21:16AM -0700, Titus Rwantare wrote:
> On Fri, 9 Sept 2022 at 12:58, Peter Delevoryas  wrote:
> 
> > > +/*
> > > + * PECI Client device
> > > + * Copyright 2021 Google LLC
> > > + *
> > > + * SPDX-License-Identifier: GPL-2.0-or-later
> >
> > Not sure, but I think the SPDX license identifier is supposed to be in
> > the first line? Maybe not though. I would have expected:
> >
> 
> That's a Linux thing as far as I can tell. QEMU has it in the top comment.

Oh ok, nevermind then.

> 
> >
> > I'm curious if we really need the CPU family here, or if we could just
> > base everything off the PECI version.
> >
> > The PECI specification doesn't mention the CPU family, does it? Or maybe
> > it does.
> >
> 
> I needed the family info anyway for RdPkgConfig() CPU ID, and thought it
> would be more readable to specify that in the board file than the PECI 
> version.
> We tend to add new machines to QEMU by copying the config of an existing
> machine, I think this way makes it more obvious that this is a field
> that is changing.

Yeah, I think you're right. And looking at the PECI spec, they refer to
families directly when describing new features, so this seems
appropriate.

Reviewed-by: Peter Delevoryas 

> 
> 
> Titus



Re: [RFC PATCH 0/3] Initial PECI bus support

2022-09-13 Thread Peter Delevoryas
On Tue, Sep 13, 2022 at 11:20:57AM -0700, Titus Rwantare wrote:
> On Fri, 9 Sept 2022 at 12:54, Peter Delevoryas  wrote:
> >
> > On Tue, Sep 06, 2022 at 10:05:49PM +, Titus Rwantare wrote:
> ...
> > >
> > > This is something that can also be extended as other parameters arise 
> > > that need
> > > to differ between platforms. So far you can have have different CPUs, 
> > > DIMM counts,
> > > DIMM temperatures here. These fields can also be adjusted at runtime 
> > > through qmp.
> >
> > That looks good to me, seems like the standard way to do it in QEMU.
> >
> > >
> > > A lot of the registers are hard coded, see hw/peci/peci-client.c. I'd 
> > > like to
> > > gauge interest in what potential users would like to be adjustable at 
> > > runtime.
> > > I've not written QEMU models that read config files at runtime, something 
> > > I'd
> > > appreciate guidance on.
> >
> > This part I don't totally understand. I also barely know anything about
> > PECI.
> >
> > Is the register location for things different between CPU generations?
> 
> Some things seem to move between generations and others don't move, someone at
> Intel would know better than I do.
> 
> 
> 
> > If so (and I expect it probably is), why is there only a configuration
> > for Sapphire Rapids, and not for the other ones?
> >
> > Is that because of PECI protocol changes between generations?
> 
> I haven't dug into the other machines because of internal demand, but
> I've found that
> with newer generations, more features get used in addition to existing
> ones. It's
> possible these features existed on older machines.
> 
> 
> 
> > In which case, maybe there needs to be a notion of PECI version
> > somewhere?
> >
> > Also, I don't understand why it would be adjustable at runtime, do we
> > change register locations during execution?
> >
> > I would expect it to be part of the board definition.
> >
> > You could provide a bunch of sample configs for the CPU's that you're
> > testing for, and the board configuration could just select the sample
> > config it is using (corresponding to the CPU model).
> >
> > That's the model I would imagine, but I might be missing some important
> > context here.
> 
> I think it would be nice to have additional registers at runtime, at
> the time of writing,
> I don't know how much of the internal workings of Sapphire Rapids
> Intel is willing to
> share publicly. If users are free to separately define registers, I
> don't then get to
> worry about this. e.g. I'd like to simulate errors from the memory 
> controllers.

Oh ok, yeah I guess making it more dynamic shouldn't really hurt
anything. That sounds ok then.  Also yeah, perhaps keeping the register
definitions separate for privacy concerns is necessary.

Reviewed-by: Peter Delevoryas 

> 
> 
> Titus



[PATCH v2 18/18] ppc4xx_sdram: Convert DDR SDRAM controller to new bank handling

2022-09-13 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 79a9efce4b..c731012940 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -137,6 +137,8 @@ static void sdram_bank_set_bcr(Ppc4xxSdramBank *bank, 
uint32_t bcr,
 
 /*/
 /* DDR SDRAM controller */
+#define SDRAM_DDR_BCR_MASK 0xFFDEE001
+
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
 {
 uint32_t bcr;
@@ -195,58 +197,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;
@@ -317,6 +267,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:
@@ -338,12 +289,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)) {
@@ -363,16 +326,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: /* 

[PATCH v2 16/18] ppc4xx_sdram: Rename local state variable for brevity

2022-09-13 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 242e2f4c6e..e36898a906 100644
--- a/hw/ppc/ppc4xx_sdram.c
+++ b/hw/ppc/ppc4xx_sdram.c
@@ -233,56 +233,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;
@@ -300,78 +300,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;
   

Re: [RFC PATCH v2 1/3] hw/peci: add initial support for PECI

2022-09-13 Thread Peter Delevoryas
On Tue, Sep 13, 2022 at 06:21:47PM +, Titus Rwantare wrote:
> PECI - Platform Environment Control Interface
> 
> This commit adds support for reading basic sensor values from a client
> on the PECI bus.
> BMCs can use the PECI wire to get thermal information out of an Intel
> cpu. Additionally, on hardware, various MSRs are exposed over the
> PECI bus. Part of PCI config space is exposed due to Intel posting
> various platform configuration in PCI config space.
> 
> Commands implemented:
> - Ping
> - GetDIB
> - GetTemp
> - GetPkgConfig (partial)
> 
> Commands not implemented:
> - RdIAMSR
> - RdPCIConfig
> - RdPCIConfigLocal
> 
> Signed-off-by: Titus Rwantare 
> Reviewed-by: Hao Wu 
> Reviewed-by: Patrick Venture 

Reviewed-by: Peter Delevoryas 

> ---
>  MAINTAINERS|   7 ++
>  hw/Kconfig |   1 +
>  hw/meson.build |   1 +
>  hw/peci/Kconfig|   2 +
>  hw/peci/meson.build|   1 +
>  hw/peci/peci-client.c  | 230 +
>  hw/peci/peci-core.c| 182 
>  hw/peci/trace-events   |   5 +
>  hw/peci/trace.h|   1 +
>  include/hw/peci/peci.h | 194 ++
>  meson.build|   1 +
>  11 files changed, 625 insertions(+)
>  create mode 100644 hw/peci/Kconfig
>  create mode 100644 hw/peci/meson.build
>  create mode 100644 hw/peci/peci-client.c
>  create mode 100644 hw/peci/peci-core.c
>  create mode 100644 hw/peci/trace-events
>  create mode 100644 hw/peci/trace.h
>  create mode 100644 include/hw/peci/peci.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5ce4227ff6..14ab29679d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3212,6 +3212,13 @@ F: tests/qtest/adm1272-test.c
>  F: tests/qtest/max34451-test.c
>  F: tests/qtest/isl_pmbus_vr-test.c
>  
> +PECI
> +M: Titus Rwantare 
> +S: Maintained
> +F: hw/peci/peci-core.c
> +F: hw/peci/peci-client.c
> +F: include/hw/peci/peci.h
> +
>  Firmware schema specifications
>  M: Philippe Mathieu-Daudé 
>  R: Daniel P. Berrange 
> diff --git a/hw/Kconfig b/hw/Kconfig
> index 38233bbb0f..300ab48127 100644
> --- a/hw/Kconfig
> +++ b/hw/Kconfig
> @@ -24,6 +24,7 @@ source net/Kconfig
>  source nubus/Kconfig
>  source nvme/Kconfig
>  source nvram/Kconfig
> +source peci/Kconfig
>  source pci-bridge/Kconfig
>  source pci-host/Kconfig
>  source pcmcia/Kconfig
> diff --git a/hw/meson.build b/hw/meson.build
> index c7ac7d3d75..340cc88a52 100644
> --- a/hw/meson.build
> +++ b/hw/meson.build
> @@ -28,6 +28,7 @@ subdir('pci')
>  subdir('pci-bridge')
>  subdir('pci-host')
>  subdir('pcmcia')
> +subdir('peci')
>  subdir('rdma')
>  subdir('rtc')
>  subdir('scsi')
> diff --git a/hw/peci/Kconfig b/hw/peci/Kconfig
> new file mode 100644
> index 00..fe4f665d21
> --- /dev/null
> +++ b/hw/peci/Kconfig
> @@ -0,0 +1,2 @@
> +config PECI
> +bool
> diff --git a/hw/peci/meson.build b/hw/peci/meson.build
> new file mode 100644
> index 00..01cfa95abe
> --- /dev/null
> +++ b/hw/peci/meson.build
> @@ -0,0 +1 @@
> +softmmu_ss.add(when: 'CONFIG_PECI', if_true: files('peci-core.c', 
> 'peci-client.c'))
> diff --git a/hw/peci/peci-client.c b/hw/peci/peci-client.c
> new file mode 100644
> index 00..2aa797b5f6
> --- /dev/null
> +++ b/hw/peci/peci-client.c
> @@ -0,0 +1,230 @@
> +/*
> + * PECI Client device
> + * Copyright 2021 Google LLC
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/peci/peci.h"
> +#include "hw/qdev-core.h"
> +#include "hw/qdev-properties.h"
> +#include "migration/vmstate.h"
> +#include "qapi/error.h"
> +#include "qapi/visitor.h"
> +#include "qemu/module.h"
> +#include "qemu/log.h"
> +#include "qom/object.h"
> +
> +/*
> + * A PECI client represents an Intel socket and the peripherals attached to 
> it
> + * that are accessible over the PECI bus.
> + */
> +
> +#define PECI_CLIENT_DEFAULT_TEMP 30
> +
> +static void peci_client_update_temps(PECIClientDevice *client)
> +{
> +uint8_t temp_cpu = 0;
> +for (size_t i = 0; i < client->cpu_cores; i++) {
> +if (temp_cpu < client->core_temp[i]) {
> +temp_cpu = client->core_temp[i];
> +}
> +}
> +client->core_temp_max = -1 * (client->tjmax - temp_cpu);
> +
> +uint8_t temp_dimm = 0;
> +for (size_t i = 0; i < client->dimms; i++) {
> +if (temp_dimm < client->dimm_temp[i]) {
> +temp_dimm = client->dimm_temp[i];
> +}
> +}
> +client->dimm_temp_max = temp_dimm;
> +}
> +
> +PECIClientDevice *peci_get_client(PECIBus *bus, uint8_t addr)
> +{
> +PECIClientDevice *client;
> +BusChild *var;
> +
> +QTAILQ_FOREACH(var, >qbus.children, sibling) {
> +DeviceState *dev = var->child;
> +client = PECI_CLIENT(dev);
> +
> +if (client->address == addr) {
> +return client;
> +}
> +}
> +return 0;
> +}
> +
> +
> +PECIClientDevice *peci_add_client(PECIBus *bus,
> + 

[PATCH v2 14/18] ppc4xx_sdram: Move ppc4xx DDR and DDR2 SDRAM controller models together

2022-09-13 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  | 321 -
 hw/ppc/ppc4xx_devs.c| 403 -
 hw/ppc/ppc4xx_sdram.c   | 752 
 include/hw/ppc/ppc4xx.h |  34 +-
 5 files changed, 771 insertions(+), 742 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 114c1a1b1c..651263926e 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -10,20 +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 "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 */
@@ -379,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;
@@ -481,317 +471,6 @@ void ppc4xx_sdr_init(CPUPPCState *env)
  sdr, _read_sdr, _write_sdr);
 }
 
-/*/
-/* SDRAM controller */
-enum {
-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;
-sdram->bank[i].base = sdram_ddr2_base(bcr);
-sdram->bank[i].size = sdram_ddr2_size(bcr);
-if (enabled && (bcr & 1)) {
-trace_ppc4xx_sdram_map(sdram_ddr2_base(bcr), sdram_ddr2_size(bcr));
-sdram_bank_map(>bank[i]);
-}
-}
-
-static void 

[PATCH v2 13/18] ppc440_sdram: QOM'ify

2022-09-13 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  | 115 +---
 hw/ppc/sam460ex.c   |   7 ++-
 include/hw/ppc/ppc4xx.h |  14 +
 4 files changed, 91 insertions(+), 47 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 f48eba215a..114c1a1b1c 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -483,13 +483,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 {
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
@@ -578,7 +571,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) {
@@ -596,7 +589,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;
 
@@ -611,7 +604,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;
 
@@ -624,7 +617,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) {
@@ -677,7 +670,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:
@@ -719,52 +712,86 @@ 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 v2 15/18] ppc4xx_sdram: Use hwaddr for memory bank size

2022-09-13 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 bc28d69a26..242e2f4c6e 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"
@@ -122,11 +121,6 @@ static void sdram_bank_unmap(Ppc4xxSdramBank *bank)
 
 /*/
 /* 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;
@@ -170,9 +164,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;
@@ -513,9 +507,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 v2 12/18] ppc440_sdram: Move RAM size check to ppc440_sdram_init

2022-09-13 Thread BALATON Zoltan
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 565bfffc22..f48eba215a 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;
 
@@ -728,18 +728,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 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)
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 v2 11/18] ppc440_sdram: Rename local variable for readibility

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

Signed-off-by: BALATON Zoltan 
---
 hw/ppc/ppc440_uc.c   | 81 ++--
 hw/ppc/ppc4xx_devs.c | 44 
 2 files changed, 63 insertions(+), 62 deletions(-)

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index b3f56c49b5..565bfffc22 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -502,7 +502,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;
 
@@ -547,12 +547,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;
@@ -578,50 +578,51 @@ 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;
-sdram->bank[i].base = sdram_base(bcr);
-sdram->bank[i].size = sdram_size(bcr);
+sdram->bank[i].base = sdram_ddr2_base(bcr);
+sdram->bank[i].size = sdram_ddr2_size(bcr);
 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;
@@ -632,8 +633,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 - SDRAM_R0BAS].size);
 }
 break;
 case SDRAM_CONF1HB:
@@ -674,7 +675,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
 return ret;
 }
 
-static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
+static void sdram_ddr2_dcr_write(void *opaque, int dcrn, uint32_t val)
 {
 ppc440_sdram_t *sdram = opaque;
 
@@ -700,12 +701,12 @@ static void dcr_write_sdram(void *opaque, int dcrn, 
uint32_t val)
 if (!(sdram->mcopt2 & BIT(27)) && (val & BIT(27))) {
 trace_ppc4xx_sdram_enable("enable");
 /* validate all RAM mappings */
-sdram_map_bcr(sdram);
+sdram_ddr2_map_bcr(sdram);
 sdram->mcopt2 |= BIT(27);
 } else if ((sdram->mcopt2 & BIT(27)) && !(val & BIT(27))) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_unmap_bcr(sdram);
+sdram_ddr2_unmap_bcr(sdram);
 sdram->mcopt2 &= ~BIT(27);
 }
 break;
@@ -718,7 +719,7 @@ static void dcr_write_sdram(void *opaque, int dcrn, 
uint32_t val)
 }
 }
 
-static void sdram_reset(void *opaque)

[PATCH v2 17/18] ppc4xx_sdram: Generalise bank setup

2022-09-13 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 | 93 ++-
 hw/ppc/trace-events   |  1 +
 2 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/hw/ppc/ppc4xx_sdram.c b/hw/ppc/ppc4xx_sdram.c
index e36898a906..79a9efce4b 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);
+}
+}
+
 /*/
 /* DDR SDRAM controller */
 static uint32_t sdram_ddr_bcr(hwaddr ram_base, hwaddr ram_size)
@@ -445,6 +461,8 @@ static void ppc4xx_sdram_ddr_class_init(ObjectClass *oc, 
void *data)
 
 /*/
 /* DDR2 SDRAM controller */
+#define SDRAM_DDR2_BCR_MASK 0xffe0ffc1
+
 enum {
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
@@ -518,50 +536,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;
-sdram->bank[i].base = sdram_ddr2_base(bcr);
-sdram->bank[i].size = sdram_ddr2_size(bcr);
-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;
@@ -618,6 +592,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:
@@ -641,12 +616,24 @@ static void sdram_ddr2_dcr_write(void *opaque, int dcrn, 
uint32_t val)
 if (!(s->mcopt2 & BIT(27)) && (val & BIT(27))) {
 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 |= BIT(27);
 } else if ((s->mcopt2 & BIT(27)) && !(val & BIT(27))) {
 trace_ppc4xx_sdram_enable("disable");
 /* invalidate all RAM mappings */
-sdram_ddr2_unmap_bcr(s);
+for (i 

[PATCH v2 10/18] ppc440_sdram: Implement enable bit in the DDR2 SDRAM controller

2022-09-13 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 
---
v2: replace 0x0800 with BIT(27)

 hw/ppc/ppc440.h|  3 +--
 hw/ppc/ppc440_uc.c | 40 +---
 hw/ppc/sam460ex.c  |  8 +++-
 3 files changed, 41 insertions(+), 10 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 01184e717b..b3f56c49b5 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 */
@@ -484,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;
@@ -581,12 +583,15 @@ static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
 {
 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));
 sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
 sdram->bank[i].base = sdram_base(bcr);
 sdram->bank[i].size = sdram_size(bcr);
 if (enabled && (bcr & 1)) {
+trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr));
 sdram_bank_map(>bank[i]);
 }
 }
@@ -596,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 {
@@ -605,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;
@@ -636,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;
@@ -680,6 +696,19 @@ 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 & BIT(27)) && (val & BIT(27))) {
+trace_ppc4xx_sdram_enable("enable");
+/* validate all RAM mappings */
+sdram_map_bcr(sdram);
+sdram->mcopt2 |= BIT(27);
+} else if ((sdram->mcopt2 & BIT(27)) && !(val & BIT(27))) {
+trace_ppc4xx_sdram_enable("disable");
+/* invalidate all RAM mappings */
+sdram_unmap_bcr(sdram);
+sdram->mcopt2 &= ~BIT(27);
+}
+break;
 default:
 break;
 }
@@ -694,11 +723,11 @@ static void sdram_reset(void *opaque)
 ppc440_sdram_t *sdram = opaque;
 
 sdram->addr = 0;
+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;
@@ -715,9 +744,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);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index f4c2a693fb..dac329d482 100644
--- a/hw/ppc/sam460ex.c
+++ 

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

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

diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 5db59d1190..01184e717b 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -561,26 +561,33 @@ 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));
+sdram_bank_unmap(>bank[i]);
 }
 sdram->bank[i].bcr = bcr & 0xffe0ffc1;
+sdram->bank[i].base = sdram_base(bcr);
+sdram->bank[i].size = sdram_size(bcr);
 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);
+sdram_bank_map(>bank[i]);
 }
 }
 
-- 
2.30.4




[PATCH v2 07/18] ppc4xx_sdram: QOM'ify

2022-09-13 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_uc.c  | 22 +
 hw/ppc/ppc440_bamboo.c  | 10 +++--
 hw/ppc/ppc4xx_devs.c| 99 ++---
 include/hw/ppc/ppc4xx.h | 27 +--
 5 files changed, 98 insertions(+), 63 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_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 9b456f1819..6052d3a2e0 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,9 +196,13 @@ 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),
+ _abort);
+ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, _fatal);
+object_unref(OBJECT(dev));
 /* 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, machine->ram);
+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 */
 if (ppc_dcr_write(env->dcr_env, 

[PATCH v2 08/18] ppc4xx_sdram: Drop extra zeros for readability

2022-09-13 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 
---
 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 375834a52b..bfe7b2d3a6 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -49,31 +49,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;
@@ -104,7 +104,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));
@@ -115,7 +115,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));
@@ -136,7 +136,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);
 }
 }
 }
@@ -213,7 +213,7 @@ static uint32_t sdram_ddr_dcr_read(void *opaque, int dcrn)
 break;
 default:
 /* Avoid gcc warning */
-ret = 0x;
+ret = 0;
 break;
 }
 
@@ -306,18 +306,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 v2 05/18] ppc440_bamboo: Add missing 4 MiB valid memory size

2022-09-13 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 2aac8a3fe9..2bd5e41140 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 v2 06/18] ppc4xx_sdram: Move size check to ppc4xx_sdram_init()

2022-09-13 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 
---
 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 bf02a71c6d..cdd4e0cb4c 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -271,22 +271,12 @@ 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();
 CPUPPCState *env;
 
-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 2bd5e41140..9b456f1819 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 */
 if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
 ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 7bdcbd6fac..eb3aa97b16 100644
--- 

[PATCH v2 03/18] ppc4xx_sdram: Get rid of the init RAM hack

2022-09-13 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. This is needed when booting a kernel directly from -kernel
without a firmware. Do this from board code accesing normal SDRAM
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 */
+env = >soc.cpu.env;
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
+error_report("Could not enable memory regions");
+exit(1);
+}
+
 /* allocate and load BIOS */
 if (machine->firmware) {
 MemoryRegion *bios = g_new(MemoryRegion, 1);
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..e3412c4fcd 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -211,7 +211,13 @@ 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 */
+if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
+ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
+error_report("couldn't enable memory regions");
+exit(1);
+}
 
 /* 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 db4e29..6ab0ad7985 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -489,8 +489,6 @@ typedef struct ppc440_sdram_t {
 } ppc440_sdram_t;
 
 enum {
-SDRAM0_CFGADDR = 0x10,
-SDRAM0_CFGDATA,
 SDRAM_R0BAS = 0x40,
 SDRAM_R1BAS,
 SDRAM_R2BAS,
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 1226ec4aa9..936d6f77fe 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -56,11 +56,6 @@ struct 

[PATCH v2 04/18] ppc4xx: Use Ppc4xxSdramBank in ppc4xx_sdram_banks()

2022-09-13 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 
---
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 e3412c4fcd..2aac8a3fe9 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 */
 if (ppc_dcr_write(env->dcr_env, SDRAM0_CFGADDR, 0x20) ||
 ppc_dcr_write(env->dcr_env, SDRAM0_CFGDATA, 0x8000)) {
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 6ab0ad7985..5db59d1190 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -690,8 +690,7 @@ static void sdram_reset(void *opaque)
 }
 
 void ppc440_sdram_init(CPUPPCState *env, int nbanks,
-   MemoryRegion 

[PATCH v2 02/18] ppc4xx: Introduce Ppc4xxSdramBank struct

2022-09-13 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 v2 00/18] ppc4xx_sdram QOMify and clean ups

2022-09-13 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.

v2: address some review comments and try to avoid compile problem with
gcc 12.2 (untested)

Regards,
BALATON Zoltan

BALATON Zoltan (18):
  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 controller
  ppc440_sdram: Rename local variable for readibility
  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

 hw/ppc/meson.build  |   3 +-
 hw/ppc/ppc405.h |   8 +-
 hw/ppc/ppc405_boards.c  |  22 +-
 hw/ppc/ppc405_uc.c  |  33 +-
 hw/ppc/ppc440.h |   4 -
 hw/ppc/ppc440_bamboo.c  |  29 +-
 hw/ppc/ppc440_uc.c  | 267 +--
 hw/ppc/ppc4xx_devs.c| 413 ---
 hw/ppc/ppc4xx_sdram.c   | 723 
 hw/ppc/sam460ex.c   |  48 +--
 hw/ppc/trace-events |   1 +
 include/hw/ppc/ppc4xx.h |  66 +++-
 12 files changed, 847 insertions(+), 770 deletions(-)
 create mode 100644 hw/ppc/ppc4xx_sdram.c

-- 
2.30.4




[PATCH v2 01/18] ppc440_bamboo: Remove unnecessary memsets

2022-09-13 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




[RFC PATCH v2 3/3] hw/peci: add support for EndPointConfig reads

2022-09-13 Thread Titus Rwantare
Signed-off-by: Titus Rwantare 
Reviewed-by: Hao Wu 
---
 hw/peci/peci-client.c  | 63 ++
 hw/peci/peci-core.c| 44 +++--
 include/hw/peci/peci.h | 23 +++
 3 files changed, 128 insertions(+), 2 deletions(-)

diff --git a/hw/peci/peci-client.c b/hw/peci/peci-client.c
index 2aa797b5f6..e54735bb53 100644
--- a/hw/peci/peci-client.c
+++ b/hw/peci/peci-client.c
@@ -23,6 +23,64 @@
 
 #define PECI_CLIENT_DEFAULT_TEMP 30
 
+/* TODO: move this out into a config */
+static const PECIEndPointConfig spr_config[] = {
+{
+.hdr.msg_type = LOCAL_PCI_CFG,
+.hdr.addr_type = 0x4,
+.hdr.bus = 31,
+.hdr.dev = 0,
+.hdr.func = 2,
+.hdr.reg = 0xD4,
+.data = BIT(31)
+},
+{
+.hdr.msg_type = LOCAL_PCI_CFG,
+.hdr.addr_type = 0x4,
+.hdr.bus = 31,
+.hdr.dev = 0,
+.hdr.func = 2,
+.hdr.reg = 0xD0,
+.data = BIT(31) | BIT(30)
+},
+{
+.hdr.msg_type = LOCAL_PCI_CFG,
+.hdr.addr_type = 0x4,
+.hdr.bus = 31,
+.hdr.dev = 30,
+.hdr.func = 6,
+.hdr.reg = 0x84,
+.data = 0x03FF
+},
+{
+.hdr.msg_type = LOCAL_PCI_CFG,
+.hdr.addr_type = 0x4,
+.hdr.bus = 31,
+.hdr.dev = 30,
+.hdr.func = 6,
+.hdr.reg = 0x80,
+.data = 0x
+},
+{
+.hdr.msg_type = LOCAL_PCI_CFG,
+.hdr.addr_type = 0x4,
+.hdr.bus = 31,
+.hdr.dev = 30,
+.hdr.func = 6,
+.hdr.reg = 0x84,
+.data = 0x03FF
+},
+{
+.hdr.msg_type = LOCAL_PCI_CFG,
+.hdr.addr_type = 0x4,
+.hdr.bus = 31,
+.hdr.dev = 30,
+.hdr.func = 6,
+.hdr.reg = 0x80,
+.data = 0x
+},
+};
+
 static void peci_client_update_temps(PECIClientDevice *client)
 {
 uint8_t temp_cpu = 0;
@@ -115,7 +173,12 @@ PECIClientDevice *peci_add_client(PECIBus *bus,
 break;
 
 case FAM6_ICELAKE_X:
+client->revision = 0x40;
+break;
+
 case FAM6_SAPPHIRE_RAPIDS_X:
+client->endpoint_conf = spr_config;
+client->num_entries = sizeof(spr_config) / sizeof(spr_config[0]);
 client->revision = 0x40;
 client->ucode = 0x8c0004a0;
 break;
diff --git a/hw/peci/peci-core.c b/hw/peci/peci-core.c
index 8210bfa198..0650a03e2d 100644
--- a/hw/peci/peci-core.c
+++ b/hw/peci/peci-core.c
@@ -22,6 +22,47 @@
 #define PECI_FCS_OK 0
 #define PECI_FCS_ERR1
 
+static PECIEndPointHeader peci_fmt_end_pt_header(PECICmd *pcmd)
+{
+uint32_t val = pcmd->rx[7] | (pcmd->rx[8] << 8) | (pcmd->rx[9] << 16) |
+  (pcmd->rx[10] << 24);
+
+PECIEndPointHeader header = {
+.msg_type = pcmd->rx[1],
+.addr_type = pcmd->rx[5],
+.bus = (val >> 20) & 0xFF,
+.dev = (val >> 15) & 0x1F,
+.func = (val >> 12) & 0x7,
+.reg = val & 0xFFF,
+};
+
+return header;
+}
+
+static void peci_rd_endpoint_cfg(PECIClientDevice *client, PECICmd *pcmd)
+{
+PECIPkgCfg *resp = (PECIPkgCfg *)pcmd->tx;
+PECIEndPointHeader req = peci_fmt_end_pt_header(pcmd);
+PECIEndPointConfig const *c;
+
+if (client->endpoint_conf) {
+for (size_t i = 0; i < client->num_entries; i++) {
+c = >endpoint_conf[i];
+
+if (!memcmp(, >hdr, sizeof(PECIEndPointHeader))) {
+resp->data = c->data;
+resp->cc = PECI_DEV_CC_SUCCESS;
+return;
+}
+}
+}
+
+qemu_log_mask(LOG_UNIMP,
+  "%s: msg_type: 0x%x bus: %u, dev: %u, func: %u, reg: 0x%x\n",
+  __func__, req.msg_type, req.bus, req.dev, req.func, req.reg);
+
+}
+
 static void peci_rd_pkg_cfg(PECIClientDevice *client, PECICmd *pcmd)
 {
 PECIPkgCfg *resp = (PECIPkgCfg *)pcmd->tx;
@@ -153,8 +194,7 @@ int peci_handle_cmd(PECIBus *bus, PECICmd *pcmd)
 break;
 
 case PECI_CMD_RD_END_PT_CFG:
-qemu_log_mask(LOG_UNIMP, "%s: unimplemented CMD_RD_END_PT_CFG\n",
-  __func__);
+peci_rd_endpoint_cfg(client, pcmd);
 break;
 
 default:
diff --git a/include/hw/peci/peci.h b/include/hw/peci/peci.h
index 1a0abe65cd..3dcfe82245 100644
--- a/include/hw/peci/peci.h
+++ b/include/hw/peci/peci.h
@@ -112,6 +112,26 @@ typedef struct PECITempTarget {
 uint8_t tjmax;
 } PECITempTarget;
 
+typedef enum PECIEndPointType {
+LOCAL_PCI_CFG = 3,
+PCI_CFG,
+MMIO_BDF,
+} PECIEndPointType;
+
+typedef struct __attribute__ ((__packed__)) {
+PECIEndPointType msg_type;
+uint8_t addr_type;
+uint8_t bus;
+uint8_t dev;
+uint8_t func;
+uint16_t reg;
+} PECIEndPointHeader;
+
+typedef struct {
+PECIEndPointHeader hdr;
+uint32_t data;
+} PECIEndPointConfig;
+
 #define PECI_BASE_ADDR  0x30
 #define PECI_BUFFER_SIZE0x100

[RFC PATCH v2 2/3] hw/peci: add PECI support for NPCM7xx BMCs

2022-09-13 Thread Titus Rwantare
This allows BMC firmware for npcm7xx BMCs to talk to a PECI client
in qemu.

Signed-off-by: Titus Rwantare 
Reviewed-by: Patrick Venture 
Reviewed-by: Peter Delevoryas 
---
 MAINTAINERS|   1 +
 hw/arm/Kconfig |   1 +
 hw/arm/npcm7xx.c   |   9 ++
 hw/peci/meson.build|   1 +
 hw/peci/npcm7xx_peci.c | 204 +
 hw/peci/trace-events   |   5 +
 include/hw/arm/npcm7xx.h   |   2 +
 include/hw/peci/npcm7xx_peci.h |  37 ++
 8 files changed, 260 insertions(+)
 create mode 100644 hw/peci/npcm7xx_peci.c
 create mode 100644 include/hw/peci/npcm7xx_peci.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 14ab29679d..f11a31cf57 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3218,6 +3218,7 @@ S: Maintained
 F: hw/peci/peci-core.c
 F: hw/peci/peci-client.c
 F: include/hw/peci/peci.h
+F: hw/peci/npcm7xx_peci.c
 
 Firmware schema specifications
 M: Philippe Mathieu-Daudé 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 15fa79afd3..cb38c6c88f 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -408,6 +408,7 @@ config NPCM7XX
 select SSI
 select UNIMP
 select PCA954X
+select PECI
 
 config FSL_IMX25
 bool
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index d85cc02765..d408dd7eb4 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -45,6 +45,7 @@
 #define NPCM7XX_CLK_BA  (0xf0801000)
 #define NPCM7XX_MC_BA   (0xf0824000)
 #define NPCM7XX_RNG_BA  (0xf000b000)
+#define NPCM7XX_PECI_BA (0xf010)
 
 /* USB Host modules */
 #define NPCM7XX_EHCI_BA (0xf0806000)
@@ -83,6 +84,7 @@ enum NPCM7xxInterrupt {
 NPCM7XX_UART1_IRQ,
 NPCM7XX_UART2_IRQ,
 NPCM7XX_UART3_IRQ,
+NPCM7XX_PECI_IRQ= 6,
 NPCM7XX_EMC1RX_IRQ  = 15,
 NPCM7XX_EMC1TX_IRQ,
 NPCM7XX_MMC_IRQ = 26,
@@ -445,6 +447,7 @@ static void npcm7xx_init(Object *obj)
 }
 
 object_initialize_child(obj, "mmc", >mmc, TYPE_NPCM7XX_SDHCI);
+object_initialize_child(obj, "peci", >peci, TYPE_NPCM7XX_PECI);
 }
 
 static void npcm7xx_realize(DeviceState *dev, Error **errp)
@@ -715,6 +718,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(>mmc), 0,
 npcm7xx_irq(s, NPCM7XX_MMC_IRQ));
 
+ /* PECI */
+sysbus_realize(SYS_BUS_DEVICE(>peci), _abort);
+sysbus_mmio_map(SYS_BUS_DEVICE(>peci), 0, NPCM7XX_PECI_BA);
+sysbus_connect_irq(SYS_BUS_DEVICE(>peci), 0,
+   npcm7xx_irq(s, NPCM7XX_PECI_IRQ));
+
 create_unimplemented_device("npcm7xx.shm",  0xc0001000,   4 * KiB);
 create_unimplemented_device("npcm7xx.vdmx", 0xe080,   4 * KiB);
 create_unimplemented_device("npcm7xx.pcierc",   0xe100,  64 * KiB);
diff --git a/hw/peci/meson.build b/hw/peci/meson.build
index 01cfa95abe..ee033eb915 100644
--- a/hw/peci/meson.build
+++ b/hw/peci/meson.build
@@ -1 +1,2 @@
 softmmu_ss.add(when: 'CONFIG_PECI', if_true: files('peci-core.c', 
'peci-client.c'))
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_peci.c'))
diff --git a/hw/peci/npcm7xx_peci.c b/hw/peci/npcm7xx_peci.c
new file mode 100644
index 00..17a2642898
--- /dev/null
+++ b/hw/peci/npcm7xx_peci.c
@@ -0,0 +1,204 @@
+/*
+ * Nuvoton NPCM7xx PECI Module
+ *
+ * Copyright 2021 Google LLC
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/peci/npcm7xx_peci.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "trace.h"
+
+#define PECI_CTL_STS0
+#define PECI_CTL_STS_DONE_EN  BIT(6)
+#define PECI_CTL_STS_ABRT_ERR BIT(4)
+#define PECI_CTL_STS_CRC_ERR  BIT(3)
+#define PECI_CTL_STS_DONE BIT(1)
+#define PECI_CTL_STS_START_BUSY   BIT(0)
+#define PECI_RD_LENGTH  0x4
+#define PECI_ADDR   0x8
+#define PECI_CMD0xC
+#define PECI_CTL2   0x10
+#define PECI_WR_LENGTH  0x1C
+#define PECI_PDDR   0x2C
+#define PECI_DAT_INOUT(reg)(0x100 + (reg) * 4)
+
+static uint64_t npcm7xx_peci_read(void *opaque, hwaddr offset, unsigned size)
+{
+NPCM7xxPECIState *ps = NPCM7XX_PECI(opaque);
+uint8_t ret = 0;
+
+if (!ps->bus->num_clients) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: no peci clients added to board\n",
+  __func__);
+return 0;
+}
+
+qemu_irq_lower(ps->irq);
+
+switch (offset) {
+case PECI_CTL_STS:
+ret = ps->status;
+break;
+
+case PECI_RD_LENGTH:
+ret = ps->pcmd.rd_length;
+break;
+
+case PECI_ADDR:
+ret = ps->pcmd.addr;
+break;
+
+case PECI_CMD:
+ret = ps->pcmd.cmd;
+break;
+
+case PECI_CTL2:
+ret = ps->ctl2;
+break;
+
+case PECI_WR_LENGTH:
+ret = ps->pcmd.wr_length;
+break;
+
+case PECI_PDDR:
+

Re: [RFC PATCH 3/3] hw/peci: add support for EndPointConfig reads

2022-09-13 Thread Titus Rwantare
On Fri, 9 Sept 2022 at 12:48, Peter Delevoryas  wrote:
>
> On Tue, Sep 06, 2022 at 10:05:52PM +, Titus Rwantare wrote:
> > Signed-off-by: Titus Rwantare 
> > Reviewed-by: Hao Wu 
> > ---
...
> > +++ b/include/hw/peci/peci.h
> > @@ -112,6 +112,26 @@ typedef struct PECITempTarget {
> >  uint8_t tjmax;
> >  } PECITempTarget;
> >
> > +typedef enum PECIEndPtType {
> > +LOCAL_PCI_CFG = 3,
> > +PCI_CFG,
> > +MMIO_BDF,
> > +} PECIEndPtType;
> > +
> > +typedef struct __attribute__ ((__packed__)) {
> > +PECIEndPtType msg_type;
> > +uint8_t addr_type;
> > +uint8_t bus;
> > +uint8_t dev;
> > +uint8_t func;
> > +uint16_t reg;
> > +} PECIEndPtHeader;
> > +
> > +typedef struct {
> > +PECIEndPtHeader hdr;
> > +uint32_t data;
> > +} PECIEndPtConfig;
>
> I noticed the summary is "hw/peci: add support for EndPointConfig reads"
> but type definitions here use "EndPt", maybe they should be
> "PECIEndPoint*"? I don't think extending to Point is too long.

Fair, fixed in v2.


Titus



  1   2   >