Re: hw/i386/acpi: fix conflicting IO address range for acpi pci hotplug in q35

2021-09-16 Thread Ani Sinha
On Fri, Sep 17, 2021 at 10:11 AM Ani Sinha  wrote:
>
>
>
> On Thu, 16 Sep 2021, Michael S. Tsirkin wrote:
>
> > On Thu, Sep 16, 2021 at 06:58:35PM +0530, Ani Sinha wrote:
> > > Here's sending v2.
> > >
> > > changelog :
> > > v1: original patch.
> > > v2: typo fixed. reviewed-by tags added.
> >
> >
> > Thanks, tagged!
> > Ani pls make sure the voer letter in the series has
> > subject
> >
> > [PATCH 0/3] hw/i386/acpi: fix conflicting IO address range for acpi pci
> >  hotplug in q35
> >
> >
> > using --cover-letter with git format-patch will do this automatically.
> >
> > It will also include diffstat and other useful info.
>
> Ah I see. I was wondering about this few days back because I saw a
> patchset with diffstat etc. I use git send-email --cover -v2 -3 -cc
> --cc-cmd etc. I did not realize that git format-patch also has similar
> options and adds more info to the cover letter. I wonder why the behavior
> is different between them.  Also --cc-cmd is missing in format-patch!

Also note that checkpatch.pl can be run without spitting out the
patches in separate files:

./scripts/checkpatch.pl HEAD~3..HEAD
1/3 Checking commit 0a4f1a3d8733 (bios-tables-test: allow changes in
DSDT ACPI tables for q35)
total: 0 errors, 0 warnings, 12 lines checked

Patch 1/3 has no obvious style problems and is ready for submission.
2/3 Checking commit 5adcc9e39e6a (hw/i386/acpi: fix conflicting IO
address range for acpi pci hotplug in q35)
total: 0 errors, 0 warnings, 8 lines checked

Patch 2/3 has no obvious style problems and is ready for submission.
3/3 Checking commit 5e0a8181d2d9 (bios-tables-test: Update ACPI DSDT
table golden blobs for q35)
total: 0 errors, 0 warnings, 1 lines checked

Patch 3/3 has no obvious style problems and is ready for submission.

So I guess the workflow should always be :
1) use git format-patch -o 
2) run checkpatch on patches in dir
3) git send-email dir/*.patch

>
> Was this an essential complexity or accidental one :-)
>
>
>
> >
> >
> > > This issue has been reported here:
> > > https://gitlab.com/qemu-project/qemu/-/issues/561
> > >
> > > We have disucssed this issue at length here:
> > > https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02146.html
> > >
> > > This issue affects Qemu version 6.1.
> > >
> > > Patch 1 : allows q35 DSDT table changes.
> > > Patch 2 : actual fix.
> > > Patch 3: updates DSDT table blobs.
> > >
> > >
> >
> >



Re: [PATCH v2] target/riscv: Set mstatus_hs.[SD|FS] bits if Clean and V=1 in mark_fs_dirty()

2021-09-16 Thread Frank Chang
On Fri, Sep 17, 2021 at 2:14 PM  wrote:

> From: Frank Chang 
>
> When V=1, both vsstauts.FS and HS-level sstatus.FS are in effect.
> Modifying the floating-point state when V=1 causes both fields to
> be set to 3 (Dirty).
>
> However, it's possible that HS-level sstatus.FS is Clean and VS-level
> vsstatus.FS is Dirty at the time mark_fs_dirty() is called when V=1.
> We can't early return for this case because we still need to set
> sstatus.FS to Dirty according to spec.
>
> Signed-off-by: Frank Chang 
> Reviewed-by: Vincent Chen 
> Tested-by: Vincent Chen 
> ---
>  target/riscv/cpu.h   |  3 +++
>  target/riscv/translate.c | 24 +++-
>  2 files changed, 18 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index e735e53e26c..c5cae45f955 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -394,6 +394,7 @@ FIELD(TB_FLAGS, SEW, 5, 3)
>  FIELD(TB_FLAGS, VILL, 8, 1)
>  /* Is a Hypervisor instruction load/store allowed? */
>  FIELD(TB_FLAGS, HLSX, 9, 1)
> +FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2)
>
>  bool riscv_cpu_is_32bit(CPURISCVState *env);
>
> @@ -450,6 +451,8 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState
> *env, target_ulong *pc,
>  get_field(env->hstatus, HSTATUS_HU))) {
>  flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
>  }
> +
> +flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
> env->mstatus_hs);
>

Oops, I should use get_field() to extract FS bits from env->mstatus_hs here.
Please ignore this one. I will revise it and resent the patch.
Sorry for the confusion.

Regards,
Frank Chang


>  }
>  #endif
>
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 74b33fa3c90..2b48db6fd02 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -58,6 +58,7 @@ typedef struct DisasContext {
>  target_ulong misa;
>  uint32_t opcode;
>  uint32_t mstatus_fs;
> +uint32_t mstatus_hs_fs;
>  uint32_t mem_idx;
>  /* Remember the rounding mode encoded in the previous fp instruction,
> which we have already installed into env->fp_status.  Or -1 for
> @@ -280,26 +281,30 @@ static void gen_jal(DisasContext *ctx, int rd,
> target_ulong imm)
>  static void mark_fs_dirty(DisasContext *ctx)
>  {
>  TCGv tmp;
> -target_ulong sd;
> +target_ulong sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
> +
> +if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
> +/* Remember the stage change for the rest of the TB. */
> +ctx->mstatus_hs_fs = MSTATUS_FS;
> +
> +tmp = tcg_temp_new();
> +tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
> +tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> +tcg_temp_free(tmp);
> +}
>
>  if (ctx->mstatus_fs == MSTATUS_FS) {
>  return;
>  }
> +
>  /* Remember the state change for the rest of the TB.  */
>  ctx->mstatus_fs = MSTATUS_FS;
>
>  tmp = tcg_temp_new();
> -sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
> -
>  tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
>  tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
>  tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
> -
> -if (ctx->virt_enabled) {
> -tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
> -tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
> -}
>  tcg_temp_free(tmp);
>  }
>  #else
> @@ -533,6 +538,7 @@ static void
> riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
>  ctx->frm = -1;  /* unknown rounding mode */
>  ctx->ext_ifencei = cpu->cfg.ext_ifencei;
>  ctx->vlen = cpu->cfg.vlen;
> +ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
>  ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
>  ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
>  ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
> --
> 2.25.1
>
>


Re: [PATCH RFC 00/13] hw/nvme: experimental user-creatable objects

2021-09-16 Thread Klaus Jensen
On Sep 16 18:30, Klaus Jensen wrote:
> On Sep 16 14:41, Kevin Wolf wrote:
> > Am 14.09.2021 um 22:37 hat Klaus Jensen geschrieben:
> > > From: Klaus Jensen 
> > > 
> > > Hi,
> > > 
> > > This is an attempt at adressing a bunch of issues that have presented
> > > themselves since we added subsystem support. It's been brewing for a
> > > while now.
> > > 
> > > Fundamentally, I've come to the conclusion that modeling namespaces and
> > > subsystems as "devices" is wrong. They should have been user-creatable
> > > objects. We've run into multiple issues with wrt. hotplugging due to how
> > > namespaces hook up to the controller with a bus. The bus-based design
> > > made a lot of sense when we didn't have subsystem support and it follows
> > > the design of hw/scsi. But, the problem here is that the bus-based
> > > design dictates a one parent relationship, and with shared namespaces,
> > > that is just not true. If the namespaces are considered to have a single
> > > parent, that parent is the subsystem, not any specific controller.
> > > 
> > > This series adds a set of experimental user-creatable objects:
> > > 
> > >   -object x-nvme-subsystem
> > >   -object x-nvme-ns-nvm
> > >   -object x-nvme-ns-zoned
> > > 
> > > It also adds a new controller device (-device x-nvme-ctrl) that supports
> > > these new objects (and gets rid of a bunch of deprecated and confusing
> > > parameters). This new approach has a bunch of benefits (other than just
> > > fixing the hotplugging issues properly) - we also get support for some
> > > nice introspection through some new dynamic properties:
> > > 
> > >   (qemu) qom-get /machine/peripheral/nvme-ctrl-1 attached-namespaces
> > >   [
> > >   "/objects/nvm-1",
> > >   "/objects/zns-1"
> > >   ]
> > > 
> > >   (qemu) qom-list /objects/zns-1
> > >   type (string)
> > >   subsys (link)
> > >   nsid (uint32)
> > >   uuid (string)
> > >   attached-ctrls (str)
> > >   eui64 (string)
> > >   blockdev (string)
> > >   pi-first (bool)
> > >   pi-type (NvmeProtInfoType)
> > >   extended-lba (bool)
> > >   metadata-size (uint16)
> > >   lba-size (size)
> > >   zone-descriptor-extension-size (size)
> > >   zone-cross-read (bool)
> > >   zone-max-open (uint32)
> > >   zone-capacity (size)
> > >   zone-size (size)
> > >   zone-max-active (uint32)
> > > 
> > >   (qemu) qom-get /objects/zns-1 pi-type
> > >   "none"
> > > 
> > >   (qemu) qom-get /objects/zns-1 eui64
> > >   "52:54:00:17:67:a0:40:15"
> > > 
> > >   (qemu) qom-get /objects/zns-1 zone-capacity
> > >   12582912
> > > 
> > > Currently, there are no shortcuts, so you have to define the full
> > > topology to get it up and running. Notice that the topology is explicit
> > > (the 'subsys' and 'attached-ctrls' links). There are no 'nvme-bus'
> > > anymore.
> > > 
> > >   -object x-nvme-subsystem,id=subsys0,subnqn=foo
> > >   -device x-nvme-ctrl,id=nvme-ctrl-0,serial=foo,subsys=subsys0
> > >   -device x-nvme-ctrl,id=nvme-ctrl-1,serial=bar,subsys=subsys0
> > >   -drive  id=nvm-1,file=nvm-1.img,format=raw,if=none,discard=unmap
> > >   -object 
> > > x-nvme-ns-nvm,id=nvm-1,blockdev=nvm-1,nsid=1,subsys=subsys0,attached-ctrls=nvme-ctrl-1
> > >   -drive  id=nvm-2,file=nvm-2.img,format=raw,if=none,discard=unmap
> > >   -object 
> > > x-nvme-ns-nvm,id=nvm-2,blockdev=nvm-2,nsid=2,subsys=subsys0,attached-ctrls=nvme-ctrl-0
> > 
> > I may be wrong here, but my first gut feeling when seeing this was that
> > referencing the controller device in the namespace object feels
> > backwards. Usually, we have objects that are created independently and
> > then the devices reference them.
> > 
> > Your need to use a machine_done notifier is probably related to that,
> > too, because it goes against the normal initialisation order, so you
> > have to wait. Error handling also isn't really possible in the notifier
> > any more, so this series seems to just print something to stderr, but
> > ignore the error otherwise.
> > 
> > Did you consider passing a list of namespaces to the controller device
> > instead?
> > 
> > I guess a problem that you have with both ways is that support for
> > list options isn't great in QemuOpts, which is still used both for
> > -object and -device in the system emulator...
> > 
> 
> Heh. Exactly. The ability to better support lists with -object through
> QAPI is why I did it like this...
> 
> Having the list of namespaces on the controller is preferable. I'll see
> what I can come up with.
> 

There is also the issue that the x-nvme-ns-nvm -object needs a blockdev
- and the ordering is also a problem here. That also requires the
machine done notifier.


signature.asc
Description: PGP signature


[PATCH v2] target/riscv: Set mstatus_hs.[SD|FS] bits if Clean and V=1 in mark_fs_dirty()

2021-09-16 Thread frank . chang
From: Frank Chang 

When V=1, both vsstauts.FS and HS-level sstatus.FS are in effect.
Modifying the floating-point state when V=1 causes both fields to
be set to 3 (Dirty).

However, it's possible that HS-level sstatus.FS is Clean and VS-level
vsstatus.FS is Dirty at the time mark_fs_dirty() is called when V=1.
We can't early return for this case because we still need to set
sstatus.FS to Dirty according to spec.

Signed-off-by: Frank Chang 
Reviewed-by: Vincent Chen 
Tested-by: Vincent Chen 
---
 target/riscv/cpu.h   |  3 +++
 target/riscv/translate.c | 24 +++-
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e735e53e26c..c5cae45f955 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -394,6 +394,7 @@ FIELD(TB_FLAGS, SEW, 5, 3)
 FIELD(TB_FLAGS, VILL, 8, 1)
 /* Is a Hypervisor instruction load/store allowed? */
 FIELD(TB_FLAGS, HLSX, 9, 1)
+FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2)
 
 bool riscv_cpu_is_32bit(CPURISCVState *env);
 
@@ -450,6 +451,8 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, 
target_ulong *pc,
 get_field(env->hstatus, HSTATUS_HU))) {
 flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
 }
+
+flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS, env->mstatus_hs);
 }
 #endif
 
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 74b33fa3c90..2b48db6fd02 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -58,6 +58,7 @@ typedef struct DisasContext {
 target_ulong misa;
 uint32_t opcode;
 uint32_t mstatus_fs;
+uint32_t mstatus_hs_fs;
 uint32_t mem_idx;
 /* Remember the rounding mode encoded in the previous fp instruction,
which we have already installed into env->fp_status.  Or -1 for
@@ -280,26 +281,30 @@ static void gen_jal(DisasContext *ctx, int rd, 
target_ulong imm)
 static void mark_fs_dirty(DisasContext *ctx)
 {
 TCGv tmp;
-target_ulong sd;
+target_ulong sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
+
+if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
+/* Remember the stage change for the rest of the TB. */
+ctx->mstatus_hs_fs = MSTATUS_FS;
+
+tmp = tcg_temp_new();
+tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
+tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+tcg_temp_free(tmp);
+}
 
 if (ctx->mstatus_fs == MSTATUS_FS) {
 return;
 }
+
 /* Remember the state change for the rest of the TB.  */
 ctx->mstatus_fs = MSTATUS_FS;
 
 tmp = tcg_temp_new();
-sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
-
 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
 tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
-
-if (ctx->virt_enabled) {
-tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
-tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
-tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
-}
 tcg_temp_free(tmp);
 }
 #else
@@ -533,6 +538,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->frm = -1;  /* unknown rounding mode */
 ctx->ext_ifencei = cpu->cfg.ext_ifencei;
 ctx->vlen = cpu->cfg.vlen;
+ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
 ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
 ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
 ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
-- 
2.25.1




[PATCH 15/15] python, iotests: replace qmp with aqmp

2021-09-16 Thread John Snow
Swap out the synchronous QEMUMonitorProtocol from qemu.qmp with the sync
wrapper from qemu.aqmp instead.

Add an escape hatch in the form of the environment variable
QEMU_PYTHON_LEGACY_QMP which allows you to cajole QEMUMachine into using
the old interface, proving that both implementations work concurrently.

Signed-off-by: John Snow 
---
 python/qemu/machine/machine.py | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 8f5a6649e5..6b005dd5d1 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -41,7 +41,6 @@
 )
 
 from qemu.qmp import (  # pylint: disable=import-error
-QEMUMonitorProtocol,
 QMPMessage,
 QMPReturnValue,
 SocketAddrT,
@@ -50,6 +49,12 @@
 from . import console_socket
 
 
+if os.environ.get('QEMU_PYTHON_LEGACY_QMP'):
+from qemu.qmp import QEMUMonitorProtocol
+else:
+from qemu.aqmp.legacy import QEMUMonitorProtocol
+
+
 LOG = logging.getLogger(__name__)
 
 
-- 
2.31.1




Re: [PATCH v3 00/16] python/iotests: Run iotest linters during Python CI

2021-09-16 Thread John Snow
On Thu, Sep 16, 2021 at 12:10 AM John Snow  wrote:

> GitLab: https://gitlab.com/jsnow/qemu/-/commits/python-package-iotest
> CI: https://gitlab.com/jsnow/qemu/-/pipelines/371611883
> Based-On: <20210915175318.853225-1-hre...@redhat.com>
>   "[PULL 00/32] Block patches"
>
> Since iotests are such a heavy and prominent user of the Python qemu.qmp
> and qemu.machine packages, it would be convenient if the Python linting
> suite also checked this client for any possible regressions introduced
> by shifting around signatures, types, or interfaces in these packages.
>
> (We'd eventually find those problems when iotest 297 ran, but with
> increasing distance between Python development and Block development,
> the risk of an accidental breakage in this regard increases. I,
> personally, know to run iotests (and especially 297) after changing
> Python code, but not everyone in the future might. Plus, I am lazy, and
> I like only having to push one button.)
>
> Add the ability for the Python CI to run the iotest linters too, which
> means that the iotest linters would be checked against:
>
> - Python 3.6, using a frozen set of linting packages at their oldest
>   supported versions, using 'pipenv'
> - Python 3.6 through Python 3.10 inclusive, using 'tox' and the latest
>   versions of mypy/pylint that happen to be installed during test
>   time. This CI test is allowed to fail with a warning, and can serve
>   as a bellwether for when new incompatible changes may disrupt the
>   linters. Testing against old and new Python interpreters alike can
>   help surface incompatibility issues we may need to be aware of.)
>
> Here are example outputs of those CI jobs with this series applied:
>  - "check-python-pipenv": https://gitlab.com/jsnow/qemu/-/jobs/1377735087
>  - "check-python-tox": https://gitlab.com/jsnow/qemu/-/jobs/1377735088
>
> You can also run these same tests locally from ./python, plus one more:
>
> - "make check-dev" to test against whatever python you have.
> - "make check-pipenv", if you have Python 3.6 and pipenv installed.
> - "make check-tox", to test against multiple python versions you have
> installed,
> from 3.6 to 3.10 inclusive. (CI tests against all 5.)
>
> See the old commit message for more sample output, etc.
>
> https://lists.gnu.org/archive/html/qemu-devel/2021-06/msg07056.html
>
> V3:
>  - Added patch 1 which has been submitted separately upstream,
>but was necessary for testing.
>  - Rebased on top of hreitz/block, which fixed some linting issues.
>  - Added a workaround for a rather nasty mypy bug ... >:(
>
> V2:
>  - Added patches 1-5 which do some more delinting.
>  - Added patch 8, which scans subdirs for tests to lint.
>  - Added patch 17, which improves the speed of mypy analysis.
>  - Patch 14 is different because of the new patch 8.
>
> John Snow (16):
>   python: Update for pylint 2.10
>   iotests/mirror-top-perms: Adjust imports
>   iotests/migrate-bitmaps-postcopy-test: declare instance variables
>   iotests/migrate-bitmaps-test: delint
>   iotests/297: modify is_python_file to work from any CWD
>   iotests/297: Add get_files() function
>   iotests/297: Don't rely on distro-specific linter binaries
>   iotests/297: Create main() function
>   iotests/297: Separate environment setup from test execution
>   iotests/297: Add 'directory' argument to run_linters
>   iotests/297: return error code from run_linters()
>   iotests/297: split linters.py off from 297
>   iotests/linters: Add entry point for Python CI linters
>   iotests/linters: Add workaround for mypy bug #9852
>   python: Add iotest linters to test suite
>   iotests/linters: check mypy files all at once
>
>  python/qemu/machine/machine.py|   9 +-
>  python/setup.cfg  |   1 +
>  python/tests/iotests.sh   |   4 +
>  tests/qemu-iotests/297|  81 ++-
>  tests/qemu-iotests/linters.py | 129 ++
>  .../tests/migrate-bitmaps-postcopy-test   |   3 +
>  tests/qemu-iotests/tests/migrate-bitmaps-test |  50 ---
>  tests/qemu-iotests/tests/mirror-top-perms |   7 +-
>  8 files changed, 186 insertions(+), 98 deletions(-)
>  create mode 100755 python/tests/iotests.sh
>  create mode 100755 tests/qemu-iotests/linters.py
>
> --
> 2.31.1
>
>
>
FWIW: I sent a new version of a pull request that adds pylint 2.10 *and*
2.11 support; the 2.11 release happened just yesterday, so I am going to
rebase this series.

Additionally, I found a new way to avoid sys.path hacking in all of our
test files entirely, so I will include that in this series, rebase, and
resend extremely soon. If you have difficulties applying this patchset or
testing it, sit tight for a refreshed version -- but most of these patches
can still be reviewed on their own merits in the meantime.

Thanks,
--js


[PATCH 11/15] python/aqmp: Create sync QMP wrapper for iotests

2021-09-16 Thread John Snow
This is a wrapper around the async QMPClient that mimics the old,
synchronous QEMUMonitorProtocol class. It is designed to be
interchangeable with the old implementation.

It does not, however, attempt to mimic Exception compatibility.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/legacy.py | 131 +
 1 file changed, 131 insertions(+)
 create mode 100644 python/qemu/aqmp/legacy.py

diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
new file mode 100644
index 00..b8544083ad
--- /dev/null
+++ b/python/qemu/aqmp/legacy.py
@@ -0,0 +1,131 @@
+"""
+Sync QMP Wrapper
+
+This class pretends to be qemu.qmp.QEMUMonitorProtocol.
+"""
+
+import asyncio
+from typing import (
+Awaitable,
+List,
+Optional,
+TypeVar,
+Union,
+)
+
+import qemu.qmp
+from qemu.qmp import QMPMessage, QMPReturnValue, SocketAddrT
+
+from .qmp_client import QMPClient
+
+
+# pylint: disable=missing-docstring
+
+
+class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol):
+def __init__(self, address: SocketAddrT,
+ server: bool = False,
+ nickname: Optional[str] = None):
+
+# pylint: disable=super-init-not-called
+self._aqmp = QMPClient(nickname)
+self._aloop = asyncio.get_event_loop()
+self._address = address
+self._timeout: Optional[float] = None
+
+_T = TypeVar('_T')
+
+def _sync(
+self, future: Awaitable[_T], timeout: Optional[float] = None
+) -> _T:
+return self._aloop.run_until_complete(
+asyncio.wait_for(future, timeout=timeout)
+)
+
+# __enter__ and __exit__ need no changes
+# parse_address needs no changes
+
+def connect(self, negotiate: bool = True) -> Optional[QMPMessage]:
+self._aqmp.await_greeting = negotiate
+self._aqmp.negotiate = negotiate
+
+self._sync(
+self._aqmp.connect(self._address)
+)
+
+if self._aqmp.greeting is not None:
+return dict(self._aqmp.greeting)
+return None
+
+def accept(self, timeout: Optional[float] = 15.0) -> QMPMessage:
+self._aqmp.await_greeting = True
+self._aqmp.negotiate = True
+
+self._sync(
+self._aqmp.accept(self._address),
+timeout
+)
+
+assert self._aqmp.greeting is not None
+return dict(self._aqmp.greeting)
+
+def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage:
+return dict(
+self._sync(
+# pylint: disable=protected-access
+
+# _raw() isn't a public API, because turning off
+# automatic ID assignment is discouraged. For
+# compatibility with iotests *only*, do it anyway.
+self._aqmp._raw(qmp_cmd, assign_id=False),
+self._timeout
+)
+)
+
+# Default impl of cmd() delegates to cmd_obj
+
+def command(self, cmd: str, **kwds: object) -> QMPReturnValue:
+return self._sync(
+self._aqmp.execute(cmd, kwds),
+self._timeout
+)
+
+def pull_event(self,
+   wait: Union[bool, float] = False) -> Optional[QMPMessage]:
+if wait is False:
+# Return None if there's no event ready to go
+if self._aqmp.events.empty():
+return None
+
+timeout = None
+if isinstance(wait, float):
+timeout = wait
+
+return dict(
+self._sync(
+self._aqmp.events.get(),
+timeout
+)
+)
+
+def get_events(self, wait: Union[bool, float] = False) -> List[QMPMessage]:
+events = [dict(x) for x in self._aqmp.events.clear()]
+if events:
+return events
+
+event = self.pull_event(wait)
+return [event] if event is not None else []
+
+def clear_events(self) -> None:
+self._aqmp.events.clear()
+
+def close(self) -> None:
+self._sync(
+self._aqmp.disconnect()
+)
+
+def settimeout(self, timeout: Optional[float]) -> None:
+self._timeout = timeout
+
+def send_fd_scm(self, fd: int) -> None:
+self._aqmp.send_fd_scm(fd)
-- 
2.31.1




[PATCH 14/15] python/aqmp: Remove scary message

2021-09-16 Thread John Snow
The scary message interferes with the iotests output. Coincidentally, if
iotests works by removing this, then it's good evidence that we don't
really need to scare people away from using it.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/__init__.py | 14 --
 1 file changed, 14 deletions(-)

diff --git a/python/qemu/aqmp/__init__.py b/python/qemu/aqmp/__init__.py
index ab1782999c..4b7df53e00 100644
--- a/python/qemu/aqmp/__init__.py
+++ b/python/qemu/aqmp/__init__.py
@@ -21,8 +21,6 @@
 # This work is licensed under the terms of the GNU GPL, version 2.  See
 # the COPYING file in the top-level directory.
 
-import warnings
-
 from .error import AQMPError
 from .events import EventListener
 from .message import Message
@@ -30,18 +28,6 @@
 from .qmp_client import ExecInterruptedError, ExecuteError, QMPClient
 
 
-_WMSG = """
-
-The Asynchronous QMP library is currently in development and its API
-should be considered highly fluid and subject to change. It should
-not be used by any other scripts checked into the QEMU tree.
-
-Proceed with caution!
-"""
-
-warnings.warn(_WMSG, FutureWarning)
-
-
 # The order of these fields impact the Sphinx documentation order.
 __all__ = (
 # Classes, most to least important
-- 
2.31.1




[PATCH 09/15] python/machine: remove has_quit argument

2021-09-16 Thread John Snow
If we spy on the QMP commands instead, we don't need callers to remember
to pass it. Seems like a fair trade-off.

The one slightly weird bit is overloading this instance variable for
wait(), where we use it to mean "don't issue the qmp 'quit'
command". This means that wait() will "fail" if the QEMU process does
not terminate of its own accord.

In most cases, we probably did already actually issue quit -- some
iotests do this -- but in some others, we may be waiting for QEMU to
terminate for some other reason.

Signed-off-by: John Snow 
---
 python/qemu/machine/machine.py | 35 +++---
 tests/qemu-iotests/040 |  7 +--
 tests/qemu-iotests/218 |  2 +-
 tests/qemu-iotests/255 |  2 +-
 4 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 056d340e35..6e58d2f951 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -170,6 +170,7 @@ def __init__(self,
 self._console_socket: Optional[socket.socket] = None
 self._remove_files: List[str] = []
 self._user_killed = False
+self._has_quit = False
 
 def __enter__(self: _T) -> _T:
 return self
@@ -368,6 +369,7 @@ def _post_shutdown(self) -> None:
 command = ''
 LOG.warning(msg, -int(exitcode), command)
 
+self._has_quit = False
 self._user_killed = False
 self._launched = False
 
@@ -443,15 +445,13 @@ def _hard_shutdown(self) -> None:
 self._subp.kill()
 self._subp.wait(timeout=60)
 
-def _soft_shutdown(self, timeout: Optional[int],
-   has_quit: bool = False) -> None:
+def _soft_shutdown(self, timeout: Optional[int]) -> None:
 """
 Perform early cleanup, attempt to gracefully shut down the VM, and wait
 for it to terminate.
 
 :param timeout: Timeout in seconds for graceful shutdown.
 A value of None is an infinite wait.
-:param has_quit: When True, don't attempt to issue 'quit' QMP command
 
 :raise ConnectionReset: On QMP communication errors
 :raise subprocess.TimeoutExpired: When timeout is exceeded waiting for
@@ -460,21 +460,19 @@ def _soft_shutdown(self, timeout: Optional[int],
 self._early_cleanup()
 
 if self._qmp_connection:
-if not has_quit:
+if not self._has_quit:
 # Might raise ConnectionReset
-self._qmp.cmd('quit')
+self.qmp('quit')
 
 # May raise subprocess.TimeoutExpired
 self._subp.wait(timeout=timeout)
 
-def _do_shutdown(self, timeout: Optional[int],
- has_quit: bool = False) -> None:
+def _do_shutdown(self, timeout: Optional[int]) -> None:
 """
 Attempt to shutdown the VM gracefully; fallback to a hard shutdown.
 
 :param timeout: Timeout in seconds for graceful shutdown.
 A value of None is an infinite wait.
-:param has_quit: When True, don't attempt to issue 'quit' QMP command
 
 :raise AbnormalShutdown: When the VM could not be shut down gracefully.
 The inner exception will likely be ConnectionReset or
@@ -482,13 +480,13 @@ def _do_shutdown(self, timeout: Optional[int],
 may result in its own exceptions, likely subprocess.TimeoutExpired.
 """
 try:
-self._soft_shutdown(timeout, has_quit)
+self._soft_shutdown(timeout)
 except Exception as exc:
 self._hard_shutdown()
 raise AbnormalShutdown("Could not perform graceful shutdown") \
 from exc
 
-def shutdown(self, has_quit: bool = False,
+def shutdown(self,
  hard: bool = False,
  timeout: Optional[int] = 30) -> None:
 """
@@ -498,7 +496,6 @@ def shutdown(self, has_quit: bool = False,
 If the VM has not yet been launched, or shutdown(), wait(), or kill()
 have already been called, this method does nothing.
 
-:param has_quit: When true, do not attempt to issue 'quit' QMP command.
 :param hard: When true, do not attempt graceful shutdown, and
  suppress the SIGKILL warning log message.
 :param timeout: Optional timeout in seconds for graceful shutdown.
@@ -512,7 +509,7 @@ def shutdown(self, has_quit: bool = False,
 self._user_killed = True
 self._hard_shutdown()
 else:
-self._do_shutdown(timeout, has_quit)
+self._do_shutdown(timeout)
 finally:
 self._post_shutdown()
 
@@ -529,7 +526,9 @@ def wait(self, timeout: Optional[int] = 30) -> None:
 :param timeout: Optional timeout in seconds. Default 30 seconds.
 A value of `None` is an infinite wait.
 """
-self.shutdown(has_quit=

[PATCH 13/15] iotests: Accommodate async QMP Exception classes

2021-09-16 Thread John Snow
(But continue to support the old ones for now, too.)

There are very few cases of any user of QEMUMachine or a subclass
thereof relying on a QMP Exception type. If you'd like to check for
yourself, you want to grep for all of the derivatives of QMPError,
excluding 'AQMPError' and its derivatives. That'd be these:

- QMPError
- QMPConnectError
- QMPCapabilitiesError
- QMPTimeoutError
- QMPProtocolError
- QMPResponseError
- QMPBadPortError


Signed-off-by: John Snow 
---
 scripts/simplebench/bench_block_job.py| 3 ++-
 tests/qemu-iotests/tests/mirror-top-perms | 6 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/scripts/simplebench/bench_block_job.py 
b/scripts/simplebench/bench_block_job.py
index 4f03c12169..a403c35b08 100755
--- a/scripts/simplebench/bench_block_job.py
+++ b/scripts/simplebench/bench_block_job.py
@@ -28,6 +28,7 @@
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
 from qemu.machine import QEMUMachine
 from qemu.qmp import QMPConnectError
+from qemu.aqmp import ConnectError
 
 
 def bench_block_job(cmd, cmd_args, qemu_args):
@@ -49,7 +50,7 @@ def bench_block_job(cmd, cmd_args, qemu_args):
 vm.launch()
 except OSError as e:
 return {'error': 'popen failed: ' + str(e)}
-except (QMPConnectError, socket.timeout):
+except (QMPConnectError, ConnectError, socket.timeout):
 return {'error': 'qemu failed: ' + str(vm.get_log())}
 
 try:
diff --git a/tests/qemu-iotests/tests/mirror-top-perms 
b/tests/qemu-iotests/tests/mirror-top-perms
index 451a0666f8..7d448f4d23 100755
--- a/tests/qemu-iotests/tests/mirror-top-perms
+++ b/tests/qemu-iotests/tests/mirror-top-perms
@@ -103,7 +103,11 @@ class TestMirrorTopPerms(iotests.QMPTestCase):
 print('ERROR: VM B launched successfully, this should not have '
   'happened')
 except qemu.qmp.QMPConnectError:
-assert 'Is another process using the image' in self.vm_b.get_log()
+pass
+except qemu.aqmp.ConnectError:
+pass
+
+assert 'Is another process using the image' in self.vm_b.get_log()
 
 result = self.vm.qmp('block-job-cancel',
  device='mirror')
-- 
2.31.1




[PATCH 06/15] python, iotests: remove socket_scm_helper

2021-09-16 Thread John Snow
It's not used anymore, now.

Signed-off-by: John Snow 
---
 tests/qemu-iotests/socket_scm_helper.c | 136 -
 python/qemu/machine/machine.py |   3 -
 python/qemu/machine/qtest.py   |   2 -
 tests/Makefile.include |   1 -
 tests/meson.build  |   4 -
 tests/qemu-iotests/iotests.py  |   3 -
 tests/qemu-iotests/meson.build |   5 -
 tests/qemu-iotests/testenv.py  |   8 +-
 8 files changed, 1 insertion(+), 161 deletions(-)
 delete mode 100644 tests/qemu-iotests/socket_scm_helper.c
 delete mode 100644 tests/qemu-iotests/meson.build

diff --git a/tests/qemu-iotests/socket_scm_helper.c 
b/tests/qemu-iotests/socket_scm_helper.c
deleted file mode 100644
index eb76d31aa9..00
--- a/tests/qemu-iotests/socket_scm_helper.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SCM_RIGHTS with unix socket help program for test
- *
- * Copyright IBM, Inc. 2013
- *
- * Authors:
- *  Wenchao Xia
- *
- * This work is licensed under the terms of the GNU LGPL, version 2 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include 
-#include 
-
-/* #define SOCKET_SCM_DEBUG */
-
-/*
- * @fd and @fd_to_send will not be checked for validation in this function,
- * a blank will be sent as iov data to notify qemu.
- */
-static int send_fd(int fd, int fd_to_send)
-{
-struct msghdr msg;
-struct iovec iov[1];
-int ret;
-char control[CMSG_SPACE(sizeof(int))];
-struct cmsghdr *cmsg;
-
-memset(&msg, 0, sizeof(msg));
-memset(control, 0, sizeof(control));
-
-/* Send a blank to notify qemu */
-iov[0].iov_base = (void *)" ";
-iov[0].iov_len = 1;
-
-msg.msg_iov = iov;
-msg.msg_iovlen = 1;
-
-msg.msg_control = control;
-msg.msg_controllen = sizeof(control);
-
-cmsg = CMSG_FIRSTHDR(&msg);
-
-cmsg->cmsg_len = CMSG_LEN(sizeof(int));
-cmsg->cmsg_level = SOL_SOCKET;
-cmsg->cmsg_type = SCM_RIGHTS;
-memcpy(CMSG_DATA(cmsg), &fd_to_send, sizeof(int));
-
-do {
-ret = sendmsg(fd, &msg, 0);
-} while (ret < 0 && errno == EINTR);
-
-if (ret < 0) {
-fprintf(stderr, "Failed to send msg, reason: %s\n", strerror(errno));
-}
-
-return ret;
-}
-
-/* Convert string to fd number. */
-static int get_fd_num(const char *fd_str, bool silent)
-{
-int sock;
-char *err;
-
-errno = 0;
-sock = strtol(fd_str, &err, 10);
-if (errno) {
-if (!silent) {
-fprintf(stderr, "Failed in strtol for socket fd, reason: %s\n",
-strerror(errno));
-}
-return -1;
-}
-if (!*fd_str || *err || sock < 0) {
-if (!silent) {
-fprintf(stderr, "bad numerical value for socket fd '%s'\n", 
fd_str);
-}
-return -1;
-}
-
-return sock;
-}
-
-/*
- * To make things simple, the caller needs to specify:
- * 1. socket fd.
- * 2. path of the file to be sent.
- */
-int main(int argc, char **argv, char **envp)
-{
-int sock, fd, ret;
-
-#ifdef SOCKET_SCM_DEBUG
-int i;
-for (i = 0; i < argc; i++) {
-fprintf(stderr, "Parameter %d: %s\n", i, argv[i]);
-}
-#endif
-
-if (argc != 3) {
-fprintf(stderr,
-"Usage: %s < socket-fd > < file-path >\n",
-argv[0]);
-return EXIT_FAILURE;
-}
-
-
-sock = get_fd_num(argv[1], false);
-if (sock < 0) {
-return EXIT_FAILURE;
-}
-
-fd = get_fd_num(argv[2], true);
-if (fd < 0) {
-/* Now only open a file in readonly mode for test purpose. If more
-   precise control is needed, use python script in file operation, 
which
-   is supposed to fork and exec this program. */
-fd = open(argv[2], O_RDONLY);
-if (fd < 0) {
-fprintf(stderr, "Failed to open file '%s'\n", argv[2]);
-return EXIT_FAILURE;
-}
-}
-
-ret = send_fd(sock, fd);
-if (ret < 0) {
-close(fd);
-return EXIT_FAILURE;
-}
-
-close(fd);
-return EXIT_SUCCESS;
-}
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 1c6532a3d6..056d340e35 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -98,7 +98,6 @@ def __init__(self,
  name: Optional[str] = None,
  base_temp_dir: str = "/var/tmp",
  monitor_address: Optional[SocketAddrT] = None,
- socket_scm_helper: Optional[str] = None,
  sock_dir: Optional[str] = None,
  drain_console: bool = False,
  console_log: Optional[str] = None,
@@ -113,7 +112,6 @@ def __init__(self,
 @param name: prefix for socket and log file names (default: qemu-PID)
 @param base_temp_dir: default location where temp files are created
 @param monitor_address: address for QMP monitor
-@param socket_scm_helper: helper program, require

[PATCH 10/15] python/machine: Add support for AQMP backend

2021-09-16 Thread John Snow
To use the AQMP backend, Machine just needs to be a little more diligent
about what happens when closing a QMP connection. The operation is no
longer a freebie in the async world.

Because async QMP continues to check for messages asynchronously, it's
almost certainly likely that the loop will have exited due to EOF after
issuing the last 'quit' command. That error will ultimately be bubbled
up when attempting to close the QMP connection. The manager class here
then is free to discard it if it was expected.

Signed-off-by: John Snow 

---

Yes, I regret that this class has become quite a dumping ground for
complexity around the exit path. It's in need of a refactor to help
separate out the exception handling and cleanup mechanisms from the
VM-related stuff, but it's not a priority to do that just yet -- but
it's on the list.

---
 python/qemu/machine/machine.py | 51 ++
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 6e58d2f951..8f5a6649e5 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -342,9 +342,15 @@ def _post_shutdown(self) -> None:
 # Comprehensive reset for the failed launch case:
 self._early_cleanup()
 
-if self._qmp_connection:
-self._qmp.close()
-self._qmp_connection = None
+try:
+self._close_qmp_connection()
+except Exception as err:  # pylint: disable=broad-except
+LOG.warning(
+"Exception closing QMP connection: %s",
+str(err) if str(err) else type(err).__name__
+)
+finally:
+assert self._qmp_connection is None
 
 self._close_qemu_log_file()
 
@@ -420,6 +426,31 @@ def _launch(self) -> None:
close_fds=False)
 self._post_launch()
 
+def _close_qmp_connection(self) -> None:
+"""
+Close the underlying QMP connection, if any.
+
+Dutifully report errors that occurred while closing, but assume
+that any error encountered indicates an abnormal termination
+process and not a failure to close.
+"""
+if self._qmp_connection is None:
+return
+
+try:
+self._qmp.close()
+except EOFError:
+# EOF can occur as an Exception here when using the Async
+# QMP backend. It indicates that the server closed the
+# stream. If we successfully issued 'quit' at any point,
+# then this was expected. If the remote went away without
+# our permission, it's worth reporting that as an abnormal
+# shutdown case.
+if not self._has_quit:
+raise
+finally:
+self._qmp_connection = None
+
 def _early_cleanup(self) -> None:
 """
 Perform any cleanup that needs to happen before the VM exits.
@@ -461,8 +492,18 @@ def _soft_shutdown(self, timeout: Optional[int]) -> None:
 
 if self._qmp_connection:
 if not self._has_quit:
-# Might raise ConnectionReset
-self.qmp('quit')
+try:
+# May raise ExecInterruptedError or StateError if the
+# connection dies or has already died.
+self.qmp('quit')
+finally:
+# If 'quit' fails, we'll still want to call close(),
+# which will raise any final errors that may have
+# occurred while trying to send 'quit'.
+self._close_qmp_connection()
+else:
+# Regardless, we want to tidy up the socket.
+self._close_qmp_connection()
 
 # May raise subprocess.TimeoutExpired
 self._subp.wait(timeout=timeout)
-- 
2.31.1




[PATCH 05/15] python/qmp: add send_fd_scm directly to QEMUMonitorProtocol

2021-09-16 Thread John Snow
It turns out you can do this directly from Python ... and because of
this, you don't need to worry about setting the inheritability of the
fds or spawning another process.

Doing this is helpful because it allows QEMUMonitorProtocol to keep its
file descriptor and socket object as private implementation details.

*that* is helpful in turn because it allows me to write a compatible,
 alternative implementation.

Signed-off-by: John Snow 
---
 python/qemu/machine/machine.py | 44 +++---
 python/qemu/qmp/__init__.py| 21 +++-
 2 files changed, 18 insertions(+), 47 deletions(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index ae945ca3c9..1c6532a3d6 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -213,48 +213,22 @@ def add_fd(self: _T, fd: int, fdset: int,
 def send_fd_scm(self, fd: Optional[int] = None,
 file_path: Optional[str] = None) -> int:
 """
-Send an fd or file_path to socket_scm_helper.
+Send an fd or file_path to the remote via SCM_RIGHTS.
 
-Exactly one of fd and file_path must be given.
-If it is file_path, the helper will open that file and pass its own fd.
+Exactly one of fd and file_path must be given.  If it is
+file_path, the file will be opened read-only and the new file
+descriptor will be sent to the remote.
 """
-# In iotest.py, the qmp should always use unix socket.
-assert self._qmp.is_scm_available()
-if self._socket_scm_helper is None:
-raise QEMUMachineError("No path to socket_scm_helper set")
-if not os.path.exists(self._socket_scm_helper):
-raise QEMUMachineError("%s does not exist" %
-   self._socket_scm_helper)
-
-# This did not exist before 3.4, but since then it is
-# mandatory for our purpose
-if hasattr(os, 'set_inheritable'):
-os.set_inheritable(self._qmp.get_sock_fd(), True)
-if fd is not None:
-os.set_inheritable(fd, True)
-
-fd_param = ["%s" % self._socket_scm_helper,
-"%d" % self._qmp.get_sock_fd()]
-
 if file_path is not None:
 assert fd is None
-fd_param.append(file_path)
+with open(file_path, "rb") as passfile:
+fd = passfile.fileno()
+self._qmp.send_fd_scm(fd)
 else:
 assert fd is not None
-fd_param.append(str(fd))
+self._qmp.send_fd_scm(fd)
 
-proc = subprocess.run(
-fd_param,
-stdin=subprocess.DEVNULL,
-stdout=subprocess.PIPE,
-stderr=subprocess.STDOUT,
-check=False,
-close_fds=False,
-)
-if proc.stdout:
-LOG.debug(proc.stdout)
-
-return proc.returncode
+return 0
 
 @staticmethod
 def _remove_if_exists(path: str) -> None:
diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
index ba15668c25..c3b8a70ec9 100644
--- a/python/qemu/qmp/__init__.py
+++ b/python/qemu/qmp/__init__.py
@@ -21,6 +21,7 @@
 import json
 import logging
 import socket
+import struct
 from types import TracebackType
 from typing import (
 Any,
@@ -408,18 +409,14 @@ def settimeout(self, timeout: Optional[float]) -> None:
 raise ValueError(msg)
 self.__sock.settimeout(timeout)
 
-def get_sock_fd(self) -> int:
+def send_fd_scm(self, fd: int) -> None:
 """
-Get the socket file descriptor.
-
-@return The file descriptor number.
-"""
-return self.__sock.fileno()
-
-def is_scm_available(self) -> bool:
+Send a file descriptor to the remote via SCM_RIGHTS.
 """
-Check if the socket allows for SCM_RIGHTS.
+if self.__sock.family != socket.AF_UNIX:
+raise RuntimeError("Can't use SCM_RIGHTS on non-AF_UNIX socket.")
 
-@return True if SCM_RIGHTS is available, otherwise False.
-"""
-return self.__sock.family == socket.AF_UNIX
+self.__sock.sendmsg(
+[b' '],
+[(socket.SOL_SOCKET, socket.SCM_RIGHTS, struct.pack('@i', fd))]
+)
-- 
2.31.1




[PATCH 07/15] python/aqmp: add send_fd_scm

2021-09-16 Thread John Snow
The single space is indeed required to successfully transmit the file
descriptor to QEMU.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/qmp_client.py | 17 +
 1 file changed, 17 insertions(+)

diff --git a/python/qemu/aqmp/qmp_client.py b/python/qemu/aqmp/qmp_client.py
index d2ad7459f9..58f85990bc 100644
--- a/python/qemu/aqmp/qmp_client.py
+++ b/python/qemu/aqmp/qmp_client.py
@@ -9,6 +9,8 @@
 
 import asyncio
 import logging
+import socket
+import struct
 from typing import (
 Dict,
 List,
@@ -624,3 +626,18 @@ async def execute(self, cmd: str,
 """
 msg = self.make_execute_msg(cmd, arguments, oob=oob)
 return await self.execute_msg(msg)
+
+@upper_half
+@require(Runstate.RUNNING)
+def send_fd_scm(self, fd: int) -> None:
+"""
+Send a file descriptor to the remote via SCM_RIGHTS.
+"""
+assert self._writer is not None
+sock = self._writer.transport.get_extra_info('socket')
+
+# Python 3.9+ adds socket.send_fds(...)
+sock.sendmsg(
+[b' '],
+[(socket.SOL_SOCKET, socket.SCM_RIGHTS, struct.pack('@i', fd))]
+)
-- 
2.31.1




[PATCH 08/15] python/aqmp: Create MessageModel and StandaloneModel classes

2021-09-16 Thread John Snow
This allows 'Greeting' to be subclass of 'Message'. We need the adapter
classes to avoid some typing problems that occur if we try to put too
much into the 'Model' class itself; the exact details of why are left as
an exercise to the reader.

Why bother? This makes 'Greeting' ⊆ 'Message', which is taxonomically
true; but the real motivation is to be able to inherit and abuse all of
the Mapping dunders so that we can call dict(greeting) or
bytes(greeting), for example.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/models.py | 67 --
 1 file changed, 50 insertions(+), 17 deletions(-)

diff --git a/python/qemu/aqmp/models.py b/python/qemu/aqmp/models.py
index 24c94123ac..eaeeebc25c 100644
--- a/python/qemu/aqmp/models.py
+++ b/python/qemu/aqmp/models.py
@@ -15,23 +15,22 @@
 Sequence,
 )
 
+from .message import Message
+
 
 class Model:
 """
-Abstract data model, representing some QMP object of some kind.
-
-:param raw: The raw object to be validated.
-:raise KeyError: If any required fields are absent.
-:raise TypeError: If any required fields have the wrong type.
+Abstract data model, representing a QMP object of some kind.
 """
-def __init__(self, raw: Mapping[str, Any]):
-self._raw = raw
+@property
+def _raw(self) -> Mapping[str, Any]:
+raise NotImplementedError
 
 def _check_key(self, key: str) -> None:
 if key not in self._raw:
 raise KeyError(f"'{self._name}' object requires '{key}' member")
 
-def _check_value(self, key: str, type_: type, typestr: str) -> None:
+def _check_type(self, key: str, type_: type, typestr: str) -> None:
 assert key in self._raw
 if not isinstance(self._raw[key], type_):
 raise TypeError(
@@ -40,7 +39,7 @@ def _check_value(self, key: str, type_: type, typestr: str) 
-> None:
 
 def _check_member(self, key: str, type_: type, typestr: str) -> None:
 self._check_key(key)
-self._check_value(key, type_, typestr)
+self._check_type(key, type_, typestr)
 
 @property
 def _name(self) -> str:
@@ -50,7 +49,37 @@ def __repr__(self) -> str:
 return f"{self._name}({self._raw!r})"
 
 
-class Greeting(Model):
+class MessageModel(Message, Model):
+"""
+Abstract data model, representing a QMP Message of some sort.
+
+Adapter class that glues together `Model` and `Message`.
+"""
+def __init__(self, raw: Mapping[str, object]):
+super().__init__(raw)
+
+@property
+def _raw(self) -> Mapping[str, Any]:
+return self._object
+
+def __setitem__(self, key: str, value: object) -> None:
+# This is not good OO, but this turns off mutability here.
+raise RuntimeError("Cannot mutate MessageModel")
+
+
+class StandaloneModel(Model):
+"""
+Abstract data model, representing a (non-Message) QMP object of some sort.
+"""
+def __init__(self, raw: Mapping[str, object]):
+self._raw_mapping = raw
+
+@property
+def _raw(self) -> Mapping[str, Any]:
+return self._raw_mapping
+
+
+class Greeting(MessageModel):
 """
 Defined in qmp-spec.txt, section 2.2, "Server Greeting".
 
@@ -58,8 +87,9 @@ class Greeting(Model):
 :raise KeyError: If any required fields are absent.
 :raise TypeError: If any required fields have the wrong type.
 """
-def __init__(self, raw: Mapping[str, Any]):
+def __init__(self, raw: Mapping[str, object]):
 super().__init__(raw)
+
 #: 'QMP' member
 self.QMP: QMPGreeting  # pylint: disable=invalid-name
 
@@ -67,7 +97,7 @@ def __init__(self, raw: Mapping[str, Any]):
 self.QMP = QMPGreeting(self._raw['QMP'])
 
 
-class QMPGreeting(Model):
+class QMPGreeting(StandaloneModel):
 """
 Defined in qmp-spec.txt, section 2.2, "Server Greeting".
 
@@ -75,8 +105,9 @@ class QMPGreeting(Model):
 :raise KeyError: If any required fields are absent.
 :raise TypeError: If any required fields have the wrong type.
 """
-def __init__(self, raw: Mapping[str, Any]):
+def __init__(self, raw: Mapping[str, object]):
 super().__init__(raw)
+
 #: 'version' member
 self.version: Mapping[str, object]
 #: 'capabilities' member
@@ -89,7 +120,7 @@ def __init__(self, raw: Mapping[str, Any]):
 self.capabilities = self._raw['capabilities']
 
 
-class ErrorResponse(Model):
+class ErrorResponse(MessageModel):
 """
 Defined in qmp-spec.txt, section 2.4.2, "error".
 
@@ -97,8 +128,9 @@ class ErrorResponse(Model):
 :raise KeyError: If any required fields are absent.
 :raise TypeError: If any required fields have the wrong type.
 """
-def __init__(self, raw: Mapping[str, Any]):
+def __init__(self, raw: Mapping[str, object]):
 super().__init__(raw)
+
 #: 'error' member
 self.error: ErrorInfo
 #: 'id' member
@@ -111,7 +143,7 @@ def __init__(self, raw: Mapping[str,

[PATCH 03/15] python/aqmp: Return cleared events from EventListener.clear()

2021-09-16 Thread John Snow
This serves two purposes:

(1) It is now possible to discern whether or not clear() removed any
event(s) from the queue with absolute certainty, and

(2) It is now very easy to get a List of all pending events in one
chunk, which is useful for the sync bridge.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/events.py | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/python/qemu/aqmp/events.py b/python/qemu/aqmp/events.py
index 271899f6b8..5f7150c78d 100644
--- a/python/qemu/aqmp/events.py
+++ b/python/qemu/aqmp/events.py
@@ -562,7 +562,7 @@ def empty(self) -> bool:
 """
 return self._queue.empty()
 
-def clear(self) -> None:
+def clear(self) -> List[Message]:
 """
 Clear this listener of all pending events.
 
@@ -570,17 +570,22 @@ def clear(self) -> None:
 pending FIFO queue synchronously. It can be also be used to
 manually clear any pending events, if desired.
 
+:return: The cleared events, if any.
+
 .. warning::
 Take care when discarding events. Cleared events will be
 silently tossed on the floor. All events that were ever
 accepted by this listener are visible in `history()`.
 """
+events = []
 while True:
 try:
-self._queue.get_nowait()
+events.append(self._queue.get_nowait())
 except asyncio.QueueEmpty:
 break
 
+return events
+
 def __aiter__(self) -> AsyncIterator[Message]:
 return self
 
-- 
2.31.1




[PATCH 12/15] iotests: Disable AQMP logging under non-debug modes

2021-09-16 Thread John Snow
Disable the aqmp logger, which likes to (at the moment) print out
intermediate warnings and errors that cause session termination; disable
them so they don't interfere with the job output.

Leave any "CRITICAL" warnings enabled though, those are ones that we
should never see, no matter what.

Signed-off-by: John Snow 
---
 tests/qemu-iotests/iotests.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 273d2777ae..47e5f9738b 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -1383,6 +1383,8 @@ def execute_setup_common(supported_fmts: Sequence[str] = 
(),
 if debug:
 sys.argv.remove('-d')
 logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
+if not debug:
+logging.getLogger("qemu.aqmp.qmp_client").setLevel(logging.CRITICAL)
 
 _verify_image_format(supported_fmts, unsupported_fmts)
 _verify_protocol(supported_protocols, unsupported_protocols)
-- 
2.31.1




[PATCH 02/15] python/aqmp: add .empty() method to EventListener

2021-09-16 Thread John Snow
Synchronous clients may want to know if they're about to block waiting
for an event or not. A method such as this is necessary to implement a
compatible interface for the old QEMUMonitorProtocol using the new async
internals.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/events.py | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/python/qemu/aqmp/events.py b/python/qemu/aqmp/events.py
index fb81d21610..271899f6b8 100644
--- a/python/qemu/aqmp/events.py
+++ b/python/qemu/aqmp/events.py
@@ -556,6 +556,12 @@ async def get(self) -> Message:
 """
 return await self._queue.get()
 
+def empty(self) -> bool:
+"""
+Return `True` if there are no pending events.
+"""
+return self._queue.empty()
+
 def clear(self) -> None:
 """
 Clear this listener of all pending events.
-- 
2.31.1




[PATCH 04/15] python/qmp: clear events on get_events() call

2021-09-16 Thread John Snow
All callers in the tree *already* clear the events after a call to
get_events(). Do it automatically instead and update callsites to remove
the manual clear call.

These semantics are quite a bit easier to emulate with async QMP, and
nobody appears to be abusing some emergent properties of what happens if
you decide not to clear them, so let's dial down to the dumber, simpler
thing.

Specifically: callers of clear() right after a call to get_events() are
more likely expressing their desire to not see any events they just
retrieved, whereas callers of clear_events() not in relation to a recent
call to pull_event/get_events are likely expressing their desire to
simply drop *all* pending events straight onto the floor. In the sync
world, this is safe enough; in the async world it's nearly impossible to
promise that nothing happens between getting and clearing the
events.

Making the retrieval also clear the queue is vastly simpler.

Signed-off-by: John Snow 
---
 python/qemu/machine/machine.py | 1 -
 python/qemu/qmp/__init__.py| 4 +++-
 python/qemu/qmp/qmp_shell.py   | 1 -
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 34131884a5..ae945ca3c9 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -631,7 +631,6 @@ def get_qmp_events(self, wait: bool = False) -> 
List[QMPMessage]:
 events = self._qmp.get_events(wait=wait)
 events.extend(self._events)
 del self._events[:]
-self._qmp.clear_events()
 return events
 
 @staticmethod
diff --git a/python/qemu/qmp/__init__.py b/python/qemu/qmp/__init__.py
index 269516a79b..ba15668c25 100644
--- a/python/qemu/qmp/__init__.py
+++ b/python/qemu/qmp/__init__.py
@@ -374,7 +374,9 @@ def get_events(self, wait: bool = False) -> 
List[QMPMessage]:
 @return The list of available QMP events.
 """
 self.__get_events(wait)
-return self.__events
+events = self.__events
+self.__events = []
+return events
 
 def clear_events(self) -> None:
 """
diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/qmp/qmp_shell.py
index 337acfce2d..e7d7eb18f1 100644
--- a/python/qemu/qmp/qmp_shell.py
+++ b/python/qemu/qmp/qmp_shell.py
@@ -381,7 +381,6 @@ def read_exec_command(self) -> bool:
 if cmdline == '':
 for event in self.get_events():
 print(event)
-self.clear_events()
 return True
 
 return self._execute_cmd(cmdline)
-- 
2.31.1




[PATCH 01/15] python/aqmp: add greeting property to QMPClient

2021-09-16 Thread John Snow
Expose the greeting as a read-only property of QMPClient so it can be
retrieved at-will.

Signed-off-by: John Snow 
---
 python/qemu/aqmp/qmp_client.py | 5 +
 1 file changed, 5 insertions(+)

diff --git a/python/qemu/aqmp/qmp_client.py b/python/qemu/aqmp/qmp_client.py
index 82e9dab124..d2ad7459f9 100644
--- a/python/qemu/aqmp/qmp_client.py
+++ b/python/qemu/aqmp/qmp_client.py
@@ -224,6 +224,11 @@ def __init__(self, name: Optional[str] = None) -> None:
 'asyncio.Queue[QMPClient._PendingT]'
 ] = {}
 
+@property
+def greeting(self) -> Optional[Greeting]:
+"""The `Greeting` from the QMP server, if any."""
+return self._greeting
+
 @upper_half
 async def _establish_session(self) -> None:
 """
-- 
2.31.1




[PATCH 00/15] Switch iotests to using Async QMP

2021-09-16 Thread John Snow
Based-on: <20210916220716.1353698-1-js...@redhat.com>
Based-on: <20210915162955.333025-1-js...@redhat.com>
  [PULL 0/2] Python patches
  [PATCH v4 00/27] python: introduce Asynchronous QMP package

Hiya,

This series continues where the first AQMP series left off and adds a
synchronous 'legacy' wrapper around the new AQMP interface, then drops
it straight into iotests to prove that AQMP is functional and totally
cool and fine.

In the event that a regression happens and I am not physically proximate
to inflict damage upon, one may set the QEMU_PYTHON_LEGACY_QMP variable
to any non-empty string as it pleases you to engage the QMP machinery
you are used to.

I'd like to try and get this committed early in the 6.2 development
cycle to give ample time to smooth over any possible regressions.
I've tested it locally and via gitlab CI and "worksforme".

John Snow (15):
  python/aqmp: add greeting property to QMPClient
  python/aqmp: add .empty() method to EventListener
  python/aqmp: Return cleared events from EventListener.clear()
  python/qmp: clear events on get_events() call
  python/qmp: add send_fd_scm directly to QEMUMonitorProtocol
  python, iotests: remove socket_scm_helper
  python/aqmp: add send_fd_scm
  python/aqmp: Create MessageModel and StandaloneModel classes
  python/machine: remove has_quit argument
  python/machine: Add support for AQMP backend
  python/aqmp: Create sync QMP wrapper for iotests
  iotests: Disable AQMP logging under non-debug modes
  iotests: Accommodate async QMP Exception classes
  python/aqmp: Remove scary message
  python, iotests: replace qmp with aqmp

 tests/qemu-iotests/socket_scm_helper.c| 136 -
 python/qemu/aqmp/__init__.py  |  14 ---
 python/qemu/aqmp/events.py|  15 ++-
 python/qemu/aqmp/legacy.py| 131 
 python/qemu/aqmp/models.py|  67 ---
 python/qemu/aqmp/qmp_client.py|  22 
 python/qemu/machine/machine.py| 139 +-
 python/qemu/machine/qtest.py  |   2 -
 python/qemu/qmp/__init__.py   |  25 ++--
 python/qemu/qmp/qmp_shell.py  |   1 -
 scripts/simplebench/bench_block_job.py|   3 +-
 tests/Makefile.include|   1 -
 tests/meson.build |   4 -
 tests/qemu-iotests/040|   7 +-
 tests/qemu-iotests/218|   2 +-
 tests/qemu-iotests/255|   2 +-
 tests/qemu-iotests/iotests.py |   5 +-
 tests/qemu-iotests/meson.build|   5 -
 tests/qemu-iotests/testenv.py |   8 +-
 tests/qemu-iotests/tests/mirror-top-perms |   6 +-
 20 files changed, 321 insertions(+), 274 deletions(-)
 delete mode 100644 tests/qemu-iotests/socket_scm_helper.c
 create mode 100644 python/qemu/aqmp/legacy.py
 delete mode 100644 tests/qemu-iotests/meson.build

-- 
2.31.1





[PATCH v3 3/9] hw/nvram: Introduce Xilinx ZynqMP eFuse device

2021-09-16 Thread Tong Ho
This implements the Xilinx ZynqMP eFuse, an one-time
field-programmable non-volatile storage device.  There is
only one such device in the Xilinx ZynqMP product family.

Co-authored-by: Edgar E. Iglesias 
Co-authored-by: Sai Pavan Boddu 

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Tong Ho 
---
 hw/nvram/Kconfig |   4 +
 hw/nvram/meson.build |   2 +
 hw/nvram/xlnx-zynqmp-efuse.c | 855 +++
 include/hw/nvram/xlnx-zynqmp-efuse.h |  44 ++
 4 files changed, 905 insertions(+)
 create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c
 create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h

diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
index 6c2bb5afe3..3059c5dae0 100644
--- a/hw/nvram/Kconfig
+++ b/hw/nvram/Kconfig
@@ -26,3 +26,7 @@ config XLNX_EFUSE
 config XLNX_EFUSE_VERSAL
 bool
 select XLNX_EFUSE
+
+config XLNX_EFUSE_ZYNQMP
+bool
+select XLNX_EFUSE
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
index 62352ad8ec..6dc54d9873 100644
--- a/hw/nvram/meson.build
+++ b/hw/nvram/meson.build
@@ -14,5 +14,7 @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: 
files('xlnx-efuse.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files(
'xlnx-versal-efuse-cache.c',
'xlnx-versal-efuse-ctrl.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files(
+   'xlnx-zynqmp-efuse.c'))
 
 specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
new file mode 100644
index 00..1f87dbf988
--- /dev/null
+++ b/hw/nvram/xlnx-zynqmp-efuse.c
@@ -0,0 +1,855 @@
+/*
+ * QEMU model of the ZynqMP eFuse
+ *
+ * Copyright (c) 2015 Xilinx Inc.
+ *
+ * Written by Edgar E. Iglesias 
+ *
+ * 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 "hw/nvram/xlnx-zynqmp-efuse.h"
+
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+
+#ifndef ZYNQMP_EFUSE_ERR_DEBUG
+#define ZYNQMP_EFUSE_ERR_DEBUG 0
+#endif
+
+REG32(WR_LOCK, 0x0)
+FIELD(WR_LOCK, LOCK, 0, 16)
+REG32(CFG, 0x4)
+FIELD(CFG, SLVERR_ENABLE, 5, 1)
+FIELD(CFG, MARGIN_RD, 2, 2)
+FIELD(CFG, PGM_EN, 1, 1)
+FIELD(CFG, EFUSE_CLK_SEL, 0, 1)
+REG32(STATUS, 0x8)
+FIELD(STATUS, AES_CRC_PASS, 7, 1)
+FIELD(STATUS, AES_CRC_DONE, 6, 1)
+FIELD(STATUS, CACHE_DONE, 5, 1)
+FIELD(STATUS, CACHE_LOAD, 4, 1)
+FIELD(STATUS, EFUSE_3_TBIT, 2, 1)
+FIELD(STATUS, EFUSE_2_TBIT, 1, 1)
+FIELD(STATUS, EFUSE_0_TBIT, 0, 1)
+REG32(EFUSE_PGM_ADDR, 0xc)
+FIELD(EFUSE_PGM_ADDR, EFUSE, 11, 2)
+FIELD(EFUSE_PGM_ADDR, ROW, 5, 6)
+FIELD(EFUSE_PGM_ADDR, COLUMN, 0, 5)
+REG32(EFUSE_RD_ADDR, 0x10)
+FIELD(EFUSE_RD_ADDR, EFUSE, 11, 2)
+FIELD(EFUSE_RD_ADDR, ROW, 5, 6)
+REG32(EFUSE_RD_DATA, 0x14)
+REG32(TPGM, 0x18)
+FIELD(TPGM, VALUE, 0, 16)
+REG32(TRD, 0x1c)
+FIELD(TRD, VALUE, 0, 8)
+REG32(TSU_H_PS, 0x20)
+FIELD(TSU_H_PS, VALUE, 0, 8)
+REG32(TSU_H_PS_CS, 0x24)
+FIELD(TSU_H_PS_CS, VALUE, 0, 8)
+REG32(TSU_H_CS, 0x2c)
+FIELD(TSU_H_CS, VALUE, 0, 4)
+REG32(EFUSE_ISR, 0x30)
+FIELD(EFUSE_ISR, APB_SLVERR, 31, 1)
+FIELD(EFUSE_ISR, CACHE_ERROR, 4, 1)
+FIELD(EFUSE_ISR, RD_ERROR, 3, 1)
+FIELD(EFUSE_ISR, RD_DONE, 2, 1)
+FIELD(EFUSE_ISR, PGM_ERROR, 1, 1)
+FIELD(EFUSE_ISR, PGM_DONE, 0, 1)
+REG32(EFUSE_IMR, 0x34)
+FIELD(EFUSE_IMR, APB_SLVERR, 31, 1)
+FIELD(EFUSE_IMR, CACHE_ERROR, 4, 1)
+FIELD(EFUSE_IMR, RD_ERROR, 3, 1)
+FIELD(EFUSE_IMR, RD_DONE, 2, 1)
+FIELD(EFUSE_IMR, PGM_ERROR, 1, 1)
+FIELD(EFUSE_IMR, PGM_DONE, 0, 1)
+REG32(EFUSE_IER, 0x38)
+FIELD(EFUSE_IER, APB_SLVERR, 31, 1)
+FIELD(EFUSE_IER, CACHE_ERROR, 4, 1

[PATCH v3 1/9] hw/nvram: Introduce Xilinx eFuse QOM

2021-09-16 Thread Tong Ho
This introduces the QOM for Xilinx eFuse, an one-time
field-programmable storage bit array.

The actual mmio interface to the array varies by device
families and will be provided in different change-sets.

Co-authored-by: Edgar E. Iglesias 
Co-authored-by: Sai Pavan Boddu 

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Tong Ho 
---
 hw/nvram/Kconfig  |   7 +
 hw/nvram/meson.build  |   2 +
 hw/nvram/xlnx-efuse-crc.c | 119 +++
 hw/nvram/xlnx-efuse.c | 280 ++
 include/hw/nvram/xlnx-efuse.h | 132 
 5 files changed, 540 insertions(+)
 create mode 100644 hw/nvram/xlnx-efuse-crc.c
 create mode 100644 hw/nvram/xlnx-efuse.c
 create mode 100644 include/hw/nvram/xlnx-efuse.h

diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
index e872fcb194..252251f366 100644
--- a/hw/nvram/Kconfig
+++ b/hw/nvram/Kconfig
@@ -15,3 +15,10 @@ config NMC93XX_EEPROM
 
 config CHRP_NVRAM
 bool
+
+config XLNX_EFUSE_CRC
+bool
+
+config XLNX_EFUSE
+bool
+select XLNX_EFUSE_CRC
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
index fd2951a860..623c94efff 100644
--- a/hw/nvram/meson.build
+++ b/hw/nvram/meson.build
@@ -9,5 +9,7 @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: 
files('eeprom_at24c.c'))
 softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c'))
 softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c'))
 softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: 
files('xlnx-efuse-crc.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c'))
 
 specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
diff --git a/hw/nvram/xlnx-efuse-crc.c b/hw/nvram/xlnx-efuse-crc.c
new file mode 100644
index 00..5a5cc13f39
--- /dev/null
+++ b/hw/nvram/xlnx-efuse-crc.c
@@ -0,0 +1,119 @@
+/*
+ * Xilinx eFuse/bbram CRC calculator
+ *
+ * Copyright (c) 2021 Xilinx Inc.
+ *
+ * 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 "hw/nvram/xlnx-efuse.h"
+
+static uint32_t xlnx_efuse_u37_crc(uint32_t prev_crc, uint32_t data,
+   uint32_t addr)
+{
+/* A table for 7-bit slicing */
+static const uint32_t crc_tab[128] = {
+0x, 0xe13b70f7, 0xc79a971f, 0x26a1e7e8,
+0x8ad958cf, 0x6be22838, 0x4d43cfd0, 0xac78bf27,
+0x105ec76f, 0xf165b798, 0xd7c45070, 0x36ff2087,
+0x9a879fa0, 0x7bbcef57, 0x5d1d08bf, 0xbc267848,
+0x20bd8ede, 0xc186fe29, 0xe72719c1, 0x061c6936,
+0xaa64d611, 0x4b5fa6e6, 0x6dfe410e, 0x8cc531f9,
+0x30e349b1, 0xd1d83946, 0xf779deae, 0x1642ae59,
+0xba3a117e, 0x5b016189, 0x7da08661, 0x9c9bf696,
+0x417b1dbc, 0xa0406d4b, 0x86e18aa3, 0x67dafa54,
+0xcba24573, 0x2a993584, 0x0c38d26c, 0xed03a29b,
+0x5125dad3, 0xb01eaa24, 0x96bf4dcc, 0x77843d3b,
+0xdbfc821c, 0x3ac7f2eb, 0x1c661503, 0xfd5d65f4,
+0x61c69362, 0x80fde395, 0xa65c047d, 0x4767748a,
+0xeb1fcbad, 0x0a24bb5a, 0x2c855cb2, 0xcdbe2c45,
+0x7198540d, 0x90a324fa, 0xb602c312, 0x5739b3e5,
+0xfb410cc2, 0x1a7a7c35, 0x3cdb9bdd, 0xdde0eb2a,
+0x82f63b78, 0x63cd4b8f, 0x456cac67, 0xa457dc90,
+0x082f63b7, 0xe9141340, 0xcfb5f4a8, 0x2e8e845f,
+0x92a8fc17, 0x73938ce0, 0x55326b08, 0xb4091bff,
+0x1871a4d8, 0xf94ad42f, 0xdfeb33c7, 0x3ed04330,
+0xa24bb5a6, 0x4370c551, 0x65d122b9, 0x84ea524e,
+0x2892ed69, 0xc9a99d9e, 0xef087a76, 0x0e330a81,
+0xb21572c9, 0x532e023e, 0x758fe5d6, 0x94b49521,
+0x38cc2a06, 0xd9f75af1, 0xff56bd19, 0x1e6dcdee,
+0xc38d26c4, 0x22b65633, 0x0417b1db, 0xe52cc12c,
+0x49547e0b, 0xa86f0efc, 0x8ecee914, 0x6ff599e3,
+0xd3d3e1ab, 0x32e8915c, 0x144976b4, 0xf5720643,
+0x590ab964, 0xb831c993, 0x9e902e7b, 0

[PATCH v3 6/9] hw/arm: xlnx-versal-virt: Add Xilinx eFUSE device

2021-09-16 Thread Tong Ho
Connect the support for Versal eFUSE one-time field-programmable
bit array.

The command argument:
  -drive if=pflash,index=1,...
Can be used to optionally connect the bit array to a
backend storage, such that field-programmed values
in one invocation can be made available to next
invocation.

The backend storage must be a seekable binary file, and
its size must be 3072 bytes or larger. A file with all
binary 0's is a 'blank'.

Signed-off-by: Tong Ho 
---
 hw/arm/Kconfig   |  1 +
 hw/arm/xlnx-versal-virt.c| 52 
 hw/arm/xlnx-versal.c | 39 +++
 include/hw/arm/xlnx-versal.h | 10 +++
 4 files changed, 102 insertions(+)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index f92fb9e568..9edc05782d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -382,6 +382,7 @@ config XLNX_VERSAL
 select XLNX_ZYNQMP
 select OR_IRQ
 select XLNX_BBRAM
+select XLNX_EFUSE_VERSAL
 
 config NPCM7XX
 bool
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index e1c5ead475..d2f55e29b6 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -376,6 +376,41 @@ static void fdt_add_bbram_node(VersalVirt *s)
 g_free(name);
 }
 
+static void fdt_add_efuse_ctrl_node(VersalVirt *s)
+{
+const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CTRL;
+const char interrupt_names[] = "pmc_efuse";
+char *name = g_strdup_printf("/pmc_efuse@%x", MM_PMC_EFUSE_CTRL);
+
+qemu_fdt_add_subnode(s->fdt, name);
+
+qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+   GIC_FDT_IRQ_TYPE_SPI, VERSAL_EFUSE_IRQ,
+   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+qemu_fdt_setprop(s->fdt, name, "interrupt-names",
+ interrupt_names, sizeof(interrupt_names));
+qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, MM_PMC_EFUSE_CTRL,
+ 2, MM_PMC_EFUSE_CTRL_SIZE);
+qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
+g_free(name);
+}
+
+static void fdt_add_efuse_cache_node(VersalVirt *s)
+{
+const char compat[] = TYPE_XLNX_VERSAL_EFUSE_CACHE;
+char *name = g_strdup_printf("/xlnx_pmc_efuse_cache@%x",
+ MM_PMC_EFUSE_CACHE);
+
+qemu_fdt_add_subnode(s->fdt, name);
+
+qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, MM_PMC_EFUSE_CACHE,
+ 2, MM_PMC_EFUSE_CACHE_SIZE);
+qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
+g_free(name);
+}
+
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
 Error *err = NULL;
@@ -542,6 +577,18 @@ static void bbram_attach_drive(XlnxBBRam *dev)
 }
 }
 
+static void efuse_attach_drive(XlnxEFuse *dev)
+{
+DriveInfo *dinfo;
+BlockBackend *blk;
+
+dinfo = drive_get_by_index(IF_PFLASH, 1);
+blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+if (blk) {
+qdev_prop_set_drive(DEVICE(dev), "drive", blk);
+}
+}
+
 static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
 {
 BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
@@ -603,6 +650,8 @@ static void versal_virt_init(MachineState *machine)
 fdt_add_sd_nodes(s);
 fdt_add_rtc_node(s);
 fdt_add_bbram_node(s);
+fdt_add_efuse_ctrl_node(s);
+fdt_add_efuse_cache_node(s);
 fdt_add_cpu_nodes(s, psci_conduit);
 fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz);
 fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz);
@@ -615,6 +664,9 @@ static void versal_virt_init(MachineState *machine)
 /* Attach bbram backend, if given */
 bbram_attach_drive(&s->soc.pmc.bbram);
 
+/* Attach efuse backend, if given */
+efuse_attach_drive(&s->soc.pmc.efuse);
+
 /* Plugin SD cards.  */
 for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
 sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD));
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 23451ae012..b2705b6925 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -331,6 +331,44 @@ static void versal_create_bbram(Versal *s, qemu_irq *pic)
 sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]);
 }
 
+static void versal_realize_efuse_part(Versal *s, Object *dev, hwaddr base)
+{
+SysBusDevice *part = SYS_BUS_DEVICE(dev);
+
+object_property_set_link(OBJECT(part), "efuse",
+ OBJECT(&s->pmc.efuse), &error_abort);
+
+sysbus_realize(part, &error_abort);
+memory_region_add_subregion(&s->mr_ps, base,
+sysbus_mmio_get_region(part, 0));
+}
+
+static void versal_create_efuse(Versal *s, qemu_irq *pic)
+{
+Object *bits = OBJECT(&s->pmc.efuse);
+Object *ctrl = OBJECT(&s->pmc.efuse_ctrl);
+Object *cache = OBJECT(&s->pmc.efuse_cache);
+
+object_initialize_child(OBJECT(s), "efuse-ctrl

[PATCH v3 7/9] hw/arm: xlnx-zcu102: Add Xilinx BBRAM device

2021-09-16 Thread Tong Ho
Connect the support for Xilinx ZynqMP Battery-Backed RAM (BBRAM)

The command argument:
  -drive if=pflash,index=2,...
Can be used to optionally connect the bbram to a backend
storage, such that field-programmed values in one
invocation can be made available to next invocation.

The backend storage must be a seekable binary file, and
its size must be 36 bytes or larger. A file with all
binary 0's is a 'blank'.

Signed-off-by: Tong Ho 
---
 hw/Kconfig   |  1 +
 hw/arm/xlnx-zcu102.c | 15 +++
 hw/arm/xlnx-zynqmp.c | 20 
 include/hw/arm/xlnx-zynqmp.h |  2 ++
 4 files changed, 38 insertions(+)

diff --git a/hw/Kconfig b/hw/Kconfig
index 8cb7664d70..b6fb6a4507 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -81,3 +81,4 @@ config XLNX_ZYNQMP
 select REGISTER
 select CAN_BUS
 select PTIMER
+select XLNX_BBRAM
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
index 6c6cb02e86..b247c5779b 100644
--- a/hw/arm/xlnx-zcu102.c
+++ b/hw/arm/xlnx-zcu102.c
@@ -98,6 +98,18 @@ static void zcu102_modify_dtb(const struct arm_boot_info 
*binfo, void *fdt)
 }
 }
 
+static void bbram_attach_drive(XlnxBBRam *dev)
+{
+DriveInfo *dinfo;
+BlockBackend *blk;
+
+dinfo = drive_get_by_index(IF_PFLASH, 2);
+blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+if (blk) {
+qdev_prop_set_drive(DEVICE(dev), "drive", blk);
+}
+}
+
 static void xlnx_zcu102_init(MachineState *machine)
 {
 XlnxZCU102 *s = ZCU102_MACHINE(machine);
@@ -136,6 +148,9 @@ static void xlnx_zcu102_init(MachineState *machine)
 
 qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
 
+/* Attach bbram backend, if given */
+bbram_attach_drive(&s->soc.bbram);
+
 /* Create and plug in the SD cards */
 for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
 BusState *bus;
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 4e5a471e30..1e8e2ddcc2 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -66,6 +66,9 @@
 #define RTC_ADDR0xffa6
 #define RTC_IRQ 26
 
+#define BBRAM_ADDR  0xffcd
+#define BBRAM_IRQ   11
+
 #define SDHCI_CAPABILITIES  0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
 
 static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
@@ -226,6 +229,22 @@ static void xlnx_zynqmp_create_rpu(MachineState *ms, 
XlnxZynqMPState *s,
 qdev_realize(DEVICE(&s->rpu_cluster), NULL, &error_fatal);
 }
 
+static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, qemu_irq *gic)
+{
+SysBusDevice *sbd;
+
+object_initialize_child_with_props(OBJECT(s), "bbram", &s->bbram,
+   sizeof(s->bbram), TYPE_XLNX_BBRAM,
+   &error_fatal,
+   "crc-zpads", "1",
+   NULL);
+sbd = SYS_BUS_DEVICE(&s->bbram);
+
+sysbus_realize(sbd, &error_fatal);
+sysbus_mmio_map(sbd, 0, BBRAM_ADDR);
+sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]);
+}
+
 static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
 {
 static const struct UnimpInfo {
@@ -626,6 +645,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, RTC_ADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
 
+xlnx_zynqmp_create_bbram(s, gic_spi);
 xlnx_zynqmp_create_unimp_mmio(s);
 
 for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index c84fe15996..067e8a5238 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -36,6 +36,7 @@
 #include "qom/object.h"
 #include "net/can_emu.h"
 #include "hw/dma/xlnx_csu_dma.h"
+#include "hw/nvram/xlnx-bbram.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
 OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
@@ -100,6 +101,7 @@ struct XlnxZynqMPState {
 
 MemoryRegion *ddr_ram;
 MemoryRegion ddr_ram_low, ddr_ram_high;
+XlnxBBRam bbram;
 
 MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS];
 
-- 
2.25.1




[PATCH v3 9/9] docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage

2021-09-16 Thread Tong Ho
Add BBRAM and eFUSE usage to the Xilinx Versal Virt board
document.

Signed-off-by: Tong Ho 
---
 docs/system/arm/xlnx-versal-virt.rst | 49 
 1 file changed, 49 insertions(+)

diff --git a/docs/system/arm/xlnx-versal-virt.rst 
b/docs/system/arm/xlnx-versal-virt.rst
index 27f73500d9..92ad10d2da 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -32,6 +32,8 @@ Implemented devices:
 - OCM (256KB of On Chip Memory)
 - XRAM (4MB of on chip Accelerator RAM)
 - DDR memory
+- BBRAM (36 bytes of Battery-backed RAM)
+- eFUSE (3072 bytes of one-time field-programmable bit array)
 
 QEMU does not yet model any other devices, including the PL and the AI Engine.
 
@@ -175,3 +177,50 @@ Run the following at the U-Boot prompt:
   fdt set /chosen/dom0 reg <0x 0x4000 0x0 0x0310>
   booti 3000 - 2000
 
+BBRAM File Backend
+""
+BBRAM can have an optional file backend, which must be a seekable
+binary file with a size of 36 bytes or larger. A file with all
+binary 0s is a 'blank'.
+
+To add a file-backend for the BBRAM:
+
+.. code-block:: bash
+
+  -drive if=pflash,index=0,file=versal-bbram.bin,format=raw
+
+To use a different index value, N, from default of 0, add:
+
+.. code-block:: bash
+
+  -global xlnx,bbram-ctrl.drive-index=N
+
+eFUSE File Backend
+""
+eFUSE can have an optional file backend, which must be a seekable
+binary file with a size of 3072 bytes or larger. A file with all
+binary 0s is a 'blank'.
+
+To add a file-backend for the eFUSE:
+
+.. code-block:: bash
+
+  -drive if=pflash,index=1,file=versal-efuse.bin,format=raw
+
+To use a different index value, N, from default of 1, add:
+
+.. code-block:: bash
+
+  -global xlnx,efuse.drive-index=N
+
+.. warning::
+  In actual physical Versal, BBRAM and eFUSE contain sensitive data.
+  The QEMU device models do **not** encrypt nor obfuscate any data
+  when holding them in models' memory or when writing them to their
+  file backends.
+
+  Thus, a file backend should be used with caution, and 'format=luks'
+  is highly recommended (albeit with usage complexity).
+
+  Better yet, do not use actual product data when running guest image
+  on this Xilinx Versal Virt board.
-- 
2.25.1




[PATCH v3 0/9] hw/nvram: hw/arm: Introduce Xilinx eFUSE and BBRAM

2021-09-16 Thread Tong Ho
This series implements the Xilinx eFUSE and BBRAM devices for
the Versal and ZynqMP product families.

Furthermore, both new devices are connected to the xlnx-versal-virt
board and the xlnx-zcu102 board.

See changes in docs/system/arm/xlnx-versal-virt.rst for detail.

---

Changelogs:

v2->v3:
* Move drive-backend attaching to board models
* Use OBJECT_DECLARE_SIMPLE_TYPE instead of OBJECT_CHECK
* Use reg_array->mem directly instead of an extra mr-container
* Add doc comments for .h file API
* Remove "qemu/osdep.h" from .h files
* Remove ad-hoc endianess detection
* Remove error_abort from device models
* Remove empty vmstate and mininum_version_id_old
* Remove unused #define macros
* Remove unavailable references from comments
* Kconfig & meson.build:
  - Add CONFIG_XLNX_EFUSE_CRC in patch 1
  - Select bbram and efuse devices from boards' Kconfig
  - Remove 'if' from meson.build
* Fix spelling and wording in comments and docs

v1->v2:
* Move doc change from 1st to last of this series
* Remove outdated comment of 'autogenerated by xregqemu.py'
  from all affected files.

---

Tong Ho (9):
  hw/nvram: Introduce Xilinx eFuse QOM
  hw/nvram: Introduce Xilinx Versal eFuse device
  hw/nvram: Introduce Xilinx ZynqMP eFuse device
  hw/nvram: Introduce Xilinx battery-backed ram
  hw/arm: xlnx-versal-virt: Add Xilinx BBRAM device
  hw/arm: xlnx-versal-virt: Add Xilinx eFUSE device
  hw/arm: xlnx-zcu102: Add Xilinx BBRAM device
  hw/arm: xlnx-zcu102: Add Xilinx eFUSE device
  docs/system/arm: xlnx-versal-virt: BBRAM and eFUSE Usage

 docs/system/arm/xlnx-versal-virt.rst |  49 ++
 hw/Kconfig   |   2 +
 hw/arm/Kconfig   |   2 +
 hw/arm/xlnx-versal-virt.c|  88 +++
 hw/arm/xlnx-versal.c |  57 ++
 hw/arm/xlnx-zcu102.c |  30 +
 hw/arm/xlnx-zynqmp.c |  49 ++
 hw/nvram/Kconfig |  19 +
 hw/nvram/meson.build |   8 +
 hw/nvram/xlnx-bbram.c| 545 +
 hw/nvram/xlnx-efuse-crc.c| 119 
 hw/nvram/xlnx-efuse.c| 280 +
 hw/nvram/xlnx-versal-efuse-cache.c   | 114 
 hw/nvram/xlnx-versal-efuse-ctrl.c| 783 
 hw/nvram/xlnx-zynqmp-efuse.c | 855 +++
 include/hw/arm/xlnx-versal.h |  15 +
 include/hw/arm/xlnx-zynqmp.h |   5 +
 include/hw/nvram/xlnx-bbram.h|  54 ++
 include/hw/nvram/xlnx-efuse.h| 132 +
 include/hw/nvram/xlnx-versal-efuse.h |  68 +++
 include/hw/nvram/xlnx-zynqmp-efuse.h |  44 ++
 21 files changed, 3318 insertions(+)
 create mode 100644 hw/nvram/xlnx-bbram.c
 create mode 100644 hw/nvram/xlnx-efuse-crc.c
 create mode 100644 hw/nvram/xlnx-efuse.c
 create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c
 create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c
 create mode 100644 hw/nvram/xlnx-zynqmp-efuse.c
 create mode 100644 include/hw/nvram/xlnx-bbram.h
 create mode 100644 include/hw/nvram/xlnx-efuse.h
 create mode 100644 include/hw/nvram/xlnx-versal-efuse.h
 create mode 100644 include/hw/nvram/xlnx-zynqmp-efuse.h

-- 
2.25.1




[PATCH v3 8/9] hw/arm: xlnx-zcu102: Add Xilinx eFUSE device

2021-09-16 Thread Tong Ho
Connect the support for ZynqMP eFUSE one-time field-programmable
bit array.

The command argument:
  -drive if=pflash,index=3,...
Can be used to optionally connect the bit array to a
backend storage, such that field-programmed values
in one invocation can be made available to next
invocation.

The backend storage must be a seekable binary file, and
its size must be 768 bytes or larger. A file with all
binary 0's is a 'blank'.

Signed-off-by: Tong Ho 
---
 hw/Kconfig   |  1 +
 hw/arm/xlnx-zcu102.c | 15 +++
 hw/arm/xlnx-zynqmp.c | 29 +
 include/hw/arm/xlnx-zynqmp.h |  3 +++
 4 files changed, 48 insertions(+)

diff --git a/hw/Kconfig b/hw/Kconfig
index b6fb6a4507..ad20cce0a9 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -82,3 +82,4 @@ config XLNX_ZYNQMP
 select CAN_BUS
 select PTIMER
 select XLNX_BBRAM
+select XLNX_EFUSE_ZYNQMP
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
index b247c5779b..3dc2b5e8ca 100644
--- a/hw/arm/xlnx-zcu102.c
+++ b/hw/arm/xlnx-zcu102.c
@@ -110,6 +110,18 @@ static void bbram_attach_drive(XlnxBBRam *dev)
 }
 }
 
+static void efuse_attach_drive(XlnxEFuse *dev)
+{
+DriveInfo *dinfo;
+BlockBackend *blk;
+
+dinfo = drive_get_by_index(IF_PFLASH, 3);
+blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+if (blk) {
+qdev_prop_set_drive(DEVICE(dev), "drive", blk);
+}
+}
+
 static void xlnx_zcu102_init(MachineState *machine)
 {
 XlnxZCU102 *s = ZCU102_MACHINE(machine);
@@ -151,6 +163,9 @@ static void xlnx_zcu102_init(MachineState *machine)
 /* Attach bbram backend, if given */
 bbram_attach_drive(&s->soc.bbram);
 
+/* Attach efuse backend, if given */
+efuse_attach_drive(&s->soc.efuse);
+
 /* Create and plug in the SD cards */
 for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
 BusState *bus;
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 1e8e2ddcc2..1c52a575aa 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -69,6 +69,9 @@
 #define BBRAM_ADDR  0xffcd
 #define BBRAM_IRQ   11
 
+#define EFUSE_ADDR  0xffcc
+#define EFUSE_IRQ   87
+
 #define SDHCI_CAPABILITIES  0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
 
 static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
@@ -245,6 +248,31 @@ static void xlnx_zynqmp_create_bbram(XlnxZynqMPState *s, 
qemu_irq *gic)
 sysbus_connect_irq(sbd, 0, gic[BBRAM_IRQ]);
 }
 
+static void xlnx_zynqmp_create_efuse(XlnxZynqMPState *s, qemu_irq *gic)
+{
+Object *bits = OBJECT(&s->efuse);
+Object *ctrl = OBJECT(&s->efuse_ctrl);
+SysBusDevice *sbd;
+
+object_initialize_child(OBJECT(s), "efuse-ctrl", &s->efuse_ctrl,
+TYPE_XLNX_ZYNQMP_EFUSE);
+
+object_initialize_child_with_props(ctrl, "xlnx-efuse@0", bits,
+   sizeof(s->efuse),
+   TYPE_XLNX_EFUSE, &error_abort,
+   "efuse-nr", "3",
+   "efuse-size", "2048",
+   NULL);
+
+qdev_realize(DEVICE(bits), NULL, &error_abort);
+object_property_set_link(ctrl, "efuse", bits, &error_abort);
+
+sbd = SYS_BUS_DEVICE(ctrl);
+sysbus_realize(sbd, &error_abort);
+sysbus_mmio_map(sbd, 0, EFUSE_ADDR);
+sysbus_connect_irq(sbd, 0, gic[EFUSE_IRQ]);
+}
+
 static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
 {
 static const struct UnimpInfo {
@@ -646,6 +674,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0, gic_spi[RTC_IRQ]);
 
 xlnx_zynqmp_create_bbram(s, gic_spi);
+xlnx_zynqmp_create_efuse(s, gic_spi);
 xlnx_zynqmp_create_unimp_mmio(s);
 
 for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 067e8a5238..062e637fe4 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -37,6 +37,7 @@
 #include "net/can_emu.h"
 #include "hw/dma/xlnx_csu_dma.h"
 #include "hw/nvram/xlnx-bbram.h"
+#include "hw/nvram/xlnx-zynqmp-efuse.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
 OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
@@ -102,6 +103,8 @@ struct XlnxZynqMPState {
 MemoryRegion *ddr_ram;
 MemoryRegion ddr_ram_low, ddr_ram_high;
 XlnxBBRam bbram;
+XlnxEFuse efuse;
+XlnxZynqMPEFuse efuse_ctrl;
 
 MemoryRegion mr_unimp[XLNX_ZYNQMP_NUM_UNIMP_AREAS];
 
-- 
2.25.1




[PATCH v3 4/9] hw/nvram: Introduce Xilinx battery-backed ram

2021-09-16 Thread Tong Ho
This device is present in Versal and ZynqMP product
families to store a 256-bit encryption key.

Co-authored-by: Edgar E. Iglesias 
Co-authored-by: Sai Pavan Boddu 

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Tong Ho 
---
 hw/nvram/Kconfig  |   4 +
 hw/nvram/meson.build  |   1 +
 hw/nvram/xlnx-bbram.c | 545 ++
 include/hw/nvram/xlnx-bbram.h |  54 
 4 files changed, 604 insertions(+)
 create mode 100644 hw/nvram/xlnx-bbram.c
 create mode 100644 include/hw/nvram/xlnx-bbram.h

diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
index 3059c5dae0..24cfc18f8b 100644
--- a/hw/nvram/Kconfig
+++ b/hw/nvram/Kconfig
@@ -30,3 +30,7 @@ config XLNX_EFUSE_VERSAL
 config XLNX_EFUSE_ZYNQMP
 bool
 select XLNX_EFUSE
+
+config XLNX_BBRAM
+bool
+select XLNX_EFUSE_CRC
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
index 6dc54d9873..202a5466e6 100644
--- a/hw/nvram/meson.build
+++ b/hw/nvram/meson.build
@@ -16,5 +16,6 @@ softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: 
files(
'xlnx-versal-efuse-ctrl.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files(
'xlnx-zynqmp-efuse.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_BBRAM', if_true: files('xlnx-bbram.c'))
 
 specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
new file mode 100644
index 00..b70828e5bf
--- /dev/null
+++ b/hw/nvram/xlnx-bbram.c
@@ -0,0 +1,545 @@
+/*
+ * QEMU model of the Xilinx BBRAM Battery Backed RAM
+ *
+ * Copyright (c) 2014-2021 Xilinx Inc.
+ *
+ * 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 "hw/nvram/xlnx-bbram.h"
+
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "sysemu/blockdev.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/nvram/xlnx-efuse.h"
+
+#ifndef XLNX_BBRAM_ERR_DEBUG
+#define XLNX_BBRAM_ERR_DEBUG 0
+#endif
+
+REG32(BBRAM_STATUS, 0x0)
+FIELD(BBRAM_STATUS, AES_CRC_PASS, 9, 1)
+FIELD(BBRAM_STATUS, AES_CRC_DONE, 8, 1)
+FIELD(BBRAM_STATUS, BBRAM_ZEROIZED, 4, 1)
+FIELD(BBRAM_STATUS, PGM_MODE, 0, 1)
+REG32(BBRAM_CTRL, 0x4)
+FIELD(BBRAM_CTRL, ZEROIZE, 0, 1)
+REG32(PGM_MODE, 0x8)
+REG32(BBRAM_AES_CRC, 0xc)
+REG32(BBRAM_0, 0x10)
+REG32(BBRAM_1, 0x14)
+REG32(BBRAM_2, 0x18)
+REG32(BBRAM_3, 0x1c)
+REG32(BBRAM_4, 0x20)
+REG32(BBRAM_5, 0x24)
+REG32(BBRAM_6, 0x28)
+REG32(BBRAM_7, 0x2c)
+REG32(BBRAM_8, 0x30)
+REG32(BBRAM_SLVERR, 0x34)
+FIELD(BBRAM_SLVERR, ENABLE, 0, 1)
+REG32(BBRAM_ISR, 0x38)
+FIELD(BBRAM_ISR, APB_SLVERR, 0, 1)
+REG32(BBRAM_IMR, 0x3c)
+FIELD(BBRAM_IMR, APB_SLVERR, 0, 1)
+REG32(BBRAM_IER, 0x40)
+FIELD(BBRAM_IER, APB_SLVERR, 0, 1)
+REG32(BBRAM_IDR, 0x44)
+FIELD(BBRAM_IDR, APB_SLVERR, 0, 1)
+REG32(BBRAM_MSW_LOCK, 0x4c)
+FIELD(BBRAM_MSW_LOCK, VAL, 0, 1)
+
+#define R_MAX (R_BBRAM_MSW_LOCK + 1)
+
+#define RAM_MAX (A_BBRAM_8 + 4 - A_BBRAM_0)
+
+#define BBRAM_PGM_MAGIC 0x757bdf0d
+
+QEMU_BUILD_BUG_ON(R_MAX != ARRAY_SIZE(((XlnxBBRam *)0)->regs));
+
+static bool bbram_msw_locked(XlnxBBRam *s)
+{
+return ARRAY_FIELD_EX32(s->regs, BBRAM_MSW_LOCK, VAL) != 0;
+}
+
+static bool bbram_pgm_enabled(XlnxBBRam *s)
+{
+return ARRAY_FIELD_EX32(s->regs, BBRAM_STATUS, PGM_MODE) != 0;
+}
+
+static void bbram_bdrv_error(XlnxBBRam *s, int rc, gchar *detail)
+{
+Error *errp;
+
+error_setg_errno(&errp, -rc, "%s: BBRAM backstore %s failed.",
+ blk_name(s->blk), detail);
+error_report("%s", error_get_pretty(errp));
+error_free(errp);
+
+g_free(detail);
+}
+
+static void bbram_bdrv_read(XlnxBBRam *s, Error **errp)
+{
+uint32_t *ram = &s->regs[R_BBRAM_0];
+int nr = RAM_MAX;

[PATCH v3 2/9] hw/nvram: Introduce Xilinx Versal eFuse device

2021-09-16 Thread Tong Ho
This implements the Xilinx Versal eFuse, an one-time
field-programmable non-volatile storage device.  There is
only one such device in the Xilinx Versal product family.

This device has two separate mmio interfaces, a controller
and a flatten readback.

The controller provides interfaces for field-programming,
configuration, control, and status.

The flatten readback is a cache to provide a byte-accessible
read-only interface to efficiently read efuse array.

Co-authored-by: Edgar E. Iglesias 
Co-authored-by: Sai Pavan Boddu 

Signed-off-by: Edgar E. Iglesias 
Signed-off-by: Sai Pavan Boddu 
Signed-off-by: Tong Ho 
---
 hw/nvram/Kconfig |   4 +
 hw/nvram/meson.build |   3 +
 hw/nvram/xlnx-versal-efuse-cache.c   | 114 
 hw/nvram/xlnx-versal-efuse-ctrl.c| 783 +++
 include/hw/nvram/xlnx-versal-efuse.h |  68 +++
 5 files changed, 972 insertions(+)
 create mode 100644 hw/nvram/xlnx-versal-efuse-cache.c
 create mode 100644 hw/nvram/xlnx-versal-efuse-ctrl.c
 create mode 100644 include/hw/nvram/xlnx-versal-efuse.h

diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
index 252251f366..6c2bb5afe3 100644
--- a/hw/nvram/Kconfig
+++ b/hw/nvram/Kconfig
@@ -22,3 +22,7 @@ config XLNX_EFUSE_CRC
 config XLNX_EFUSE
 bool
 select XLNX_EFUSE_CRC
+
+config XLNX_EFUSE_VERSAL
+bool
+select XLNX_EFUSE
diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build
index 623c94efff..62352ad8ec 100644
--- a/hw/nvram/meson.build
+++ b/hw/nvram/meson.build
@@ -11,5 +11,8 @@ softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: 
files('npcm7xx_otp.c'))
 softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: 
files('xlnx-efuse-crc.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files(
+   'xlnx-versal-efuse-cache.c',
+   'xlnx-versal-efuse-ctrl.c'))
 
 specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c'))
diff --git a/hw/nvram/xlnx-versal-efuse-cache.c 
b/hw/nvram/xlnx-versal-efuse-cache.c
new file mode 100644
index 00..eaec64d785
--- /dev/null
+++ b/hw/nvram/xlnx-versal-efuse-cache.c
@@ -0,0 +1,114 @@
+/*
+ * QEMU model of the EFuse_Cache
+ *
+ * Copyright (c) 2017 Xilinx Inc.
+ *
+ * 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 "hw/nvram/xlnx-versal-efuse.h"
+
+#include "qemu/log.h"
+#include "hw/qdev-properties.h"
+
+#define MR_SIZE 0xC00
+
+static uint64_t efuse_cache_read(void *opaque, hwaddr addr, unsigned size)
+{
+XlnxVersalEFuseCache *s = XLNX_VERSAL_EFUSE_CACHE(opaque);
+unsigned int w0 = QEMU_ALIGN_DOWN(addr * 8, 32);
+unsigned int w1 = QEMU_ALIGN_DOWN((addr + size - 1) * 8, 32);
+
+uint64_t ret;
+
+assert(w0 == w1 || (w0 + 32) == w1);
+
+ret = xlnx_versal_efuse_read_row(s->efuse, w1, NULL);
+if (w0 < w1) {
+ret <<= 32;
+ret |= xlnx_versal_efuse_read_row(s->efuse, w0, NULL);
+}
+
+/* If 'addr' unaligned, the guest is always assumed to be little-endian. */
+addr &= 3;
+if (addr) {
+ret >>= 8 * addr;
+}
+
+return ret;
+}
+
+static void efuse_cache_write(void *opaque, hwaddr addr, uint64_t value,
+  unsigned size)
+{
+/* No Register Writes allowed */
+qemu_log_mask(LOG_GUEST_ERROR, "%s: efuse cache registers are read-only",
+  __func__);
+}
+
+static const MemoryRegionOps efuse_cache_ops = {
+.read = efuse_cache_read,
+.write = efuse_cache_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 1,
+.max_access_size = 4,
+},
+};
+
+static void efuse_cache_init(Object *obj)
+{
+XlnxVersalEFuseCache *s = XLNX_VERSAL_EFUSE_CACHE(obj);
+ 

[PATCH v3 5/9] hw/arm: xlnx-versal-virt: Add Xilinx BBRAM device

2021-09-16 Thread Tong Ho
Connect the support for Versal Battery-Backed RAM (BBRAM)

The command argument:
  -drive if=pflash,index=0,...
Can be used to optionally connect the bbram to a backend
storage, such that field-programmed values in one
invocation can be made available to next invocation.

The backend storage must be a seekable binary file, and
its size must be 36 bytes or larger. A file with all
binary 0's is a 'blank'.

Signed-off-by: Tong Ho 
---
 hw/arm/Kconfig   |  1 +
 hw/arm/xlnx-versal-virt.c| 36 
 hw/arm/xlnx-versal.c | 18 ++
 include/hw/arm/xlnx-versal.h |  5 +
 4 files changed, 60 insertions(+)

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 78fdd1b935..f92fb9e568 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -381,6 +381,7 @@ config XLNX_VERSAL
 select XLNX_ZDMA
 select XLNX_ZYNQMP
 select OR_IRQ
+select XLNX_BBRAM
 
 config NPCM7XX
 bool
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 5bca360dce..e1c5ead475 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -356,6 +356,26 @@ static void fdt_add_rtc_node(VersalVirt *s)
 g_free(name);
 }
 
+static void fdt_add_bbram_node(VersalVirt *s)
+{
+const char compat[] = TYPE_XLNX_BBRAM;
+const char interrupt_names[] = "bbram-error";
+char *name = g_strdup_printf("/bbram@%x", MM_PMC_BBRAM_CTRL);
+
+qemu_fdt_add_subnode(s->fdt, name);
+
+qemu_fdt_setprop_cells(s->fdt, name, "interrupts",
+   GIC_FDT_IRQ_TYPE_SPI, VERSAL_BBRAM_APB_IRQ_0,
+   GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+qemu_fdt_setprop(s->fdt, name, "interrupt-names",
+ interrupt_names, sizeof(interrupt_names));
+qemu_fdt_setprop_sized_cells(s->fdt, name, "reg",
+ 2, MM_PMC_BBRAM_CTRL,
+ 2, MM_PMC_BBRAM_CTRL_SIZE);
+qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat));
+g_free(name);
+}
+
 static void fdt_nop_memory_nodes(void *fdt, Error **errp)
 {
 Error *err = NULL;
@@ -510,6 +530,18 @@ static void create_virtio_regions(VersalVirt *s)
 }
 }
 
+static void bbram_attach_drive(XlnxBBRam *dev)
+{
+DriveInfo *dinfo;
+BlockBackend *blk;
+
+dinfo = drive_get_by_index(IF_PFLASH, 0);
+blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+if (blk) {
+qdev_prop_set_drive(DEVICE(dev), "drive", blk);
+}
+}
+
 static void sd_plugin_card(SDHCIState *sd, DriveInfo *di)
 {
 BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
@@ -570,6 +602,7 @@ static void versal_virt_init(MachineState *machine)
 fdt_add_usb_xhci_nodes(s);
 fdt_add_sd_nodes(s);
 fdt_add_rtc_node(s);
+fdt_add_bbram_node(s);
 fdt_add_cpu_nodes(s, psci_conduit);
 fdt_add_clk_node(s, "/clk125", 12500, s->phandle.clk_125Mhz);
 fdt_add_clk_node(s, "/clk25", 2500, s->phandle.clk_25Mhz);
@@ -579,6 +612,9 @@ static void versal_virt_init(MachineState *machine)
 memory_region_add_subregion_overlap(get_system_memory(),
 0, &s->soc.fpd.apu.mr, 0);
 
+/* Attach bbram backend, if given */
+bbram_attach_drive(&s->soc.pmc.bbram);
+
 /* Plugin SD cards.  */
 for (i = 0; i < ARRAY_SIZE(s->soc.pmc.iou.sd); i++) {
 sd_plugin_card(&s->soc.pmc.iou.sd[i], drive_get_next(IF_SD));
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 547a26603a..23451ae012 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -314,6 +314,23 @@ static void versal_create_xrams(Versal *s, qemu_irq *pic)
 }
 }
 
+static void versal_create_bbram(Versal *s, qemu_irq *pic)
+{
+SysBusDevice *sbd;
+
+object_initialize_child_with_props(OBJECT(s), "bbram", &s->pmc.bbram,
+   sizeof(s->pmc.bbram), TYPE_XLNX_BBRAM,
+   &error_fatal,
+   "crc-zpads", "0",
+   NULL);
+sbd = SYS_BUS_DEVICE(&s->pmc.bbram);
+
+sysbus_realize(sbd, &error_fatal);
+memory_region_add_subregion(&s->mr_ps, MM_PMC_BBRAM_CTRL,
+sysbus_mmio_get_region(sbd, 0));
+sysbus_connect_irq(sbd, 0, pic[VERSAL_BBRAM_APB_IRQ_0]);
+}
+
 /* This takes the board allocated linear DDR memory and creates aliases
  * for each split DDR range/aperture on the Versal address map.
  */
@@ -402,6 +419,7 @@ static void versal_realize(DeviceState *dev, Error **errp)
 versal_create_sds(s, pic);
 versal_create_rtc(s, pic);
 versal_create_xrams(s, pic);
+versal_create_bbram(s, pic);
 versal_map_ddr(s);
 versal_unimp(s);
 
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index 9b79051747..1cac613338 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -24,6 +24,7 @@
 #include "qom/object.h"
 #include "hw/usb

Re: hw/i386/acpi: fix conflicting IO address range for acpi pci hotplug in q35

2021-09-16 Thread Ani Sinha



On Thu, 16 Sep 2021, Michael S. Tsirkin wrote:

> On Thu, Sep 16, 2021 at 06:58:35PM +0530, Ani Sinha wrote:
> > Here's sending v2.
> >
> > changelog :
> > v1: original patch.
> > v2: typo fixed. reviewed-by tags added.
>
>
> Thanks, tagged!
> Ani pls make sure the voer letter in the series has
> subject
>
> [PATCH 0/3] hw/i386/acpi: fix conflicting IO address range for acpi pci
>  hotplug in q35
>
>
> using --cover-letter with git format-patch will do this automatically.
>
> It will also include diffstat and other useful info.

Ah I see. I was wondering about this few days back because I saw a
patchset with diffstat etc. I use git send-email --cover -v2 -3 -cc
--cc-cmd etc. I did not realize that git format-patch also has similar
options and adds more info to the cover letter. I wonder why the behavior
is different between them.  Also --cc-cmd is missing in format-patch!

Was this an essential complexity or accidental one :-)



>
>
> > This issue has been reported here:
> > https://gitlab.com/qemu-project/qemu/-/issues/561
> >
> > We have disucssed this issue at length here:
> > https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02146.html
> >
> > This issue affects Qemu version 6.1.
> >
> > Patch 1 : allows q35 DSDT table changes.
> > Patch 2 : actual fix.
> > Patch 3: updates DSDT table blobs.
> >
> >
>
>



[Bug 1749393] Re: sbrk() not working under qemu-user with a PIE-compiled binary?

2021-09-16 Thread Sebastian Unger
I'm running qemu-arm version 4.2.1 (Debian 1:4.2-3ubuntu6.17) on Ubuntu
20.04.03, but I seem to still be affected by this (or something very
much like it). In my case it is armhf exim4 crashing while creating a
chroot on an amd64 host. The final command run from deeply within
exim4's postinst is:

/usr/sbin/exim4 -C /var/lib/exim4/config.autogenerated.tmp -bV

and produces

Exim version 4.93 #5 built 28-Apr-2021 13:19:17
Copyright (c) University of Cambridge, 1995 - 2018
(c) The Exim Maintainers and contributors in ACKNOWLEDGMENTS file, 2007 - 2018
Berkeley DB: Berkeley DB 5.3.28: (September  9, 2013)
Support for: crypteq iconv() IPv6 GnuTLS move_frozen_messages DANE DKIM DNSSEC 
Event I18N OCSP PRDR SOCKS TCP_Fast_Open
Lookups (built-in): lsearch wildlsearch nwildlsearch iplsearch cdb dbm dbmjz 
dbmnz dnsdb dsearch nis nis0 passwd
Authenticators: cram_md5 plaintext
Routers: accept dnslookup ipliteral manualroute queryprogram redirect
Transports: appendfile/maildir/mailstore autoreply lmtp pipe smtp
Fixed never_users: 0
Configure owner: 0:0
Size of off_t: 8
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault (core dumped)

Interestingly, even

/usr/sbin/exim4 -C /dev/null -bV

produces the same result, so it likely doesn't depend on any
configuration at my end and should be reproducible.

Please let me know if there is anything I can do to help debug further.

Should I create a separate ticket?

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

Title:
  sbrk() not working under qemu-user with a PIE-compiled binary?

Status in QEMU:
  Fix Released
Status in qemu package in Ubuntu:
  Fix Released
Status in qemu source package in Focal:
  Triaged

Bug description:
  [Impact]

   * The current space reserved can be too small and we can end up
 with no space at all for BRK. It can happen to any case, but is
 much more likely with the now common PIE binaries.

   * Backport the upstream fix which reserves a bit more space while loading
 and giving it back after interpreter and stack is loaded.

  [Test Plan]

   * On x86 run:
  sudo apt install -y qemu-user-static docker.io
  sudo docker run --rm arm64v8/debian:bullseye bash -c 'apt update && apt 
install -y wget'
  ...
  Running hooks in /etc/ca-certificates/update.d...
  done.
  Errors were encountered while processing:
   libc-bin
  E: Sub-process /usr/bin/dpkg returned an error code (1)

  
  [Where problems could occur]

   * Regressions would be around use-cases of linux-user that is
 emulation not of a system but of binaries.
 Commonly uses for cross-tests and cross-builds so that is the
 space to watch for regressions

  [Other Info]
   
   * n/a


  ---

  In Debian unstable, we recently switched bash to be a PIE-compiled
  binary (for hardening). Unfortunately this resulted in bash being
  broken when run under qemu-user (for all target architectures, host
  being amd64 for me).

  $ sudo chroot /srv/chroots/sid-i386/ qemu-i386-static /bin/bash
  bash: xmalloc: .././shell.c:1709: cannot allocate 10 bytes (0 bytes allocated)

  bash has its own malloc implementation based on sbrk():
  https://git.savannah.gnu.org/cgit/bash.git/tree/lib/malloc/malloc.c

  When we disable this internal implementation and rely on glibc's
  malloc, then everything is fine. But it might be that glibc has a
  fallback when sbrk() is not working properly and it might hide the
  underlying problem in qemu-user.

  This issue has also been reported to the bash upstream author and he 
suggested that the issue might be in qemu-user so I'm opening a ticket here. 
Here's the discussion with the bash upstream author:
  https://lists.gnu.org/archive/html/bug-bash/2018-02/threads.html#00080

  You can find the problematic bash binary in that .deb file:
  
http://snapshot.debian.org/archive/debian/20180206T154716Z/pool/main/b/bash/bash_4.4.18-1_i386.deb

  The version of qemu I have been using is 2.11 (Debian package qemu-
  user-static version 1:2.11+dfsg-1) but I have had reports that the
  problem is reproducible with older versions (back to 2.8 at least).

  Here are the related Debian bug reports:
  https://bugs.debian.org/889869
  https://bugs.debian.org/865599

  It's worth noting that bash used to have this problem (when compiled as a PIE 
binary) even when run directly but then something got fixed in the kernel and 
now the problem only appears when run under qemu-user:
  https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1518483

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




Re: [PATCH 7/9] bsd-user: Don't try to mmap fd when it is -1 independently from MAP_ANONYMOUS flag

2021-09-16 Thread Warner Losh
On Thu, Sep 16, 2021 at 8:56 PM Warner Losh  wrote:

> From: Guy Yur 
>

I need to fix this email address in the next round or for the pull request.
It's gmail.com, not ngmail.com.

Switch checks for !(flags & MAP_ANONYMOUS) with checks for fd != -1.
> MAP_STACK and MAP_GUARD also force fd == -1 and they don't require
> mapping the fd either.
>
> Signed-off-by: Guy Yur 
> [ partially merged before, finishing the job and documenting origin]
> Signed-off-by: Warner Losh 
> ---
>  bsd-user/mmap.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
> index 8b763fffc3..347d314aa9 100644
> --- a/bsd-user/mmap.c
> +++ b/bsd-user/mmap.c
> @@ -154,7 +154,7 @@ static int mmap_frag(abi_ulong real_start,
>  if (prot1 == 0) {
>  /* no page was there, so we allocate one */
>  void *p = mmap(host_start, qemu_host_page_size, prot,
> -   flags | MAP_ANON, -1, 0);
> +   flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
>  if (p == MAP_FAILED)
>  return -1;
>  prot1 = prot;
> @@ -162,7 +162,7 @@ static int mmap_frag(abi_ulong real_start,
>  prot1 &= PAGE_BITS;
>
>  prot_new = prot | prot1;
> -if (!(flags & MAP_ANON)) {
> +if (fd != -1) {
>  /* msync() won't work here, so we return an error if write is
> possible while it is a shared mapping */
>  if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
> @@ -571,7 +571,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len,
> int prot,
>   * worst case: we cannot map the file because the offset is not
>   * aligned, so we read it
>   */
> -if (!(flags & MAP_ANON) &&
> +if (fd != -1 &&
>  (offset & ~qemu_host_page_mask) != (start &
> ~qemu_host_page_mask)) {
>  /*
>   * msync() won't work here, so we return an error if write is
> --
> 2.32.0
>
>


[PATCH 9/9] bsd-user: Apply 86abac06c14 from linux-user (target_mprotect can't fail)

2021-09-16 Thread Warner Losh
From: Paolo Bonzini 

linux-user: assert that target_mprotect cannot fail

All error conditions that target_mprotect checks are also checked
by target_mmap.  EACCESS cannot happen because we are just removing
PROT_WRITE.  ENOMEM should not happen because we are modifying a
whole VMA (and we have bigger problems anyway if it happens).

Fixes a Coverity false positive, where Coverity complains about
target_mprotect's return value being passed to tb_invalidate_phys_range.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Riku Voipio 
Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 792ff00548..4ddbd50b62 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -591,10 +591,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 goto fail;
 if (!(prot & PROT_WRITE)) {
 ret = target_mprotect(start, len, prot);
-if (ret != 0) {
-start = ret;
-goto the_end;
-}
+assert(ret == 0);
 }
 goto the_end;
 }
-- 
2.32.0




[PATCH 8/9] bsd-user: Implement MAP_EXCL, required by jemalloc in head

2021-09-16 Thread Warner Losh
From: Kyle Evans 

jemalloc requires a working MAP_EXCL. Emulate it by ensuring we don't
double map anything.

Signed-off-by: Kyle Evans 
Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 347d314aa9..792ff00548 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -387,7 +387,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
 abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
  int flags, int fd, off_t offset)
 {
-abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
+abi_ulong addr, ret, end, real_start, real_end, retaddr, host_offset, 
host_len;
 
 mmap_lock();
 #ifdef DEBUG_MMAP
@@ -599,6 +599,14 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 goto the_end;
 }
 
+/* Reject the mapping if any page within the range is mapped */
+if (flags & MAP_EXCL) {
+for (addr = start; addr < end; addr++) {
+if (page_get_flags(addr) != 0)
+goto fail;
+}
+}
+
 /* handle the start of the mapping */
 if (start > real_start) {
 if (real_end == real_start + qemu_host_page_size) {
-- 
2.32.0




[PATCH 4/9] bsd-user: mmap return ENOMEM on overflow

2021-09-16 Thread Warner Losh
mmap should return ENOMEM on len overflow rather than EINVAL. Return
EINVAL when len == 0 and ENOMEM when the rounded to a page length is 0.
Found by make check-tcg.

Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index c40059d7fc..0acc2db712 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -454,11 +454,18 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 goto fail;
 }
 
-len = TARGET_PAGE_ALIGN(len);
 if (len == 0) {
 errno = EINVAL;
 goto fail;
 }
+
+/* Check for overflows */
+len = TARGET_PAGE_ALIGN(len);
+if (len == 0) {
+errno = ENOMEM;
+goto fail;
+}
+
 real_start = start & qemu_host_page_mask;
 host_offset = offset & qemu_host_page_mask;
 
-- 
2.32.0




[PATCH 5/9] bsd-user: mmap prefer MAP_ANON for BSD

2021-09-16 Thread Warner Losh
MAP_ANON and MAP_ANONYMOUS are identical. Prefer MAP_ANON for BSD since
the file is now a confusing mix of the two.

Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 0acc2db712..bafbdacd31 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -284,7 +284,7 @@ static abi_ulong mmap_find_vma_aligned(abi_ulong start, 
abi_ulong size,
 addr = start;
 wrapped = repeat = 0;
 prev = 0;
-flags = MAP_ANONYMOUS | MAP_PRIVATE;
+flags = MAP_ANON | MAP_PRIVATE;
 if (alignment != 0) {
 flags |= MAP_ALIGNED(alignment);
 }
@@ -408,7 +408,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 if (flags & MAP_FIXED) {
 printf("MAP_FIXED ");
 }
-if (flags & MAP_ANONYMOUS) {
+if (flags & MAP_ANON) {
 printf("MAP_ANON ");
 }
 if (flags & MAP_EXCL) {
@@ -430,7 +430,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 }
 #endif
 
-if ((flags & MAP_ANONYMOUS) && fd != -1) {
+if ((flags & MAP_ANON) && fd != -1) {
 errno = EINVAL;
 goto fail;
 }
@@ -532,7 +532,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
  * qemu_real_host_page_size
  */
 p = mmap(g2h_untagged(start), host_len, prot,
- flags | MAP_FIXED | ((fd != -1) ? MAP_ANONYMOUS : 0), -1, 0);
+ flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1, 0);
 if (p == MAP_FAILED)
 goto fail;
 /* update start so that it points to the file position at 'offset' */
@@ -694,8 +694,7 @@ static void mmap_reserve(abi_ulong start, abi_ulong size)
 }
 if (real_start != real_end) {
 mmap(g2h_untagged(real_start), real_end - real_start, PROT_NONE,
- MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE,
- -1, 0);
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
 }
 }
 
-- 
2.32.0




[PATCH 7/9] bsd-user: Don't try to mmap fd when it is -1 independently from MAP_ANONYMOUS flag

2021-09-16 Thread Warner Losh
From: Guy Yur 

Switch checks for !(flags & MAP_ANONYMOUS) with checks for fd != -1.
MAP_STACK and MAP_GUARD also force fd == -1 and they don't require
mapping the fd either.

Signed-off-by: Guy Yur 
[ partially merged before, finishing the job and documenting origin]
Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 8b763fffc3..347d314aa9 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -154,7 +154,7 @@ static int mmap_frag(abi_ulong real_start,
 if (prot1 == 0) {
 /* no page was there, so we allocate one */
 void *p = mmap(host_start, qemu_host_page_size, prot,
-   flags | MAP_ANON, -1, 0);
+   flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
 if (p == MAP_FAILED)
 return -1;
 prot1 = prot;
@@ -162,7 +162,7 @@ static int mmap_frag(abi_ulong real_start,
 prot1 &= PAGE_BITS;
 
 prot_new = prot | prot1;
-if (!(flags & MAP_ANON)) {
+if (fd != -1) {
 /* msync() won't work here, so we return an error if write is
possible while it is a shared mapping */
 if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
@@ -571,7 +571,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
  * worst case: we cannot map the file because the offset is not
  * aligned, so we read it
  */
-if (!(flags & MAP_ANON) &&
+if (fd != -1 &&
 (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) 
{
 /*
  * msync() won't work here, so we return an error if write is
-- 
2.32.0




[PATCH 3/9] bsd-user: MAP_ symbols are defined, so no need for ifdefs

2021-09-16 Thread Warner Losh
All these MAP_ symbols are always defined on supported FreeBSD versions
(12.2 and newer), so remove the #ifdefs since they aren't needed.

Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 14 --
 1 file changed, 14 deletions(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 90b6313161..c40059d7fc 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -285,13 +285,9 @@ static abi_ulong mmap_find_vma_aligned(abi_ulong start, 
abi_ulong size,
 wrapped = repeat = 0;
 prev = 0;
 flags = MAP_ANONYMOUS | MAP_PRIVATE;
-#ifdef MAP_ALIGNED
 if (alignment != 0) {
 flags |= MAP_ALIGNED(alignment);
 }
-#else
-/* XXX TODO */
-#endif
 
 for (;; prev = ptr) {
 /*
@@ -406,22 +402,18 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 printf("MAP_ALIGNED(%u) ", (flags & MAP_ALIGNMENT_MASK)
 >> MAP_ALIGNMENT_SHIFT);
 }
-#if MAP_GUARD
 if (flags & MAP_GUARD) {
 printf("MAP_GUARD ");
 }
-#endif
 if (flags & MAP_FIXED) {
 printf("MAP_FIXED ");
 }
 if (flags & MAP_ANONYMOUS) {
 printf("MAP_ANON ");
 }
-#ifdef MAP_EXCL
 if (flags & MAP_EXCL) {
 printf("MAP_EXCL ");
 }
-#endif
 if (flags & MAP_PRIVATE) {
 printf("MAP_PRIVATE ");
 }
@@ -431,11 +423,9 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 if (flags & MAP_NOCORE) {
 printf("MAP_NOCORE ");
 }
-#ifdef MAP_STACK
 if (flags & MAP_STACK) {
 printf("MAP_STACK ");
 }
-#endif
 printf("fd=%d offset=0x%llx\n", fd, offset);
 }
 #endif
@@ -444,7 +434,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 errno = EINVAL;
 goto fail;
 }
-#ifdef MAP_STACK
 if (flags & MAP_STACK) {
 if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) !=
 (PROT_READ | PROT_WRITE))) {
@@ -452,8 +441,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 goto fail;
 }
 }
-#endif /* MAP_STACK */
-#ifdef MAP_GUARD
 if ((flags & MAP_GUARD) && (prot != PROT_NONE || fd != -1 ||
 offset != 0 || (flags & (MAP_SHARED | MAP_PRIVATE |
 /* MAP_PREFAULT | */ /* MAP_PREFAULT not in mman.h */
@@ -461,7 +448,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
 errno = EINVAL;
 goto fail;
 }
-#endif
 
 if (offset & ~TARGET_PAGE_MASK) {
 errno = EINVAL;
-- 
2.32.0




[PATCH 1/9] bsd-user: Apply e6deac9cf99 from linux-user (zero anonymous memory)

2021-09-16 Thread Warner Losh
From: Mikaël Urankar 

linux-user/mmap.c: Always zero MAP_ANONYMOUS memory in mmap_frag()

When mapping MAP_ANONYMOUS memory fragments, still need notice about to
set it zero, or it will cause issues.

Signed-off-by: Chen Gang 
Reviewed-by: Laurent Vivier 
Signed-off-by: Riku Voipio 
[ bsd-user merge by Mikaël Urankar, updated for untagged by Warner Losh ]
Signed-off-by: Mikaël Urankar 
Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index b40ab9045f..fc3c1480f5 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -180,10 +180,12 @@ static int mmap_frag(abi_ulong real_start,
 if (prot_new != (prot1 | PROT_WRITE))
 mprotect(host_start, qemu_host_page_size, prot_new);
 } else {
-/* just update the protection */
 if (prot_new != prot1) {
 mprotect(host_start, qemu_host_page_size, prot_new);
 }
+if (prot_new & PROT_WRITE) {
+memset(g2h_untagged(start), 0, end - start);
+}
 }
 return 0;
 }
-- 
2.32.0




[PATCH 6/9] bsd-user: mmap line wrap change

2021-09-16 Thread Warner Losh
Keep the shifted expression on one line. It's the same number of lines
and easier to read like this.

Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index bafbdacd31..8b763fffc3 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -399,8 +399,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
 if (flags & MAP_ALIGNMENT_MASK) {
-printf("MAP_ALIGNED(%u) ", (flags & MAP_ALIGNMENT_MASK)
->> MAP_ALIGNMENT_SHIFT);
+printf("MAP_ALIGNED(%u) ",
+   (flags & MAP_ALIGNMENT_MASK) >> MAP_ALIGNMENT_SHIFT);
 }
 if (flags & MAP_GUARD) {
 printf("MAP_GUARD ");
-- 
2.32.0




[PATCH 2/9] bsd-user: Apply fb7e378cf9c from linux-user (fix FORTIFY warnings)

2021-09-16 Thread Warner Losh
From: Mikaël Urankar 

linux-user/mmap.c: fix warnings with _FORTIFY_SOURCE

CCi386-linux-user/mmap.o
cc1: warnings being treated as errors
/usr/src/RPM/BUILD/qemu-0.11.92/linux-user/mmap.c: In function 'mmap_frag':
/usr/src/RPM/BUILD/qemu-0.11.92/linux-user/mmap.c:253: error: ignoring return 
value of 'pread', declared with attribute warn_unused_result
/usr/src/RPM/BUILD/qemu-0.11.92/linux-user/mmap.c: In function 'target_mmap':
/usr/src/RPM/BUILD/qemu-0.11.92/linux-user/mmap.c:477: error: ignoring return 
value of 'pread', declared with attribute warn_unused_result
make[1]: *** [mmap.o] Error 1

Signed-off-by: Kirill A. Shutemov 
Signed-off-by: Juan Quintela 
Signed-off-by: Anthony Liguori 
[ Merged to bsd-user by Mikaël Urankared updated by Warner Losh for untagged ]
Signed-off-by: Mikaël Urankar 
Signed-off-by: Warner Losh 
---
 bsd-user/mmap.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index fc3c1480f5..90b6313161 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -174,7 +174,8 @@ static int mmap_frag(abi_ulong real_start,
 mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
 
 /* read the corresponding file data */
-pread(fd, g2h_untagged(start), end - start, offset);
+if (pread(fd, g2h_untagged(start), end - start, offset) == -1)
+return -1;
 
 /* put final protection */
 if (prot_new != (prot1 | PROT_WRITE))
@@ -593,7 +594,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int 
prot,
   -1, 0);
 if (retaddr == -1)
 goto fail;
-pread(fd, g2h_untagged(start), len, offset);
+if (pread(fd, g2h_untagged(start), len, offset) == -1)
+goto fail;
 if (!(prot & PROT_WRITE)) {
 ret = target_mprotect(start, len, prot);
 if (ret != 0) {
-- 
2.32.0




[PATCH 0/9] bsd-user mmap fixes

2021-09-16 Thread Warner Losh
This series synchronizes mmap.c with the bsd-user fork. This is a mix of old bug
fixes pulled in from linux-user, as well as some newer fixes to adress bugs
found in check-tcg and recent FreeBSD developments. There are also a couple of
style commits.

Guy Yur (1):
  bsd-user: Don't try to mmap fd when it is -1 independently from
MAP_ANONYMOUS flag

Kyle Evans (1):
  bsd-user: Implement MAP_EXCL, required by jemalloc in head

Mikaël Urankar (2):
  bsd-user: Apply e6deac9cf99 from linux-user (zero anonymous memory)
  bsd-user: Apply fb7e378cf9c from linux-user (fix FORTIFY warnings)

Paolo Bonzini (1):
  bsd-user: Apply 86abac06c14 from linux-user (target_mprotect can't
fail)

Warner Losh (4):
  bsd-user: MAP_ symbols are defined, so no need for ifdefs
  bsd-user: mmap return ENOMEM on overflow
  bsd-user: mmap prefer MAP_ANON for BSD
  bsd-user: mmap line wrap change

 bsd-user/mmap.c | 69 +
 1 file changed, 35 insertions(+), 34 deletions(-)

-- 
2.32.0




[PATCH 2/2] modules: use a list of supported arch for each module

2021-09-16 Thread Jose R. Ziviani
When compiling QEMU with more than one target, for instance,
--target-list=s390x-softmmu,x86_64-softmmu, modinfo.c will be
filled with modules available for both, with no specification
of what modules can/cannot be loaded for a particular target.

This will cause message errors when executing the target that
shouldn't be loading that module, such as:

$ qemu-system-s390x -nodefaults -display none -accel qtest -M none -device help
Failed to open module: /.../hw-display-virtio-vga.so: undefined symbol: 
vmstate_vga_common

This patch changes the module infrastructure to use a list of
architectures, obtained during the build time, to specify what
targets can load each module.

Signed-off-by: Jose R. Ziviani 
---
 include/qemu/module.h   |  2 +-
 meson.build | 18 +-
 scripts/modinfo-collect.py  | 10 ++
 scripts/modinfo-generate.py |  7 +++
 util/module.c   | 18 +-
 5 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/include/qemu/module.h b/include/qemu/module.h
index 3deac0078b..3b487c646c 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -144,7 +144,7 @@ void module_allow_arch(const char *arch);
 typedef struct QemuModinfo QemuModinfo;
 struct QemuModinfo {
 const char *name;
-const char *arch;
+const char **archs;
 const char **objs;
 const char **deps;
 const char **opts;
diff --git a/meson.build b/meson.build
index d1d3fd84ec..efba275092 100644
--- a/meson.build
+++ b/meson.build
@@ -2343,11 +2343,19 @@ foreach d, list : modules
 # unique when it comes to lookup in compile_commands.json.
 # Depnds on a mesion version with
 # https://github.com/mesonbuild/meson/pull/8900
-modinfo_files += custom_target(d + '-' + m + '.modinfo',
-   output: d + '-' + m + '.modinfo',
-   input: module_ss.sources() + genh,
-   capture: true,
-   command: [modinfo_collect, 
module_ss.sources()])
+if modules_arch.has_key(m)
+  modinfo_files += custom_target(d + '-' + m + '.modinfo',
+output: d + '-' + m + '.modinfo',
+input: module_ss.sources() + genh,
+capture: true,
+command: [modinfo_collect, 
module_ss.sources(), '--archs', modules_arch[m]])
+else
+  modinfo_files += custom_target(d + '-' + m + '.modinfo',
+output: d + '-' + m + '.modinfo',
+input: module_ss.sources() + genh,
+capture: true,
+command: [modinfo_collect, 
module_ss.sources()])
+endif
   endif
 else
   if d == 'block'
diff --git a/scripts/modinfo-collect.py b/scripts/modinfo-collect.py
index 4acb188c3e..739cd23e2f 100755
--- a/scripts/modinfo-collect.py
+++ b/scripts/modinfo-collect.py
@@ -50,6 +50,16 @@ def main(args):
 print("MODINFO_START arch \"%s\" MODINFO_END" % arch)
 with open('compile_commands.json') as f:
 compile_commands = json.load(f)
+
+try:
+arch_idx = args.index('--archs')
+archs = args[arch_idx + 1:]
+args = args[:arch_idx]
+for arch in archs:
+print("MODINFO_START arch \"%s\" MODINFO_END" % arch)
+except ValueError:
+pass
+
 for src in args:
 print("MODINFO_DEBUG src %s" % src)
 command = find_command(src, target, compile_commands)
diff --git a/scripts/modinfo-generate.py b/scripts/modinfo-generate.py
index f559eed007..e1d13acd92 100755
--- a/scripts/modinfo-generate.py
+++ b/scripts/modinfo-generate.py
@@ -33,7 +33,7 @@ def parse_line(line):
 return (kind, data)
 
 def generate(name, lines):
-arch = ""
+archs = []
 objs = []
 deps = []
 opts = []
@@ -47,14 +47,13 @@ def generate(name, lines):
 elif kind == 'opts':
 opts.append(data)
 elif kind == 'arch':
-arch = data;
+archs.append(data);
 else:
 print("unknown:", kind)
 exit(1)
 
 print(".name = \"%s\"," % name)
-if arch != "":
-print(".arch = %s," % arch)
+print_array("archs", archs)
 print_array("objs", objs)
 print_array("deps", deps)
 print_array("opts", opts)
diff --git a/util/module.c b/util/module.c
index 6bb4ad915a..7009143bfc 100644
--- a/util/module.c
+++ b/util/module.c
@@ -131,16 +131,24 @@ void module_allow_arch(const char *arch)
 
 static bool module_check_arch(const QemuModinfo *modinfo)
 {
-if (modinfo->arch) {
+const char **arch;
+
+if (modinfo->archs) {
 if (!module_arch) {
 /* no arch set -> ignore all 

[PATCH 1/2] meson: introduce modules_arch

2021-09-16 Thread Jose R. Ziviani
This variable keeps track of all modules enabled for a target
architecture. This will be used in modinfo to refine the
architectures that can really load the .so to avoid errors.

Signed-off-by: Jose R. Ziviani 
---
 hw/display/meson.build | 48 ++
 hw/usb/meson.build | 36 +++
 meson.build|  1 +
 3 files changed, 85 insertions(+)

diff --git a/hw/display/meson.build b/hw/display/meson.build
index 861c43ff98..ba06f58ff1 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -43,6 +43,18 @@ if config_all_devices.has_key('CONFIG_QXL')
   qxl_ss.add(when: 'CONFIG_QXL', if_true: [files('qxl.c', 'qxl-logger.c', 
'qxl-render.c'),
pixman, spice])
   hw_display_modules += {'qxl': qxl_ss}
+
+  archs = []
+  foreach target: target_dirs
+if target.endswith('-softmmu')
+  cfg_target = config_target_mak[target]
+  if cfg_target.has_key('CONFIG_QXL') and cfg_target['CONFIG_QXL'] == 'y'
+archs += [cfg_target['TARGET_NAME']]
+  endif
+endif
+  endforeach
+
+  modules_arch += {'qxl': archs}
 endif
 
 softmmu_ss.add(when: 'CONFIG_DPCD', if_true: files('dpcd.c'))
@@ -65,6 +77,18 @@ if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
   virtio_gpu_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', virgl, opengl],
if_true: [files('virtio-gpu-gl.c', 
'virtio-gpu-virgl.c'), pixman, virgl])
   hw_display_modules += {'virtio-gpu-gl': virtio_gpu_gl_ss}
+
+  archs = []
+  foreach target: target_dirs
+if target.endswith('-softmmu')
+  cfg_target = config_target_mak[target]
+  if cfg_target.has_key('CONFIG_VIRTIO_GPU') and 
cfg_target['CONFIG_VIRTIO_GPU'] == 'y'
+archs += [cfg_target['TARGET_NAME']]
+  endif
+endif
+  endforeach
+
+  modules_arch += {'virtio-gpu': archs, 'virtio-gpu-gl': archs}
 endif
 
 if config_all_devices.has_key('CONFIG_VIRTIO_PCI')
@@ -79,6 +103,18 @@ if config_all_devices.has_key('CONFIG_VIRTIO_PCI')
   virtio_gpu_pci_gl_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_PCI', 
virgl, opengl],
if_true: [files('virtio-gpu-pci-gl.c'), pixman])
   hw_display_modules += {'virtio-gpu-pci-gl': virtio_gpu_pci_gl_ss}
+
+  archs = []
+  foreach target: target_dirs
+if target.endswith('-softmmu')
+  cfg_target = config_target_mak[target]
+  if cfg_target.has_key('CONFIG_VIRTIO_PCI') and 
cfg_target['CONFIG_VIRTIO_PCI'] == 'y'
+archs += [cfg_target['TARGET_NAME']]
+  endif
+endif
+  endforeach
+
+  modules_arch += {'virtio-gpu-pci': archs, 'virtio-gpu-pci-gl': archs}
 endif
 
 if config_all_devices.has_key('CONFIG_VIRTIO_VGA')
@@ -93,6 +129,18 @@ if config_all_devices.has_key('CONFIG_VIRTIO_VGA')
   virtio_vga_gl_ss.add(when: ['CONFIG_VIRTIO_VGA', virgl, opengl],
if_true: [files('virtio-vga-gl.c'), pixman])
   hw_display_modules += {'virtio-vga-gl': virtio_vga_gl_ss}
+
+  archs = []
+  foreach target: target_dirs
+if target.endswith('-softmmu')
+  cfg_target = config_target_mak[target]
+  if cfg_target.has_key('CONFIG_VIRTIO_VGA') and 
cfg_target['CONFIG_VIRTIO_VGA'] == 'y'
+archs += [cfg_target['TARGET_NAME']]
+  endif
+endif
+  endforeach
+
+  modules_arch += {'virtio-vga': archs, 'virtio-vga-gl': archs}
 endif
 
 specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_lcdc.c'))
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index de853d780d..6b889d2ee2 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -54,6 +54,18 @@ if cacard.found()
   usbsmartcard_ss.add(when: 'CONFIG_USB_SMARTCARD',
   if_true: [cacard, files('ccid-card-emulated.c', 
'ccid-card-passthru.c')])
   hw_usb_modules += {'smartcard': usbsmartcard_ss}
+
+  archs = []
+  foreach target: target_dirs
+if target.endswith('-softmmu')
+  cfg_target = config_target_mak[target]
+  if cfg_target.has_key('CONFIG_USB_SMARTCARD') and 
cfg_target['CONFIG_USB_SMARTCARD'] == 'y'
+archs += [cfg_target['TARGET_NAME']]
+  endif
+endif
+  endforeach
+
+  modules_arch += {'smartcard': archs}
 endif
 
 # U2F
@@ -69,6 +81,18 @@ if usbredir.found()
   usbredir_ss.add(when: 'CONFIG_USB',
   if_true: [usbredir, files('redirect.c', 'quirks.c')])
   hw_usb_modules += {'redirect': usbredir_ss}
+
+  archs = []
+  foreach target: target_dirs
+if target.endswith('-softmmu')
+  cfg_target = config_target_mak[target]
+  if cfg_target.has_key('CONFIG_USB') and cfg_target['CONFIG_USB'] == 'y'
+archs += [cfg_target['TARGET_NAME']]
+  endif
+endif
+  endforeach
+
+  modules_arch += {'redirect': archs}
 endif
 
 # usb pass-through
@@ -77,6 +101,18 @@ if libusb.found()
   usbhost_ss.add(when: ['CONFIG_USB', libusb],
  if_true: files('host-libusb.c'))
   hw_usb_modules += {'host': usbhost_ss}
+
+  archs = []
+  foreach target: target_dirs
+if target.endswith('-s

[PATCH 0/2] modules: Improve modinfo.c architecture support

2021-09-16 Thread Jose R. Ziviani
When building a single target, the build system detects the architecture
and generates a modinfo.c with modules related to that arch only.
However, when more than one target is built, modinfo.c is generated with
modules available for each architecture - without any way to know what
arch supports what.

The problem is when executing the target, it will try to load modules
that is not supported by it and will throw errors to users, for
instance:

$ ./configure --enable-modules # all targets
$ ./qemu-system-avr -nodefaults -display none -accel tcg -M none -device help | 
head
Failed to open module: /.../hw-display-qxl.so: undefined symbol: vga_ioport_read
Failed to open module: /.../hw-display-virtio-gpu.so: undefined symbol: 
virtio_vmstate_info
Failed to open module: /.../hw-display-virtio-gpu.so: undefined symbol: 
virtio_vmstate_info
Failed to open module: /.../hw-display-virtio-gpu-gl.so: undefined symbol: 
virtio_gpu_ctrl_response
Failed to open module: /.../hw-display-virtio-gpu-pci.so: undefined symbol: 
virtio_instance_init_common
Failed to open module: /.../hw-display-virtio-gpu-pci.so: undefined symbol: 
virtio_instance_init_common
Failed to open module: /.../hw-display-virtio-gpu-pci-gl.so: undefined symbol: 
virtio_instance_init_common
Failed to open module: /.../hw-display-virtio-vga.so: undefined symbol: 
vmstate_vga_common
Failed to open module: /.../hw-display-virtio-vga.so: undefined symbol: 
vmstate_vga_common
Failed to open module: /.../hw-display-virtio-vga-gl.so: undefined symbol: 
have_vga
Failed to open module: /.../hw-usb-smartcard.so: undefined symbol: 
ccid_card_ccid_attach
Failed to open module: /.../hw-usb-redirect.so: undefined symbol: 
vmstate_usb_device
Failed to open module: /.../hw-usb-host.so: undefined symbol: vmstate_usb_device
...

$ ./qemu-system-s390x -nodefaults -display none -accel tcg -M none -device help 
| head 
Failed to open module: /.../hw-display-qxl.so: undefined symbol: vga_ioport_read
Failed to open module: /.../hw-display-virtio-vga.so: undefined symbol: 
vmstate_vga_common
Failed to open module: /.../hw-display-virtio-vga.so: undefined symbol: 
vmstate_vga_common
Failed to open module: /.../hw-display-virtio-vga-gl.so: undefined symbol: 
have_vga
Failed to open module: /.../hw-usb-smartcard.so: undefined symbol: 
ccid_card_ccid_attach
Failed to open module: /.../hw-usb-redirect.so: undefined symbol: 
vmstate_usb_device
Failed to open module: /.../hw-usb-host.so: undefined symbol: vmstate_usb_device

This patchset tries to improve by collecting the modules are currently
enabled for each target, obtaining information in meson from kconfig
and passing that to modinfo.c, which now uses a list to store supported
architectures for each module.

$ ./qemu-system-s390x -nodefaults -display none -accel tcg -M none -device help 
| head
Controller/Bridge/Hub devices:
name "pci-bridge", bus PCI, desc "Standard PCI Bridge"
name "pci-bridge-seat", bus PCI, desc "Standard PCI Bridge (multiseat)"
...

$ ./qemu-system-avr -nodefaults -display none -accel tcg -M none -device help | 
head
...
Misc devices:
name "guest-loader", desc "Guest Loader"
name "loader", desc "Generic Loader"

Jose R. Ziviani (2):
  meson: introduce modules_arch
  modules: use a list of supported arch for each module

 hw/display/meson.build  | 48 +
 hw/usb/meson.build  | 36 
 include/qemu/module.h   |  2 +-
 meson.build | 19 +++
 scripts/modinfo-collect.py  | 10 
 scripts/modinfo-generate.py |  7 +++---
 util/module.c   | 18 ++
 7 files changed, 125 insertions(+), 15 deletions(-)

-- 
2.33.0




[PATCH 3/4] ui/gtk: gd_draw_event returns FALSE when no cairo surface is bound

2021-09-16 Thread Dongwon Kim
gd_draw_event shouldn't try to repaint if surface does not exist
for the VC.

Cc: Gerd Hoffmann 
Signed-off-by: Dongwon Kim 
---
 ui/gtk.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index 92df3d4c5c..5346c331f4 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -778,6 +778,9 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t 
*cr, void *opaque)
 if (!vc->gfx.ds) {
 return FALSE;
 }
+if (!vc->gfx.surface) {
+return FALSE;
+}
 
 vc->gfx.dcl.update_interval =
 gd_monitor_update_interval(vc->window ? vc->window : s->window);
-- 
2.17.1




[PATCH 4/4] ui/gtk-egl: guest fb texture needs to be regenerated when reinitializing egl

2021-09-16 Thread Dongwon Kim
If guest fb is backed by dmabuf (blob-resource), the texture bound to the
old context needs to be recreated in case the egl is re-initialized (e.g.
new window for vc is created in case of detaching/reattaching of the tab)

v2: call egl_dmabuf_release_texutre instead of putting 0 to dmabuf->texture
(Vivek Kasireddy)

Cc: Gerd Hoffmann 
Signed-off-by: Dongwon Kim 
---
 ui/gtk-egl.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 7c9629d6cc..8c55ed18fb 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -142,6 +142,10 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
 surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
 surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds);
 }
+if (vc->gfx.guest_fb.dmabuf) {
+egl_dmabuf_release_texture(vc->gfx.guest_fb.dmabuf);
+gd_egl_scanout_dmabuf(dcl, vc->gfx.guest_fb.dmabuf);
+}
 }
 
 graphic_hw_update(dcl->con);
-- 
2.17.1




[PATCH 0/4] ui/gtk-egl: fix for untab/tab problem

2021-09-16 Thread Dongwon Kim
This series fixes several problems happening while doing VC untab/tab.

Dongwon Kim (4):
  ui/gtk-egl: un-tab and re-tab should destroy egl surface and context
  ui/gtk-egl: make sure the right context is set as the current
  ui/gtk: gd_draw_event returns FALSE when no cairo surface is bound
  ui/gtk-egl: guest fb texture needs to be regenerated when
reinitializing egl

 ui/gtk-egl.c | 10 ++
 ui/gtk.c | 19 +++
 2 files changed, 29 insertions(+)

-- 
2.17.1




[PATCH 2/4] ui/gtk-egl: make sure the right context is set as the current

2021-09-16 Thread Dongwon Kim
Making the vc->gfx.ectx current before handling texture
associated with it

Cc: Gerd Hoffmann 
Signed-off-by: Dongwon Kim 
---
 ui/gtk-egl.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 72ce5e1f8f..7c9629d6cc 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -139,6 +139,7 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
 }
 vc->gfx.gls = qemu_gl_init_shader();
 if (vc->gfx.ds) {
+surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
 surface_gl_create_texture(vc->gfx.gls, vc->gfx.ds);
 }
 }
@@ -165,6 +166,8 @@ void gd_egl_switch(DisplayChangeListener *dcl,
 surface_height(vc->gfx.ds) == surface_height(surface)) {
 resized = false;
 }
+eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
+   vc->gfx.esurface, vc->gfx.ectx);
 
 surface_gl_destroy_texture(vc->gfx.gls, vc->gfx.ds);
 vc->gfx.ds = surface;
@@ -224,6 +227,9 @@ void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl,
 #ifdef CONFIG_GBM
 VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
 
+eglMakeCurrent(qemu_egl_display, vc->gfx.esurface,
+   vc->gfx.esurface, vc->gfx.ectx);
+
 egl_dmabuf_import_texture(dmabuf);
 if (!dmabuf->texture) {
 return;
-- 
2.17.1




[PATCH 1/4] ui/gtk-egl: un-tab and re-tab should destroy egl surface and context

2021-09-16 Thread Dongwon Kim
An old esurface should be destroyed and set to be NULL when doing
un-tab and re-tab so that a new esurface an context can be created
for the window widget that those will be bound to.

Cc: Gerd Hoffmann 
Signed-off-by: Dongwon Kim 
Signed-off-by: Khairul Anuar Romli 
---
 ui/gtk.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index b0564d80c1..92df3d4c5c 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1242,6 +1242,14 @@ static gboolean gd_tab_window_close(GtkWidget *widget, 
GdkEvent *event,
 vc->tab_item, vc->label);
 gtk_widget_destroy(vc->window);
 vc->window = NULL;
+if (vc->gfx.esurface) {
+eglDestroySurface(qemu_egl_display, vc->gfx.esurface);
+vc->gfx.esurface = NULL;
+}
+if (vc->gfx.ectx) {
+eglDestroyContext(qemu_egl_display, vc->gfx.ectx);
+vc->gfx.ectx = NULL;
+}
 return TRUE;
 }
 
@@ -1271,6 +1279,14 @@ static void gd_menu_untabify(GtkMenuItem *item, void 
*opaque)
 if (!vc->window) {
 gtk_widget_set_sensitive(vc->menu_item, false);
 vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+if (vc->gfx.esurface) {
+eglDestroySurface(qemu_egl_display, vc->gfx.esurface);
+vc->gfx.esurface = NULL;
+}
+if (vc->gfx.esurface) {
+eglDestroyContext(qemu_egl_display, vc->gfx.ectx);
+vc->gfx.ectx = NULL;
+}
 gd_widget_reparent(s->notebook, vc->window, vc->tab_item);
 
 g_signal_connect(vc->window, "delete-event",
-- 
2.17.1




[PATCH] ui/gtk: skip any extra draw of same guest scanout blob res

2021-09-16 Thread Dongwon Kim
Any extra draw call for the same blob resource representing guest scanout
before the previous drawing is not finished can break synchronous draw
sequence. To prevent this, drawing is now done only once for each draw
submission (when draw_submitted == true). Mutex is added to protect this
draw iteration and the flag.

Cc: Gerd Hoffmann 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 hw/display/virtio-gpu-udmabuf.c |  3 ++
 include/ui/console.h|  3 ++
 ui/gtk-egl.c| 44 +++
 ui/gtk-gl-area.c| 53 +
 4 files changed, 71 insertions(+), 32 deletions(-)

diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index c6f7f58784..aabc7b81b5 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -186,6 +186,9 @@ static VGPUDMABuf
 dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
 dmabuf->buf.fd = res->dmabuf_fd;
 dmabuf->buf.allow_fences = true;
+dmabuf->buf.draw_submitted = false;
+
+qemu_mutex_init(&dmabuf->buf.mutex);
 
 dmabuf->scanout_id = scanout_id;
 QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);
diff --git a/include/ui/console.h b/include/ui/console.h
index 244664d727..0f931c3696 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -5,6 +5,7 @@
 #include "qom/object.h"
 #include "qemu/notify.h"
 #include "qemu/error-report.h"
+#include "qemu/lockable.h"
 #include "qapi/qapi-types-ui.h"
 
 #ifdef CONFIG_OPENGL
@@ -171,6 +172,8 @@ typedef struct QemuDmaBuf {
 void  *sync;
 int   fence_fd;
 bool  allow_fences;
+bool  draw_submitted;
+QemuMutex mutex;
 } QemuDmaBuf;
 
 typedef struct DisplayState DisplayState;
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 72ce5e1f8f..17727d040b 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -63,6 +63,9 @@ void gd_egl_init(VirtualConsole *vc)
 void gd_egl_draw(VirtualConsole *vc)
 {
 GdkWindow *window;
+#ifdef CONFIG_GBM
+QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
 int ww, wh;
 
 if (!vc->gfx.gls) {
@@ -74,10 +77,35 @@ void gd_egl_draw(VirtualConsole *vc)
 wh = gdk_window_get_height(window);
 
 if (vc->gfx.scanout_mode) {
+#ifdef CONFIG_GBM
+if (dmabuf) {
+qemu_mutex_lock(&dmabuf->mutex);
+if (!dmabuf->draw_submitted) {
+qemu_mutex_unlock(&dmabuf->mutex);
+return;
+} else {
+dmabuf->draw_submitted = false;
+}
+}
+#endif
 gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
 
 vc->gfx.scale_x = (double)ww / vc->gfx.w;
 vc->gfx.scale_y = (double)wh / vc->gfx.h;
+
+glFlush();
+#ifdef CONFIG_GBM
+if (dmabuf) {
+egl_dmabuf_create_fence(dmabuf);
+if (dmabuf->fence_fd > 0) {
+qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, 
vc);
+qemu_mutex_unlock(&dmabuf->mutex);
+return;
+}
+graphic_hw_gl_block(vc->gfx.dcl.con, false);
+qemu_mutex_unlock(&dmabuf->mutex);
+}
+#endif
 } else {
 if (!vc->gfx.ds) {
 return;
@@ -92,21 +120,10 @@ void gd_egl_draw(VirtualConsole *vc)
 
 vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
 vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
-}
-
-glFlush();
-#ifdef CONFIG_GBM
-if (vc->gfx.guest_fb.dmabuf) {
-QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
 
-egl_dmabuf_create_fence(dmabuf);
-if (dmabuf->fence_fd > 0) {
-qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
-return;
-}
-graphic_hw_gl_block(vc->gfx.dcl.con, false);
+glFlush();
 }
-#endif
+
 graphic_hw_gl_flushed(vc->gfx.dcl.con);
 }
 
@@ -317,6 +334,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
 
 if (vc->gfx.guest_fb.dmabuf) {
 graphic_hw_gl_block(vc->gfx.dcl.con, true);
+vc->gfx.guest_fb.dmabuf->draw_submitted = true;
 gtk_widget_queue_draw_area(area, x, y, w, h);
 return;
 }
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index b23523748e..7b432ad7f4 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -38,6 +38,9 @@ static void gtk_gl_area_set_scanout_mode(VirtualConsole *vc, 
bool scanout)
 
 void gd_gl_area_draw(VirtualConsole *vc)
 {
+#ifdef CONFIG_GBM
+QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
 int ww, wh, y1, y2;
 
 if (!vc->gfx.gls) {
@@ -53,6 +56,18 @@ void gd_gl_area_draw(VirtualConsole *vc)
 return;
 }
 
+#ifdef CONFIG_GBM
+if (dmabuf) {
+qemu_mutex_lock(&dmabuf->mutex);
+if (!dmabuf->draw_submitted) {
+qemu_mutex_unlock(&dmabuf->mutex);
+return;
+} else {
+dmabuf->draw_submi

Re: hw/i386/acpi: fix conflicting IO address range for acpi pci hotplug in q35

2021-09-16 Thread Michael S. Tsirkin
On Thu, Sep 16, 2021 at 06:58:35PM +0530, Ani Sinha wrote:
> Here's sending v2.
> 
> changelog :
> v1: original patch.
> v2: typo fixed. reviewed-by tags added.


Thanks, tagged!
Ani pls make sure the voer letter in the series has
subject

[PATCH 0/3] hw/i386/acpi: fix conflicting IO address range for acpi pci
 hotplug in q35


using --cover-letter with git format-patch will do this automatically.

It will also include diffstat and other useful info.


> This issue has been reported here:
> https://gitlab.com/qemu-project/qemu/-/issues/561
> 
> We have disucssed this issue at length here:
> https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02146.html
> 
> This issue affects Qemu version 6.1.
> 
> Patch 1 : allows q35 DSDT table changes.
> Patch 2 : actual fix.
> Patch 3: updates DSDT table blobs.
> 
> 




[PULL 0/2] Python patches

2021-09-16 Thread John Snow
The following changes since commit 831aaf24967a49d7750090b9dcfd6bf356f16529:

  Merge remote-tracking branch 'remotes/marcandre/tags/misc-pull-request' into 
staging (2021-09-14 18:14:56 +0100)

are available in the Git repository at:

  https://gitlab.com/jsnow/qemu.git tags/python-pull-request

for you to fetch changes up to eb8033f658e8b6f23ba9f4ef4a1b55894f7ea486:

  python: pylint 2.11 support (2021-09-16 15:04:04 -0400)


Python Pull request

This fixes the check-python-tox job.

CI including optional jobs is all green:
https://gitlab.com/jsnow/qemu/-/pipelines/372151147



John Snow (2):
  python: Update for pylint 2.10
  python: pylint 2.11 support

 python/qemu/machine/machine.py | 7 ++-
 python/setup.cfg   | 3 ++-
 2 files changed, 8 insertions(+), 2 deletions(-)

-- 
2.31.1





[PULL 2/2] python: pylint 2.11 support

2021-09-16 Thread John Snow
We're not ready to enforce f-strings everywhere, so just silence this
new warning.

Signed-off-by: John Snow 
Reviewed-by: Eduardo Habkost 
Reviewed-by: Willian Rampazzo 
Message-id: 20210916182248.721529-3-js...@redhat.com
Signed-off-by: John Snow 
---
 python/setup.cfg | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python/setup.cfg b/python/setup.cfg
index 0f0cab098f..fdca265fec 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -87,7 +87,7 @@ ignore_missing_imports = True
 # --enable=similarities". If you want to run only the classes checker, but have
 # no Warning level messages displayed, use "--disable=all --enable=classes
 # --disable=W".
-disable=
+disable=consider-using-f-string,
 
 [pylint.basic]
 # Good variable names which should always be accepted, separated by a comma.
-- 
2.31.1




[PULL 1/2] python: Update for pylint 2.10

2021-09-16 Thread John Snow
A few new annoyances. Of note is the new warning for an unspecified
encoding when opening a text file, which actually does indicate a
potentially real problem; see
https://www.python.org/dev/peps/pep-0597/#motivation

Use LC_CTYPE to determine an encoding to use for interpreting QEMU's
terminal output. Note that Python states: "language code and encoding
may be None if their values cannot be determined" -- use a platform
default as a backup.

Notes: Passing encoding=None will generate a suppressed warning on
Python 3.10+ that 'None' should not be passed as the encoding
argument. This behavior may be deprecated in the future and the default
switched to be a ubiquitous UTF-8. Opting in to the locale default will
be done by passing the encoding 'locale', but that isn't available in
3.6 through 3.9. Presumably this warning will be unsuppressed some time
prior to the actual switch and we can re-investigate these issues at
that time if necessary.

Signed-off-by: John Snow 
Reviewed-by: Eduardo Habkost 
Reviewed-by: Willian Rampazzo 
Message-id: 20210916182248.721529-2-js...@redhat.com
Signed-off-by: John Snow 
---
 python/qemu/machine/machine.py | 7 ++-
 python/setup.cfg   | 1 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index a7081b1845..34131884a5 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -19,6 +19,7 @@
 
 import errno
 from itertools import chain
+import locale
 import logging
 import os
 import shutil
@@ -290,8 +291,12 @@ def get_pid(self) -> Optional[int]:
 return self._subp.pid
 
 def _load_io_log(self) -> None:
+# Assume that the output encoding of QEMU's terminal output is
+# defined by our locale. If indeterminate, allow open() to fall
+# back to the platform default.
+_, encoding = locale.getlocale()
 if self._qemu_log_path is not None:
-with open(self._qemu_log_path, "r") as iolog:
+with open(self._qemu_log_path, "r", encoding=encoding) as iolog:
 self._iolog = iolog.read()
 
 @property
diff --git a/python/setup.cfg b/python/setup.cfg
index 83909c1c97..0f0cab098f 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -104,6 +104,7 @@ good-names=i,
 [pylint.similarities]
 # Ignore imports when computing similarities.
 ignore-imports=yes
+ignore-signatures=yes
 
 # Minimum lines number of a similarity.
 # TODO: Remove after we opt in to Pylint 2.8.3. See commit msg.
-- 
2.31.1




[PULL 19/21] target/riscv: Backup/restore mstatus.SD bit when virtual register swapped

2021-09-16 Thread Alistair Francis
From: Frank Chang 

When virtual registers are swapped, mstatus.SD bit should also be
backed up/restored. Otherwise, mstatus.SD bit will be incorrectly kept
across the world switches.

Signed-off-by: Frank Chang 
Reviewed-by: Vincent Chen 
Reviewed-by: Alistair Francis 
Message-id: 20210914013717.881430-1-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 701858d670..00ad21f1e1 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -106,9 +106,10 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
 
 void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
 {
+target_ulong sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
 uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
 MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
-MSTATUS64_UXL;
+MSTATUS64_UXL | sd;
 bool current_virt = riscv_cpu_virt_enabled(env);
 
 g_assert(riscv_has_ext(env, RVH));
-- 
2.31.1




[PULL 21/21] hw/riscv: opentitan: Correct the USB Dev address

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 
d6cb4dfe75a2f536f217d7075b750ece3acb1535.1631767043.git.alistair.fran...@wdc.com
Signed-off-by: Alistair Francis 
---
 hw/riscv/opentitan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index f7cfcf1c3a..9803ae6d70 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -39,12 +39,12 @@ static const MemMapEntry ibex_memmap[] = {
 [IBEX_DEV_TIMER] =  {  0x4010,  0x1000  },
 [IBEX_DEV_SENSOR_CTRL] ={  0x4011,  0x1000  },
 [IBEX_DEV_OTP_CTRL] =   {  0x4013,  0x4000  },
+[IBEX_DEV_USBDEV] = {  0x4015,  0x1000  },
 [IBEX_DEV_PWRMGR] = {  0x4040,  0x1000  },
 [IBEX_DEV_RSTMGR] = {  0x4041,  0x1000  },
 [IBEX_DEV_CLKMGR] = {  0x4042,  0x1000  },
 [IBEX_DEV_PINMUX] = {  0x4046,  0x1000  },
 [IBEX_DEV_PADCTRL] ={  0x4047,  0x1000  },
-[IBEX_DEV_USBDEV] = {  0x4050,  0x1000  },
 [IBEX_DEV_FLASH_CTRL] = {  0x4100,  0x1000  },
 [IBEX_DEV_PLIC] =   {  0x4101,  0x1000  },
 [IBEX_DEV_AES] ={  0x4110,  0x1000  },
-- 
2.31.1




[PULL 18/21] docs/system/riscv: sifive_u: Update U-Boot instructions

2021-09-16 Thread Alistair Francis
From: Bin Meng 

In U-Boot v2021.07 release, there were 2 major changes for the
SiFive Unleashed board support:

- Board config name was changed from sifive_fu540_defconfig to
  sifive_unleashed_defconfig
- The generic binman tool was used to generate the FIT image
  (combination of U-Boot proper, DTB and OpenSBI firmware)

which make the existing U-Boot instructions out of date.

Update the doc with latest instructions.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210911153431.10362-1-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 docs/system/riscv/sifive_u.rst | 49 ++
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
index 7c65e9c440..7b166567f9 100644
--- a/docs/system/riscv/sifive_u.rst
+++ b/docs/system/riscv/sifive_u.rst
@@ -210,15 +210,16 @@ command line options with ``qemu-system-riscv32``.
 Running U-Boot
 --
 
-U-Boot mainline v2021.01 release is tested at the time of writing. To build a
+U-Boot mainline v2021.07 release is tested at the time of writing. To build a
 U-Boot mainline bootloader that can be booted by the ``sifive_u`` machine, use
-the sifive_fu540_defconfig with similar commands as described above for Linux:
+the sifive_unleashed_defconfig with similar commands as described above for
+Linux:
 
 .. code-block:: bash
 
   $ export CROSS_COMPILE=riscv64-linux-
   $ export OPENSBI=/path/to/opensbi-riscv64-generic-fw_dynamic.bin
-  $ make sifive_fu540_defconfig
+  $ make sifive_unleashed_defconfig
 
 You will get spl/u-boot-spl.bin and u-boot.itb file in the build tree.
 
@@ -313,31 +314,29 @@ board on QEMU ``sifive_u`` machine out of the box. This 
allows users to
 develop and test the recommended RISC-V boot flow with a real world use
 case: ZSBL (in QEMU) loads U-Boot SPL from SD card or SPI flash to L2LIM,
 then U-Boot SPL loads the combined payload image of OpenSBI fw_dynamic
-firmware and U-Boot proper. However sometimes we want to have a quick test
-of booting U-Boot on QEMU without the needs of preparing the SPI flash or
-SD card images, an alternate way can be used, which is to create a U-Boot
-S-mode image by modifying the configuration of U-Boot:
+firmware and U-Boot proper.
+
+However sometimes we want to have a quick test of booting U-Boot on QEMU
+without the needs of preparing the SPI flash or SD card images, an alternate
+way can be used, which is to create a U-Boot S-mode image by modifying the
+configuration of U-Boot:
 
 .. code-block:: bash
 
+  $ export CROSS_COMPILE=riscv64-linux-
+  $ make sifive_unleashed_defconfig
   $ make menuconfig
 
-then manually select the following configuration in U-Boot:
-
-  Device Tree Control > Provider of DTB for DT Control > Prior Stage 
bootloader DTB
+then manually select the following configuration:
 
-This lets U-Boot to use the QEMU generated device tree blob. During the build,
-a build error will be seen below:
+  * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage 
bootloader DTB
 
-.. code-block:: none
+and unselect the following configuration:
 
-  MKIMAGE u-boot.img
-  ./tools/mkimage: Can't open arch/riscv/dts/hifive-unleashed-a00.dtb: No such 
file or directory
-  ./tools/mkimage: failed to build FIT
-  make: *** [Makefile:1440: u-boot.img] Error 1
+  * Library routines ---> Allow access to binman information in the device tree
 
-The above errors can be safely ignored as we don't run U-Boot SPL under QEMU
-in this alternate configuration.
+This changes U-Boot to use the QEMU generated device tree blob, and bypass
+running the U-Boot SPL stage.
 
 Boot the 64-bit U-Boot S-mode image directly:
 
@@ -352,14 +351,18 @@ It's possible to create a 32-bit U-Boot S-mode image as 
well.
 .. code-block:: bash
 
   $ export CROSS_COMPILE=riscv64-linux-
-  $ make sifive_fu540_defconfig
+  $ make sifive_unleashed_defconfig
   $ make menuconfig
 
 then manually update the following configuration in U-Boot:
 
-  Device Tree Control > Provider of DTB for DT Control > Prior Stage 
bootloader DTB
-  RISC-V architecture > Base ISA > RV32I
-  Boot images > Text Base > 0x8040
+  * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage 
bootloader DTB
+  * RISC-V architecture ---> Base ISA ---> RV32I
+  * Boot options ---> Boot images ---> Text Base ---> 0x8040
+
+and unselect the following configuration:
+
+  * Library routines ---> Allow access to binman information in the device tree
 
 Use the same command line options to boot the 32-bit U-Boot S-mode image:
 
-- 
2.31.1




[PULL 20/21] target/riscv: csr: Rename HCOUNTEREN_CY and friends

2021-09-16 Thread Alistair Francis
From: Bin Meng 

The macro name HCOUNTEREN_CY suggests it is for CSR HCOUNTEREN, but
in fact it applies to M-mode and S-mode CSR too. Rename these macros
to have the COUNTEREN_ prefix.

Signed-off-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210915084601.24304-1-bmeng...@gmail.com
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_bits.h |  8 
 target/riscv/csr.c  | 24 
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index ce9dcc030c..999187a9ee 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -397,10 +397,10 @@
 #define HSTATUS32_WPRI   0xFF8FF87E
 #define HSTATUS64_WPRI   0xFF8FF87EULL
 
-#define HCOUNTEREN_CY(1 << 0)
-#define HCOUNTEREN_TM(1 << 1)
-#define HCOUNTEREN_IR(1 << 2)
-#define HCOUNTEREN_HPM3  (1 << 3)
+#define COUNTEREN_CY (1 << 0)
+#define COUNTEREN_TM (1 << 1)
+#define COUNTEREN_IR (1 << 2)
+#define COUNTEREN_HPM3   (1 << 3)
 
 /* Privilege modes */
 #define PRV_U 0
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index ba9818f6a5..23fbbd3216 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -71,20 +71,20 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 if (riscv_cpu_virt_enabled(env)) {
 switch (csrno) {
 case CSR_CYCLE:
-if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
-get_field(env->mcounteren, HCOUNTEREN_CY)) {
+if (!get_field(env->hcounteren, COUNTEREN_CY) &&
+get_field(env->mcounteren, COUNTEREN_CY)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
 case CSR_TIME:
-if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
-get_field(env->mcounteren, HCOUNTEREN_TM)) {
+if (!get_field(env->hcounteren, COUNTEREN_TM) &&
+get_field(env->mcounteren, COUNTEREN_TM)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
 case CSR_INSTRET:
-if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
-get_field(env->mcounteren, HCOUNTEREN_IR)) {
+if (!get_field(env->hcounteren, COUNTEREN_IR) &&
+get_field(env->mcounteren, COUNTEREN_IR)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
@@ -98,20 +98,20 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 if (riscv_cpu_is_32bit(env)) {
 switch (csrno) {
 case CSR_CYCLEH:
-if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
-get_field(env->mcounteren, HCOUNTEREN_CY)) {
+if (!get_field(env->hcounteren, COUNTEREN_CY) &&
+get_field(env->mcounteren, COUNTEREN_CY)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
 case CSR_TIMEH:
-if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
-get_field(env->mcounteren, HCOUNTEREN_TM)) {
+if (!get_field(env->hcounteren, COUNTEREN_TM) &&
+get_field(env->mcounteren, COUNTEREN_TM)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
 case CSR_INSTRETH:
-if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
-get_field(env->mcounteren, HCOUNTEREN_IR)) {
+if (!get_field(env->hcounteren, COUNTEREN_IR) &&
+get_field(env->mcounteren, COUNTEREN_IR)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
-- 
2.31.1




[PULL 17/21] hw/dma: sifive_pdma: don't set Control.error if 0 bytes to transfer

2021-09-16 Thread Alistair Francis
From: Frank Chang 

Real PDMA doesn't set Control.error if there are 0 bytes to be
transferred. The DMA transfer is still success.

The following result is PDMA tested in U-Boot on Unmatched board:

=> mw.l 0x300 0x0  <= Disclaim channel 0
=> mw.l 0x300 0x1  <= Claim channel 0
=> mw.l 0x304 0x5500   <= wsize = rsize = 5 (2^5 = 32 bytes)
=> mw.q 0x308 0x0  <= NextBytes = 0
=> mw.q 0x310 0x8400   <= NextDestination = 0x8400
=> mw.q 0x318 0x84001000   <= NextSource = 0x84001000
=> mw.l 0x8400 0x87654321  <= Fill test data to dst
=> mw.l 0x84001000 0x12345678  <= Fill test data to src
=> md.l 0x8400 1; md.l 0x84001000 1<= Dump src/dst memory contents
8400: 87654321   !Ce.
84001000: 12345678   xV4.
=> md.l 0x300 8<= Dump PDMA status
0300: 0001 5500  ...U
0310: 8400  84001000 
=> mw.l 0x300 0x3  <= Set channel 0 run and claim bits
=> md.l 0x300 8<= Dump PDMA status
0300: 4001 5500  ...@...U
0310: 8400  84001000 
=> md.l 0x8400 1; md.l 0x84001000 1<= Dump src/dst memory contents
8400: 87654321   !Ce.
84001000: 12345678   xV4.

Signed-off-by: Frank Chang 
Tested-by: Max Hsu 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-id: 20210912130553.179501-5-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 hw/dma/sifive_pdma.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
index d7d2c53e97..b4fd40573a 100644
--- a/hw/dma/sifive_pdma.c
+++ b/hw/dma/sifive_pdma.c
@@ -80,7 +80,7 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
 
 /* do nothing if bytes to transfer is zero */
 if (!bytes) {
-goto error;
+goto done;
 }
 
 /*
@@ -135,11 +135,6 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
 s->chan[ch].exec_bytes -= remainder;
 }
 
-/* indicate a DMA transfer is done */
-s->chan[ch].state = DMA_CHAN_STATE_DONE;
-s->chan[ch].control &= ~CONTROL_RUN;
-s->chan[ch].control |= CONTROL_DONE;
-
 /* reload exec_ registers if repeat is required */
 if (s->chan[ch].next_config & CONFIG_REPEAT) {
 s->chan[ch].exec_bytes = bytes;
@@ -147,6 +142,11 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
 s->chan[ch].exec_src = src;
 }
 
+done:
+/* indicate a DMA transfer is done */
+s->chan[ch].state = DMA_CHAN_STATE_DONE;
+s->chan[ch].control &= ~CONTROL_RUN;
+s->chan[ch].control |= CONTROL_DONE;
 return;
 
 error:
-- 
2.31.1




[PULL 13/21] hw/riscv: virt: Add optional ACLINT support to virt machine

2021-09-16 Thread Alistair Francis
From: Anup Patel 

We extend virt machine to emulate ACLINT devices only when "aclint=on"
parameter is passed along with machine name in QEMU command-line.

Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 20210831110603.338681-5-anup.pa...@wdc.com
Signed-off-by: Alistair Francis 
---
 docs/system/riscv/virt.rst |  10 
 include/hw/riscv/virt.h|   2 +
 hw/riscv/virt.c| 113 -
 3 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
index 321d77e07d..fa016584bf 100644
--- a/docs/system/riscv/virt.rst
+++ b/docs/system/riscv/virt.rst
@@ -53,6 +53,16 @@ with the default OpenSBI firmware image as the -bios. It 
also supports
 the recommended RISC-V bootflow: U-Boot SPL (M-mode) loads OpenSBI fw_dynamic
 firmware and U-Boot proper (S-mode), using the standard -bios functionality.
 
+Machine-specific options
+
+
+The following machine-specific options are supported:
+
+- aclint=[on|off]
+
+  When this option is "on", ACLINT devices will be emulated instead of
+  SiFive CLINT. When not specified, this option is assumed to be "off".
+
 Running Linux kernel
 
 
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 349fee1f89..d9105c1886 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -43,6 +43,7 @@ struct RISCVVirtState {
 FWCfgState *fw_cfg;
 
 int fdt_size;
+bool have_aclint;
 };
 
 enum {
@@ -51,6 +52,7 @@ enum {
 VIRT_TEST,
 VIRT_RTC,
 VIRT_CLINT,
+VIRT_ACLINT_SSWI,
 VIRT_PLIC,
 VIRT_UART0,
 VIRT_VIRTIO,
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 7f716901ef..ec0cb69b8c 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -48,6 +48,7 @@ static const MemMapEntry virt_memmap[] = {
 [VIRT_TEST] ={   0x10,0x1000 },
 [VIRT_RTC] = {   0x101000,0x1000 },
 [VIRT_CLINT] =   {  0x200,   0x1 },
+[VIRT_ACLINT_SSWI] = {  0x2F0,0x4000 },
 [VIRT_PCIE_PIO] ={  0x300,   0x1 },
 [VIRT_PLIC] ={  0xc00, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
 [VIRT_UART0] =   { 0x1000, 0x100 },
@@ -281,6 +282,82 @@ static void create_fdt_socket_clint(RISCVVirtState *s,
 g_free(clint_cells);
 }
 
+static void create_fdt_socket_aclint(RISCVVirtState *s,
+ const MemMapEntry *memmap, int socket,
+ uint32_t *intc_phandles)
+{
+int cpu;
+char *name;
+unsigned long addr;
+uint32_t aclint_cells_size;
+uint32_t *aclint_mswi_cells;
+uint32_t *aclint_sswi_cells;
+uint32_t *aclint_mtimer_cells;
+MachineState *mc = MACHINE(s);
+
+aclint_mswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
+aclint_mtimer_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
+aclint_sswi_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
+
+for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
+aclint_mswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+aclint_mswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_SOFT);
+aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);
+aclint_sswi_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+aclint_sswi_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_SOFT);
+}
+aclint_cells_size = s->soc[socket].num_harts * sizeof(uint32_t) * 2;
+
+addr = memmap[VIRT_CLINT].base + (memmap[VIRT_CLINT].size * socket);
+name = g_strdup_printf("/soc/mswi@%lx", addr);
+qemu_fdt_add_subnode(mc->fdt, name);
+qemu_fdt_setprop_string(mc->fdt, name, "compatible", "riscv,aclint-mswi");
+qemu_fdt_setprop_cells(mc->fdt, name, "reg",
+0x0, addr, 0x0, RISCV_ACLINT_SWI_SIZE);
+qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
+aclint_mswi_cells, aclint_cells_size);
+qemu_fdt_setprop(mc->fdt, name, "interrupt-controller", NULL, 0);
+qemu_fdt_setprop_cell(mc->fdt, name, "#interrupt-cells", 0);
+riscv_socket_fdt_write_id(mc, mc->fdt, name, socket);
+g_free(name);
+
+addr = memmap[VIRT_CLINT].base + RISCV_ACLINT_SWI_SIZE +
+(memmap[VIRT_CLINT].size * socket);
+name = g_strdup_printf("/soc/mtimer@%lx", addr);
+qemu_fdt_add_subnode(mc->fdt, name);
+qemu_fdt_setprop_string(mc->fdt, name, "compatible",
+"riscv,aclint-mtimer");
+qemu_fdt_setprop_cells(mc->fdt, name, "reg",
+0x0, addr + RISCV_ACLINT_DEFAULT_MTIME,
+0x0, memmap[VIRT_CLINT].size - RISCV_ACLINT_SWI_SIZE -
+ RISCV_ACLINT_DEFAULT_MTIME,
+0x0, addr + RISCV_ACLINT_DEFAULT_MTIMECMP,
+0x0, RISCV_ACLINT_DEFAULT_MTIME);
+qemu_fdt_setprop(mc->fdt, name, "interrupts-extended",
+aclint_mtimer_ce

[PULL 10/21] hw/intc: Rename sifive_clint sources to riscv_aclint sources

2021-09-16 Thread Alistair Francis
From: Anup Patel 

We will be upgrading SiFive CLINT implementation into RISC-V ACLINT
implementation so let's first rename the sources.

Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 20210831110603.338681-2-anup.pa...@wdc.com
Signed-off-by: Alistair Francis 
---
 include/hw/intc/{sifive_clint.h => riscv_aclint.h} |  0
 hw/intc/{sifive_clint.c => riscv_aclint.c} |  2 +-
 hw/riscv/microchip_pfsoc.c |  2 +-
 hw/riscv/shakti_c.c|  2 +-
 hw/riscv/sifive_e.c|  2 +-
 hw/riscv/sifive_u.c|  2 +-
 hw/riscv/spike.c   |  2 +-
 hw/riscv/virt.c|  2 +-
 hw/intc/Kconfig|  2 +-
 hw/intc/meson.build|  2 +-
 hw/riscv/Kconfig   | 12 ++--
 11 files changed, 15 insertions(+), 15 deletions(-)
 rename include/hw/intc/{sifive_clint.h => riscv_aclint.h} (100%)
 rename hw/intc/{sifive_clint.c => riscv_aclint.c} (99%)

diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/riscv_aclint.h
similarity index 100%
rename from include/hw/intc/sifive_clint.h
rename to include/hw/intc/riscv_aclint.h
diff --git a/hw/intc/sifive_clint.c b/hw/intc/riscv_aclint.c
similarity index 99%
rename from hw/intc/sifive_clint.c
rename to hw/intc/riscv_aclint.c
index ab172d8e40..31ce990d0e 100644
--- a/hw/intc/sifive_clint.c
+++ b/hw/intc/riscv_aclint.c
@@ -26,7 +26,7 @@
 #include "hw/sysbus.h"
 #include "target/riscv/cpu.h"
 #include "hw/qdev-properties.h"
-#include "hw/intc/sifive_clint.h"
+#include "hw/intc/riscv_aclint.h"
 #include "qemu/timer.h"
 #include "hw/irq.h"
 
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index eef55f69fd..eed9e81355 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -49,7 +49,7 @@
 #include "hw/riscv/boot.h"
 #include "hw/riscv/riscv_hart.h"
 #include "hw/riscv/microchip_pfsoc.h"
-#include "hw/intc/sifive_clint.h"
+#include "hw/intc/riscv_aclint.h"
 #include "hw/intc/sifive_plic.h"
 #include "sysemu/device_tree.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c
index 09d4e1433e..f9f0a45651 100644
--- a/hw/riscv/shakti_c.c
+++ b/hw/riscv/shakti_c.c
@@ -21,7 +21,7 @@
 #include "hw/riscv/shakti_c.h"
 #include "qapi/error.h"
 #include "hw/intc/sifive_plic.h"
-#include "hw/intc/sifive_clint.h"
+#include "hw/intc/riscv_aclint.h"
 #include "sysemu/sysemu.h"
 #include "hw/qdev-properties.h"
 #include "exec/address-spaces.h"
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 04265c5640..a73848958e 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -41,7 +41,7 @@
 #include "hw/riscv/sifive_e.h"
 #include "hw/riscv/boot.h"
 #include "hw/char/sifive_uart.h"
-#include "hw/intc/sifive_clint.h"
+#include "hw/intc/riscv_aclint.h"
 #include "hw/intc/sifive_plic.h"
 #include "hw/misc/sifive_e_prci.h"
 #include "chardev/char.h"
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index f4cde10667..aaab46c43c 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -52,7 +52,7 @@
 #include "hw/riscv/sifive_u.h"
 #include "hw/riscv/boot.h"
 #include "hw/char/sifive_uart.h"
-#include "hw/intc/sifive_clint.h"
+#include "hw/intc/riscv_aclint.h"
 #include "hw/intc/sifive_plic.h"
 #include "chardev/char.h"
 #include "net/eth.h"
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index aae36f2cb4..690c19c12a 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -35,7 +35,7 @@
 #include "hw/riscv/boot.h"
 #include "hw/riscv/numa.h"
 #include "hw/char/riscv_htif.h"
-#include "hw/intc/sifive_clint.h"
+#include "hw/intc/riscv_aclint.h"
 #include "chardev/char.h"
 #include "sysemu/device_tree.h"
 #include "sysemu/sysemu.h"
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 47f1beb473..df33fd74c2 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -32,7 +32,7 @@
 #include "hw/riscv/virt.h"
 #include "hw/riscv/boot.h"
 #include "hw/riscv/numa.h"
-#include "hw/intc/sifive_clint.h"
+#include "hw/intc/riscv_aclint.h"
 #include "hw/intc/sifive_plic.h"
 #include "hw/misc/sifive_test.h"
 #include "chardev/char.h"
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index f4694088a4..78aed93c45 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -62,7 +62,7 @@ config RX_ICU
 config LOONGSON_LIOINTC
 bool
 
-config SIFIVE_CLINT
+config RISCV_ACLINT
 bool
 
 config SIFIVE_PLIC
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 4dcfea6aa8..a1d00aa48d 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -47,7 +47,7 @@ specific_ss.add(when: 'CONFIG_RX_ICU', if_true: 
files('rx_icu.c'))
 specific_ss.add(when: 'CONFIG_S390_FLIC', if_true: files('s390_flic.c'))
 specific_ss.add(when: 'CONFIG_S390_FLIC_KVM', if_true: 
files('s390_flic_kvm.c'))
 specific_ss.add(when: 'CONFIG_SH_INTC', if_t

[PULL 11/21] hw/intc: Upgrade the SiFive CLINT implementation to RISC-V ACLINT

2021-09-16 Thread Alistair Francis
From: Anup Patel 

The RISC-V ACLINT is more modular and backward compatible with
original SiFive CLINT so instead of duplicating the original
SiFive CLINT implementation we upgrade the current SiFive CLINT
implementation to RISC-V ACLINT implementation.

Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 20210831110603.338681-3-anup.pa...@wdc.com
Signed-off-by: Alistair Francis 
---
 include/hw/intc/riscv_aclint.h |  54 +++--
 hw/intc/riscv_aclint.c | 373 +++--
 hw/riscv/microchip_pfsoc.c |   9 +-
 hw/riscv/shakti_c.c|  11 +-
 hw/riscv/sifive_e.c|  11 +-
 hw/riscv/sifive_u.c|   9 +-
 hw/riscv/spike.c   |  14 +-
 hw/riscv/virt.c|  14 +-
 8 files changed, 339 insertions(+), 156 deletions(-)

diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h
index 921b1561dd..229bd08d25 100644
--- a/include/hw/intc/riscv_aclint.h
+++ b/include/hw/intc/riscv_aclint.h
@@ -1,8 +1,9 @@
 /*
- * SiFive CLINT (Core Local Interruptor) interface
+ * RISC-V ACLINT (Advanced Core Local Interruptor) interface
  *
  * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
  * Copyright (c) 2017 SiFive, Inc.
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -17,17 +18,17 @@
  * this program.  If not, see .
  */
 
-#ifndef HW_SIFIVE_CLINT_H
-#define HW_SIFIVE_CLINT_H
+#ifndef HW_RISCV_ACLINT_H
+#define HW_RISCV_ACLINT_H
 
 #include "hw/sysbus.h"
 
-#define TYPE_SIFIVE_CLINT "riscv.sifive.clint"
+#define TYPE_RISCV_ACLINT_MTIMER "riscv.aclint.mtimer"
 
-#define SIFIVE_CLINT(obj) \
-OBJECT_CHECK(SiFiveCLINTState, (obj), TYPE_SIFIVE_CLINT)
+#define RISCV_ACLINT_MTIMER(obj) \
+OBJECT_CHECK(RISCVAclintMTimerState, (obj), TYPE_RISCV_ACLINT_MTIMER)
 
-typedef struct SiFiveCLINTState {
+typedef struct RISCVAclintMTimerState {
 /*< private >*/
 SysBusDevice parent_obj;
 
@@ -35,28 +36,45 @@ typedef struct SiFiveCLINTState {
 MemoryRegion mmio;
 uint32_t hartid_base;
 uint32_t num_harts;
-uint32_t sip_base;
 uint32_t timecmp_base;
 uint32_t time_base;
 uint32_t aperture_size;
 uint32_t timebase_freq;
 qemu_irq *timer_irqs;
-qemu_irq *soft_irqs;
-} SiFiveCLINTState;
+} RISCVAclintMTimerState;
 
-DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
-uint32_t hartid_base, uint32_t num_harts, uint32_t sip_base,
+DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size,
+uint32_t hartid_base, uint32_t num_harts,
 uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq,
 bool provide_rdtime);
 
-enum {
-SIFIVE_SIP_BASE = 0x0,
-SIFIVE_TIMECMP_BASE = 0x4000,
-SIFIVE_TIME_BASE= 0xBFF8
-};
+#define TYPE_RISCV_ACLINT_SWI "riscv.aclint.swi"
+
+#define RISCV_ACLINT_SWI(obj) \
+OBJECT_CHECK(RISCVAclintSwiState, (obj), TYPE_RISCV_ACLINT_SWI)
+
+typedef struct RISCVAclintSwiState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion mmio;
+uint32_t hartid_base;
+uint32_t num_harts;
+uint32_t sswi;
+qemu_irq *soft_irqs;
+} RISCVAclintSwiState;
+
+DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base,
+uint32_t num_harts, bool sswi);
 
 enum {
-SIFIVE_CLINT_TIMEBASE_FREQ = 1000
+RISCV_ACLINT_DEFAULT_MTIMECMP  = 0x0,
+RISCV_ACLINT_DEFAULT_MTIME = 0x7ff8,
+RISCV_ACLINT_DEFAULT_MTIMER_SIZE   = 0x8000,
+RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ = 1000,
+RISCV_ACLINT_MAX_HARTS = 4095,
+RISCV_ACLINT_SWI_SIZE  = 0x4000
 };
 
 #endif
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 31ce990d0e..f1a5d3d284 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -1,8 +1,10 @@
 /*
- * SiFive CLINT (Core Local Interruptor)
+ * RISC-V ACLINT (Advanced Core Local Interruptor)
+ * URL: https://github.com/riscv/riscv-aclint
  *
  * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
  * Copyright (c) 2017 SiFive, Inc.
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
  *
  * This provides real-time clock, timer and interprocessor interrupts.
  *
@@ -22,6 +24,7 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
+#include "qemu/log.h"
 #include "qemu/module.h"
 #include "hw/sysbus.h"
 #include "target/riscv/cpu.h"
@@ -30,10 +33,10 @@
 #include "qemu/timer.h"
 #include "hw/irq.h"
 
-typedef struct sifive_clint_callback {
-SiFiveCLINTState *s;
+typedef struct riscv_aclint_mtimer_callback {
+RISCVAclintMTimerState *s;
 int num;
-} sifive_clint_callback;
+} riscv_aclint_mtimer_callback;
 
 static uint64_t cpu_riscv_read_rtc(uint32_t timebase_fr

[PULL 15/21] hw/dma: sifive_pdma: claim bit must be set before DMA transactions

2021-09-16 Thread Alistair Francis
From: Frank Chang 

Real PDMA must have Control.claim bit to be set before
Control.run bit is set to start any DMA transactions.
Otherwise nothing will be transferred.

The following result is PDMA tested in U-Boot on Unmatched board:

=> mw.l 0x300 0x0  <= Disclaim channel 0
  (Channel 0 is not claimed)
=> mw.l 0x304 0x5500   <= wsize = rsize = 5 (2^5 = 32 bytes)
=> mw.q 0x308 0x2  <= NextBytes = 2
=> mw.q 0x310 0x8400   <= NextDestination = 0x8400
=> mw.q 0x318 0x84001000   <= NextSource = 0x84001000
=> mw.l 0x8400 0x87654321  <= Fill test data to dst
=> mw.l 0x84001000 0x12345678  <= Fill test data to src
=> md.l 0x8400 1; md.l 0x84001000 1<= Dump src/dst memory contents
8400: 87654321   !Ce.
84001000: 12345678   xV4.
=> md.l 0x300 8<= Dump PDMA status
0300:  5500 0002 ...U
0310: 8400  84001000 
=> mw.l 0x300 0x3  <= Set channel 0 run and claim bits
=> md.l 0x300 8<= Dump PDMA status
0300: 0001 6600  ...f
0310:    
=> md.l 0x8400 1; md.l 0x84001000 1<= Dump src/dst memory contents
8400: 87654321   !Ce.
84001000: 12345678   xV4.

Signed-off-by: Frank Chang 
Tested-by: Max Hsu 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-id: 20210912130553.179501-3-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 hw/dma/sifive_pdma.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
index d92e27dfdc..a8ce3e6699 100644
--- a/hw/dma/sifive_pdma.c
+++ b/hw/dma/sifive_pdma.c
@@ -252,6 +252,15 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
 
 s->chan[ch].control = value;
 
+/*
+ * If channel was not claimed before run bit is set,
+ * DMA won't run.
+ */
+if (!claimed) {
+s->chan[ch].control &= ~CONTROL_RUN;
+return;
+}
+
 if (value & CONTROL_RUN) {
 sifive_pdma_run(s, ch);
 }
-- 
2.31.1




[PULL 16/21] hw/dma: sifive_pdma: allow non-multiple transaction size transactions

2021-09-16 Thread Alistair Francis
From: Green Wan 

Real PDMA is able to deal with non-multiple transaction size transactions.

The following result is PDMA tested in U-Boot on Unmatched board:

=> mw.l 0x300 0x0  <= Disclaim channel 0
=> mw.l 0x300 0x1  <= Claim channel 0
=> mw.l 0x304 0x1100   <= wsize = rsize = 1 (2^1 = 2 bytes)
=> mw.q 0x308 0x3  <= NextBytes = 3
=> mw.q 0x310 0x8400   <= NextDestination = 0x8400
=> mw.q 0x318 0x84001000   <= NextSource = 0x84001000
=> mw.l 0x8400 0x87654321  <= Fill test data to dst
=> mw.l 0x84001000 0x12345678  <= Fill test data to src
=> md.l 0x8400 1; md.l 0x84001000 1<= Dump src/dst memory contents
8400: 87654321   !Ce.
84001000: 12345678   xV4.
=> md.l 0x300 8<= Dump PDMA status
0300: 0001 1100 0003 
0310: 8400  84001000 
=> mw.l 0x300 0x3  <= Set channel 0 run and claim bits
=> md.l 0x300 8<= Dump PDMA status
0300: 4001 1100 0003 ...@
0310: 8400  84001000 
=> md.l 0x8400 1; md.l 0x84001000 1<= Dump src/dst memory contents
8400: 87345678   xV4.
84001000: 12345678   xV4.

Signed-off-by: Green Wan 
Reviewed-by: Frank Chang 
Tested-by: Max Hsu 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Signed-off-by: Frank Chang 
Message-id: 20210912130553.179501-4-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 hw/dma/sifive_pdma.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
index a8ce3e6699..d7d2c53e97 100644
--- a/hw/dma/sifive_pdma.c
+++ b/hw/dma/sifive_pdma.c
@@ -74,7 +74,7 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
 uint64_t dst = s->chan[ch].next_dst;
 uint64_t src = s->chan[ch].next_src;
 uint32_t config = s->chan[ch].next_config;
-int wsize, rsize, size;
+int wsize, rsize, size, remainder;
 uint8_t buf[64];
 int n;
 
@@ -106,11 +106,7 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
 size = 6;
 }
 size = 1 << size;
-
-/* the bytes to transfer should be multiple of transaction size */
-if (bytes % size) {
-goto error;
-}
+remainder = bytes % size;
 
 /* indicate a DMA transfer is started */
 s->chan[ch].state = DMA_CHAN_STATE_STARTED;
@@ -131,6 +127,14 @@ static void sifive_pdma_run(SiFivePDMAState *s, int ch)
 s->chan[ch].exec_bytes -= size;
 }
 
+if (remainder) {
+cpu_physical_memory_read(s->chan[ch].exec_src, buf, remainder);
+cpu_physical_memory_write(s->chan[ch].exec_dst, buf, remainder);
+s->chan[ch].exec_src += remainder;
+s->chan[ch].exec_dst += remainder;
+s->chan[ch].exec_bytes -= remainder;
+}
+
 /* indicate a DMA transfer is done */
 s->chan[ch].state = DMA_CHAN_STATE_DONE;
 s->chan[ch].control &= ~CONTROL_RUN;
-- 
2.31.1




[PULL 08/21] hw/timer: Add SiFive PWM support

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

This is the initial commit of the SiFive PWM timer. This is used by
guest software as a timer and is included in the SiFive FU540 SoC.

Signed-off-by: Justin Restivo 
Signed-off-by: Alexandra Clifford 
Signed-off-by: Amanda Strnad 
Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 
9f70a210acbfaf0e1ea6ad311ab892ac69134d8b.1631159656.git.alistair.fran...@wdc.com
---
 include/hw/timer/sifive_pwm.h |  62 +
 hw/timer/sifive_pwm.c | 468 ++
 hw/timer/Kconfig  |   3 +
 hw/timer/meson.build  |   1 +
 hw/timer/trace-events |   6 +
 5 files changed, 540 insertions(+)
 create mode 100644 include/hw/timer/sifive_pwm.h
 create mode 100644 hw/timer/sifive_pwm.c

diff --git a/include/hw/timer/sifive_pwm.h b/include/hw/timer/sifive_pwm.h
new file mode 100644
index 00..6a8cf7b29e
--- /dev/null
+++ b/include/hw/timer/sifive_pwm.h
@@ -0,0 +1,62 @@
+/*
+ * SiFive PWM
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * Author:  Alistair Francis 
+ *
+ * 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.
+ */
+
+#ifndef HW_SIFIVE_PWM_H
+#define HW_SIFIVE_PWM_H
+
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+
+#define TYPE_SIFIVE_PWM "sifive-pwm"
+
+#define SIFIVE_PWM(obj) \
+OBJECT_CHECK(SiFivePwmState, (obj), TYPE_SIFIVE_PWM)
+
+#define SIFIVE_PWM_CHANS  4
+#define SIFIVE_PWM_IRQS   SIFIVE_PWM_CHANS
+
+typedef struct SiFivePwmState {
+/*  */
+SysBusDevice parent_obj;
+
+/*  */
+MemoryRegion mmio;
+QEMUTimer timer[SIFIVE_PWM_CHANS];
+/*
+ * if en bit(s) set, is the number of ticks when pwmcount was 0
+ * if en bit(s) not set, is the number of ticks in pwmcount
+ */
+uint64_t tick_offset;
+uint64_t freq_hz;
+
+uint32_t pwmcfg;
+uint32_t pwmcmp[SIFIVE_PWM_CHANS];
+
+qemu_irq irqs[SIFIVE_PWM_IRQS];
+} SiFivePwmState;
+
+#endif /* HW_SIFIVE_PWM_H */
diff --git a/hw/timer/sifive_pwm.c b/hw/timer/sifive_pwm.c
new file mode 100644
index 00..c664480ccf
--- /dev/null
+++ b/hw/timer/sifive_pwm.c
@@ -0,0 +1,468 @@
+/*
+ * SiFive PWM
+ *
+ * Copyright (c) 2020 Western Digital
+ *
+ * Author:  Alistair Francis 
+ *
+ * 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 "trace.h"
+#include "hw/irq.h"
+#include "hw/timer/sifive_pwm.h"
+#include "hw/qdev-properties.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+
+#define HAS_PWM_EN_BITS(cfg) ((cfg & R_CONFIG_ENONESHOT_MASK) || \
+  (cfg & R_CONFIG_ENALWAYS_MASK))
+
+#define PWMCMP_MASK 0x
+#define PWMCOUNT_MASK 0x7FFF
+
+REG32(CONFIG,   0x00)
+FIELD(CONFIG, SCALE,0, 4)
+FIELD(CONFIG, STICKY,   8, 1)
+FIELD(CONFIG, ZEROCMP,  9, 1)
+

[PULL 12/21] hw/riscv: virt: Re-factor FDT generation

2021-09-16 Thread Alistair Francis
From: Anup Patel 

We re-factor and break the FDT generation into smaller functions
so that it is easier to modify FDT generation for different
configurations of virt machine.

Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 20210831110603.338681-4-anup.pa...@wdc.com
Signed-off-by: Alistair Francis 
---
 hw/riscv/virt.c | 527 ++--
 1 file changed, 327 insertions(+), 200 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 1cd7ac1546..7f716901ef 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -176,214 +176,262 @@ static void create_pcie_irq_map(void *fdt, char 
*nodename,
0x1800, 0, 0, 0x7);
 }
 
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
-   uint64_t mem_size, const char *cmdline, bool is_32_bit)
+static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
+   char *clust_name, uint32_t *phandle,
+   bool is_32_bit, uint32_t *intc_phandles)
 {
-void *fdt;
-int i, cpu, socket;
+int cpu;
+uint32_t cpu_phandle;
 MachineState *mc = MACHINE(s);
+char *name, *cpu_name, *core_name, *intc_name;
+
+for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
+cpu_phandle = (*phandle)++;
+
+cpu_name = g_strdup_printf("/cpus/cpu@%d",
+s->soc[socket].hartid_base + cpu);
+qemu_fdt_add_subnode(mc->fdt, cpu_name);
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
+(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
+name = riscv_isa_string(&s->soc[socket].harts[cpu]);
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
+g_free(name);
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "compatible", "riscv");
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "status", "okay");
+qemu_fdt_setprop_cell(mc->fdt, cpu_name, "reg",
+s->soc[socket].hartid_base + cpu);
+qemu_fdt_setprop_string(mc->fdt, cpu_name, "device_type", "cpu");
+riscv_socket_fdt_write_id(mc, mc->fdt, cpu_name, socket);
+qemu_fdt_setprop_cell(mc->fdt, cpu_name, "phandle", cpu_phandle);
+
+intc_phandles[cpu] = (*phandle)++;
+
+intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name);
+qemu_fdt_add_subnode(mc->fdt, intc_name);
+qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
+intc_phandles[cpu]);
+qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
+"riscv,cpu-intc");
+qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
+qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
+
+core_name = g_strdup_printf("%s/core%d", clust_name, cpu);
+qemu_fdt_add_subnode(mc->fdt, core_name);
+qemu_fdt_setprop_cell(mc->fdt, core_name, "cpu", cpu_phandle);
+
+g_free(core_name);
+g_free(intc_name);
+g_free(cpu_name);
+}
+}
+
+static void create_fdt_socket_memory(RISCVVirtState *s,
+ const MemMapEntry *memmap, int socket)
+{
+char *mem_name;
 uint64_t addr, size;
-uint32_t *clint_cells, *plic_cells;
-unsigned long clint_addr, plic_addr;
-uint32_t plic_phandle[MAX_NODES];
-uint32_t cpu_phandle, intc_phandle, test_phandle;
-uint32_t phandle = 1, plic_mmio_phandle = 1;
-uint32_t plic_pcie_phandle = 1, plic_virtio_phandle = 1;
-char *mem_name, *cpu_name, *core_name, *intc_name;
-char *name, *clint_name, *plic_name, *clust_name;
-hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
-hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
+MachineState *mc = MACHINE(s);
+
+addr = memmap[VIRT_DRAM].base + riscv_socket_mem_offset(mc, socket);
+size = riscv_socket_mem_size(mc, socket);
+mem_name = g_strdup_printf("/memory@%lx", (long)addr);
+qemu_fdt_add_subnode(mc->fdt, mem_name);
+qemu_fdt_setprop_cells(mc->fdt, mem_name, "reg",
+addr >> 32, addr, size >> 32, size);
+qemu_fdt_setprop_string(mc->fdt, mem_name, "device_type", "memory");
+riscv_socket_fdt_write_id(mc, mc->fdt, mem_name, socket);
+g_free(mem_name);
+}
+
+static void create_fdt_socket_clint(RISCVVirtState *s,
+const MemMapEntry *memmap, int socket,
+uint32_t *intc_phandles)
+{
+int cpu;
+char *clint_name;
+uint32_t *clint_cells;
+unsigned long clint_addr;
+MachineState *mc = MACHINE(s);
 static const char * const clint_compat[2] = {
 "sifive,clint0", "riscv,clint0"
 };
+
+clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4);
+
+for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
+clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]);
+clint_cells[cpu * 4 + 1] = cpu_to_be32

[PULL 09/21] sifive_u: Connect the SiFive PWM device

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Connect the SiFive PWM device and expose it via the device tree.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 
22f98648b4e012f78529a56f5ca60b0b27852a4d.1631159656.git.alistair.fran...@wdc.com
---
 docs/system/riscv/sifive_u.rst |  1 +
 include/hw/riscv/sifive_u.h| 14 -
 hw/riscv/sifive_u.c| 55 +-
 hw/riscv/Kconfig   |  1 +
 4 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
index 01108b5ecc..7c65e9c440 100644
--- a/docs/system/riscv/sifive_u.rst
+++ b/docs/system/riscv/sifive_u.rst
@@ -24,6 +24,7 @@ The ``sifive_u`` machine supports the following devices:
 * 2 QSPI controllers
 * 1 ISSI 25WP256 flash
 * 1 SD card in SPI mode
+* PWM0 and PWM1
 
 Please note the real world HiFive Unleashed board has a fixed configuration of
 1 E51 core and 4 U54 core combination and the RISC-V core boots in 64-bit mode.
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index 2656b39808..f71c90c94c 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -27,6 +27,7 @@
 #include "hw/misc/sifive_u_otp.h"
 #include "hw/misc/sifive_u_prci.h"
 #include "hw/ssi/sifive_spi.h"
+#include "hw/timer/sifive_pwm.h"
 
 #define TYPE_RISCV_U_SOC "riscv.sifive.u.soc"
 #define RISCV_U_SOC(obj) \
@@ -49,6 +50,7 @@ typedef struct SiFiveUSoCState {
 SiFiveSPIState spi0;
 SiFiveSPIState spi2;
 CadenceGEMState gem;
+SiFivePwmState pwm[2];
 
 uint32_t serial;
 char *cpu_type;
@@ -92,7 +94,9 @@ enum {
 SIFIVE_U_DEV_FLASH0,
 SIFIVE_U_DEV_DRAM,
 SIFIVE_U_DEV_GEM,
-SIFIVE_U_DEV_GEM_MGMT
+SIFIVE_U_DEV_GEM_MGMT,
+SIFIVE_U_DEV_PWM0,
+SIFIVE_U_DEV_PWM1
 };
 
 enum {
@@ -126,6 +130,14 @@ enum {
 SIFIVE_U_PDMA_IRQ5 = 28,
 SIFIVE_U_PDMA_IRQ6 = 29,
 SIFIVE_U_PDMA_IRQ7 = 30,
+SIFIVE_U_PWM0_IRQ0 = 42,
+SIFIVE_U_PWM0_IRQ1 = 43,
+SIFIVE_U_PWM0_IRQ2 = 44,
+SIFIVE_U_PWM0_IRQ3 = 45,
+SIFIVE_U_PWM1_IRQ0 = 46,
+SIFIVE_U_PWM1_IRQ1 = 47,
+SIFIVE_U_PWM1_IRQ2 = 48,
+SIFIVE_U_PWM1_IRQ3 = 49,
 SIFIVE_U_QSPI0_IRQ = 51,
 SIFIVE_U_GEM_IRQ = 53
 };
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 6766edc1d0..f4cde10667 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -17,6 +17,7 @@
  * 7) DMA (Direct Memory Access Controller)
  * 8) SPI0 connected to an SPI flash
  * 9) SPI2 connected to an SD card
+ * 10) PWM0 and PWM1
  *
  * This board currently generates devicetree dynamically that indicates at 
least
  * two harts and up to five harts.
@@ -75,6 +76,8 @@ static const MemMapEntry sifive_u_memmap[] = {
 [SIFIVE_U_DEV_PRCI] = { 0x1000, 0x1000 },
 [SIFIVE_U_DEV_UART0] ={ 0x1001, 0x1000 },
 [SIFIVE_U_DEV_UART1] ={ 0x10011000, 0x1000 },
+[SIFIVE_U_DEV_PWM0] = { 0x1002, 0x1000 },
+[SIFIVE_U_DEV_PWM1] = { 0x10021000, 0x1000 },
 [SIFIVE_U_DEV_QSPI0] ={ 0x1004, 0x1000 },
 [SIFIVE_U_DEV_QSPI2] ={ 0x1005, 0x1000 },
 [SIFIVE_U_DEV_GPIO] = { 0x1006, 0x1000 },
@@ -441,6 +444,38 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry 
*memmap,
 qemu_fdt_setprop_cell(fdt, nodename, "reg", 0x0);
 g_free(nodename);
 
+nodename = g_strdup_printf("/soc/pwm@%lx",
+(long)memmap[SIFIVE_U_DEV_PWM0].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+0x0, memmap[SIFIVE_U_DEV_PWM0].base,
+0x0, memmap[SIFIVE_U_DEV_PWM0].size);
+qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
+qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
+   SIFIVE_U_PWM0_IRQ0, SIFIVE_U_PWM0_IRQ1,
+   SIFIVE_U_PWM0_IRQ2, SIFIVE_U_PWM0_IRQ3);
+qemu_fdt_setprop_cells(fdt, nodename, "clocks",
+   prci_phandle, PRCI_CLK_TLCLK);
+qemu_fdt_setprop_cell(fdt, nodename, "#pwm-cells", 0);
+g_free(nodename);
+
+nodename = g_strdup_printf("/soc/pwm@%lx",
+(long)memmap[SIFIVE_U_DEV_PWM1].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,pwm0");
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+0x0, memmap[SIFIVE_U_DEV_PWM1].base,
+0x0, memmap[SIFIVE_U_DEV_PWM1].size);
+qemu_fdt_setprop_cell(fdt, nodename, "interrupt-parent", plic_phandle);
+qemu_fdt_setprop_cells(fdt, nodename, "interrupts",
+   SIFIVE_U_PWM1_IRQ0, SIFIVE_U_PWM1_IRQ1,
+   SIFIVE_U_PWM1_IRQ2, SIFIVE_U_PWM1_IRQ3);
+qemu_fdt_setprop_cells(fdt, nodename, "clocks",
+   prci_phandle, PRCI_CLK_TLCLK);
+qemu_fdt_setprop_cell(fdt, nodename, "#pwm-cells", 0)

[PULL 14/21] hw/dma: sifive_pdma: reset Next* registers when Control.claim is set

2021-09-16 Thread Alistair Francis
From: Frank Chang 

Setting Control.claim clears all of the chanel's Next registers.
This is effective only when Control.claim is set from 0 to 1.

Signed-off-by: Frank Chang 
Tested-by: Max Hsu 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-id: 20210912130553.179501-2-frank.ch...@sifive.com
Signed-off-by: Alistair Francis 
---
 hw/dma/sifive_pdma.c | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c
index 9b2ac2017d..d92e27dfdc 100644
--- a/hw/dma/sifive_pdma.c
+++ b/hw/dma/sifive_pdma.c
@@ -54,6 +54,13 @@
 #define DMA_EXEC_DST0x110
 #define DMA_EXEC_SRC0x118
 
+/*
+ * FU540/FU740 docs are incorrect with NextConfig.wsize/rsize reset values.
+ * The reset values tested on Unleashed/Unmatched boards are 6 instead of 0.
+ */
+#define CONFIG_WRSZ_DEFAULT 6
+#define CONFIG_RDSZ_DEFAULT 6
+
 enum dma_chan_state {
 DMA_CHAN_STATE_IDLE,
 DMA_CHAN_STATE_STARTED,
@@ -221,6 +228,7 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
 {
 SiFivePDMAState *s = opaque;
 int ch = SIFIVE_PDMA_CHAN_NO(offset);
+bool claimed;
 
 if (ch >= SIFIVE_PDMA_CHANS) {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n",
@@ -231,6 +239,17 @@ static void sifive_pdma_write(void *opaque, hwaddr offset,
 offset &= 0xfff;
 switch (offset) {
 case DMA_CONTROL:
+claimed = !!s->chan[ch].control & CONTROL_CLAIM;
+
+if (!claimed && (value & CONTROL_CLAIM)) {
+/* reset Next* registers */
+s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << 
CONFIG_RDSZ_SHIFT) |
+  (CONFIG_WRSZ_DEFAULT << 
CONFIG_WRSZ_SHIFT);
+s->chan[ch].next_bytes = 0;
+s->chan[ch].next_dst = 0;
+s->chan[ch].next_src = 0;
+}
+
 s->chan[ch].control = value;
 
 if (value & CONTROL_RUN) {
-- 
2.31.1




[PULL 04/21] hw/intc: sifive_clint: Use RISC-V CPU GPIO lines

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
CPU GPIO lines to set the timer and soft MIP bits.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Reviewed-by: LIU Zhiwei 
Message-id: 
946e1ef5e268b24084c7ddad84c146de62a56736.1630301632.git.alistair.fran...@wdc.com
---
 include/hw/intc/sifive_clint.h |  2 +
 hw/intc/sifive_clint.c | 68 --
 2 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/include/hw/intc/sifive_clint.h b/include/hw/intc/sifive_clint.h
index a30be0f3d6..921b1561dd 100644
--- a/include/hw/intc/sifive_clint.h
+++ b/include/hw/intc/sifive_clint.h
@@ -40,6 +40,8 @@ typedef struct SiFiveCLINTState {
 uint32_t time_base;
 uint32_t aperture_size;
 uint32_t timebase_freq;
+qemu_irq *timer_irqs;
+qemu_irq *soft_irqs;
 } SiFiveCLINTState;
 
 DeviceState *sifive_clint_create(hwaddr addr, hwaddr size,
diff --git a/hw/intc/sifive_clint.c b/hw/intc/sifive_clint.c
index 99c870ced2..ab172d8e40 100644
--- a/hw/intc/sifive_clint.c
+++ b/hw/intc/sifive_clint.c
@@ -28,6 +28,12 @@
 #include "hw/qdev-properties.h"
 #include "hw/intc/sifive_clint.h"
 #include "qemu/timer.h"
+#include "hw/irq.h"
+
+typedef struct sifive_clint_callback {
+SiFiveCLINTState *s;
+int num;
+} sifive_clint_callback;
 
 static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
 {
@@ -39,7 +45,9 @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
  * Called when timecmp is written to update the QEMU timer or immediately
  * trigger timer interrupt if mtimecmp <= current timer value.
  */
-static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value,
+static void sifive_clint_write_timecmp(SiFiveCLINTState *s, RISCVCPU *cpu,
+   int hartid,
+   uint64_t value,
uint32_t timebase_freq)
 {
 uint64_t next;
@@ -51,12 +59,12 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, 
uint64_t value,
 if (cpu->env.timecmp <= rtc_r) {
 /* if we're setting an MTIMECMP value in the "past",
immediately raise the timer interrupt */
-riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
+qemu_irq_raise(s->timer_irqs[hartid - s->hartid_base]);
 return;
 }
 
 /* otherwise, set up the future timer interrupt */
-riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
+qemu_irq_lower(s->timer_irqs[hartid - s->hartid_base]);
 diff = cpu->env.timecmp - rtc_r;
 /* back to ns (note args switched in muldiv64) */
 uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq);
@@ -91,8 +99,9 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, 
uint64_t value,
  */
 static void sifive_clint_timer_cb(void *opaque)
 {
-RISCVCPU *cpu = opaque;
-riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
+sifive_clint_callback *state = opaque;
+
+qemu_irq_raise(state->s->timer_irqs[state->num]);
 }
 
 /* CPU wants to read rtc or timecmp register */
@@ -158,7 +167,7 @@ static void sifive_clint_write(void *opaque, hwaddr addr, 
uint64_t value,
 if (!env) {
 error_report("clint: invalid timecmp hartid: %zu", hartid);
 } else if ((addr & 0x3) == 0) {
-riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MSIP, 
BOOL_TO_MASK(value));
+qemu_set_irq(clint->soft_irqs[hartid - clint->hartid_base], value);
 } else {
 error_report("clint: invalid sip write: %08x", (uint32_t)addr);
 }
@@ -174,13 +183,13 @@ static void sifive_clint_write(void *opaque, hwaddr addr, 
uint64_t value,
 } else if ((addr & 0x7) == 0) {
 /* timecmp_lo */
 uint64_t timecmp_hi = env->timecmp >> 32;
-sifive_clint_write_timecmp(RISCV_CPU(cpu),
+sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
 timecmp_hi << 32 | (value & 0x), clint->timebase_freq);
 return;
 } else if ((addr & 0x7) == 4) {
 /* timecmp_hi */
 uint64_t timecmp_lo = env->timecmp;
-sifive_clint_write_timecmp(RISCV_CPU(cpu),
+sifive_clint_write_timecmp(clint, RISCV_CPU(cpu), hartid,
 value << 32 | (timecmp_lo & 0x), clint->timebase_freq);
 } else {
 error_report("clint: invalid timecmp write: %08x", (uint32_t)addr);
@@ -226,6 +235,12 @@ static void sifive_clint_realize(DeviceState *dev, Error 
**errp)
 memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_clint_ops, s,
   TYPE_SIFIVE_CLINT, s->aperture_size);
 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+
+s->timer_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
+qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts);
+
+s->soft_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
+qdev_init_gpio_o

[PULL 06/21] hw/intc: sifive_plic: Convert the PLIC to use RISC-V CPU GPIO lines

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
CPU GPIO lines to set the external MIP bits.

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-id: 
0364190bfa935058a845c0fa1ecf650328840ad5.1630301632.git.alistair.fran...@wdc.com
---
 include/hw/intc/sifive_plic.h |  4 
 hw/intc/sifive_plic.c | 30 +++---
 hw/riscv/microchip_pfsoc.c|  2 +-
 hw/riscv/shakti_c.c   |  3 ++-
 hw/riscv/sifive_e.c   |  2 +-
 hw/riscv/sifive_u.c   |  2 +-
 hw/riscv/virt.c   |  2 +-
 7 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/include/hw/intc/sifive_plic.h b/include/hw/intc/sifive_plic.h
index 1e451a270c..134cf39a96 100644
--- a/include/hw/intc/sifive_plic.h
+++ b/include/hw/intc/sifive_plic.h
@@ -72,9 +72,13 @@ struct SiFivePLICState {
 uint32_t context_base;
 uint32_t context_stride;
 uint32_t aperture_size;
+
+qemu_irq *m_external_irqs;
+qemu_irq *s_external_irqs;
 };
 
 DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
+uint32_t num_harts,
 uint32_t hartid_base, uint32_t num_sources,
 uint32_t num_priorities, uint32_t priority_base,
 uint32_t pending_base, uint32_t enable_base,
diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
index 78903beb06..9ba36dc0b3 100644
--- a/hw/intc/sifive_plic.c
+++ b/hw/intc/sifive_plic.c
@@ -29,6 +29,7 @@
 #include "hw/intc/sifive_plic.h"
 #include "target/riscv/cpu.h"
 #include "migration/vmstate.h"
+#include "hw/irq.h"
 
 #define RISCV_DEBUG_PLIC 0
 
@@ -139,18 +140,14 @@ static void sifive_plic_update(SiFivePLICState *plic)
 for (addrid = 0; addrid < plic->num_addrs; addrid++) {
 uint32_t hartid = plic->addr_config[addrid].hartid;
 PLICMode mode = plic->addr_config[addrid].mode;
-CPUState *cpu = qemu_get_cpu(hartid);
-CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
-if (!env) {
-continue;
-}
 int level = sifive_plic_irqs_pending(plic, addrid);
+
 switch (mode) {
 case PLICMode_M:
-riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, 
BOOL_TO_MASK(level));
+qemu_set_irq(plic->m_external_irqs[hartid - plic->hartid_base], 
level);
 break;
 case PLICMode_S:
-riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, 
BOOL_TO_MASK(level));
+qemu_set_irq(plic->s_external_irqs[hartid - plic->hartid_base], 
level);
 break;
 default:
 break;
@@ -456,6 +453,12 @@ static void sifive_plic_realize(DeviceState *dev, Error 
**errp)
 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
 qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
 
+plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
+qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts);
+
+plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
+qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts);
+
 /* We can't allow the supervisor to control SEIP as this would allow the
  * supervisor to clear a pending external interrupt which will result in
  * lost a interrupt in the case a PLIC is attached. The SEIP bit must be
@@ -520,6 +523,7 @@ type_init(sifive_plic_register_types)
  * Create PLIC device.
  */
 DeviceState *sifive_plic_create(hwaddr addr, char *hart_config,
+uint32_t num_harts,
 uint32_t hartid_base, uint32_t num_sources,
 uint32_t num_priorities, uint32_t priority_base,
 uint32_t pending_base, uint32_t enable_base,
@@ -527,6 +531,8 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,
 uint32_t context_stride, uint32_t aperture_size)
 {
 DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC);
+int i;
+
 assert(enable_stride == (enable_stride & -enable_stride));
 assert(context_stride == (context_stride & -context_stride));
 qdev_prop_set_string(dev, "hart-config", hart_config);
@@ -542,5 +548,15 @@ DeviceState *sifive_plic_create(hwaddr addr, char 
*hart_config,
 qdev_prop_set_uint32(dev, "aperture-size", aperture_size);
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+
+for (i = 0; i < num_harts; i++) {
+CPUState *cpu = qemu_get_cpu(hartid_base + i);
+
+qdev_connect_gpio_out(dev, i,
+  qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT));
+qdev_connect_gpio_out(dev, num_harts + i,
+  qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
+}
+
 return dev;
 }
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index eb8e79e0a1..eef55f69fd 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -274,7 +274,7 @@ static void microchip_pfsoc_soc_reali

[PULL 05/21] hw/intc: ibex_plic: Convert the PLIC to use RISC-V CPU GPIO lines

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
CPU GPIO lines to set the external MIP bits.

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Message-id: 
0a76946981852f5bd15f0c37ab35b253371027a8.1630301632.git.alistair.fran...@wdc.com
---
 include/hw/intc/ibex_plic.h |  2 ++
 hw/intc/ibex_plic.c | 17 ++---
 hw/riscv/opentitan.c|  8 
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/include/hw/intc/ibex_plic.h b/include/hw/intc/ibex_plic.h
index 7fc495db99..d596436e06 100644
--- a/include/hw/intc/ibex_plic.h
+++ b/include/hw/intc/ibex_plic.h
@@ -60,6 +60,8 @@ struct IbexPlicState {
 uint32_t threshold_base;
 
 uint32_t claim_base;
+
+qemu_irq *external_irqs;
 };
 
 #endif /* HW_IBEX_PLIC_H */
diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c
index edf76e4f61..ff430356f8 100644
--- a/hw/intc/ibex_plic.c
+++ b/hw/intc/ibex_plic.c
@@ -27,6 +27,7 @@
 #include "target/riscv/cpu_bits.h"
 #include "target/riscv/cpu.h"
 #include "hw/intc/ibex_plic.h"
+#include "hw/irq.h"
 
 static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
 {
@@ -92,19 +93,10 @@ static bool ibex_plic_irqs_pending(IbexPlicState *s, 
uint32_t context)
 
 static void ibex_plic_update(IbexPlicState *s)
 {
-CPUState *cpu;
-int level, i;
+int i;
 
 for (i = 0; i < s->num_cpus; i++) {
-cpu = qemu_get_cpu(i);
-
-if (!cpu) {
-continue;
-}
-
-level = ibex_plic_irqs_pending(s, 0);
-
-riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, BOOL_TO_MASK(level));
+qemu_set_irq(s->external_irqs[i], ibex_plic_irqs_pending(s, 0));
 }
 }
 
@@ -268,6 +260,9 @@ static void ibex_plic_realize(DeviceState *dev, Error 
**errp)
 
 qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources);
 
+s->external_irqs = g_malloc(sizeof(qemu_irq) * s->num_cpus);
+qdev_init_gpio_out(dev, s->external_irqs, s->num_cpus);
+
 /*
  * We can't allow the supervisor to control SEIP as this would allow the
  * supervisor to clear a pending external interrupt which will result in
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 36a41c8b5b..048aced0ec 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -118,6 +118,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, 
Error **errp)
 MachineState *ms = MACHINE(qdev_get_machine());
 LowRISCIbexSoCState *s = RISCV_IBEX_SOC(dev_soc);
 MemoryRegion *sys_mem = get_system_memory();
+int i;
 
 object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type,
 &error_abort);
@@ -149,6 +150,13 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, 
Error **errp)
 }
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->plic), 0, memmap[IBEX_DEV_PLIC].base);
 
+for (i = 0; i < ms->smp.cpus; i++) {
+CPUState *cpu = qemu_get_cpu(i);
+
+qdev_connect_gpio_out(DEVICE(&s->plic), i,
+  qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
+}
+
 /* UART */
 qdev_prop_set_chr(DEVICE(&(s->uart)), "chardev", serial_hd(0));
 if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) {
-- 
2.31.1




[PULL 01/21] target/riscv: Update the ePMP CSR address

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Update the ePMP CSRs to match the 0.9.3 ePMP spec
https://github.com/riscv/riscv-tee/blob/61455747230a26002d741f64879dd78cc9689323/Smepmp/Smepmp.pdf

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Message-id: 
28c908de60b9b04fa20e63d113885c98586053f3.1630543194.git.alistair.fran...@wdc.com
---
 target/riscv/cpu_bits.h | 4 ++--
 target/riscv/cpu.c  | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 7330ff5a19..ce9dcc030c 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -210,8 +210,8 @@
 #define CSR_MTVAL2  0x34b
 
 /* Enhanced Physical Memory Protection (ePMP) */
-#define CSR_MSECCFG 0x390
-#define CSR_MSECCFGH0x391
+#define CSR_MSECCFG 0x747
+#define CSR_MSECCFGH0x757
 /* Physical Memory Protection */
 #define CSR_PMPCFG0 0x3a0
 #define CSR_PMPCFG1 0x3a1
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 13575c1408..d4d5961807 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -599,6 +599,7 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
 DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
 DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
+/* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
 
 DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC),
-- 
2.31.1




[PULL 07/21] hw/intc: ibex_timer: Convert the timer to use RISC-V CPU GPIO lines

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Instead of using riscv_cpu_update_mip() let's instead use the new RISC-V
CPU GPIO lines to set the timer MIP bits.

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Message-id: 
84d5b1d5783d2e79eee69a2f7ac480cc0c070db3.1630301632.git.alistair.fran...@wdc.com
---
 include/hw/timer/ibex_timer.h |  2 ++
 hw/riscv/opentitan.c  |  3 +++
 hw/timer/ibex_timer.c | 17 -
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h
index 6a43537003..b6f69b38ee 100644
--- a/include/hw/timer/ibex_timer.h
+++ b/include/hw/timer/ibex_timer.h
@@ -48,5 +48,7 @@ struct IbexTimerState {
 uint32_t timebase_freq;
 
 qemu_irq irq;
+
+qemu_irq m_timer_irq;
 };
 #endif /* HW_IBEX_TIMER_H */
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
index 048aced0ec..f7cfcf1c3a 100644
--- a/hw/riscv/opentitan.c
+++ b/hw/riscv/opentitan.c
@@ -183,6 +183,9 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, 
Error **errp)
 sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer),
0, qdev_get_gpio_in(DEVICE(&s->plic),
IBEX_TIMER_TIMEREXPIRED0_0));
+qdev_connect_gpio_out(DEVICE(&s->timer), 0,
+  qdev_get_gpio_in(DEVICE(qemu_get_cpu(0)),
+   IRQ_M_TIMER));
 
 create_unimplemented_device("riscv.lowrisc.ibex.gpio",
 memmap[IBEX_DEV_GPIO].base, memmap[IBEX_DEV_GPIO].size);
diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c
index 5befb53506..66e1f8e48c 100644
--- a/hw/timer/ibex_timer.c
+++ b/hw/timer/ibex_timer.c
@@ -77,7 +77,7 @@ static void ibex_timer_update_irqs(IbexTimerState *s)
 /*
  * If the mtimecmp was in the past raise the interrupt now.
  */
-riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
+qemu_irq_raise(s->m_timer_irq);
 if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
 s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
 qemu_set_irq(s->irq, true);
@@ -86,7 +86,7 @@ static void ibex_timer_update_irqs(IbexTimerState *s)
 }
 
 /* Setup a timer to trigger the interrupt in the future */
-riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(0));
+qemu_irq_lower(s->m_timer_irq);
 qemu_set_irq(s->irq, false);
 
 diff = cpu->env.timecmp - now;
@@ -106,10 +106,8 @@ static void ibex_timer_update_irqs(IbexTimerState *s)
 static void ibex_timer_cb(void *opaque)
 {
 IbexTimerState *s = opaque;
-CPUState *cs = qemu_get_cpu(0);
-RISCVCPU *cpu = RISCV_CPU(cs);
 
-riscv_cpu_update_mip(cpu, MIP_MTIP, BOOL_TO_MASK(1));
+qemu_irq_raise(s->m_timer_irq);
 if (s->timer_intr_enable & R_INTR_ENABLE_IE_0_MASK) {
 s->timer_intr_state |= R_INTR_STATE_IS_0_MASK;
 qemu_set_irq(s->irq, true);
@@ -280,12 +278,21 @@ static void ibex_timer_init(Object *obj)
 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 }
 
+static void ibex_timer_realize(DeviceState *dev, Error **errp)
+{
+IbexTimerState *s = IBEX_TIMER(dev);
+
+qdev_init_gpio_out(dev, &s->m_timer_irq, 1);
+}
+
+
 static void ibex_timer_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
 dc->reset = ibex_timer_reset;
 dc->vmsd = &vmstate_ibex_timer;
+dc->realize = ibex_timer_realize;
 device_class_set_props(dc, ibex_timer_properties);
 }
 
-- 
2.31.1




[PULL 03/21] target/riscv: Expose interrupt pending bits as GPIO lines

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

Expose the 12 interrupt pending bits in MIP as GPIO lines.

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
Message-id: 
069d6162f0bc2f4a4f5a44e73f6442b11c703c53.1630301632.git.alistair.fran...@wdc.com
---
 target/riscv/cpu.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d4d5961807..7c626d89cd 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -567,11 +567,41 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 mcc->parent_realize(dev, errp);
 }
 
+#ifndef CONFIG_USER_ONLY
+static void riscv_cpu_set_irq(void *opaque, int irq, int level)
+{
+RISCVCPU *cpu = RISCV_CPU(opaque);
+
+switch (irq) {
+case IRQ_U_SOFT:
+case IRQ_S_SOFT:
+case IRQ_VS_SOFT:
+case IRQ_M_SOFT:
+case IRQ_U_TIMER:
+case IRQ_S_TIMER:
+case IRQ_VS_TIMER:
+case IRQ_M_TIMER:
+case IRQ_U_EXT:
+case IRQ_S_EXT:
+case IRQ_VS_EXT:
+case IRQ_M_EXT:
+riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
+break;
+default:
+g_assert_not_reached();
+}
+}
+#endif /* CONFIG_USER_ONLY */
+
 static void riscv_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
 
 cpu_set_cpustate_pointers(cpu);
+
+#ifndef CONFIG_USER_ONLY
+qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, 12);
+#endif /* CONFIG_USER_ONLY */
 }
 
 static Property riscv_cpu_properties[] = {
-- 
2.31.1




[PULL 02/21] target/riscv: Fix satp write

2021-09-16 Thread Alistair Francis
From: LIU Zhiwei 

These variables should be target_ulong. If truncated to int,
the bool conditions they indicate will be wrong.

As satp is very important for Linux, this bug almost fails every boot.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Bin Meng 
Reviewed-by: Alistair Francis 
Message-id: 20210901124539.222868-1-zhiwei_...@c-sky.com
Signed-off-by: Alistair Francis 
---
 target/riscv/csr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 50a2c3a3b4..ba9818f6a5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -986,7 +986,7 @@ static RISCVException read_satp(CPURISCVState *env, int 
csrno,
 static RISCVException write_satp(CPURISCVState *env, int csrno,
  target_ulong val)
 {
-int vm, mask, asid;
+target_ulong vm, mask, asid;
 
 if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
 return RISCV_EXCP_NONE;
-- 
2.31.1




[PULL 00/21] riscv-to-apply queue

2021-09-16 Thread Alistair Francis
From: Alistair Francis 

The following changes since commit d1fe59377bbbf91dfded1f08ffe3c636e9db8dc0:

  Merge remote-tracking branch 
'remotes/vivier2/tags/trivial-branch-for-6.2-pull-request' into staging 
(2021-09-16 16:02:31 +0100)

are available in the Git repository at:

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

for you to fetch changes up to c14620db9b66de88bb4fef1d0cfc283bb3d53f85:

  hw/riscv: opentitan: Correct the USB Dev address (2021-09-17 07:43:55 +1000)


Second RISC-V PR for QEMU 6.2

 - ePMP CSR address updates
 - Convert internal interrupts to use QEMU GPIO lines
 - SiFive PWM support
 - Support for RISC-V ACLINT
 - SiFive PDMA fixes
 - Update to u-boot instructions for sifive_u
 - mstatus.SD bug fix for hypervisor extensions
 - OpenTitan fix for USB dev address


Alistair Francis (9):
  target/riscv: Update the ePMP CSR address
  target/riscv: Expose interrupt pending bits as GPIO lines
  hw/intc: sifive_clint: Use RISC-V CPU GPIO lines
  hw/intc: ibex_plic: Convert the PLIC to use RISC-V CPU GPIO lines
  hw/intc: sifive_plic: Convert the PLIC to use RISC-V CPU GPIO lines
  hw/intc: ibex_timer: Convert the timer to use RISC-V CPU GPIO lines
  hw/timer: Add SiFive PWM support
  sifive_u: Connect the SiFive PWM device
  hw/riscv: opentitan: Correct the USB Dev address

Anup Patel (4):
  hw/intc: Rename sifive_clint sources to riscv_aclint sources
  hw/intc: Upgrade the SiFive CLINT implementation to RISC-V ACLINT
  hw/riscv: virt: Re-factor FDT generation
  hw/riscv: virt: Add optional ACLINT support to virt machine

Bin Meng (2):
  docs/system/riscv: sifive_u: Update U-Boot instructions
  target/riscv: csr: Rename HCOUNTEREN_CY and friends

Frank Chang (4):
  hw/dma: sifive_pdma: reset Next* registers when Control.claim is set
  hw/dma: sifive_pdma: claim bit must be set before DMA transactions
  hw/dma: sifive_pdma: don't set Control.error if 0 bytes to transfer
  target/riscv: Backup/restore mstatus.SD bit when virtual register swapped

Green Wan (1):
  hw/dma: sifive_pdma: allow non-multiple transaction size transactions

LIU Zhiwei (1):
  target/riscv: Fix satp write

 docs/system/riscv/sifive_u.rst |  50 ++--
 docs/system/riscv/virt.rst |  10 +
 include/hw/intc/ibex_plic.h|   2 +
 include/hw/intc/riscv_aclint.h |  80 +
 include/hw/intc/sifive_clint.h |  60 
 include/hw/intc/sifive_plic.h  |   4 +
 include/hw/riscv/sifive_u.h|  14 +-
 include/hw/riscv/virt.h|   2 +
 include/hw/timer/ibex_timer.h  |   2 +
 include/hw/timer/sifive_pwm.h  |  62 
 target/riscv/cpu_bits.h|  12 +-
 hw/dma/sifive_pdma.c   |  54 +++-
 hw/intc/ibex_plic.c|  17 +-
 hw/intc/riscv_aclint.c | 460 +
 hw/intc/sifive_clint.c | 287 --
 hw/intc/sifive_plic.c  |  30 +-
 hw/riscv/microchip_pfsoc.c |  13 +-
 hw/riscv/opentitan.c   |  13 +-
 hw/riscv/shakti_c.c|  16 +-
 hw/riscv/sifive_e.c|  15 +-
 hw/riscv/sifive_u.c|  68 -
 hw/riscv/spike.c   |  16 +-
 hw/riscv/virt.c| 654 -
 hw/timer/ibex_timer.c  |  17 +-
 hw/timer/sifive_pwm.c  | 468 +
 target/riscv/cpu.c |  31 ++
 target/riscv/cpu_helper.c  |   3 +-
 target/riscv/csr.c |  26 +-
 hw/intc/Kconfig|   2 +-
 hw/intc/meson.build|   2 +-
 hw/riscv/Kconfig   |  13 +-
 hw/timer/Kconfig   |   3 +
 hw/timer/meson.build   |   1 +
 hw/timer/trace-events  |   6 +
 34 files changed, 1844 insertions(+), 669 deletions(-)
 create mode 100644 include/hw/intc/riscv_aclint.h
 delete mode 100644 include/hw/intc/sifive_clint.h
 create mode 100644 include/hw/timer/sifive_pwm.h
 create mode 100644 hw/intc/riscv_aclint.c
 delete mode 100644 hw/intc/sifive_clint.c
 create mode 100644 hw/timer/sifive_pwm.c



Re: [PATCH v1 1/1] hw/riscv: opentitan: Correct the USB Dev address

2021-09-16 Thread Alistair Francis
On Thu, Sep 16, 2021 at 2:37 PM Alistair Francis
 wrote:
>
> From: Alistair Francis 
>
> Signed-off-by: Alistair Francis 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  hw/riscv/opentitan.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
> index 36a41c8b5b..d38c43abc1 100644
> --- a/hw/riscv/opentitan.c
> +++ b/hw/riscv/opentitan.c
> @@ -39,12 +39,12 @@ static const MemMapEntry ibex_memmap[] = {
>  [IBEX_DEV_TIMER] =  {  0x4010,  0x1000  },
>  [IBEX_DEV_SENSOR_CTRL] ={  0x4011,  0x1000  },
>  [IBEX_DEV_OTP_CTRL] =   {  0x4013,  0x4000  },
> +[IBEX_DEV_USBDEV] = {  0x4015,  0x1000  },
>  [IBEX_DEV_PWRMGR] = {  0x4040,  0x1000  },
>  [IBEX_DEV_RSTMGR] = {  0x4041,  0x1000  },
>  [IBEX_DEV_CLKMGR] = {  0x4042,  0x1000  },
>  [IBEX_DEV_PINMUX] = {  0x4046,  0x1000  },
>  [IBEX_DEV_PADCTRL] ={  0x4047,  0x1000  },
> -[IBEX_DEV_USBDEV] = {  0x4050,  0x1000  },
>  [IBEX_DEV_FLASH_CTRL] = {  0x4100,  0x1000  },
>  [IBEX_DEV_PLIC] =   {  0x4101,  0x1000  },
>  [IBEX_DEV_AES] ={  0x4110,  0x1000  },
> --
> 2.31.1
>



Re: [PATCH] target/riscv: csr: Rename HCOUNTEREN_CY and friends

2021-09-16 Thread Alistair Francis
On Wed, Sep 15, 2021 at 6:47 PM Bin Meng  wrote:
>
> The macro name HCOUNTEREN_CY suggests it is for CSR HCOUNTEREN, but
> in fact it applies to M-mode and S-mode CSR too. Rename these macros
> to have the COUNTEREN_ prefix.
>
> Signed-off-by: Bin Meng 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>
>  target/riscv/cpu_bits.h |  8 
>  target/riscv/csr.c  | 24 
>  2 files changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 7330ff5a19..34564d367c 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -397,10 +397,10 @@
>  #define HSTATUS32_WPRI   0xFF8FF87E
>  #define HSTATUS64_WPRI   0xFF8FF87EULL
>
> -#define HCOUNTEREN_CY(1 << 0)
> -#define HCOUNTEREN_TM(1 << 1)
> -#define HCOUNTEREN_IR(1 << 2)
> -#define HCOUNTEREN_HPM3  (1 << 3)
> +#define COUNTEREN_CY (1 << 0)
> +#define COUNTEREN_TM (1 << 1)
> +#define COUNTEREN_IR (1 << 2)
> +#define COUNTEREN_HPM3   (1 << 3)
>
>  /* Privilege modes */
>  #define PRV_U 0
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 50a2c3a3b4..1cd34a6453 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -71,20 +71,20 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
>  if (riscv_cpu_virt_enabled(env)) {
>  switch (csrno) {
>  case CSR_CYCLE:
> -if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
> -get_field(env->mcounteren, HCOUNTEREN_CY)) {
> +if (!get_field(env->hcounteren, COUNTEREN_CY) &&
> +get_field(env->mcounteren, COUNTEREN_CY)) {
>  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
>  }
>  break;
>  case CSR_TIME:
> -if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
> -get_field(env->mcounteren, HCOUNTEREN_TM)) {
> +if (!get_field(env->hcounteren, COUNTEREN_TM) &&
> +get_field(env->mcounteren, COUNTEREN_TM)) {
>  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
>  }
>  break;
>  case CSR_INSTRET:
> -if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
> -get_field(env->mcounteren, HCOUNTEREN_IR)) {
> +if (!get_field(env->hcounteren, COUNTEREN_IR) &&
> +get_field(env->mcounteren, COUNTEREN_IR)) {
>  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
>  }
>  break;
> @@ -98,20 +98,20 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
>  if (riscv_cpu_is_32bit(env)) {
>  switch (csrno) {
>  case CSR_CYCLEH:
> -if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
> -get_field(env->mcounteren, HCOUNTEREN_CY)) {
> +if (!get_field(env->hcounteren, COUNTEREN_CY) &&
> +get_field(env->mcounteren, COUNTEREN_CY)) {
>  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
>  }
>  break;
>  case CSR_TIMEH:
> -if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
> -get_field(env->mcounteren, HCOUNTEREN_TM)) {
> +if (!get_field(env->hcounteren, COUNTEREN_TM) &&
> +get_field(env->mcounteren, COUNTEREN_TM)) {
>  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
>  }
>  break;
>  case CSR_INSTRETH:
> -if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
> -get_field(env->mcounteren, HCOUNTEREN_IR)) {
> +if (!get_field(env->hcounteren, COUNTEREN_IR) &&
> +get_field(env->mcounteren, COUNTEREN_IR)) {
>  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
>  }
>  break;
> --
> 2.25.1
>
>



plugins: Missing Store Exclusive Memory Accesses

2021-09-16 Thread Aaron Lindsay
Hello,

I recently noticed that the plugin interface does not appear to be
emitting callbacks to functions registered via
`qemu_plugin_register_vcpu_mem_cb` for AArch64 store exclusives. This
would include instructions like `stxp  w16, x2, x3, [x4]` (encoding:
0xc8300c82). Seeing as how I'm only running with a single CPU, I don't
see how this could be due to losing exclusivity after the preceding
`ldxp`.

In looking at QEMU's source, I *think* this is because the
`gen_store_exclusive` function in translate-a64.c is not making the same
calls to `plugin_gen_mem_callbacks` & company that are being made by
"normal" stores handled by functions like `tcg_gen_qemu_st_i64` (at
least in my case; I do see some code paths under `gen_store_exclusive`
call down into `tcg_gen_qemu_st_i64` eventually, but it appears not all
of them do?).

Does my initial guess check out? And, if so, does anyone have insight
into how to fix this issue most cleanly/generically? I suspect if/when I
debug my particular case I can discover one code path to fix, but I'm
wondering if my discovery may be part of a larger class of cases which
fell through the cracks and ought to be fixed together.

Thanks for any help,

Aaron



Re: [PULL 00/10] Trivial branch for 6.2 patches

2021-09-16 Thread Peter Maydell
On Thu, 16 Sept 2021 at 15:19, Laurent Vivier  wrote:
>
> The following changes since commit 831aaf24967a49d7750090b9dcfd6bf356f16529:
>
>   Merge remote-tracking branch 'remotes/marcandre/tags/misc-pull-request' 
> into staging (2021-09-14 18:14:56 +0100)
>
> are available in the Git repository at:
>
>   git://github.com/vivier/qemu.git tags/trivial-branch-for-6.2-pull-request
>
> for you to fetch changes up to 9ac200acce8c27ef44da31246f337a2454e54e0d:
>
>   target/sparc: Make sparc_cpu_dump_state() static (2021-09-16 14:52:46 +0200)
>
> ----
> Trivial patches pull request 20210916
>
> 


Applied, thanks.

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

-- PMM



Re: [RFC PATCH 0/4] block layer: split block APIs in graph and I/O

2021-09-16 Thread Paolo Bonzini
I think either -global or -global-state.

Paolo


Il gio 16 set 2021, 16:03 Emanuele Giuseppe Esposito 
ha scritto:

>
>
> On 15/09/2021 16:43, Stefan Hajnoczi wrote:
> > On Wed, Sep 15, 2021 at 02:11:41PM +0200, Paolo Bonzini wrote:
> >> On 13/09/21 15:10, Stefan Hajnoczi wrote:
> >>> On Wed, Sep 08, 2021 at 09:10:17AM -0400, Emanuele Giuseppe Esposito
> wrote:
>  Currently, block layer APIs like block-backend.h contain a mix of
>  functions that are either running in the main loop and under the
>  BQL, or are thread-safe functions and run in iothreads performing I/O.
>  The functions running under BQL also take care of modifying the
>  block graph, by using drain and/or aio_context_acquire/release.
>  This makes it very confusing to understand where each function
>  runs, and what assumptions it provided with regards to thread
>  safety.
> 
>  We call the functions running under BQL "graph API", and
>  distinguish them from the thread-safe "I/O API".
> >>>
> >>> Maybe "BQL" is clearer than "graph" because not all functions
> classified
> >>> as "graph" need to traverse/modify the graph.
> >>
> >> Bikeshedding, I like it! :)
> >>
> >> ... on the other hand, qemu-storage-daemon does not have a BQL (see
> patch
> >> 1); "graph API" functions run from the main (monitor) thread.
> >>
> >> The characteristic of the "graph API" is that they affect global state,
> so
> >> another possibility could be "global state API".  But is there any
> global
> >> state apart from the BlockDriverState graph and the associated
> >> BlockBackends?
> >
> > I would be happy with that name too.
> >
>
> Sounds good to me too, thanks.
> One more minor cosmetic thing: should I name the header
> block-backend-global-state.h or using block-backend-gs.h is
> straightforward enough?
>
> Thank you,
> Emanuele
>
>


[PATCH v2 4/4] ui/console: prevent use after free error

2021-09-16 Thread Volker Rümelin
Make chr in the QemuConsole object a strong reference to the
referenced chardev device. This prevents a use after free error
if the chardev device goes away unexpectedly.

To reproduce the error start qemu-system built with address
sanitizer with the the following command line options.

-display sdl -chardev vc,id=test0,cols=132,rows=50.

Open the monitor console with CTRL-ALT-3 and remove the
unconnected chardev device test0.

(qemu) chardev-remove test0

Open the text console test0 with CTRL-ALT-2 and type a character.
QEMU immediately exits with this error message.

==28148==ERROR: AddressSanitizer: heap-use-after-free
  on address 0x60e43778 at pc 0x558712ba7125
  bp 0x7fff270980b0 sp 0x7fff270980a8
READ of size 8 at 0x60e43778 thread T0
#0 0x558712ba7124 in qemu_chr_be_can_write
  ../qemu-master/chardev/char.c:188
#1 0x558711624770 in kbd_send_chars
  ../qemu-master/ui/console.c:1113
#2 0x558711634e91 in kbd_put_keysym_console
  ../qemu-master/ui/console.c:1175
#3 0x55871163532a in kbd_put_string_console
  ../qemu-master/ui/console.c:1221
#4 0x5587120a21e4 in handle_textinput
  ../qemu-master/ui/sdl2.c:464
#5 0x5587120a21e4 in sdl2_poll_events
  ../qemu-master/ui/sdl2.c:650
#6 0x5587116269c3 in dpy_refresh
  ../qemu-master/ui/console.c:1673
#7 0x5587116269c3 in gui_update
  ../qemu-master/ui/console.c:158
#8 0x558712d3a919 in timerlist_run_timers
  ../qemu-master/util/qemu-timer.c:573
#9 0x558712d3b183 in qemu_clock_run_timers
  ../qemu-master/util/qemu-timer.c:587
#10 0x558712d3b183 in qemu_clock_run_all_timers
  ../qemu-master/util/qemu-timer.c:669
#11 0x558712d286d9 in main_loop_wait
  ../qemu-master/util/main-loop.c:542
#12 0x5587123d313b in qemu_main_loop
  ../qemu-master/softmmu/runstate.c:726
#13 0x5587115f989d in main
  ../qemu-master/softmmu/main.c:50
#14 0x7f832ee0934c in __libc_start_main
  (/lib64/libc.so.6+0x2534c)
#15 0x55871160b6e9 in _start
  (/home/ruemelin/rpmbuild/BUILD/qemu-6.1.50-build/
  qemu-system-x86_64+0x1f4f6e9)

Signed-off-by: Volker Rümelin 
---
 ui/console.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ui/console.c b/ui/console.c
index 29a3e3f0f5..1ef5a96295 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -2264,6 +2264,7 @@ static void vc_chr_open(Chardev *chr,
 }
 
 s->chr = chr;
+object_ref(chr);
 drv->console = s;
 
 if (display_state) {
-- 
2.31.1




[PATCH v2 2/4] ui/console: replace kbd_timer with chr_accept_input callback

2021-09-16 Thread Volker Rümelin
There's a ChardevClass chr_accept_input() callback function that
can replace the write retry timer.

Reviewed-by: Marc-André Lureau 
Signed-off-by: Volker Rümelin 
---
 ui/console.c | 28 +---
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index d2433c0636..dda1e6861d 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -116,7 +116,6 @@ struct QemuConsole {
 Chardev *chr;
 /* fifo for key pressed */
 Fifo8 out_fifo;
-QEMUTimer *kbd_timer;
 CoQueue dump_queue;
 
 QTAILQ_ENTRY(QemuConsole) next;
@@ -1106,30 +1105,21 @@ static int vc_chr_write(Chardev *chr, const uint8_t 
*buf, int len)
 return len;
 }
 
-static void kbd_send_chars(void *opaque)
+static void kbd_send_chars(QemuConsole *s)
 {
-QemuConsole *s = opaque;
 uint32_t len, avail;
 
 len = qemu_chr_be_can_write(s->chr);
 avail = fifo8_num_used(&s->out_fifo);
-if (len > avail) {
-len = avail;
-}
-while (len > 0) {
+while (len > 0 && avail > 0) {
 const uint8_t *buf;
 uint32_t size;
 
-buf = fifo8_pop_buf(&s->out_fifo, len, &size);
+buf = fifo8_pop_buf(&s->out_fifo, MIN(len, avail), &size);
 qemu_chr_be_write(s->chr, (uint8_t *)buf, size);
-len -= size;
+len = qemu_chr_be_can_write(s->chr);
 avail -= size;
 }
-/* characters are pending: we send them a bit later (XXX:
-   horrible, should change char device API) */
-if (avail > 0) {
-timer_mod(s->kbd_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1);
-}
 }
 
 /* called when an ascii key is pressed */
@@ -2141,6 +2131,14 @@ int qemu_console_get_height(QemuConsole *con, int 
fallback)
 return con ? surface_height(con->surface) : fallback;
 }
 
+static void vc_chr_accept_input(Chardev *chr)
+{
+VCChardev *drv = VC_CHARDEV(chr);
+QemuConsole *s = drv->console;
+
+kbd_send_chars(s);
+}
+
 static void vc_chr_set_echo(Chardev *chr, bool echo)
 {
 VCChardev *drv = VC_CHARDEV(chr);
@@ -2189,7 +2187,6 @@ static void text_console_do_init(Chardev *chr, 
DisplayState *ds)
 int g_height = 24 * FONT_HEIGHT;
 
 fifo8_create(&s->out_fifo, 16);
-s->kbd_timer = timer_new_ms(QEMU_CLOCK_REALTIME, kbd_send_chars, s);
 s->ds = ds;
 
 s->y_displayed = 0;
@@ -2439,6 +2436,7 @@ static void char_vc_class_init(ObjectClass *oc, void 
*data)
 cc->parse = qemu_chr_parse_vc;
 cc->open = vc_chr_open;
 cc->chr_write = vc_chr_write;
+cc->chr_accept_input = vc_chr_accept_input;
 cc->chr_set_echo = vc_chr_set_echo;
 }
 
-- 
2.31.1




[PATCH v2 3/4] ui/console: remove chardev frontend connected test

2021-09-16 Thread Volker Rümelin
The test if the chardev frontend is connected in
kbd_put_keysym_console() is redundant, because the call
to qemu_chr_be_can_write() in kbd_send_chars() tests
the connected condition again.

Remove the redundant test whether the chardev frontend
is connected.

Reviewed-by: Marc-André Lureau 
Signed-off-by: Volker Rümelin 
---
 ui/console.c | 13 +
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index dda1e6861d..29a3e3f0f5 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -28,10 +28,11 @@
 #include "qapi/error.h"
 #include "qapi/qapi-commands-ui.h"
 #include "qemu/fifo8.h"
+#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
 #include "qemu/timer.h"
-#include "chardev/char-fe.h"
+#include "chardev/char.h"
 #include "trace.h"
 #include "exec/memory.h"
 #include "io/channel-file.h"
@@ -1126,7 +1127,6 @@ static void kbd_send_chars(QemuConsole *s)
 void kbd_put_keysym_console(QemuConsole *s, int keysym)
 {
 uint8_t buf[16], *q;
-CharBackend *be;
 int c;
 uint32_t num_free;
 
@@ -1170,12 +1170,9 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
 if (s->echo) {
 vc_chr_write(s->chr, buf, q - buf);
 }
-be = s->chr->be;
-if (be && be->chr_read) {
-num_free = fifo8_num_free(&s->out_fifo);
-fifo8_push_all(&s->out_fifo, buf, MIN(num_free, q - buf));
-kbd_send_chars(s);
-}
+num_free = fifo8_num_free(&s->out_fifo);
+fifo8_push_all(&s->out_fifo, buf, MIN(num_free, q - buf));
+kbd_send_chars(s);
 break;
 }
 }
-- 
2.31.1




[PATCH v2 1/4] ui/console: replace QEMUFIFO with Fifo8

2021-09-16 Thread Volker Rümelin
One of the two FIFO implementations QEMUFIFO and Fifo8 is
redundant. Replace QEMUFIFO with Fifo8.

Signed-off-by: Volker Rümelin 
---
 ui/console.c | 86 
 1 file changed, 20 insertions(+), 66 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index eabbbc951c..d2433c0636 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -27,6 +27,7 @@
 #include "hw/qdev-core.h"
 #include "qapi/error.h"
 #include "qapi/qapi-commands-ui.h"
+#include "qemu/fifo8.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
 #include "qemu/timer.h"
@@ -62,57 +63,6 @@ enum TTYState {
 TTY_STATE_CSI,
 };
 
-typedef struct QEMUFIFO {
-uint8_t *buf;
-int buf_size;
-int count, wptr, rptr;
-} QEMUFIFO;
-
-static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
-{
-int l, len;
-
-l = f->buf_size - f->count;
-if (len1 > l)
-len1 = l;
-len = len1;
-while (len > 0) {
-l = f->buf_size - f->wptr;
-if (l > len)
-l = len;
-memcpy(f->buf + f->wptr, buf, l);
-f->wptr += l;
-if (f->wptr >= f->buf_size)
-f->wptr = 0;
-buf += l;
-len -= l;
-}
-f->count += len1;
-return len1;
-}
-
-static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
-{
-int l, len;
-
-if (len1 > f->count)
-len1 = f->count;
-len = len1;
-while (len > 0) {
-l = f->buf_size - f->rptr;
-if (l > len)
-l = len;
-memcpy(buf, f->buf + f->rptr, l);
-f->rptr += l;
-if (f->rptr >= f->buf_size)
-f->rptr = 0;
-buf += l;
-len -= l;
-}
-f->count -= len1;
-return len1;
-}
-
 typedef enum {
 GRAPHIC_CONSOLE,
 TEXT_CONSOLE,
@@ -165,8 +115,7 @@ struct QemuConsole {
 
 Chardev *chr;
 /* fifo for key pressed */
-QEMUFIFO out_fifo;
-uint8_t out_fifo_buf[16];
+Fifo8 out_fifo;
 QEMUTimer *kbd_timer;
 CoQueue dump_queue;
 
@@ -1160,21 +1109,25 @@ static int vc_chr_write(Chardev *chr, const uint8_t 
*buf, int len)
 static void kbd_send_chars(void *opaque)
 {
 QemuConsole *s = opaque;
-int len;
-uint8_t buf[16];
+uint32_t len, avail;
 
 len = qemu_chr_be_can_write(s->chr);
-if (len > s->out_fifo.count)
-len = s->out_fifo.count;
-if (len > 0) {
-if (len > sizeof(buf))
-len = sizeof(buf);
-qemu_fifo_read(&s->out_fifo, buf, len);
-qemu_chr_be_write(s->chr, buf, len);
+avail = fifo8_num_used(&s->out_fifo);
+if (len > avail) {
+len = avail;
+}
+while (len > 0) {
+const uint8_t *buf;
+uint32_t size;
+
+buf = fifo8_pop_buf(&s->out_fifo, len, &size);
+qemu_chr_be_write(s->chr, (uint8_t *)buf, size);
+len -= size;
+avail -= size;
 }
 /* characters are pending: we send them a bit later (XXX:
horrible, should change char device API) */
-if (s->out_fifo.count > 0) {
+if (avail > 0) {
 timer_mod(s->kbd_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1);
 }
 }
@@ -1185,6 +1138,7 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
 uint8_t buf[16], *q;
 CharBackend *be;
 int c;
+uint32_t num_free;
 
 if (!s || (s->console_type == GRAPHIC_CONSOLE))
 return;
@@ -1228,7 +1182,8 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
 }
 be = s->chr->be;
 if (be && be->chr_read) {
-qemu_fifo_write(&s->out_fifo, buf, q - buf);
+num_free = fifo8_num_free(&s->out_fifo);
+fifo8_push_all(&s->out_fifo, buf, MIN(num_free, q - buf));
 kbd_send_chars(s);
 }
 break;
@@ -2233,8 +2188,7 @@ static void text_console_do_init(Chardev *chr, 
DisplayState *ds)
 int g_width = 80 * FONT_WIDTH;
 int g_height = 24 * FONT_HEIGHT;
 
-s->out_fifo.buf = s->out_fifo_buf;
-s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
+fifo8_create(&s->out_fifo, 16);
 s->kbd_timer = timer_new_ms(QEMU_CLOCK_REALTIME, kbd_send_chars, s);
 s->ds = ds;
 
-- 
2.31.1




[PATCH v2 0/4] ui/console: chardev backend improvements

2021-09-16 Thread Volker Rümelin

A few things I learnt while writing a fix for a chardev bug
in the GTK backend.

v2:
Patch "ui/console: replace QEMUFIFO with Fifo8". Renamed the
variable free to num_free to help reading the code. (Marc-André)

New patch "ui/console: prevent use after free error".
ui/gtk.c needs a similar patch. I'll take care of it.

Volker Rümelin (4):
  ui/console: replace QEMUFIFO with Fifo8
  ui/console: replace kbd_timer with chr_accept_input callback
  ui/console: remove chardev frontend connected test
  ui/console: prevent use after free error

 ui/console.c | 110 ++-
 1 file changed, 30 insertions(+), 80 deletions(-)

--
2.31.1



Re: [PATCH 0/2] Python: update CI tests for pylint 2.10 and 2.11

2021-09-16 Thread John Snow
On Thu, Sep 16, 2021 at 2:22 PM John Snow  wrote:

> GitLab: https://gitlab.com/jsnow/qemu/-/commits/python-package-pylint-211
> CI: https://gitlab.com/jsnow/qemu/-/pipelines/372122981
>
> While debating the fix for 2.10, 2.11 released and added new warnings to
> suppress.
>
> This version includes everything needed to get the Gitlab CI green again.
>
> John Snow (2):
>   python: Update for pylint 2.10
>   python: pylint 2.11 support
>
>  python/qemu/machine/machine.py | 7 ++-
>  python/setup.cfg   | 3 ++-
>  2 files changed, 8 insertions(+), 2 deletions(-)
>
>
Eduardo, Willian: Thank you very much!

I have staged this on my python branch:
https://gitlab.com/jsnow/qemu/-/commits/python

PR to follow as soon as the lights turn green.

--js


Re: [ RFC v2 3/9] target/riscv: pmu: Make number of counters configurable

2021-09-16 Thread Atish Patra
On Wed, Sep 15, 2021 at 7:51 AM Bin Meng  wrote:
>
> On Fri, Sep 10, 2021 at 4:29 AM Atish Patra  wrote:
> >
> > The RISC-V privilege specification provides flexibility to implement
> > any number of counters from 29 programmable counters. However, the Qemu
>
> nits: %s/Qemu/QEMU
>
> > implements all the counters.
> >
> > Make it configurable through pmu config parameter which now will indicate
> > how many programmable counters should be implemented by the cpu.
> >
> > Signed-off-by: Atish Patra 
> > ---
> >  target/riscv/cpu.c |  2 +-
> >  target/riscv/cpu.h |  2 +-
> >  target/riscv/csr.c | 96 ++
> >  3 files changed, 65 insertions(+), 35 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 7a486450ebc6..eba6050324a0 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -587,7 +587,7 @@ static Property riscv_cpu_properties[] = {
> >  DEFINE_PROP_BOOL("x-b", RISCVCPU, cfg.ext_b, false),
> >  DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
> >  DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false),
> > -DEFINE_PROP_BOOL("pmu", RISCVCPU, cfg.ext_pmu, true),
> > +DEFINE_PROP_UINT16("pmu", RISCVCPU, cfg.ext_pmu, 16),
>
> UINT8 should be enough. The name should better be changed to pmu-num
> (cfg.pmu_num).

ok. will change it.

>
> >  DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
> >  DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
> >  DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index 5e67003e58a3..0e2e88f3bbea 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -293,9 +293,9 @@ struct RISCVCPU {
> >  bool ext_u;
> >  bool ext_h;
> >  bool ext_v;
> > -bool ext_pmu;
> >  bool ext_ifencei;
> >  bool ext_icsr;
> > +uint16_t ext_pmu;
> >
> >  char *priv_spec;
> >  char *user_spec;
> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > index c3ce7d83a6b2..fa014bac72ab 100644
> > --- a/target/riscv/csr.c
> > +++ b/target/riscv/csr.c
> > @@ -57,15 +57,45 @@ static RISCVException vs(CPURISCVState *env, int csrno)
> >  return RISCV_EXCP_ILLEGAL_INST;
> >  }
> >
> > +static RISCVException mctr(CPURISCVState *env, int csrno)
> > +{
> > +#if !defined(CONFIG_USER_ONLY)
> > +CPUState *cs = env_cpu(env);
> > +RISCVCPU *cpu = RISCV_CPU(cs);
> > +int ctr_index;
> > +int base_csrno = CSR_MHPMCOUNTER3;
> > +
> > +if (riscv_cpu_is_32bit(env) && csrno >= CSR_MCYCLEH) {
> > +/* Offset for RV32 hpmcounternh counters */
>
> should be mhpmcounternh

yeah.

>
> > +base_csrno += 0x80;
> > +}
> > +ctr_index = csrno - base_csrno;
> > +if (!cpu->cfg.ext_pmu || ctr_index > cpu->cfg.ext_pmu) {
>
> ctr_index >= cpu->cfg.ext_pmu

Yup.

>
> > +/* The Counters extensions is not enabled or out of range*/
>
> PMU extension
>
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +
> > +return RISCV_EXCP_NONE;
> > +#endif
> > +}
> > +
> >  static RISCVException ctr(CPURISCVState *env, int csrno)
> >  {
> >  #if !defined(CONFIG_USER_ONLY)
> >  CPUState *cs = env_cpu(env);
> >  RISCVCPU *cpu = RISCV_CPU(cs);
> >  int ctr_index;
> > +int base_csrno = CSR_CYCLE;
> > +bool brv32 = riscv_cpu_is_32bit(env);
> > +
> > +if (brv32 && csrno >= CSR_CYCLEH) {
> > +/* Offset for RV32 hpmcounternh counters */
> > +base_csrno += 0x80;
> > +}
> > +ctr_index = csrno - base_csrno;
> >
> > -if (!cpu->cfg.ext_pmu) {
> > -/* The Counters extensions is not enabled */
> > +if (!cpu->cfg.ext_pmu || ctr_index > (cpu->cfg.ext_pmu + 3)) {
>
> ctr_index >=
>
> > +/* The Counters extensions is not enabled or out of range */
>
> PMU extension

Thanks. I will address all these in v3.

>
> >  return RISCV_EXCP_ILLEGAL_INST;
> >  }
> >
> > @@ -93,7 +123,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
> >  }
> >  break;
> >  }
> > -if (riscv_cpu_is_32bit(env)) {
> > +if (brv32) {
> >  switch (csrno) {
> >  case CSR_CYCLEH:
> >  if (!get_field(env->mcounteren, HCOUNTEREN_CY)) {
> > @@ -148,7 +178,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
> >  }
> >  break;
> >  }
> > -if (riscv_cpu_is_32bit(env)) {
> > +if (brv32) {
> >  switch (csrno) {
> >  case CSR_CYCLEH:
> >  if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
> > @@ -1721,35 +1751,35 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> >  [CSR_HPMCOUNTER30]   = { "hpmcounter30",   ctr,read_zero },
> >  [CSR_HPMCOUNTER31]   = { "hpmcounter31",   ctr,read_zero },
> >
> > -[CSR_MHPMCOUNTER3]   = { "mhpmcounter3",   any,read_zero 

Re: [ RFC v2 4/9] target/riscv: Implement mcountinhibit CSR

2021-09-16 Thread Atish Patra
On Wed, Sep 15, 2021 at 7:54 AM Bin Meng  wrote:
>
> On Fri, Sep 10, 2021 at 4:29 AM Atish Patra  wrote:
> >
> > As per the privilege specification v1.11, mcountinhibit allows to start/stop
> > a pmu counter selectively.
> >
> > Signed-off-by: Atish Patra 
> > ---
> >  target/riscv/cpu.h  |  2 ++
> >  target/riscv/cpu_bits.h |  4 
> >  target/riscv/csr.c  | 25 +
> >  target/riscv/machine.c  |  5 +++--
> >  4 files changed, 34 insertions(+), 2 deletions(-)
> >
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index 0e2e88f3bbea..bdb488cdbccc 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -219,6 +219,8 @@ struct CPURISCVState {
> >  target_ulong scounteren;
> >  target_ulong mcounteren;
> >
> > +target_ulong mcountinhibit;
> > +
> >  target_ulong sscratch;
> >  target_ulong mscratch;
> >
> > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> > index 7330ff5a194c..ac519dcdc4df 100644
> > --- a/target/riscv/cpu_bits.h
> > +++ b/target/riscv/cpu_bits.h
> > @@ -275,6 +275,10 @@
> >  #define CSR_MHPMCOUNTER29   0xb1d
> >  #define CSR_MHPMCOUNTER30   0xb1e
> >  #define CSR_MHPMCOUNTER31   0xb1f
> > +
> > +/* Machine counter-inhibit register */
> > +#define CSR_MCOUNTINHIBIT   0x320
> > +
> >  #define CSR_MHPMEVENT3  0x323
> >  #define CSR_MHPMEVENT4  0x324
> >  #define CSR_MHPMEVENT5  0x325
> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > index fa014bac72ab..a155a4370d6b 100644
> > --- a/target/riscv/csr.c
> > +++ b/target/riscv/csr.c
> > @@ -766,6 +766,28 @@ static RISCVException write_mtvec(CPURISCVState *env, 
> > int csrno,
> >  return RISCV_EXCP_NONE;
> >  }
> >
> > +static RISCVException read_mcountinhibit(CPURISCVState *env, int csrno,
> > + target_ulong *val)
> > +{
> > +if (env->priv_ver < PRIV_VERSION_1_11_0) {
> > +return -RISCV_EXCP_ILLEGAL_INST;
>
> This should be RISCV_EXCP_ILLEGAL_INST
>

Argh. Not sure how this happen :(. My bad.

> > +}
> > +
> > +*val = env->mcountinhibit;
> > +return RISCV_EXCP_NONE;
> > +}
> > +
> > +static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno,
> > +  target_ulong val)
> > +{
> > +if (env->priv_ver < PRIV_VERSION_1_11_0) {
> > +return -RISCV_EXCP_ILLEGAL_INST;
>
> ditto
>
> > +}
> > +
> > +env->mcountinhibit = val;
> > +return RISCV_EXCP_NONE;
> > +}
> > +
> >  static RISCVException read_mcounteren(CPURISCVState *env, int csrno,
> >target_ulong *val)
> >  {
> > @@ -1781,6 +1803,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> >  [CSR_MHPMCOUNTER30]  = { "mhpmcounter30",  mctr,   read_zero },
> >  [CSR_MHPMCOUNTER31]  = { "mhpmcounter31",  mctr,   read_zero },
> >
> > +[CSR_MCOUNTINHIBIT]  = { "mcountinhibi",   any,read_mcountinhibit,
>
> missing 't' in the register name

Thanks. Will fix it in the next version.

>
> > +   write_mcountinhibit 
> > },
> > +
> >  [CSR_MHPMEVENT3] = { "mhpmevent3", any,read_zero },
> >  [CSR_MHPMEVENT4] = { "mhpmevent4", any,read_zero },
> >  [CSR_MHPMEVENT5] = { "mhpmevent5", any,read_zero },
> > diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> > index 16a08302daff..20dea0843604 100644
> > --- a/target/riscv/machine.c
> > +++ b/target/riscv/machine.c
> > @@ -140,8 +140,8 @@ static const VMStateDescription vmstate_hyper = {
> >
> >  const VMStateDescription vmstate_riscv_cpu = {
> >  .name = "cpu",
> > -.version_id = 2,
> > -.minimum_version_id = 2,
> > +.version_id = 3,
> > +.minimum_version_id = 3,
> >  .fields = (VMStateField[]) {
> >  VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
> >  VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
> > @@ -177,6 +177,7 @@ const VMStateDescription vmstate_riscv_cpu = {
> >  VMSTATE_UINTTL(env.mtval, RISCVCPU),
> >  VMSTATE_UINTTL(env.scounteren, RISCVCPU),
> >  VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
> > +VMSTATE_UINTTL(env.mcountinhibit, RISCVCPU),
> >  VMSTATE_UINTTL(env.sscratch, RISCVCPU),
> >  VMSTATE_UINTTL(env.mscratch, RISCVCPU),
> >  VMSTATE_UINT64(env.mfromhost, RISCVCPU),
> > --
>
> Regards,
> Bin
>


-- 
Regards,
Atish



Re: [PATCH 1/2] python: Update for pylint 2.10

2021-09-16 Thread Willian Rampazzo
On Thu, Sep 16, 2021 at 3:29 PM John Snow  wrote:
>
> A few new annoyances. Of note is the new warning for an unspecified
> encoding when opening a text file, which actually does indicate a
> potentially real problem; see
> https://www.python.org/dev/peps/pep-0597/#motivation
>
> Use LC_CTYPE to determine an encoding to use for interpreting QEMU's
> terminal output. Note that Python states: "language code and encoding
> may be None if their values cannot be determined" -- use a platform
> default as a backup.
>
> Notes: Passing encoding=None will generate a suppressed warning on
> Python 3.10+ that 'None' should not be passed as the encoding
> argument. This behavior may be deprecated in the future and the default
> switched to be a ubiquitous UTF-8. Opting in to the locale default will
> be done by passing the encoding 'locale', but that isn't available in
> 3.6 through 3.9. Presumably this warning will be unsuppressed some time
> prior to the actual switch and we can re-investigate these issues at
> that time if necessary.
>
> Signed-off-by: John Snow 
> ---
>  python/qemu/machine/machine.py | 7 ++-
>  python/setup.cfg   | 1 +
>  2 files changed, 7 insertions(+), 1 deletion(-)
>

Reviewed-by: Willian Rampazzo 




Re: [PATCH 2/2] python: pylint 2.11 support

2021-09-16 Thread Willian Rampazzo
On Thu, Sep 16, 2021 at 3:24 PM John Snow  wrote:
>
> We're not ready to enforce f-strings everywhere, so just silence this
> new warning.

Oh, boy! We are good, thanks :)

>
> Signed-off-by: John Snow 
> ---
>  python/setup.cfg | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>

Reviewed-by: Willian Rampazzo 




Re: [PATCH 2/2] python: pylint 2.11 support

2021-09-16 Thread Eduardo Habkost
On Thu, Sep 16, 2021 at 02:22:48PM -0400, John Snow wrote:
> We're not ready to enforce f-strings everywhere, so just silence this
> new warning.
> 
> Signed-off-by: John Snow 

Reviewed-by: Eduardo Habkost 

-- 
Eduardo




Re: [ RFC v2 1/9] target/riscv: Fix PMU CSR predicate function

2021-09-16 Thread Atish Patra
On Wed, Sep 15, 2021 at 7:51 AM Bin Meng  wrote:
>
> On Fri, Sep 10, 2021 at 4:27 AM Atish Patra  wrote:
> >
> > Currently, the predicate function for PMU related CSRs only works if
> > virtualization is enabled. Ideally, they should check the mcountern
> > bits before cycle/minstret/hpmcounterx access. The predicate function
> > also calculates the counter index incorrectly for hpmcounterx.
> >
> > Signed-off-by: Atish Patra 
> > ---
> >  target/riscv/csr.c | 62 +++---
> >  1 file changed, 58 insertions(+), 4 deletions(-)
> >
> > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > index 9a4ed18ac597..0515d851b948 100644
> > --- a/target/riscv/csr.c
> > +++ b/target/riscv/csr.c
> > @@ -62,12 +62,64 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
> >  #if !defined(CONFIG_USER_ONLY)
> >  CPUState *cs = env_cpu(env);
> >  RISCVCPU *cpu = RISCV_CPU(cs);
> > +int ctr_index;
> >
> >  if (!cpu->cfg.ext_counters) {
> >  /* The Counters extensions is not enabled */
> >  return RISCV_EXCP_ILLEGAL_INST;
> >  }
> >
> > +if (env->priv == PRV_S) {
> > +switch (csrno) {
> > +case CSR_CYCLE:
> > +if (!get_field(env->mcounteren, HCOUNTEREN_CY)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +case CSR_TIME:
> > +if (!get_field(env->mcounteren, HCOUNTEREN_TM)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +case CSR_INSTRET:
> > +if (!get_field(env->mcounteren, HCOUNTEREN_IR)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
> > +ctr_index = csrno - CSR_HPMCOUNTER3 + 3;
> > +if (!get_field(env->mcounteren, 1 << ctr_index)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +}
> > +if (riscv_cpu_is_32bit(env)) {
> > +switch (csrno) {
> > +case CSR_CYCLEH:
> > +if (!get_field(env->mcounteren, HCOUNTEREN_CY)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +case CSR_TIMEH:
> > +if (!get_field(env->mcounteren, HCOUNTEREN_TM)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +case CSR_INSTRETH:
> > +if (!get_field(env->mcounteren, HCOUNTEREN_IR)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
> > +ctr_index = csrno - CSR_HPMCOUNTER3H + 3;
> > +if (!get_field(env->mcounteren, 1 << ctr_index)) {
> > +return RISCV_EXCP_ILLEGAL_INST;
> > +}
> > +break;
> > +}
> > +}
> > +}
> > +
> >  if (riscv_cpu_virt_enabled(env)) {
> >  switch (csrno) {
> >  case CSR_CYCLE:
> > @@ -89,8 +141,9 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
> >  }
> >  break;
> >  case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
> > -if (!get_field(env->hcounteren, 1 << (csrno - 
> > CSR_HPMCOUNTER3)) &&
> > -get_field(env->mcounteren, 1 << (csrno - 
> > CSR_HPMCOUNTER3))) {
> > +ctr_index = csrno - CSR_HPMCOUNTER3 + 3;
>
> ctr_index = csrno - CSR_CYCLE;

Will update it.

>
> > +if (!get_field(env->hcounteren, 1 << ctr_index) &&
> > +get_field(env->mcounteren, 1 << ctr_index)) {
>
> This fix (along with the H part below) should be put in a separate patch.

Sure.

>
> >  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> >  }
> >  break;
> > @@ -116,8 +169,9 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
> >  }
> >  break;
> >  case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
> > -if (!get_field(env->hcounteren, 1 << (csrno - 
> > CSR_HPMCOUNTER3H)) &&
> > -get_field(env->mcounteren, 1 << (csrno - 
> > CSR_HPMCOUNTER3H))) {
> > +ctr_index = csrno - CSR_HPMCOUNTER3H + 3;
>
> ctr_index = csrno - CSR_CYCLEH;
>
> > +if (!get_field(env->hcounteren, 1 << ctr_index) &&
> > +get_field(env->mcounteren, 1 << ctr_index)) {
> >  return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> >  }
> >  break;
> > --
>
> You may need to rebase the patch on:
> http://patchwork.ozlabs.org/project/qemu-devel/patch/20210915084601.24304-1-bmeng...@gmail.com/
>

Sure.

> Regards,
> Bin
>


-- 
Regards,
Atish



Re: [PATCH 1/2] python: Update for pylint 2.10

2021-09-16 Thread Eduardo Habkost
On Thu, Sep 16, 2021 at 02:22:47PM -0400, John Snow wrote:
> A few new annoyances. Of note is the new warning for an unspecified
> encoding when opening a text file, which actually does indicate a
> potentially real problem; see
> https://www.python.org/dev/peps/pep-0597/#motivation
> 
> Use LC_CTYPE to determine an encoding to use for interpreting QEMU's
> terminal output. Note that Python states: "language code and encoding
> may be None if their values cannot be determined" -- use a platform
> default as a backup.
> 
> Notes: Passing encoding=None will generate a suppressed warning on
> Python 3.10+ that 'None' should not be passed as the encoding
> argument. This behavior may be deprecated in the future and the default
> switched to be a ubiquitous UTF-8. Opting in to the locale default will
> be done by passing the encoding 'locale', but that isn't available in
> 3.6 through 3.9. Presumably this warning will be unsuppressed some time
> prior to the actual switch and we can re-investigate these issues at
> that time if necessary.

So, in the very worst case this will trigger a warning that is
currently suppressed.  And that will happen only if we are in the
unlikely situation where we have absolutely no information about
the encoding being used by other parts of the system.

Sounds reasonable to me, so:

Reviewed-by: Eduardo Habkost 

> 
> Signed-off-by: John Snow 
> ---
>  python/qemu/machine/machine.py | 7 ++-
>  python/setup.cfg   | 1 +
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
> index a7081b1845..34131884a5 100644
> --- a/python/qemu/machine/machine.py
> +++ b/python/qemu/machine/machine.py
> @@ -19,6 +19,7 @@
>  
>  import errno
>  from itertools import chain
> +import locale
>  import logging
>  import os
>  import shutil
> @@ -290,8 +291,12 @@ def get_pid(self) -> Optional[int]:
>  return self._subp.pid
>  
>  def _load_io_log(self) -> None:
> +# Assume that the output encoding of QEMU's terminal output is
> +# defined by our locale. If indeterminate, allow open() to fall
> +# back to the platform default.
> +_, encoding = locale.getlocale()
>  if self._qemu_log_path is not None:
> -with open(self._qemu_log_path, "r") as iolog:
> +with open(self._qemu_log_path, "r", encoding=encoding) as iolog:
>  self._iolog = iolog.read()
>  
>  @property
> diff --git a/python/setup.cfg b/python/setup.cfg
> index 83909c1c97..0f0cab098f 100644
> --- a/python/setup.cfg
> +++ b/python/setup.cfg
> @@ -104,6 +104,7 @@ good-names=i,
>  [pylint.similarities]
>  # Ignore imports when computing similarities.
>  ignore-imports=yes
> +ignore-signatures=yes
>  
>  # Minimum lines number of a similarity.
>  # TODO: Remove after we opt in to Pylint 2.8.3. See commit msg.
> -- 
> 2.31.1
> 

-- 
Eduardo




Re: [PATCH] hw/rtc/pl031: Send RTC_CHANGE QMP event

2021-09-16 Thread Peter Maydell
On Thu, 16 Sept 2021 at 18:19, Eric Auger  wrote:
>
> Hi Peter,
> On 9/16/21 3:32 PM, Peter Maydell wrote:
> > None of the other users of qapi_event_send_rtc_change()
> > seem to have to track the baseline time like this. Shouldn't
> > this be doing something involving using qemu_ref_timedate()
> > as the baseline that it uses to figure out the change value ?
> > (The other users do this via qemu_timedate_diff() but since we
> > start with a value-in-seconds we might want to expose some other
> > API in softmmu/rtc.c.)
>
> I struggled understanding the various kinds of clocks modeled in qemu
> and the PL031 implementation. Both devices calling
> qapi_event_send_rtc_change() seem to store the base rtc in their state
> (mc146818rtc.c cmos data or spapr_rtc tas_ld(args, )) and then
> effectivelly call qemu_timedate_diff() on this base rtc value. I did not
> figure to do the equivalent with the pl031. I will further investigate
> how I can mimic their implementation though.

mc146818rtc.c calls qapi_event_send_rtc_change() in rtc_set_time().
It looks to me like that is just "when the guest writes to an
RTC register such that the guest RTC time has changed, use
qemu_timedate_diff() to find out the delta between that and what
the softmmu/rtc.c clock has as its baseline time, and then pass
that delta in seconds to qapi_event_send_rtc_change()".
This RTC has a lot of separate day/month/year registers, so the
implementation's idea of "current guest RTC setting" is a
complicated thing that it fills in into a struct tm, and which
qemu_timedate_diff() then parses back out into a "seconds" value.

spapr_rtc() is a hypercall implementation, so the guest passes it
a complete set of year/month/day/etc values all at once to set the time.

pl031 is a lot simpler as it is essentially just a count of
time in seconds, which we set up as "seconds since the Unix epoch".
But the basic principle is the same: the device contains the state
that tells you what it thinks the guest RTC value is now, and the
value we want to pass qapi_event_send_rtc_change() is the
difference between that and the reference time kept in
softmmu/rtc.c.

I think what you want is probably:

struct tm tm;

qemu_get_timedate(&tm, s->tick_offset);
qapi_event_send_rtc_change(qemu_timedate_diff(&tm));

But I'm not 100% sure. I also feel like this is doing a
roundtrip from seconds to struct tm to seconds again, which
seems a bit silly (but it might matter if the rtc is configured
to 'localtime'? At any rate it's not completely clear that
it's always a no-op roundtrip).

I've cc'd Paolo who might be a bit more familiar with the rtc code
than I am.

-- PMM



[PATCH 1/2] python: Update for pylint 2.10

2021-09-16 Thread John Snow
A few new annoyances. Of note is the new warning for an unspecified
encoding when opening a text file, which actually does indicate a
potentially real problem; see
https://www.python.org/dev/peps/pep-0597/#motivation

Use LC_CTYPE to determine an encoding to use for interpreting QEMU's
terminal output. Note that Python states: "language code and encoding
may be None if their values cannot be determined" -- use a platform
default as a backup.

Notes: Passing encoding=None will generate a suppressed warning on
Python 3.10+ that 'None' should not be passed as the encoding
argument. This behavior may be deprecated in the future and the default
switched to be a ubiquitous UTF-8. Opting in to the locale default will
be done by passing the encoding 'locale', but that isn't available in
3.6 through 3.9. Presumably this warning will be unsuppressed some time
prior to the actual switch and we can re-investigate these issues at
that time if necessary.

Signed-off-by: John Snow 
---
 python/qemu/machine/machine.py | 7 ++-
 python/setup.cfg   | 1 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index a7081b1845..34131884a5 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -19,6 +19,7 @@
 
 import errno
 from itertools import chain
+import locale
 import logging
 import os
 import shutil
@@ -290,8 +291,12 @@ def get_pid(self) -> Optional[int]:
 return self._subp.pid
 
 def _load_io_log(self) -> None:
+# Assume that the output encoding of QEMU's terminal output is
+# defined by our locale. If indeterminate, allow open() to fall
+# back to the platform default.
+_, encoding = locale.getlocale()
 if self._qemu_log_path is not None:
-with open(self._qemu_log_path, "r") as iolog:
+with open(self._qemu_log_path, "r", encoding=encoding) as iolog:
 self._iolog = iolog.read()
 
 @property
diff --git a/python/setup.cfg b/python/setup.cfg
index 83909c1c97..0f0cab098f 100644
--- a/python/setup.cfg
+++ b/python/setup.cfg
@@ -104,6 +104,7 @@ good-names=i,
 [pylint.similarities]
 # Ignore imports when computing similarities.
 ignore-imports=yes
+ignore-signatures=yes
 
 # Minimum lines number of a similarity.
 # TODO: Remove after we opt in to Pylint 2.8.3. See commit msg.
-- 
2.31.1




[PATCH 0/2] Python: update CI tests for pylint 2.10 and 2.11

2021-09-16 Thread John Snow
GitLab: https://gitlab.com/jsnow/qemu/-/commits/python-package-pylint-211
CI: https://gitlab.com/jsnow/qemu/-/pipelines/372122981

While debating the fix for 2.10, 2.11 released and added new warnings to
suppress.

This version includes everything needed to get the Gitlab CI green again.

John Snow (2):
  python: Update for pylint 2.10
  python: pylint 2.11 support

 python/qemu/machine/machine.py | 7 ++-
 python/setup.cfg   | 3 ++-
 2 files changed, 8 insertions(+), 2 deletions(-)

-- 
2.31.1





  1   2   3   4   >