Re: [PATCH] hw/i386: Add unaccepted memory configuration

2022-06-20 Thread Gerd Hoffman
On Mon, Jun 20, 2022 at 10:33:00PM +, Dionna Glaze wrote:
> For SEV-SNP, an OS is "SEV-SNP capable" without supporting this UEFI
> v2.9 memory type. In order for OVMF to be able to avoid pre-validating
> potentially hundreds of gibibytes of data before booting, it needs to
> know if the guest OS can support its use of the new type of memory in
> the memory map.

I think this should be wired up via sev-guest object (see
SevGuestProperties in qapi/qom.json and target/i386/sev.c),
i.e.

qemu -object sev-guest,accept-all-memory=true,$args

(and likewise for -object tdx-guest once merged).

take care,
  Gerd




Re: [PATCH v18 02/13] linux-user: Add LoongArch signal support

2022-06-20 Thread gaosong

Hi Richard

On 2022/6/21 上午12:23, Richard Henderson wrote:

On 6/20/22 02:33, Song Gao wrote:

+static int restore_sigcontext(CPULoongArchState *env,
+   struct target_sigcontext *sc)
+{
+    int i;
+    int ret = 0;
+    struct extctx_layout extctx;
+
+    memset(, 0, sizeof(struct extctx_layout));
+
+    __get_user(extctx.flags, >sc_flags);
+
+    ret = parse_extcontext(sc, );
+    if (ret < 0) {
+    goto bad;
+    }
+
+    __get_user(env->pc, >sc_pc);
+    for (i = 1; i < 32; ++i) {
+    __get_user(env->gpr[i], >sc_regs[i]);
+    }
+
+    if (extctx.fpu.addr) {
+    copy_fpu_from_sigcontext(env, );
+    restore_fp_status(env);
+    }
+bad:
+    return ret;
+}


This is missing lock_user/unlock_user somewhere.
You can't use the double-underscore __get/__put_user without having 
done that.


My understanding is that the struct exctx need 
lock_user_struct/unlock_user_struct,  then we can use __get/__put the 
struct extctx.
You can use the non-underscore get_user in parse_extcontext, and 
separately lock the target_fpu_context.  Failures must goto invalid.




+void setup_rt_frame(int sig, struct target_sigaction *ka,
+    target_siginfo_t *info,
+    target_sigset_t *set, CPULoongArchState *env)
+{
+    struct target_rt_sigframe *frame;
+    struct extctx_layout extctx;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame), );
+    trace_user_setup_rt_frame(env, frame_addr);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+    goto give_sigsegv;
+    }


Similarly, this lock...


+
+    tswap_siginfo(>rs_info, info);
+
+    __put_user(0, >rs_uc.tuc_flags);
+    __put_user(0, >rs_uc.tuc_link);
+    target_save_altstack(>rs_uc.tuc_stack, env);
+
+    setup_sigcontext(env, >rs_uc.tuc_mcontext, );


... fails to cover the extra memory allocated for extctx.

This is why I suggested statically allocating the extra
pieces of the signal frame *on write*.  You obviously
cannot rely on the signal frame being identical on
signal return -- the guest is allowed to create any valid
context to give to rt_sigreturn.


I don’t know if my understanding is correct,

we can put the exctx or target_fpu_context into target_rt_sigframe, like 
this:

struct target_rt_sigframe {
    struct target_siginfo rs_info;
    struct target_ucontext rs_uc;
    struct extctx_layout rs_ext;
};
This way  that we just need lo lock/unlock target_rt_sigframe on 
setup_sigcontext/restore_sigcontext,


Thanks.
Song Gao




Re: [PATCH v4 3/4] migration: zero-copy flush only at the end of bitmap scanning

2022-06-20 Thread Leonardo Brás
On Mon, 2022-06-20 at 11:44 -0400, Peter Xu wrote:
> On Mon, Jun 20, 2022 at 11:23:53AM +0200, Juan Quintela wrote:
> > Once discussed this, what I asked in the past is that you are having too
> > much dirty memory on zero_copy.  When you have a Multiterabyte guest, in
> > a single round you have a "potentially" dirty memory on each channel of:
> > 
> >    total_amount_memory / number of channels.
> > 
> > In a Multiterabyte guest, this is going to be more that probably in the
> > dozens of gigabytes.  As far as I know there is no card/driver that will
> > benefit for so many pages in zero_copy, and kernel will move to
> > synchronous copy at some point.  (In older threads, daniel showed how to
> > test for this case).
> 
> I was wondering whether the kernel needs to cache a lot of messages for
> zero copy if we don't flush it for a long time, as recvmsg(MSG_ERRQUEUE)
> seems to be fetching one message from the kernel one at a time.  And,
> whether that queue has a limit in length or something.

IIRC, if all messages look the same, it 'merges' them in a single message, like,
'this range has these flags and output'.

So, if no issue happens, we should have a single message with the confirmation
of all sent buffers, meaning just a little memory is used for that.

> 
> Does it mean that when the kernel could have cached enough of these
> messages then it'll fallback to the no-zero-copy mode?  And probably that's
> the way how kernel protects itself from using too much buffer for the error
> msgs?

Since it merges the messages, I don't think it uses a lot of space for that.

IIRC, the kernel will fall back to copying only if the network adapter / driver
does not support MSG_ZEROCOPY, like when it does not support scatter-gather.

> 
> This reminded me - Leo, have you considered adding the patch altogether to
> detect the "fallback to non-zero-copy" condition?  Because when with it and
> when the fallback happens at some point (e.g. when the guest memory is
> larger than some value) we'll know.

I still did not consider that, but sure, how do you see that working?

We can't just disable zero-copy-send because the user actually opted in, so we
could instead add a one time error message for when it falls back to copying, as
it should happen in the first try of zero-copy send.

Or we could fail the migration, stating the interface does not support
MSG_ZEROCOPY, since it should happen in the first sendmsg().

I would personally opt for the last option.

What do you think?

> 
> Thanks,
> 

Thanks Peter!

Best regards,
Leo




Re: [PATCH v4 3/4] migration: zero-copy flush only at the end of bitmap scanning

2022-06-20 Thread Leonardo Brás
On Mon, 2022-06-20 at 11:23 +0200, Juan Quintela wrote:
> Leonardo Bras  wrote:
> > When sending memory pages with MSG_ZEROCOPY, it's necessary to flush
> > to make sure all dirty pages are sent before a future version of them
> > happens to be sent.
> > 
> > Currently, the flush happens every time at the end of ram_save_iterate(),
> > which usually happens around 20x per second, due to a timeout.
> > 
> > Change so it flushes only after a whole scanning of the dirty bimap,
> > so it never sends a newer version of a page before an older one, while
> > avoiding unnecessary overhead.
> > 
> > Signed-off-by: Leonardo Bras 
> 
> I agree that previous one is too many flushes, but this one changes to too
> much memory to be uncommitted, and that is important because otherwise we
> have unlimited amount of dirty memory.

I don't quite understand what you meant here.
What does it mean to be uncommitted at this context?
I don't see how we get unlimited amounts of dirty memory here. 

Zero-copy is not supposed to copy memory pages, so let's say all pages are dirty
and enqueued to send, but our network interface is stalling the send:
All memory we should have allocated is VM ram pagecount x sizeof(iov), because
then we flush.

Unless... are you referring to locked memory (as dirty enqueued memory -> locked
memory)? 
That would be a point: If we enqueue more memory than the locked memory amount
our user support, the migration will fail. 

But that would mean a very fast CPU (lots of sendmsgs) and a very slow network
interface. 

> 
> > +/*
> > + * Set zero_copy_flush = true for every multifd channel
> > + *
> > + * When using zero-copy, it's necessary to flush the pages before any of
> > + * the pages can be sent again, so we'll make sure the new version of the
> > + * pages will always arrive _later_ than the old pages.
> > + *
> > + * Should be called only after we finished one whole scanning of
> > + * all the dirty bitmaps.
> > + */
> > +int multifd_zero_copy_flush(void)
> > +{
> > +    int i;
> > +    Error *local_err = NULL;
> > +
> > +    if (!migrate_use_multifd()) {
> > +    return 0;
> > +    }
> > +
> > +    for (i = 0; i < migrate_multifd_channels(); i++) {
> > +    MultiFDSendParams *p = _send_state->params[i];
> > +    int ret;
> > +
> > +    ret = qio_channel_flush(p->c, _err);
> > +    if (ret < 0) {
> > +    error_report_err(local_err);
> > +    return ret;
> > +    }
> > +    }
> > +
> > +    return 0;
> > +}
> 
> 
> Here you flush every channel, Only at the end of a range you want to do this.

Yes, the idea is to flush after a full scan of the dirty-bitmap.

> 
> 
> >  int multifd_send_sync_main(QEMUFile *f)
> >  {
> >  int i;
> > -    bool flush_zero_copy;
> >  
> >  if (!migrate_use_multifd()) {
> >  return 0;
> > @@ -581,19 +613,6 @@ int multifd_send_sync_main(QEMUFile *f)
> >  }
> >  }
> >  
> > -    /*
> > - * When using zero-copy, it's necessary to flush the pages before any
> > of
> > - * the pages can be sent again, so we'll make sure the new version of
> > the
> > - * pages will always arrive _later_ than the old pages.
> > - *
> > - * Currently we achieve this by flushing the zero-page requested writes
> > - * per ram iteration, but in the future we could potentially optimize
> > it
> > - * to be less frequent, e.g. only after we finished one whole scanning
> > of
> > - * all the dirty bitmaps.
> > - */
> > -
> > -    flush_zero_copy = migrate_use_zero_copy_send();
> > -
> >  for (i = 0; i < migrate_multifd_channels(); i++) {
> >  MultiFDSendParams *p = _send_state->params[i];
> >  
> > @@ -615,17 +634,6 @@ int multifd_send_sync_main(QEMUFile *f)
> >  ram_counters.transferred += p->packet_len;
> >  qemu_mutex_unlock(>mutex);
> >  qemu_sem_post(>sem);
> > -
> > -    if (flush_zero_copy && p->c) {
> > -    int ret;
> > -    Error *err = NULL;
> > -
> > -    ret = qio_channel_flush(p->c, );
> > -    if (ret < 0) {
> > -    error_report_err(err);
> > -    return -1;
> > -    }
> > -    }
> 
> This synchronization already happens once every iteration through all
> ram.
> 
> 
> 
> And low and behold, it doesn't.
> 
> The problem here is that we are calling multifd_send_sync_main() in the
> wrong place, i.e. we are being too conservative.
> 
> We need to call multifd_send_sync_main() just before doing
> migration_bitmap_sync().  The reason that we need to call that function
> is exactly the same that we need to flush for zero_copy.
> 
> So, what we need to change is remove the call to
> multifd_send_sync_main(), not how it handles zero_copy.

So, IIUC, multifd have been syncing in a conservative way (i.e. more than
actually needed), and we need to do the same improvement (sync less) for multifd
too, instead of just changing it for zero-copy. Is that correct?

> 
> >  }
> >  for 

Re: [PATCH 0/2] target/arm: Fix issue 1078

2022-06-20 Thread He Zhe



On 6/19/22 08:15, Richard Henderson wrote:
> Nicely summarized by the reporter, but I thought it would be
> nicer to pull all of the logic into arm_pamax, rather than
> leave it separated.

Reported-by: He Zhe 

I ran a quick test. qemu still hangs with these two commits applied.

One fact that might help, qemu can boot up successfully if the change of the
following commit is reverted.
https://gitlab.com/qemu-project/qemu/-/commit/39a1fd25287f5dece59fdf4752491faf59310296
The change had been moved to target/arm/ptw.c.

Zhe

>
>
> r~
>
>
> Richard Henderson (2):
>   target/arm: Extend arm_pamax to more than aarch64
>   target/arm: Check V7VE as well as LPAE in arm_pamax
>
>  hw/arm/virt.c| 10 +-
>  target/arm/ptw.c | 26 --
>  2 files changed, 21 insertions(+), 15 deletions(-)
>




[PATCH v2 3/3] util/cacheflush: Optimize flushing when ppc host has coherent icache

2022-06-20 Thread Richard Henderson
From: Nicholas Piggin 

On linux, the AT_HWCAP bit PPC_FEATURE_ICACHE_SNOOP indicates
that we can use a simplified 3 instruction flush sequence.

Signed-off-by: Nicholas Piggin 
Message-Id: <20220519141131.29839-1-npig...@gmail.com>
[rth: update after merging cacheflush.c and cacheinfo.c]
Signed-off-by: Richard Henderson 
---
 util/cacheflush.c | 25 +++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/util/cacheflush.c b/util/cacheflush.c
index 01b6cb7583..2c2c73e085 100644
--- a/util/cacheflush.c
+++ b/util/cacheflush.c
@@ -117,6 +117,10 @@ static void sys_cache_info(int *isize, int *dsize)
  * Architecture (+ OS) specific cache detection mechanisms.
  */
 
+#if defined(__powerpc__)
+static bool have_coherent_icache;
+#endif
+
 #if defined(__aarch64__) && !defined(CONFIG_DARWIN)
 /* Apple does not expose CTR_EL0, so we must use system interfaces. */
 static uint64_t save_ctr_el0;
@@ -156,6 +160,7 @@ static void arch_cache_info(int *isize, int *dsize)
 if (*dsize == 0) {
 *dsize = qemu_getauxval(AT_DCACHEBSIZE);
 }
+have_coherent_icache = qemu_getauxval(AT_HWCAP) & PPC_FEATURE_ICACHE_SNOOP;
 }
 
 #else
@@ -298,8 +303,24 @@ void flush_idcache_range(uintptr_t rx, uintptr_t rw, 
size_t len)
 void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t len)
 {
 uintptr_t p, b, e;
-size_t dsize = qemu_dcache_linesize;
-size_t isize = qemu_icache_linesize;
+size_t dsize, isize;
+
+/*
+ * Some processors have coherent caches and support a simplified
+ * flushing procedure.  See
+ *   POWER9 UM, 4.6.2.2 Instruction Cache Block Invalidate (icbi) 
+ *   https://ibm.ent.box.com/s/tmklq90ze7aj8f4n32er1mu3sy9u8k3k
+ */
+if (have_coherent_icache) {
+asm volatile ("sync\n\t"
+  "icbi 0,%0\n\t"
+  "isync"
+  : : "r"(rx) : "memory");
+return;
+}
+
+dsize = qemu_dcache_linesize;
+isize = qemu_icache_linesize;
 
 b = rw & ~(dsize - 1);
 e = (rw + len + dsize - 1) & ~(dsize - 1);
-- 
2.34.1




[PATCH v2 1/3] util: Merge cacheflush.c and cacheinfo.c

2022-06-20 Thread Richard Henderson
Combine the two files into cacheflush.c.  There's a couple of bits
that would be helpful to share between the two, and combining them
seems better than exporting the bits.

Signed-off-by: Richard Henderson 
---
 util/cacheflush.c | 202 +-
 util/cacheinfo.c  | 200 -
 util/meson.build  |   2 +-
 3 files changed, 202 insertions(+), 202 deletions(-)
 delete mode 100644 util/cacheinfo.c

diff --git a/util/cacheflush.c b/util/cacheflush.c
index 4b57186d89..8096afd33c 100644
--- a/util/cacheflush.c
+++ b/util/cacheflush.c
@@ -1,5 +1,5 @@
 /*
- * Flush the host cpu caches.
+ * Info about, and flushing the host cpu caches.
  *
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
@@ -9,8 +9,208 @@
 #include "qemu/cacheflush.h"
 #include "qemu/cacheinfo.h"
 #include "qemu/bitops.h"
+#include "qemu/host-utils.h"
+#include "qemu/atomic.h"
 
 
+int qemu_icache_linesize = 0;
+int qemu_icache_linesize_log;
+int qemu_dcache_linesize = 0;
+int qemu_dcache_linesize_log;
+
+/*
+ * Operating system specific cache detection mechanisms.
+ */
+
+#if defined(_WIN32)
+
+static void sys_cache_info(int *isize, int *dsize)
+{
+SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buf;
+DWORD size = 0;
+BOOL success;
+size_t i, n;
+
+/*
+ * Check for the required buffer size first.  Note that if the zero
+ * size we use for the probe results in success, then there is no
+ * data available; fail in that case.
+ */
+success = GetLogicalProcessorInformation(0, );
+if (success || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+return;
+}
+
+n = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+size = n * sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+buf = g_new0(SYSTEM_LOGICAL_PROCESSOR_INFORMATION, n);
+if (!GetLogicalProcessorInformation(buf, )) {
+goto fail;
+}
+
+for (i = 0; i < n; i++) {
+if (buf[i].Relationship == RelationCache
+&& buf[i].Cache.Level == 1) {
+switch (buf[i].Cache.Type) {
+case CacheUnified:
+*isize = *dsize = buf[i].Cache.LineSize;
+break;
+case CacheInstruction:
+*isize = buf[i].Cache.LineSize;
+break;
+case CacheData:
+*dsize = buf[i].Cache.LineSize;
+break;
+default:
+break;
+}
+}
+}
+ fail:
+g_free(buf);
+}
+
+#elif defined(__APPLE__)
+# include 
+static void sys_cache_info(int *isize, int *dsize)
+{
+/* There's only a single sysctl for both I/D cache line sizes.  */
+long size;
+size_t len = sizeof(size);
+if (!sysctlbyname("hw.cachelinesize", , , NULL, 0)) {
+*isize = *dsize = size;
+}
+}
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+# include 
+static void sys_cache_info(int *isize, int *dsize)
+{
+/* There's only a single sysctl for both I/D cache line sizes.  */
+int size;
+size_t len = sizeof(size);
+if (!sysctlbyname("machdep.cacheline_size", , , NULL, 0)) {
+*isize = *dsize = size;
+}
+}
+#else
+/* POSIX */
+
+static void sys_cache_info(int *isize, int *dsize)
+{
+# ifdef _SC_LEVEL1_ICACHE_LINESIZE
+int tmp_isize = (int) sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
+if (tmp_isize > 0) {
+*isize = tmp_isize;
+}
+# endif
+# ifdef _SC_LEVEL1_DCACHE_LINESIZE
+int tmp_dsize = (int) sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+if (tmp_dsize > 0) {
+*dsize = tmp_dsize;
+}
+# endif
+}
+#endif /* sys_cache_info */
+
+
+/*
+ * Architecture (+ OS) specific cache detection mechanisms.
+ */
+
+#if defined(__aarch64__)
+
+static void arch_cache_info(int *isize, int *dsize)
+{
+if (*isize == 0 || *dsize == 0) {
+uint64_t ctr;
+
+/*
+ * The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1,
+ * but (at least under Linux) these are marked protected by the
+ * kernel.  However, CTR_EL0 contains the minimum linesize in the
+ * entire hierarchy, and is used by userspace cache flushing.
+ */
+asm volatile("mrs\t%0, ctr_el0" : "=r"(ctr));
+if (*isize == 0) {
+*isize = 4 << (ctr & 0xf);
+}
+if (*dsize == 0) {
+*dsize = 4 << ((ctr >> 16) & 0xf);
+}
+}
+}
+
+#elif defined(_ARCH_PPC) && defined(__linux__)
+# include "elf.h"
+
+static void arch_cache_info(int *isize, int *dsize)
+{
+if (*isize == 0) {
+*isize = qemu_getauxval(AT_ICACHEBSIZE);
+}
+if (*dsize == 0) {
+*dsize = qemu_getauxval(AT_DCACHEBSIZE);
+}
+}
+
+#else
+static void arch_cache_info(int *isize, int *dsize) { }
+#endif /* arch_cache_info */
+
+/*
+ * ... and if all else fails ...
+ */
+
+static void fallback_cache_info(int *isize, int *dsize)
+{
+/* 

[PATCH v2 2/3] util/cacheflush: Merge aarch64 ctr_el0 usage

2022-06-20 Thread Richard Henderson
Merge init_ctr_el0 into arch_cache_info.  In flush_idcache_range,
use the pre-computed line sizes from the global variables.
Use CONFIG_DARWIN in preference to __APPLE__.

Signed-off-by: Richard Henderson 
---
 util/cacheflush.c | 44 +++-
 1 file changed, 19 insertions(+), 25 deletions(-)

diff --git a/util/cacheflush.c b/util/cacheflush.c
index 8096afd33c..01b6cb7583 100644
--- a/util/cacheflush.c
+++ b/util/cacheflush.c
@@ -70,7 +70,7 @@ static void sys_cache_info(int *isize, int *dsize)
 g_free(buf);
 }
 
-#elif defined(__APPLE__)
+#elif defined(CONFIG_DARWIN)
 # include 
 static void sys_cache_info(int *isize, int *dsize)
 {
@@ -117,20 +117,25 @@ static void sys_cache_info(int *isize, int *dsize)
  * Architecture (+ OS) specific cache detection mechanisms.
  */
 
-#if defined(__aarch64__)
-
+#if defined(__aarch64__) && !defined(CONFIG_DARWIN)
+/* Apple does not expose CTR_EL0, so we must use system interfaces. */
+static uint64_t save_ctr_el0;
 static void arch_cache_info(int *isize, int *dsize)
 {
-if (*isize == 0 || *dsize == 0) {
-uint64_t ctr;
+uint64_t ctr;
 
-/*
- * The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1,
- * but (at least under Linux) these are marked protected by the
- * kernel.  However, CTR_EL0 contains the minimum linesize in the
- * entire hierarchy, and is used by userspace cache flushing.
- */
-asm volatile("mrs\t%0, ctr_el0" : "=r"(ctr));
+/*
+ * The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1,
+ * but (at least under Linux) these are marked protected by the
+ * kernel.  However, CTR_EL0 contains the minimum linesize in the
+ * entire hierarchy, and is used by userspace cache flushing.
+ *
+ * We will also use this value in flush_idcache_range.
+ */
+asm volatile("mrs\t%0, ctr_el0" : "=r"(ctr));
+save_ctr_el0 = ctr;
+
+if (*isize == 0 || *dsize == 0) {
 if (*isize == 0) {
 *isize = 4 << (ctr & 0xf);
 }
@@ -228,17 +233,6 @@ void flush_idcache_range(uintptr_t rx, uintptr_t rw, 
size_t len)
 }
 #else
 
-/*
- * TODO: unify this with cacheinfo.c.
- * We want to save the whole contents of CTR_EL0, so that we
- * have more than the linesize, but also IDC and DIC.
- */
-static uint64_t save_ctr_el0;
-static void __attribute__((constructor)) init_ctr_el0(void)
-{
-asm volatile("mrs\t%0, ctr_el0" : "=r"(save_ctr_el0));
-}
-
 /*
  * This is a copy of gcc's __aarch64_sync_cache_range, modified
  * to fit this three-operand interface.
@@ -248,8 +242,8 @@ void flush_idcache_range(uintptr_t rx, uintptr_t rw, size_t 
len)
 const unsigned CTR_IDC = 1u << 28;
 const unsigned CTR_DIC = 1u << 29;
 const uint64_t ctr_el0 = save_ctr_el0;
-const uintptr_t icache_lsize = 4 << extract64(ctr_el0, 0, 4);
-const uintptr_t dcache_lsize = 4 << extract64(ctr_el0, 16, 4);
+const uintptr_t icache_lsize = qemu_icache_linesize;
+const uintptr_t dcache_lsize = qemu_dcache_linesize;
 uintptr_t p;
 
 /*
-- 
2.34.1




[PATCH v2 0/3] util: Optimize flushing when ppc host has coherent icache

2022-06-20 Thread Richard Henderson
This is Nick's patch, with the merge of the two files
as I suggested, and the aarch64 cleanup I promised.


r~


Nicholas Piggin (1):
  util/cacheflush: Optimize flushing when ppc host has coherent icache

Richard Henderson (2):
  util: Merge cacheflush.c and cacheinfo.c
  util/cacheflush: Merge aarch64 ctr_el0 usage

 util/cacheflush.c | 247 +++---
 util/cacheinfo.c  | 200 -
 util/meson.build  |   2 +-
 3 files changed, 232 insertions(+), 217 deletions(-)
 delete mode 100644 util/cacheinfo.c

-- 
2.34.1




Re: [PULL 20/33] configure: handle host compiler in probe_target_compiler

2022-06-20 Thread Richard Henderson

On 6/20/22 09:41, Matheus Kowalczuk Ferst wrote:

On 17/06/2022 07:12, Paolo Bonzini wrote:

Hi Matheus,

could you please test the tests-tcg-next branch at
https://gitlab.com/bonzini/qemu?


At be6090bcac10, it works if no BE toolchain is present. Otherwise, the
script probes powerpc64-linux-gnu-gcc instead of the native tools for
ppc64le-linux-user, and then do_compiler fails because the
$target_cflags contains -mlittle-endian.


Also testing this branch, -m32 may not be supported:

make[1]: Entering directory `/home/rth/qemu/bld/pc-bios/vof'

cc -m32 -mbig-endian -mcpu=power4 -c -o entry.o 
/home/rth/qemu/src/pc-bios/vof/entry.S

cc1: error: ‘-m32’ not supported in this configuration

make[1]: *** [entry.o] Error 1



This is with a self-built compiler, rather than distro packaged, but with default 
configure options to gcc.



r~



Re: [PATCH v3 1/1] target/riscv: Add Zihintpause support

2022-06-20 Thread Alistair Francis
On Thu, Jun 9, 2022 at 2:42 PM Dao Lu  wrote:
>
> Added support for RISC-V PAUSE instruction from Zihintpause extension,
> enabled by default.
>
> Tested-by: Heiko Stuebner 
> Signed-off-by: Dao Lu 
> ---
>  target/riscv/cpu.c  |  2 ++
>  target/riscv/cpu.h  |  1 +
>  target/riscv/insn32.decode  |  7 ++-
>  target/riscv/insn_trans/trans_rvi.c.inc | 18 ++
>  4 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index ccacdee215..183fb37fdf 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -825,6 +825,7 @@ static Property riscv_cpu_properties[] = {
>  DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
>  DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
>  DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
> +DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true),
>  DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
>  DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false),
>  DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false),
> @@ -996,6 +997,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char 
> **isa_str, int max_str_len)
>   *extensions by an underscore.
>   */
>  struct isa_ext_data isa_edata_arr[] = {
> +ISA_EDATA_ENTRY(zihintpause, ext_zihintpause),
>  ISA_EDATA_ENTRY(zfh, ext_zfh),
>  ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
>  ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index fe6c9a2c92..e466a04a59 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -394,6 +394,7 @@ struct RISCVCPUConfig {
>  bool ext_counters;
>  bool ext_ifencei;
>  bool ext_icsr;
> +bool ext_zihintpause;
>  bool ext_svinval;
>  bool ext_svnapot;
>  bool ext_svpbmt;
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 4033565393..595fdcdad8 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -149,7 +149,12 @@ srl  000 .. 101 . 0110011 @r
>  sra  010 .. 101 . 0110011 @r
>  or   000 .. 110 . 0110011 @r
>  and  000 .. 111 . 0110011 @r
> -fence pred:4 succ:4 - 000 - 000
> +
> +{
> +  pause   0001      0 000 0 000
> +  fence   pred:4 succ:4 - 000 - 000
> +}
> +
>  fence_i         - 001 - 000
>  csrrw . 001 . 1110011 @csr
>  csrrs . 010 . 1110011 @csr
> diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
> b/target/riscv/insn_trans/trans_rvi.c.inc
> index f1342f30f8..ca75e05f4b 100644
> --- a/target/riscv/insn_trans/trans_rvi.c.inc
> +++ b/target/riscv/insn_trans/trans_rvi.c.inc
> @@ -796,6 +796,24 @@ static bool trans_srad(DisasContext *ctx, arg_srad *a)
>  return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL);
>  }
>
> +static bool trans_pause(DisasContext *ctx, arg_pause *a)
> +{
> +if (!ctx->cfg_ptr->ext_zihintpause) {
> +return false;
> +}
> +
> +/*
> + * PAUSE is a no-op in QEMU,
> + * however we need to clear the reservation,
> + * end the TB and return to main loop
> + */
> +tcg_gen_movi_tl(load_res, -1);

I'm not clear why we need to clear the load_res? We don't do it for
fence instruction

Alistair

> +gen_set_pc_imm(ctx, ctx->pc_succ_insn);
> +tcg_gen_exit_tb(NULL, 0);
> +ctx->base.is_jmp = DISAS_NORETURN;
> +
> +return true;
> +}
>
>  static bool trans_fence(DisasContext *ctx, arg_fence *a)
>  {
> --
> 2.25.1
>
>



[PATCH v10 09/12] target/riscv: Simplify counter predicate function

2022-06-20 Thread Atish Patra
All the hpmcounters and the fixed counters (CY, IR, TM) can be represented
as a unified counter. Thus, the predicate function doesn't need handle each
case separately.

Simplify the predicate function so that we just handle things differently
between RV32/RV64 and S/HS mode.

Reviewed-by: Bin Meng 
Acked-by: Alistair Francis 
Signed-off-by: Atish Patra 
---
 target/riscv/csr.c | 112 +
 1 file changed, 11 insertions(+), 101 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 2664ce265784..9367e2af9b90 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -74,6 +74,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 CPUState *cs = env_cpu(env);
 RISCVCPU *cpu = RISCV_CPU(cs);
 int ctr_index;
+target_ulong ctr_mask;
 int base_csrno = CSR_CYCLE;
 bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false;
 
@@ -82,122 +83,31 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 base_csrno += 0x80;
 }
 ctr_index = csrno - base_csrno;
+ctr_mask = BIT(ctr_index);
 
 if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) ||
 (csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) {
 goto skip_ext_pmu_check;
 }
 
-if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & BIT(ctr_index {
+if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & ctr_mask))) {
 /* No counter is enabled in PMU or the counter is out of range */
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
 skip_ext_pmu_check:
 
-if (env->priv == PRV_S) {
-switch (csrno) {
-case CSR_CYCLE:
-if (!get_field(env->mcounteren, COUNTEREN_CY)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-case CSR_TIME:
-if (!get_field(env->mcounteren, COUNTEREN_TM)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-case CSR_INSTRET:
-if (!get_field(env->mcounteren, COUNTEREN_IR)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
-if (!get_field(env->mcounteren, 1 << ctr_index)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-}
-if (rv32) {
-switch (csrno) {
-case CSR_CYCLEH:
-if (!get_field(env->mcounteren, COUNTEREN_CY)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-case CSR_TIMEH:
-if (!get_field(env->mcounteren, COUNTEREN_TM)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-case CSR_INSTRETH:
-if (!get_field(env->mcounteren, COUNTEREN_IR)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
-if (!get_field(env->mcounteren, 1 << ctr_index)) {
-return RISCV_EXCP_ILLEGAL_INST;
-}
-break;
-}
-}
+if (((env->priv == PRV_S) && (!get_field(env->mcounteren, ctr_mask))) ||
+   ((env->priv == PRV_U) && (!get_field(env->scounteren, ctr_mask {
+return RISCV_EXCP_ILLEGAL_INST;
 }
 
 if (riscv_cpu_virt_enabled(env)) {
-switch (csrno) {
-case CSR_CYCLE:
-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, COUNTEREN_TM) &&
-get_field(env->mcounteren, COUNTEREN_TM)) {
-return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
-}
-break;
-case CSR_INSTRET:
-if (!get_field(env->hcounteren, COUNTEREN_IR) &&
-get_field(env->mcounteren, COUNTEREN_IR)) {
-return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
-}
-break;
-case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
-if (!get_field(env->hcounteren, 1 << ctr_index) &&
- get_field(env->mcounteren, 1 << ctr_index)) {
-return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
-}
-break;
-}
-if (rv32) {
-switch (csrno) {
-case CSR_CYCLEH:
-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, COUNTEREN_TM) &&
-get_field(env->mcounteren, COUNTEREN_TM)) {
-return 

[PATCH v10 08/12] target/riscv: Add sscofpmf extension support

2022-06-20 Thread Atish Patra
The Sscofpmf ('Ss' for Privileged arch and Supervisor-level extensions,
and 'cofpmf' for Count OverFlow and Privilege Mode Filtering)
extension allows the perf to handle overflow interrupts and filtering
support. This patch provides a framework for programmable
counters to leverage the extension. As the extension doesn't have any
provision for the overflow bit for fixed counters, the fixed events
can also be monitoring using programmable counters. The underlying
counters for cycle and instruction counters are always running. Thus,
a separate timer device is programmed to handle the overflow.

Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/cpu.c  |  11 ++
 target/riscv/cpu.h  |  25 +++
 target/riscv/cpu_bits.h |  55 +++
 target/riscv/csr.c  | 165 ++-
 target/riscv/machine.c  |   1 +
 target/riscv/pmu.c  | 357 +++-
 target/riscv/pmu.h  |   7 +
 7 files changed, 610 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d12c6dc630ca..7d9e2aca12a9 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -22,6 +22,7 @@
 #include "qemu/ctype.h"
 #include "qemu/log.h"
 #include "cpu.h"
+#include "pmu.h"
 #include "internals.h"
 #include "exec/exec-all.h"
 #include "qapi/error.h"
@@ -775,6 +776,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 set_misa(env, env->misa_mxl, ext);
 }
 
+#ifndef CONFIG_USER_ONLY
+if (cpu->cfg.pmu_num) {
+if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
+cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+  riscv_pmu_timer_cb, cpu);
+}
+ }
+#endif
+
 riscv_cpu_register_gdb_regs_for_features(cs);
 
 qemu_init_vcpu(cs);
@@ -879,6 +889,7 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
 DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
 DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
+DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
 DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5c7acc055ac9..db193c3d 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -137,6 +137,8 @@ typedef struct PMUCTRState {
 /* Snapshort value of a counter in RV32 */
 target_ulong mhpmcounterh_prev;
 bool started;
+/* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */
+target_ulong irq_overflow_left;
 } PMUCTRState;
 
 struct CPUArchState {
@@ -297,6 +299,9 @@ struct CPUArchState {
 /* PMU event selector configured values. First three are unused*/
 target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
 
+/* PMU event selector configured values for RV32*/
+target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS];
+
 target_ulong sscratch;
 target_ulong mscratch;
 
@@ -433,6 +438,7 @@ struct RISCVCPUConfig {
 bool ext_zve32f;
 bool ext_zve64f;
 bool ext_zmmul;
+bool ext_sscofpmf;
 bool rvv_ta_all_1s;
 
 uint32_t mvendorid;
@@ -479,6 +485,12 @@ struct ArchCPU {
 
 /* Configuration Settings */
 RISCVCPUConfig cfg;
+
+QEMUTimer *pmu_timer;
+/* A bitmask of Available programmable counters */
+uint32_t pmu_avail_ctrs;
+/* Mapping of events to counters */
+GHashTable *pmu_event_ctr_map;
 };
 
 static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
@@ -738,6 +750,19 @@ enum {
 CSR_TABLE_SIZE = 0x1000
 };
 
+/**
+ * The event id are encoded based on the encoding specified in the
+ * SBI specification v0.3
+ */
+
+enum riscv_pmu_event_idx {
+RISCV_PMU_EVENT_HW_CPU_CYCLES = 0x01,
+RISCV_PMU_EVENT_HW_INSTRUCTIONS = 0x02,
+RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS = 0x10019,
+RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS = 0x1001B,
+RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021,
+};
+
 /* CSR function table */
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
 
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index b3f7fa713000..d94abefdaa0f 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -400,6 +400,37 @@
 #define CSR_MHPMEVENT29 0x33d
 #define CSR_MHPMEVENT30 0x33e
 #define CSR_MHPMEVENT31 0x33f
+
+#define CSR_MHPMEVENT3H 0x723
+#define CSR_MHPMEVENT4H 0x724
+#define CSR_MHPMEVENT5H 0x725
+#define CSR_MHPMEVENT6H 0x726
+#define CSR_MHPMEVENT7H 0x727
+#define CSR_MHPMEVENT8H 0x728
+#define CSR_MHPMEVENT9H 0x729
+#define CSR_MHPMEVENT10H0x72a
+#define CSR_MHPMEVENT11H0x72b
+#define CSR_MHPMEVENT12H0x72c
+#define CSR_MHPMEVENT13H0x72d
+#define CSR_MHPMEVENT14H0x72e
+#define CSR_MHPMEVENT15H0x72f
+#define CSR_MHPMEVENT16H

[PATCH v10 07/12] target/riscv: Support mcycle/minstret write operation

2022-06-20 Thread Atish Patra
From: Atish Patra 

mcycle/minstret are actually WARL registers and can be written with any
given value. With SBI PMU extension, it will be used to store a initial
value provided from supervisor OS. The Qemu also need prohibit the counter
increment if mcountinhibit is set.

Support mcycle/minstret through generic counter infrastructure.

Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/cpu.h   |  23 --
 target/riscv/csr.c   | 155 ---
 target/riscv/machine.c   |  25 ++-
 target/riscv/meson.build |   3 +-
 target/riscv/pmu.c   |  32 
 target/riscv/pmu.h   |  28 +++
 6 files changed, 213 insertions(+), 53 deletions(-)
 create mode 100644 target/riscv/pmu.c
 create mode 100644 target/riscv/pmu.h

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 199d0d570bdd..5c7acc055ac9 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -117,7 +117,7 @@ typedef struct CPUArchState CPURISCVState;
 #endif
 
 #define RV_VLEN_MAX 1024
-#define RV_MAX_MHPMEVENTS 29
+#define RV_MAX_MHPMEVENTS 32
 #define RV_MAX_MHPMCOUNTERS 32
 
 FIELD(VTYPE, VLMUL, 0, 3)
@@ -127,6 +127,18 @@ FIELD(VTYPE, VMA, 7, 1)
 FIELD(VTYPE, VEDIV, 8, 2)
 FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
 
+typedef struct PMUCTRState {
+/* Current value of a counter */
+target_ulong mhpmcounter_val;
+/* Current value of a counter in RV32*/
+target_ulong mhpmcounterh_val;
+/* Snapshot values of counter */
+target_ulong mhpmcounter_prev;
+/* Snapshort value of a counter in RV32 */
+target_ulong mhpmcounterh_prev;
+bool started;
+} PMUCTRState;
+
 struct CPUArchState {
 target_ulong gpr[32];
 target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
@@ -279,13 +291,10 @@ struct CPUArchState {
 
 target_ulong mcountinhibit;
 
-/* PMU counter configured values */
-target_ulong mhpmcounter_val[RV_MAX_MHPMCOUNTERS];
-
-/* for RV32 */
-target_ulong mhpmcounterh_val[RV_MAX_MHPMCOUNTERS];
+/* PMU counter state */
+PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
 
-/* PMU event selector configured values */
+/* PMU event selector configured values. First three are unused*/
 target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
 
 target_ulong sscratch;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b931a3970e0f..d65318dcc62d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -21,6 +21,7 @@
 #include "qemu/log.h"
 #include "qemu/timer.h"
 #include "cpu.h"
+#include "pmu.h"
 #include "qemu/main-loop.h"
 #include "exec/exec-all.h"
 #include "sysemu/cpu-timers.h"
@@ -597,34 +598,28 @@ static int write_vcsr(CPURISCVState *env, int csrno, 
target_ulong val)
 }
 
 /* User Timers and Counters */
-static RISCVException read_instret(CPURISCVState *env, int csrno,
-   target_ulong *val)
+static target_ulong get_ticks(bool shift)
 {
+int64_t val;
+target_ulong result;
+
 #if !defined(CONFIG_USER_ONLY)
 if (icount_enabled()) {
-*val = icount_get();
+val = icount_get();
 } else {
-*val = cpu_get_host_ticks();
+val = cpu_get_host_ticks();
 }
 #else
-*val = cpu_get_host_ticks();
+val = cpu_get_host_ticks();
 #endif
-return RISCV_EXCP_NONE;
-}
 
-static RISCVException read_instreth(CPURISCVState *env, int csrno,
-target_ulong *val)
-{
-#if !defined(CONFIG_USER_ONLY)
-if (icount_enabled()) {
-*val = icount_get() >> 32;
+if (shift) {
+result = val >> 32;
 } else {
-*val = cpu_get_host_ticks() >> 32;
+result = val;
 }
-#else
-*val = cpu_get_host_ticks() >> 32;
-#endif
-return RISCV_EXCP_NONE;
+
+return result;
 }
 
 #if defined(CONFIG_USER_ONLY)
@@ -642,11 +637,23 @@ static RISCVException read_timeh(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = get_ticks(false);
+return RISCV_EXCP_NONE;
+}
+
+static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = get_ticks(true);
+return RISCV_EXCP_NONE;
+}
+
 #else /* CONFIG_USER_ONLY */
 
 static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val)
 {
-int evt_index = csrno - CSR_MHPMEVENT3;
+int evt_index = csrno - CSR_MCOUNTINHIBIT;
 
 *val = env->mhpmevent_val[evt_index];
 
@@ -655,7 +662,7 @@ static int read_mhpmevent(CPURISCVState *env, int csrno, 
target_ulong *val)
 
 static int write_mhpmevent(CPURISCVState *env, int csrno, target_ulong val)
 {
-int evt_index = csrno - CSR_MHPMEVENT3;
+int evt_index = csrno - CSR_MCOUNTINHIBIT;
 
 env->mhpmevent_val[evt_index] = val;
 
@@ -664,55 +671,105 @@ static int write_mhpmevent(CPURISCVState *env, int 
csrno, target_ulong val)
 
 static int 

[PATCH v10 05/12] target/riscv: Implement mcountinhibit CSR

2022-06-20 Thread Atish Patra
From: Atish Patra 

As per the privilege specification v1.11, mcountinhibit allows to start/stop
a pmu counter selectively.

Reviewed-by: Bin Meng 
Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
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  |  1 +
 4 files changed, 32 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index ffee54ea5c27..0a916db9f614 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -275,6 +275,8 @@ struct CPUArchState {
 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 4d04b20d064e..b3f7fa713000 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -367,6 +367,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 b4a8e15f498f..94d39a4ce1c5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1475,6 +1475,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;
+}
+
+*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;
+}
+
+env->mcountinhibit = val;
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_mcounteren(CPURISCVState *env, int csrno,
   target_ulong *val)
 {
@@ -3745,6 +3767,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MHPMCOUNTER30]  = { "mhpmcounter30",  mctr,   read_zero },
 [CSR_MHPMCOUNTER31]  = { "mhpmcounter31",  mctr,   read_zero },
 
+[CSR_MCOUNTINHIBIT]  = { "mcountinhibit",   any,read_mcountinhibit,
+   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 2a437b29a1ce..87cd55bfd3a7 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -330,6 +330,7 @@ const VMStateDescription vmstate_riscv_cpu = {
 VMSTATE_UINTTL(env.siselect, 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),
-- 
2.25.1




[PATCH v10 11/12] hw/riscv: virt: Add PMU DT node to the device tree

2022-06-20 Thread Atish Patra
Qemu virt machine can support few cache events and cycle/instret counters.
It also supports counter overflow for these events.

Add a DT node so that OpenSBI/Linux kernel is aware of the virt machine
capabilities. There are some dummy nodes added for testing as well.

Acked-by: Alistair Francis 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 hw/riscv/virt.c| 28 +++
 target/riscv/cpu.c |  1 +
 target/riscv/pmu.c | 57 ++
 target/riscv/pmu.h |  1 +
 4 files changed, 87 insertions(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index bc424dd2f523..0f3fdb4908b8 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -29,6 +29,7 @@
 #include "hw/char/serial.h"
 #include "target/riscv/cpu.h"
 #include "hw/core/sysbus-fdt.h"
+#include "target/riscv/pmu.h"
 #include "hw/riscv/riscv_hart.h"
 #include "hw/riscv/virt.h"
 #include "hw/riscv/boot.h"
@@ -714,6 +715,32 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
 aplic_phandles[socket] = aplic_s_phandle;
 }
 
+static void create_fdt_socket_pmu(RISCVVirtState *s,
+  int socket, uint32_t *phandle,
+  uint32_t *intc_phandles)
+{
+int cpu;
+char *pmu_name;
+uint32_t *pmu_cells;
+MachineState *mc = MACHINE(s);
+RISCVCPU hart = s->soc[socket].harts[0];
+
+pmu_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2);
+
+for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) {
+pmu_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
+pmu_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_PMU_OVF);
+}
+
+pmu_name = g_strdup_printf("/soc/pmu");
+qemu_fdt_add_subnode(mc->fdt, pmu_name);
+qemu_fdt_setprop_string(mc->fdt, pmu_name, "compatible", "riscv,pmu");
+riscv_pmu_generate_fdt_node(mc->fdt, hart.cfg.pmu_num, pmu_name);
+
+g_free(pmu_name);
+g_free(pmu_cells);
+}
+
 static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
bool is_32_bit, uint32_t *phandle,
uint32_t *irq_mmio_phandle,
@@ -759,6 +786,7 @@ static void create_fdt_sockets(RISCVVirtState *s, const 
MemMapEntry *memmap,
 _phandles[phandle_pos]);
 }
 }
+create_fdt_socket_pmu(s, socket, phandle, intc_phandles);
 }
 
 if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 7d9e2aca12a9..69bbd9fff4e1 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1110,6 +1110,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char 
**isa_str, int max_str_len)
 ISA_EDATA_ENTRY(zve64f, ext_zve64f),
 ISA_EDATA_ENTRY(zhinx, ext_zhinx),
 ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
+ISA_EDATA_ENTRY(sscofpmf, ext_sscofpmf),
 ISA_EDATA_ENTRY(svinval, ext_svinval),
 ISA_EDATA_ENTRY(svnapot, ext_svnapot),
 ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index 34096941c0ce..59feb3c243dd 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -20,11 +20,68 @@
 #include "cpu.h"
 #include "pmu.h"
 #include "sysemu/cpu-timers.h"
+#include "sysemu/device_tree.h"
 
 #define RISCV_TIMEBASE_FREQ 10 /* 1Ghz */
 #define MAKE_32BIT_MASK(shift, length) \
 (((uint32_t)(~0UL) >> (32 - (length))) << (shift))
 
+/**
+ * To keep it simple, any event can be mapped to any programmable counters in
+ * QEMU. The generic cycle & instruction count events can also be monitored
+ * using programmable counters. In that case, mcycle & minstret must continue
+ * to provide the correct value as well. Heterogeneous PMU per hart is not
+ * supported yet. Thus, number of counters are same across all harts.
+ */
+void riscv_pmu_generate_fdt_node(void *fdt, int num_ctrs, char *pmu_name)
+{
+uint32_t fdt_event_ctr_map[20] = {};
+uint32_t cmask;
+
+/* All the programmable counters can map to any event */
+cmask = MAKE_32BIT_MASK(3, num_ctrs);
+
+   /**
+* The event encoding is specified in the SBI specification
+* Event idx is a 20bits wide number encoded as follows:
+* event_idx[19:16] = type
+* event_idx[15:0] = code
+* The code field in cache events are encoded as follows:
+* event_idx.code[15:3] = cache_id
+* event_idx.code[2:1] = op_id
+* event_idx.code[0:0] = result_id
+*/
+
+   /* SBI_PMU_HW_CPU_CYCLES: 0x01 : type(0x00) */
+   fdt_event_ctr_map[0] = cpu_to_be32(0x0001);
+   fdt_event_ctr_map[1] = cpu_to_be32(0x0001);
+   fdt_event_ctr_map[2] = cpu_to_be32(cmask | 1 << 0);
+
+   /* SBI_PMU_HW_INSTRUCTIONS: 0x02 : type(0x00) */
+   fdt_event_ctr_map[3] = cpu_to_be32(0x0002);
+   fdt_event_ctr_map[4] = cpu_to_be32(0x0002);
+   fdt_event_ctr_map[5] = cpu_to_be32(cmask | 1 << 2);
+
+   /* SBI_PMU_HW_CACHE_DTLB : 0x03 READ : 0x00 MISS : 0x00 type(0x01) */
+   fdt_event_ctr_map[6] = 

[PATCH v10 12/12] target/riscv: Update the privilege field for sscofpmf CSRs

2022-06-20 Thread Atish Patra
The sscofpmf extension was ratified as a part of priv spec v1.12.
Mark the csr_ops accordingly.

Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
---
 target/riscv/csr.c | 90 ++
 1 file changed, 60 insertions(+), 30 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 9367e2af9b90..dabd531e0355 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -4002,63 +4002,92 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
write_mhpmevent },
 
 [CSR_MHPMEVENT3H]= { "mhpmevent3h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+  write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT4H]= { "mhpmevent4h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+  write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT5H]= { "mhpmevent5h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+  write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT6H]= { "mhpmevent6h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+  write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT7H]= { "mhpmevent7h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+  write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT8H]= { "mhpmevent8h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+  write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT9H]= { "mhpmevent9h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+  write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT10H]   = { "mhpmevent10h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+   write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT11H]   = { "mhpmevent11h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+   write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT12H]   = { "mhpmevent12h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+   write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT13H]   = { "mhpmevent13h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+   write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT14H]   = { "mhpmevent14h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+   write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT15H]   = { "mhpmevent15h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+   write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT16H]   = { "mhpmevent16h",sscofpmf,  read_mhpmeventh,
-   write_mhpmeventh},
+   write_mhpmeventh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
 [CSR_MHPMEVENT17H]   = { "mhpmevent17h",sscofpmf,  read_mhpmeventh,
-

[PATCH v10 04/12] target/riscv: pmu: Make number of counters configurable

2022-06-20 Thread Atish Patra
The RISC-V privilege specification provides flexibility to implement
any number of counters from 29 programmable counters. However, the 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.

Reviewed-by: Bin Meng 
Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/cpu.c |  3 +-
 target/riscv/cpu.h |  2 +-
 target/riscv/csr.c | 94 ++
 3 files changed, 63 insertions(+), 36 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1b57b3c43980..d12c6dc630ca 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -851,7 +851,6 @@ static void riscv_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
 
-cpu->cfg.ext_pmu = true;
 cpu->cfg.ext_ifencei = true;
 cpu->cfg.ext_icsr = true;
 cpu->cfg.mmu = true;
@@ -879,7 +878,7 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
 DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
 DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
-DEFINE_PROP_BOOL("pmu", RISCVCPU, cfg.ext_pmu, true),
+DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
 DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 252c30a55d78..ffee54ea5c27 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -397,7 +397,6 @@ struct RISCVCPUConfig {
 bool ext_zksed;
 bool ext_zksh;
 bool ext_zkt;
-bool ext_pmu;
 bool ext_ifencei;
 bool ext_icsr;
 bool ext_svinval;
@@ -421,6 +420,7 @@ struct RISCVCPUConfig {
 /* Vendor-specific custom extensions */
 bool ext_XVentanaCondOps;
 
+uint8_t pmu_num;
 char *priv_spec;
 char *user_spec;
 char *bext_spec;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0ca05c77883c..b4a8e15f498f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -73,9 +73,17 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 CPUState *cs = env_cpu(env);
 RISCVCPU *cpu = RISCV_CPU(cs);
 int ctr_index;
+int base_csrno = CSR_HPMCOUNTER3;
+bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false;
 
-if (!cpu->cfg.ext_pmu) {
-/* The PMU extension is not enabled */
+if (rv32 && csrno >= CSR_CYCLEH) {
+/* Offset for RV32 hpmcounternh counters */
+base_csrno += 0x80;
+}
+ctr_index = csrno - base_csrno;
+
+if (!cpu->cfg.pmu_num || ctr_index >= (cpu->cfg.pmu_num)) {
+/* No counter is enabled in PMU or the counter is out of range */
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
@@ -103,7 +111,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 }
 break;
 }
-if (riscv_cpu_mxl(env) == MXL_RV32) {
+if (rv32) {
 switch (csrno) {
 case CSR_CYCLEH:
 if (!get_field(env->mcounteren, COUNTEREN_CY)) {
@@ -158,7 +166,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 }
 break;
 }
-if (riscv_cpu_mxl(env) == MXL_RV32) {
+if (rv32) {
 switch (csrno) {
 case CSR_CYCLEH:
 if (!get_field(env->hcounteren, COUNTEREN_CY) &&
@@ -202,6 +210,26 @@ static RISCVException ctr32(CPURISCVState *env, int csrno)
 }
 
 #if !defined(CONFIG_USER_ONLY)
+static RISCVException mctr(CPURISCVState *env, int csrno)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+int ctr_index;
+int base_csrno = CSR_MHPMCOUNTER3;
+
+if ((riscv_cpu_mxl(env) == MXL_RV32) && csrno >= CSR_MCYCLEH) {
+/* Offset for RV32 mhpmcounternh counters */
+base_csrno += 0x80;
+}
+ctr_index = csrno - base_csrno;
+if (!cpu->cfg.pmu_num || ctr_index >= cpu->cfg.pmu_num) {
+/* The PMU is not enabled or counter is out of range*/
+return RISCV_EXCP_ILLEGAL_INST;
+}
+
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException any(CPURISCVState *env, int csrno)
 {
 return RISCV_EXCP_NONE;
@@ -3687,35 +3715,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 },
-[CSR_MHPMCOUNTER4]   = { "mhpmcounter4",   any,read_zero },
-[CSR_MHPMCOUNTER5]   = { "mhpmcounter5",   any,read_zero },
-[CSR_MHPMCOUNTER6]   = { "mhpmcounter6",   any,read_zero },
-[CSR_MHPMCOUNTER7]   = { "mhpmcounter7",   any,read_zero },
-[CSR_MHPMCOUNTER8]   = { "mhpmcounter8",   any,read_zero },
-[CSR_MHPMCOUNTER9]   

[PATCH v10 03/12] target/riscv: pmu: Rename the counters extension to pmu

2022-06-20 Thread Atish Patra
From: Atish Patra 

The PMU counters are supported via cpu config "Counters" which doesn't
indicate the correct purpose of those counters.

Rename the config property to pmu to indicate that these counters
are performance monitoring counters. This aligns with cpu options for
ARM architecture as well.

Reviewed-by: Bin Meng 
Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/cpu.c | 4 ++--
 target/riscv/cpu.h | 2 +-
 target/riscv/csr.c | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 05e652135171..1b57b3c43980 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -851,7 +851,7 @@ static void riscv_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
 
-cpu->cfg.ext_counters = true;
+cpu->cfg.ext_pmu = true;
 cpu->cfg.ext_ifencei = true;
 cpu->cfg.ext_icsr = true;
 cpu->cfg.mmu = true;
@@ -879,7 +879,7 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
 DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
 DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
-DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
+DEFINE_PROP_BOOL("pmu", RISCVCPU, cfg.ext_pmu, true),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
 DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d6397acdfb1..252c30a55d78 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -397,7 +397,7 @@ struct RISCVCPUConfig {
 bool ext_zksed;
 bool ext_zksh;
 bool ext_zkt;
-bool ext_counters;
+bool ext_pmu;
 bool ext_ifencei;
 bool ext_icsr;
 bool ext_svinval;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 58d07c511f98..0ca05c77883c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -74,8 +74,8 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 RISCVCPU *cpu = RISCV_CPU(cs);
 int ctr_index;
 
-if (!cpu->cfg.ext_counters) {
-/* The Counters extensions is not enabled */
+if (!cpu->cfg.ext_pmu) {
+/* The PMU extension is not enabled */
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
-- 
2.25.1




[PATCH v10 10/12] target/riscv: Add few cache related PMU events

2022-06-20 Thread Atish Patra
From: Atish Patra 

Qemu can monitor the following cache related PMU events through
tlb_fill functions.

1. DTLB load/store miss
3. ITLB prefetch miss

Increment the PMU counter in tlb_fill function.

Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/cpu_helper.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4a6700c89086..99e944a8c115 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -21,10 +21,12 @@
 #include "qemu/log.h"
 #include "qemu/main-loop.h"
 #include "cpu.h"
+#include "pmu.h"
 #include "exec/exec-all.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
+#include "cpu_bits.h"
 
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 {
@@ -1180,6 +1182,28 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 cpu_loop_exit_restore(cs, retaddr);
 }
 
+
+static void pmu_tlb_fill_incr_ctr(RISCVCPU *cpu, MMUAccessType access_type)
+{
+enum riscv_pmu_event_idx pmu_event_type;
+
+switch (access_type) {
+case MMU_INST_FETCH:
+pmu_event_type = RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS;
+break;
+case MMU_DATA_LOAD:
+pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS;
+break;
+case MMU_DATA_STORE:
+pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS;
+break;
+default:
+return;
+}
+
+riscv_pmu_incr_ctr(cpu, pmu_event_type);
+}
+
 bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
 bool probe, uintptr_t retaddr)
@@ -1276,6 +1300,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 }
 }
 } else {
+pmu_tlb_fill_incr_ctr(cpu, access_type);
 /* Single stage lookup */
 ret = get_physical_address(env, , , address, NULL,
access_type, mmu_idx, true, false, false);
-- 
2.25.1




[PATCH v10 00/12] Improve PMU support

2022-06-20 Thread Atish Patra
The latest version of the SBI specification includes a Performance Monitoring
Unit(PMU) extension[1] which allows the supervisor to start/stop/configure
various PMU events. The Sscofpmf ('Ss' for Privileged arch and Supervisor-level
extensions, and 'cofpmf' for Count OverFlow and Privilege Mode Filtering)
extension[2] allows the perf like tool to handle overflow interrupts and
filtering support.

This series implements full PMU infrastructure to support
PMU in virt machine. This will allow us to add any PMU events in future.

Currently, this series enables the following omu events.
1. cycle count
2. instruction count
3. DTLB load/store miss
4. ITLB prefetch miss

The first two are computed using host ticks while last three are counted during
cpu_tlb_fill. We can do both sampling and count from guest userspace.
This series has been tested on both RV64 and RV32. Both Linux[3] and Opensbi[4]
patches are required to get the perf working.

Here is an output of perf stat/report while running hackbench with latest
OpenSBI & Linux kernel.

Perf stat:
==
[root@fedora-riscv ~]# perf stat -e cycles -e instructions -e dTLB-load-misses 
-e dTLB-store-misses -e iTLB-load-misses \
> perf bench sched messaging -g 1 -l 10
# Running 'sched/messaging' benchmark:
# 20 sender and receiver processes per group
# 1 groups == 40 processes run

 Total time: 0.265 [sec]

 Performance counter stats for 'perf bench sched messaging -g 1 -l 10':

 4,167,825,362  cycles  

 4,166,609,256  instructions  #1.00  insn per cycle 

 3,092,026  dTLB-load-misses

   258,280  dTLB-store-misses   

 2,068,966  iTLB-load-misses


   0.585791767 seconds time elapsed

   0.373802000 seconds user
   1.042359000 seconds sys

Perf record:

[root@fedora-riscv ~]# perf record -e cycles -e instructions \
> -e dTLB-load-misses -e dTLB-store-misses -e iTLB-load-misses -c 1 \
> perf bench sched messaging -g 1 -l 10
# Running 'sched/messaging' benchmark:
# 20 sender and receiver processes per group
# 1 groups == 40 processes run

 Total time: 1.397 [sec]
[ perf record: Woken up 10 times to write data ]
Check IO/CPU overload!
[ perf record: Captured and wrote 8.211 MB perf.data (214486 samples) ]

[root@fedora-riscv riscv]# perf report
Available samples   
107K cycles◆
107K instructions  ▒
250 dTLB-load-misses   ▒
13 dTLB-store-misses   ▒
172 iTLB-load-misses  
..

Changes from v8->v9:
1. Added the write_done flags to the vmstate.
2. Fixed the hpmcounter read access from M-mode.

Changes from v7->v8:
1. Removeding ordering constraints for mhpmcounter & mhpmevent.

Changes from v6->v7:
1. Fixed all the compilation errors for the usermode.

Changes from v5->v6:
1. Fixed compilation issue with PATCH 1.
2. Addressed other comments.

Changes from v4->v5:
1. Rebased on top of the -next with following patches.
   - isa extension
   - priv 1.12 spec
2. Addressed all the comments on v4
3. Removed additional isa-ext DT node in favor of riscv,isa string update

Changes from v3->v4:
1. Removed the dummy events from pmu DT node.
2. Fixed pmu_avail_counters mask generation.
3. Added a patch to simplify the predicate function for counters. 

Changes from v2->v3:
1. Addressed all the comments on PATCH1-4.
2. Split patch1 into two separate patches.
3. Added explicit comments to explain the event types in DT node.
4. Rebased on latest Qemu.

Changes from v1->v2:
1. Dropped the ACks from v1 as signficant changes happened after v1.
2. sscofpmf support.
3. A generic counter management framework.

[1] https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.adoc
[2] https://drive.google.com/file/d/171j4jFjIkKdj5LWcExphq4xG_2sihbfd/edit
[3] https://github.com/atishp04/qemu/tree/riscv_pmu_v10

Atish Patra (12):
target/riscv: Fix PMU CSR predicate function
target/riscv: Implement PMU CSR predicate function for S-mode
target/riscv: pmu: Rename the counters extension to pmu
target/riscv: pmu: Make number of counters configurable
target/riscv: Implement mcountinhibit CSR
target/riscv: Add support for hpmcounters/hpmevents
target/riscv: Support mcycle/minstret write operation
target/riscv: Add sscofpmf extension support
target/riscv: Simplify counter predicate function
target/riscv: Add few cache related PMU events
hw/riscv: virt: Add PMU DT node to the device tree
target/riscv: Update the privilege field for sscofpmf CSRs

hw/riscv/virt.c   |  28 ++
target/riscv/cpu.c

[PATCH v10 02/12] target/riscv: Implement PMU CSR predicate function for S-mode

2022-06-20 Thread Atish Patra
From: Atish Patra 

Currently, the predicate function for PMU related CSRs only works if
virtualization is enabled. It also does not check mcounteren bits before
before cycle/minstret/hpmcounterx access.

Support supervisor mode access in the predicate function as well.

Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/csr.c | 51 ++
 1 file changed, 51 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 46bd417cc182..58d07c511f98 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -79,6 +79,57 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
+if (env->priv == PRV_S) {
+switch (csrno) {
+case CSR_CYCLE:
+if (!get_field(env->mcounteren, COUNTEREN_CY)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+break;
+case CSR_TIME:
+if (!get_field(env->mcounteren, COUNTEREN_TM)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+break;
+case CSR_INSTRET:
+if (!get_field(env->mcounteren, COUNTEREN_IR)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+break;
+case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
+ctr_index = csrno - CSR_CYCLE;
+if (!get_field(env->mcounteren, 1 << ctr_index)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+break;
+}
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+switch (csrno) {
+case CSR_CYCLEH:
+if (!get_field(env->mcounteren, COUNTEREN_CY)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+break;
+case CSR_TIMEH:
+if (!get_field(env->mcounteren, COUNTEREN_TM)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+break;
+case CSR_INSTRETH:
+if (!get_field(env->mcounteren, COUNTEREN_IR)) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+break;
+case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
+ctr_index = csrno - CSR_CYCLEH;
+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:
-- 
2.25.1




[PATCH v10 06/12] target/riscv: Add support for hpmcounters/hpmevents

2022-06-20 Thread Atish Patra
From: Atish Patra 

With SBI PMU extension, user can use any of the available hpmcounters to
track any perf events based on the value written to mhpmevent csr.
Add read/write functionality for these csrs.

Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/cpu.h |  11 +
 target/riscv/csr.c | 469 -
 target/riscv/machine.c |   3 +
 3 files changed, 331 insertions(+), 152 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 0a916db9f614..199d0d570bdd 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -117,6 +117,8 @@ typedef struct CPUArchState CPURISCVState;
 #endif
 
 #define RV_VLEN_MAX 1024
+#define RV_MAX_MHPMEVENTS 29
+#define RV_MAX_MHPMCOUNTERS 32
 
 FIELD(VTYPE, VLMUL, 0, 3)
 FIELD(VTYPE, VSEW, 3, 3)
@@ -277,6 +279,15 @@ struct CPUArchState {
 
 target_ulong mcountinhibit;
 
+/* PMU counter configured values */
+target_ulong mhpmcounter_val[RV_MAX_MHPMCOUNTERS];
+
+/* for RV32 */
+target_ulong mhpmcounterh_val[RV_MAX_MHPMCOUNTERS];
+
+/* PMU event selector configured values */
+target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
+
 target_ulong sscratch;
 target_ulong mscratch;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 94d39a4ce1c5..b931a3970e0f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -230,6 +230,15 @@ static RISCVException mctr(CPURISCVState *env, int csrno)
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException mctr32(CPURISCVState *env, int csrno)
+{
+if (riscv_cpu_mxl(env) != MXL_RV32) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+
+return mctr(env, csrno);
+}
+
 static RISCVException any(CPURISCVState *env, int csrno)
 {
 return RISCV_EXCP_NONE;
@@ -635,6 +644,75 @@ static RISCVException read_timeh(CPURISCVState *env, int 
csrno,
 
 #else /* CONFIG_USER_ONLY */
 
+static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val)
+{
+int evt_index = csrno - CSR_MHPMEVENT3;
+
+*val = env->mhpmevent_val[evt_index];
+
+return RISCV_EXCP_NONE;
+}
+
+static int write_mhpmevent(CPURISCVState *env, int csrno, target_ulong val)
+{
+int evt_index = csrno - CSR_MHPMEVENT3;
+
+env->mhpmevent_val[evt_index] = val;
+
+return RISCV_EXCP_NONE;
+}
+
+static int write_mhpmcounter(CPURISCVState *env, int csrno, target_ulong val)
+{
+int ctr_index = csrno - CSR_MHPMCOUNTER3 + 3;
+
+env->mhpmcounter_val[ctr_index] = val;
+
+return RISCV_EXCP_NONE;
+}
+
+static int write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val)
+{
+int ctr_index = csrno - CSR_MHPMCOUNTER3H + 3;
+
+env->mhpmcounterh_val[ctr_index] = val;
+
+return RISCV_EXCP_NONE;
+}
+
+static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val)
+{
+int ctr_index;
+
+if (csrno >= CSR_MCYCLE && csrno <= CSR_MHPMCOUNTER31) {
+ctr_index = csrno - CSR_MHPMCOUNTER3 + 3;
+} else if (csrno >= CSR_CYCLE && csrno <= CSR_HPMCOUNTER31) {
+ctr_index = csrno - CSR_HPMCOUNTER3 + 3;
+} else {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+*val = env->mhpmcounter_val[ctr_index];
+
+return RISCV_EXCP_NONE;
+}
+
+static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val)
+{
+int ctr_index;
+
+if (csrno >= CSR_MCYCLEH && csrno <= CSR_MHPMCOUNTER31H) {
+ctr_index = csrno - CSR_MHPMCOUNTER3H + 3;
+} else if (csrno >= CSR_CYCLEH && csrno <= CSR_HPMCOUNTER31H) {
+ctr_index = csrno - CSR_HPMCOUNTER3H + 3;
+} else {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+*val = env->mhpmcounterh_val[ctr_index];
+
+return RISCV_EXCP_NONE;
+}
+
+
 static RISCVException read_time(CPURISCVState *env, int csrno,
 target_ulong *val)
 {
@@ -3707,157 +3785,244 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_SPMBASE] ={ "spmbase", pointer_masking, read_spmbase, 
write_spmbase },
 
 /* Performance Counters */
-[CSR_HPMCOUNTER3]= { "hpmcounter3",ctr,read_zero },
-[CSR_HPMCOUNTER4]= { "hpmcounter4",ctr,read_zero },
-[CSR_HPMCOUNTER5]= { "hpmcounter5",ctr,read_zero },
-[CSR_HPMCOUNTER6]= { "hpmcounter6",ctr,read_zero },
-[CSR_HPMCOUNTER7]= { "hpmcounter7",ctr,read_zero },
-[CSR_HPMCOUNTER8]= { "hpmcounter8",ctr,read_zero },
-[CSR_HPMCOUNTER9]= { "hpmcounter9",ctr,read_zero },
-[CSR_HPMCOUNTER10]   = { "hpmcounter10",   ctr,read_zero },
-[CSR_HPMCOUNTER11]   = { "hpmcounter11",   ctr,read_zero },
-[CSR_HPMCOUNTER12]   = { "hpmcounter12",   ctr,read_zero },
-[CSR_HPMCOUNTER13]   = { "hpmcounter13",   ctr,read_zero },
-[CSR_HPMCOUNTER14]   = { "hpmcounter14",   ctr,read_zero },
-[CSR_HPMCOUNTER15]   = { "hpmcounter15",   ctr,read_zero },
-[CSR_HPMCOUNTER16]   = { 

[PATCH v10 01/12] target/riscv: Fix PMU CSR predicate function

2022-06-20 Thread Atish Patra
From: Atish Patra 

The predicate function calculates the counter index incorrectly for
hpmcounterx. Fix the counter index to reflect correct CSR number.

Fixes: e39a8320b088 ("target/riscv: Support the Virtual Instruction fault")

Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
Signed-off-by: Atish Patra 
Signed-off-by: Atish Patra 
---
 target/riscv/csr.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6dbe9b541fd8..46bd417cc182 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -72,6 +72,7 @@ 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 */
@@ -99,8 +100,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_CYCLE;
+if (!get_field(env->hcounteren, 1 << ctr_index) &&
+ get_field(env->mcounteren, 1 << ctr_index)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
@@ -126,8 +128,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_CYCLEH;
+if (!get_field(env->hcounteren, 1 << ctr_index) &&
+ get_field(env->mcounteren, 1 << ctr_index)) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
 break;
-- 
2.25.1




Re: [PATCH 4/4] slirp: Add oob-eth-addr to -netdev options

2022-06-20 Thread Peter Delevoryas


> On Jun 18, 2022, at 3:05 AM, Samuel Thibault  wrote:
> 
> Peter Delevoryas, le mer. 15 juin 2022 18:05:26 -0700, a ecrit:
>> With this change, you can now request the out-of-band MAC address from
>> slirp in fby35-bmc:
>> 
>>wget 
>> https://github.com/facebook/openbmc/releases/download/openbmc-e2294ff5d31d/fby35.mtd
>>qemu-system-arm -machine fby35-bmc \
>>-drive file=fby35.mtd,format=raw,if=mtd \
>>-nographic \
>>-netdev 
>> user,id=nic,mfr-id=0x8119,oob-eth-addr=de:ad:be:ef:ca:fe,hostfwd=::-:22 \
>>-net nic,model=ftgmac100,netdev=nic
>> 
>>...
>>username: root
>>password: 0penBmc
>>...
>> 
>>root@bmc-oob:~# ncsi-util -n eth0 -c 0 0x50 0 0 0x81 0x19 0 0 0x1b 0
>>NC-SI Command Response:
>>cmd: NCSI_OEM_CMD(0x50)
>>Response: COMMAND_COMPLETED(0x)  Reason: NO_ERROR(0x)
>>Payload length = 24
>> 
>>20: 0x00 0x00 0x81 0x19
>>24: 0x01 0x00 0x1b 0x00
>>28: 0x00 0x00 0x00 0x00
>>32: 0xde 0xad 0xbe 0xef
>>36: 0xca 0xfe 0x00 0x00
>> 
>>root@bmc-oob:~# ifconfig
>>eth0  Link encap:Ethernet  HWaddr DE:AD:BE:EF:CA:FE
>>inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
>>inet6 addr: fec0::dcad:beff:feef:cafe/64 Scope:Site
>>inet6 addr: fe80::dcad:beff:feef:cafe/64 Scope:Link
>>UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
>>RX packets:253 errors:0 dropped:0 overruns:0 frame:0
>>TX packets:271 errors:0 dropped:0 overruns:0 carrier:0
>>collisions:0 txqueuelen:1000
>>RX bytes:24638 (24.0 KiB)  TX bytes:18876 (18.4 KiB)
>>Interrupt:32
>> 
>>loLink encap:Local Loopback
>>inet addr:127.0.0.1  Mask:255.0.0.0
>>inet6 addr: ::1/128 Scope:Host
>>UP LOOPBACK RUNNING  MTU:65536  Metric:1
>>RX packets:2 errors:0 dropped:0 overruns:0 frame:0
>>TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
>>collisions:0 txqueuelen:1000
>>RX bytes:120 (120.0 B)  TX bytes:120 (120.0 B)
>> 
>> Signed-off-by: Peter Delevoryas 
>> ---
>> net/slirp.c   | 13 +++--
>> qapi/net.json |  5 -
>> 2 files changed, 15 insertions(+), 3 deletions(-)
>> 
>> diff --git a/net/slirp.c b/net/slirp.c
>> index 231068c1e2..858d3da859 100644
>> --- a/net/slirp.c
>> +++ b/net/slirp.c
>> @@ -414,7 +414,7 @@ static int net_slirp_init(NetClientState *peer, const 
>> char *model,
>>   const char *smb_export, const char *vsmbserver,
>>   const char **dnssearch, const char *vdomainname,
>>   const char *tftp_server_name, uint32_t mfr_id,
>> -  Error **errp)
>> +  uint8_t oob_eth_addr[ETH_ALEN], Error **errp)
>> {
>> /* default settings according to historic slirp */
>> struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
>> @@ -637,6 +637,7 @@ static int net_slirp_init(NetClientState *peer, const 
>> char *model,
>> cfg.vdnssearch = dnssearch;
>> cfg.vdomainname = vdomainname;
>> cfg.mfr_id = mfr_id;
>> +memcpy(cfg.oob_eth_addr, oob_eth_addr, ETH_ALEN);
> 
> And similarly here.

Copy that, thanks again for the review comments!

> 
>> s->slirp = slirp_new(, _cb, s);
>> QTAILQ_INSERT_TAIL(_stacks, s, entry);
>> 
>> @@ -1142,6 +1143,7 @@ int net_init_slirp(const Netdev *netdev, const char 
>> *name,
>> const NetdevUserOptions *user;
>> const char **dnssearch;
>> bool ipv4 = true, ipv6 = true;
>> +MACAddr oob_eth_addr = {};
>> 
>> assert(netdev->type == NET_CLIENT_DRIVER_USER);
>> user = >u.user;
>> @@ -1166,6 +1168,12 @@ int net_init_slirp(const Netdev *netdev, const char 
>> *name,
>> net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD);
>> net_init_slirp_configs(user->guestfwd, 0);
>> 
>> +if (user->has_oob_eth_addr &&
>> +net_parse_macaddr(oob_eth_addr.a, user->oob_eth_addr) < 0) {
>> +error_setg(errp, "invalid syntax for OOB ethernet address");
>> +return -1;
>> +}
>> +
>> ret = net_slirp_init(peer, "user", name, user->q_restrict,
>>  ipv4, vnet, user->host,
>>  ipv6, user->ipv6_prefix, user->ipv6_prefixlen,
>> @@ -1173,7 +1181,8 @@ int net_init_slirp(const Netdev *netdev, const char 
>> *name,
>>  user->bootfile, user->dhcpstart,
>>  user->dns, user->ipv6_dns, user->smb,
>>  user->smbserver, dnssearch, user->domainname,
>> - user->tftp_server_name, user->mfr_id, errp);
>> + user->tftp_server_name, user->mfr_id, 
>> oob_eth_addr.a,
>> + errp);
>> 
>> while (slirp_configs) {
>> config = slirp_configs;
>> diff --git a/qapi/net.json b/qapi/net.json
>> index efc5cb3fb6..7b2c3c205c 100644
>> --- 

Re: [PATCH 3/4] slirp: Add mfr-id to -netdev options

2022-06-20 Thread Peter Delevoryas


> On Jun 18, 2022, at 3:05 AM, Samuel Thibault  wrote:
> 
> Peter Delevoryas, le mer. 15 juin 2022 18:05:25 -0700, a ecrit:
>> This lets you set the manufacturer's ID for a slirp netdev, which can be
>> queried from the guest through the Get Version ID NC-SI command. For
>> example, by setting the manufacturer's ID to 0x8119:
>> 
>> wget 
>> https://github.com/facebook/openbmc/releases/download/openbmc-e2294ff5d31d/fby35.mtd
>> qemu-system-arm -machine fby35-bmc \
>> -drive file=fby35.mtd,format=raw,if=mtd -nographic \
>> -netdev user,id=nic,mfr-id=0x8119,hostfwd=::-:22 \
>> -net nic,model=ftgmac100,netdev=nic
>> ...
>> username: root
>> password: 0penBmc
>> ...
>> root@bmc-oob:~# ncsi-util 0x15
>> NC-SI Command Response:
>> cmd: GET_VERSION_ID(0x15)
>> Response: COMMAND_COMPLETED(0x) Reason: NO_ERROR(0x)
>> Payload length = 40
>> 
>> 20: 0xf1 0xf0 0xf0 0x00
>> 24: 0x00 0x00 0x00 0x00
>> 28: 0x00 0x00 0x00 0x00
>> 32: 0x00 0x00 0x00 0x00
>> 36: 0x00 0x00 0x00 0x00
>> 40: 0x00 0x00 0x00 0x00
>> 44: 0x00 0x00 0x00 0x00
>> 48: 0x00 0x00 0x00 0x00
>> 52: 0x00 0x00 0x81 0x19
>> 
>> Signed-off-by: Peter Delevoryas 
>> ---
>> net/slirp.c | 5 +++--
>> qapi/net.json | 5 -
>> 2 files changed, 7 insertions(+), 3 deletions(-)
>> 
>> diff --git a/net/slirp.c b/net/slirp.c
>> index 75e5ccafd9..231068c1e2 100644
>> --- a/net/slirp.c
>> +++ b/net/slirp.c
>> @@ -413,7 +413,7 @@ static int net_slirp_init(NetClientState *peer, const 
>> char *model,
>> const char *vnameserver, const char *vnameserver6,
>> const char *smb_export, const char *vsmbserver,
>> const char **dnssearch, const char *vdomainname,
>> - const char *tftp_server_name,
>> + const char *tftp_server_name, uint32_t mfr_id,
>> Error **errp)
>> {
>> /* default settings according to historic slirp */
>> @@ -636,6 +636,7 @@ static int net_slirp_init(NetClientState *peer, const 
>> char *model,
>> cfg.vnameserver6 = ip6_dns;
>> cfg.vdnssearch = dnssearch;
>> cfg.vdomainname = vdomainname;
>> + cfg.mfr_id = mfr_id;
> 
> You will need a #if to only include it with slirp 4.8.0 indeed.
> Otherwise the mfr_id field won't exist.
> 

Oh, right. I’ll test this code with 4.7.0 and 4.8.0 and make
sure the behavior is correct (and perhaps even with earlier
versions like 1.0).

> In the #else part, it would probably useful to give the user at least a
> warning that tells her to upgrade slirp to 4.8.0 to get the mfr_id
> functionality working.

Ah yes good idea, I’ll include that.

> 
>> s->slirp = slirp_new(, _cb, s);
>> QTAILQ_INSERT_TAIL(_stacks, s, entry);
>> 
>> @@ -1172,7 +1173,7 @@ int net_init_slirp(const Netdev *netdev, const char 
>> *name,
>> user->bootfile, user->dhcpstart,
>> user->dns, user->ipv6_dns, user->smb,
>> user->smbserver, dnssearch, user->domainname,
>> - user->tftp_server_name, errp);
>> + user->tftp_server_name, user->mfr_id, errp);
>> 
>> while (slirp_configs) {
>> config = slirp_configs;
>> diff --git a/qapi/net.json b/qapi/net.json
>> index d6f7cfd4d6..efc5cb3fb6 100644
>> --- a/qapi/net.json
>> +++ b/qapi/net.json
>> @@ -167,6 +167,8 @@
>> #
>> # @tftp-server-name: RFC2132 "TFTP server name" string (Since 3.1)
>> #
>> +# @mfr-id: Manufacturer ID (Private Enterprise Number: IANA)
>> +#
>> # Since: 1.2
>> ##
>> { 'struct': 'NetdevUserOptions',
>> @@ -192,7 +194,8 @@
>> '*smbserver': 'str',
>> '*hostfwd': ['String'],
>> '*guestfwd': ['String'],
>> - '*tftp-server-name': 'str' } }
>> + '*tftp-server-name': 'str',
>> + '*mfr-id': 'uint32' } }
>> 
>> ##
>> # @NetdevTapOptions:
>> -- 
>> 2.30.2



[PATCH] linux-user: Add partial support for MADV_DONTNEED

2022-06-20 Thread Ilya Leoshkevich
Currently QEMU ignores madvise(MADV_DONTNEED), which break apps that
rely on this for zeroing out memory [1]. Improve the situation by doing
a passthrough when the range in question is a host-page-aligned
anonymous mapping.

This is based on the patches from Simon Hausmann [2] and Chris Fallin
[3]. The structure is taken from Simon's patch. The PAGE_MAP_ANONYMOUS
bits are superseded by commit 26bab757d41b ("linux-user: Introduce
PAGE_ANON"). In the end the patch acts like the one from Chris: we
either pass-through the entire syscall, or do nothing, since doing this
only partially would not help the affected applications much. Finally,
add some extra checks to match the behavior of the Linux kernel [4].

[1] https://gitlab.com/qemu-project/qemu/-/issues/326
[2] https://patchew.org/QEMU/20180827084037.25316-1-simon.hausm...@qt.io/
[3] 
https://github.com/bytecodealliance/wasmtime/blob/v0.37.0/ci/qemu-madvise.patch
[4] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/madvise.c?h=v5.19-rc3#n1368

Signed-off-by: Ilya Leoshkevich 
---
 linux-user/mmap.c  | 68 ++
 linux-user/syscall.c   |  6 +---
 linux-user/user-mmap.h |  1 +
 3 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 48e1373796..900df7b28c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -835,3 +835,71 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong 
old_size,
 mmap_unlock();
 return new_addr;
 }
+
+static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end)
+{
+ulong addr;
+
+if ((start | end) & ~qemu_host_page_mask) {
+return false;
+}
+
+for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+if (!(page_get_flags(addr) & PAGE_ANON)) {
+return false;
+}
+}
+
+return true;
+}
+
+int target_madvise(abi_ulong start, abi_ulong len_in, int advice)
+{
+abi_ulong len, end;
+int ret = 0;
+
+if (start & ~TARGET_PAGE_MASK) {
+errno = EINVAL;
+return -1;
+}
+len = TARGET_PAGE_ALIGN(len_in);
+
+if (len_in && !len) {
+errno = EINVAL;
+return -1;
+}
+
+end = start + len;
+if (end < start) {
+errno = EINVAL;
+return -1;
+}
+
+if (end == start) {
+return 0;
+}
+
+if (!guest_range_valid_untagged(start, len)) {
+errno = EINVAL;
+return -1;
+}
+
+/*
+ * A straight passthrough may not be safe because qemu sometimes turns
+ * private file-backed mappings into anonymous mappings.
+ *
+ * This is a hint, so ignoring and returning success is ok.
+ *
+ * This breaks MADV_DONTNEED, completely implementing which is quite
+ * complicated. However, there is one low-hanging fruit: host-page-aligned
+ * anonymous mappings. In this case passthrough is safe, so do it.
+ */
+mmap_lock();
+if ((advice & MADV_DONTNEED) &&
+can_passthrough_madv_dontneed(start, end)) {
+ret = madvise(g2h_untagged(start), len, MADV_DONTNEED);
+}
+mmap_unlock();
+
+return ret;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f55cdebee5..d25759b992 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -11807,11 +11807,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int 
num, abi_long arg1,
 
 #ifdef TARGET_NR_madvise
 case TARGET_NR_madvise:
-/* A straight passthrough may not be safe because qemu sometimes
-   turns private file-backed mappings into anonymous mappings.
-   This will break MADV_DONTNEED.
-   This is a hint, so ignoring and returning success is ok.  */
-return 0;
+return get_errno(target_madvise(arg1, arg2, arg3));
 #endif
 #ifdef TARGET_NR_fcntl64
 case TARGET_NR_fcntl64:
diff --git a/linux-user/user-mmap.h b/linux-user/user-mmap.h
index d1dec99c02..41cd358c7a 100644
--- a/linux-user/user-mmap.h
+++ b/linux-user/user-mmap.h
@@ -25,6 +25,7 @@ int target_munmap(abi_ulong start, abi_ulong len);
 abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
abi_ulong new_addr);
+int target_madvise(abi_ulong start, abi_ulong len_in, int advice);
 extern unsigned long last_brk;
 extern abi_ulong mmap_next_start;
 abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
-- 
2.35.3




[PATCH] hw/i386: Add unaccepted memory configuration

2022-06-20 Thread Dionna Glaze
For SEV-SNP, an OS is "SEV-SNP capable" without supporting this UEFI
v2.9 memory type. In order for OVMF to be able to avoid pre-validating
potentially hundreds of gibibytes of data before booting, it needs to
know if the guest OS can support its use of the new type of memory in
the memory map.

Cc: Xu, Min M 
Cc: Xiaoyao Li 
Cc: Thomas Lendacky 
Cc: Gerd Hoffman 
Signed-off-by: Dionna Glaze 
---
 hw/core/machine.c   | 33 +
 hw/i386/fw_cfg.c|  5 +
 include/hw/boards.h |  1 +
 3 files changed, 39 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index c53548d0b1..d2b9513951 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -263,6 +263,15 @@ GlobalProperty hw_compat_2_1[] = {
 };
 const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
 
+static QEnumLookup memory_acceptance_lookup = {
+.array = (const char *const[]) {
+"default",
+"true",
+"false",
+},
+.size = 3,
+};
+
 MachineState *current_machine;
 
 static char *machine_get_kernel(Object *obj, Error **errp)
@@ -502,6 +511,20 @@ static void machine_check_confidential_guest_support(const 
Object *obj,
  */
 }
 
+static int machine_get_accept_all_memory(Object *obj, Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+
+return ms->accept_all_memory;
+}
+
+static void machine_set_accept_all_memory(Object *obj, int value, Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+
+ms->accept_all_memory = value;
+}
+
 static bool machine_get_nvdimm(Object *obj, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
@@ -1022,6 +1045,15 @@ static void machine_class_init(ObjectClass *oc, void 
*data)
 object_class_property_set_description(oc, "confidential-guest-support",
   "Set confidential guest scheme to 
support");
 
+object_class_property_add_enum(oc, "accept-all-memory",
+   "MemoryAcceptance",
+   _acceptance_lookup,
+machine_get_accept_all_memory, machine_set_accept_all_memory);
+object_class_property_set_description(
+oc, "accept-all-memory",
+"false: Accept all memory, true: Accept up to 4G and leave the rest 
unaccepted (UEFI"
+" v2.9 memory type), default: default firmware behavior.");
+
 /* For compatibility */
 object_class_property_add_str(oc, "memory-encryption",
 machine_get_memory_encryption, machine_set_memory_encryption);
@@ -1072,6 +1104,7 @@ static void machine_initfn(Object *obj)
 ms->kernel_cmdline = g_strdup("");
 ms->ram_size = mc->default_ram_size;
 ms->maxram_size = mc->default_ram_size;
+ms->accept_all_memory = 0;
 
 if (mc->nvdimm_supported) {
 Object *obj = OBJECT(ms);
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index a283785a8d..96164994f8 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -131,6 +131,11 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms,
  _reserve, sizeof(e820_reserve));
 fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
 sizeof(struct e820_entry) * e820_get_num_entries());
+if (ms->accept_all_memory) {
+bool accept_all = ms->accept_all_memory == 1;
+fw_cfg_add_file(fw_cfg, "opt/ovmf/AcceptAllMemory",
+_all, sizeof(accept_all));
+}
 
 fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, _cfg, sizeof(hpet_cfg));
 /* allocate memory for the NUMA channel: one (64bit) word for the number
diff --git a/include/hw/boards.h b/include/hw/boards.h
index fa57bac4fb..eaf73498c4 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -362,6 +362,7 @@ struct MachineState {
 struct NVDIMMState *nvdimms_state;
 struct CXLState *cxl_devices_state;
 struct NumaState *numa_state;
+int accept_all_memory;
 };
 
 #define DEFINE_MACHINE(namestr, machine_initfn) \
-- 
2.37.0.rc0.104.g0611611a94-goog




Re: [PATCH v4 2/3] target/nios2: Move nios2-semi.c to nios2_softmmu_ss

2022-06-20 Thread Richard Henderson

On 6/9/22 03:36, Peter Maydell wrote:

On Wed, 8 Jun 2022 at 03:43, Richard Henderson
 wrote:


Semihosting is not enabled for nios2-linux-user.


True, but maybe it ought to be (in an ideal world)?


No, I think ideally there'd be no semihosting for user-only.
If you can write to semihosting, you can write to regular syscalls.

Semihosting is good for when we want to do testing of system-mode stuff, and we don't want 
the complication of a full os getting in the way.



r~



Re: [PATCH 2/4] slirp: Update SlirpConfig version to 5

2022-06-20 Thread Peter Delevoryas



> On Jun 18, 2022, at 3:03 AM, Samuel Thibault  wrote:
> 
> Hello,
> 
> Peter Delevoryas, le mer. 15 juin 2022 18:05:24 -0700, a ecrit:
>> I think we probably need a new Slirp release
>> (4.8.0) and a switch statement here instead, right?
>> 
>> So that we can preserve the behavior for 4.7.0?
> 
> Yes, that's the idea.

Ok great, thanks!

> 
> Samuel




Re: [PATCH 3/4] slirp: Add mfr-id to -netdev options

2022-06-20 Thread Peter Delevoryas


On Jun 20, 2022, at 12:16 AM, Markus Armbruster 
mailto:arm...@redhat.com>> wrote:

Peter Delevoryas mailto:p...@fb.com>> writes:

This lets you set the manufacturer's ID for a slirp netdev, which can be
queried from the guest through the Get Version ID NC-SI command. For
example, by setting the manufacturer's ID to 0x8119:

   wget 
https://github.com/facebook/openbmc/releases/download/openbmc-e2294ff5d31d/fby35.mtd
   qemu-system-arm -machine fby35-bmc \
   -drive file=fby35.mtd,format=raw,if=mtd -nographic \
   -netdev user,id=nic,mfr-id=0x8119,hostfwd=::-:22 \
   -net nic,model=ftgmac100,netdev=nic
   ...
   username: root
   password: 0penBmc
   ...
   root@bmc-oob:~# ncsi-util 0x15
   NC-SI Command Response:
   cmd: GET_VERSION_ID(0x15)
   Response: COMMAND_COMPLETED(0x)  Reason: NO_ERROR(0x)
   Payload length = 40

   20: 0xf1 0xf0 0xf0 0x00
   24: 0x00 0x00 0x00 0x00
   28: 0x00 0x00 0x00 0x00
   32: 0x00 0x00 0x00 0x00
   36: 0x00 0x00 0x00 0x00
   40: 0x00 0x00 0x00 0x00
   44: 0x00 0x00 0x00 0x00
   48: 0x00 0x00 0x00 0x00
   52: 0x00 0x00 0x81 0x19

Signed-off-by: Peter Delevoryas mailto:p...@fb.com>>
---

[...]

diff --git a/qapi/net.json b/qapi/net.json
index d6f7cfd4d6..efc5cb3fb6 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -167,6 +167,8 @@
#
# @tftp-server-name: RFC2132 "TFTP server name" string (Since 3.1)
#
+# @mfr-id: Manufacturer ID (Private Enterprise Number: IANA)
+#

Is 'mfr-id' an established technical term, or an abbreviation you came
up with?  If the latter, please use @manufacturer-id instead.

I don’t think so, I used that particular variable name throughout these patches
because that’s what the Linux kernel driver was using, but you’re right, we 
should
not use an abbreviation, in v2 I’ll change it to @manufacturer-id.


Documentation is rather terse.  It basically provides a bunch of
keywords you can throw at the search engine of your choice.  Can we cut
out that middle man and point straight to a suitable resource?

Erg, yeah, sorry about that, you’re right, it would probably be more useful
to point to the NC-SI specification directly:

https://www.dmtf.org/sites/default/files/standards/documents/DSP0222_1.0.0.pdf

Note: there have been some newer revisions to the specification lately, and the
full list of spec versions is here:

https://www.dmtf.org/dsp/DSP0222

Get Version ID and the OEM Vendor extension are both specified in 1.0.0, so I
think it should be ok to link to 1.0.0.

I’m not totally sure if I should directly link to the actual URL, but I’ll
definitely say: “This is defined in DMTF NC-SI 1.0.0” or something like that.
Unless URL’s in the code would be preferred. Theoretically, the DMTF
spec URL should be pretty long-lasting.

Thanks,
Peter


# Since: 1.2
##
{ 'struct': 'NetdevUserOptions',
@@ -192,7 +194,8 @@
'*smbserver': 'str',
'*hostfwd':   ['String'],
'*guestfwd':  ['String'],
-'*tftp-server-name': 'str' } }
+'*tftp-server-name': 'str',
+'*mfr-id': 'uint32' } }

##
# @NetdevTapOptions:




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

2022-06-20 Thread Vladimir Sementsov-Ogievskiy

On 6/13/22 12:07, Hanna Reitz wrote:

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

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

What is the problem with it?

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


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


Currently, CBW don't unshare write, when have no parent. It's kind of 
"inactive" state.

That's not quite correct. For example, if we just don't have parents on start of the job, 
nothing prevents user of adding new parents that write directly to source, ignoring CBW 
filter. Of course, user is responsible for his actions. But ideally, CBW filter should 
guarantee, that we are doing correct thing. It become more important when we consider 
"snapshot-access" interface. CBW filter provides this interface, and it should 
guarantee that it works correctly.

And to achieve this we want to effectively remove nodes during transaction, not 
just postpone removal to commit(). And that's in good sync with global concept: 
do all modifications first, than update permissions.

The other way could be removing permissions from nodes "to be removed", but 
that seems less correct to me.

Does these strong permissions for CBW worh a complexity? Good question) And 
actually it's hard to estimate it in such a big series. I can try to split this 
thing out of the series and see, could we at least postpone it, keeping for now 
only the interfaces with weaker protection.




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

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

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

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

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

So, the logic of new bdrv_unref_tran() is:

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

commit:
   do bdrv_delete() if refcnt is 0

abort:
   restore children and refcnt

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

Signed-off-by: Vladimir Sementsov-Ogievskiy 






--
Best regards,
Vladimir



[PATCH v2 0/2] ppc: Implement ISA 3.00 tlbie[l]

2022-06-20 Thread Leandro Lupori
Changes from v1:
- squashed first 2 commits into 1, because adding PPC_MEM_TLBIE to
  P9/P10's insns_flags and moving only tlbie (and not tlbiel) to
  decode tree breaks PowerPC64 instruction decoder initialization.

Leandro Lupori (2):
  target/ppc: Move tlbie[l] to decode tree
  target/ppc: Implement ISA 3.00 tlbie[l]

 target/ppc/cpu_init.c|   4 +-
 target/ppc/helper.h  |  18 +++
 target/ppc/insn32.decode |   8 +
 target/ppc/mmu_helper.c  | 154 +++
 target/ppc/translate.c   |  64 +---
 target/ppc/translate/storage-ctrl-impl.c.inc | 102 
 6 files changed, 286 insertions(+), 64 deletions(-)
 create mode 100644 target/ppc/translate/storage-ctrl-impl.c.inc

-- 
2.25.1




[PATCH v2 1/2] target/ppc: Move tlbie[l] to decode tree

2022-06-20 Thread Leandro Lupori
Also decode RIC, PRS and R operands.

Signed-off-by: Leandro Lupori 
---
 target/ppc/cpu_init.c|  4 +-
 target/ppc/insn32.decode |  8 ++
 target/ppc/translate.c   | 64 +-
 target/ppc/translate/storage-ctrl-impl.c.inc | 87 
 4 files changed, 99 insertions(+), 64 deletions(-)
 create mode 100644 target/ppc/translate/storage-ctrl-impl.c.inc

diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 0f891afa04..b802bbb641 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -6368,7 +6368,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
-   PPC_MEM_TLBSYNC |
+   PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD |
@@ -6585,7 +6585,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
PPC_FLOAT_EXT |
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
-   PPC_MEM_TLBSYNC |
+   PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD |
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 18a94fa3b5..44ac5f0785 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -786,3 +786,11 @@ XVF64GERPP  111011 ... --  0 . 00111010 ..-  
@XX3_at xa=%xx_xa_pair
 XVF64GERPN  111011 ... --  0 . 10111010 ..-  @XX3_at xa=%xx_xa_pair
 XVF64GERNP  111011 ... --  0 . 0010 ..-  @XX3_at xa=%xx_xa_pair
 XVF64GERNN  111011 ... --  0 . 1010 ..-  @XX3_at xa=%xx_xa_pair
+
+## TLB Management Instructions
+
+_tlbierb rs ric prs:bool r:bool
+@X_tlbie.. rs:5 - ric:2 prs:1 r:1 rb:5 .. . _tlbie
+
+TLBIE   01 . - .. . . . 0100110010 -@X_tlbie
+TLBIEL  01 . - .. . . . 0100010010 -@X_tlbie
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 1d6daa4608..4fcb311c2d 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -5424,64 +5424,6 @@ static void gen_tlbia(DisasContext *ctx)
 #endif  /* defined(CONFIG_USER_ONLY) */
 }
 
-/* tlbiel */
-static void gen_tlbiel(DisasContext *ctx)
-{
-#if defined(CONFIG_USER_ONLY)
-GEN_PRIV;
-#else
-bool psr = (ctx->opcode >> 17) & 0x1;
-
-if (ctx->pr || (!ctx->hv && !psr && ctx->hr)) {
-/*
- * tlbiel is privileged except when PSR=0 and HR=1, making it
- * hypervisor privileged.
- */
-GEN_PRIV;
-}
-
-gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
-#endif /* defined(CONFIG_USER_ONLY) */
-}
-
-/* tlbie */
-static void gen_tlbie(DisasContext *ctx)
-{
-#if defined(CONFIG_USER_ONLY)
-GEN_PRIV;
-#else
-bool psr = (ctx->opcode >> 17) & 0x1;
-TCGv_i32 t1;
-
-if (ctx->pr) {
-/* tlbie is privileged... */
-GEN_PRIV;
-} else if (!ctx->hv) {
-if (!ctx->gtse || (!psr && ctx->hr)) {
-/*
- * ... except when GTSE=0 or when PSR=0 and HR=1, making it
- * hypervisor privileged.
- */
-GEN_PRIV;
-}
-}
-
-if (NARROW_MODE(ctx)) {
-TCGv t0 = tcg_temp_new();
-tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]);
-gen_helper_tlbie(cpu_env, t0);
-tcg_temp_free(t0);
-} else {
-gen_helper_tlbie(cpu_env, cpu_gpr[rB(ctx->opcode)]);
-}
-t1 = tcg_temp_new_i32();
-tcg_gen_ld_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
-tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH);
-tcg_gen_st_i32(t1, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
-tcg_temp_free_i32(t1);
-#endif /* defined(CONFIG_USER_ONLY) */
-}
-
 /* tlbsync */
 static void gen_tlbsync(DisasContext *ctx)
 {
@@ -6699,6 +6641,8 @@ static bool resolve_PLS_D(DisasContext *ctx, arg_D *d, 
arg_PLS_D *a)
 
 #include "translate/branch-impl.c.inc"
 
+#include "translate/storage-ctrl-impl.c.inc"
+
 /* Handles lfdp */
 static void gen_dform39(DisasContext *ctx)
 {
@@ -6937,10 +6881,6 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, 
PPC_MEM_TLBIA),
  * XXX Those instructions will need to be handled differently for
  * different ISA versions
  */
-GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE),
-GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE),
-GEN_HANDLER_E(tlbiel, 0x1F, 0x12, 0x08, 0x0011, PPC_NONE, PPC2_ISA300),
-GEN_HANDLER_E(tlbie, 

[PATCH v2 2/2] target/ppc: Implement ISA 3.00 tlbie[l]

2022-06-20 Thread Leandro Lupori
This initial version supports the invalidation of one or all
TLB entries. Flush by PID/LPID, or based in process/partition
scope is not supported, because it would make using the
generic QEMU TLB implementation hard. In these cases, all
entries are flushed.

Signed-off-by: Leandro Lupori 
---
 target/ppc/helper.h  |  18 +++
 target/ppc/mmu_helper.c  | 154 +++
 target/ppc/translate/storage-ctrl-impl.c.inc |  15 ++
 3 files changed, 187 insertions(+)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 6233e28d85..0b2bc8020b 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -664,6 +664,24 @@ DEF_HELPER_FLAGS_1(tlbia, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_2(tlbiva, TCG_CALL_NO_RWG, void, env, tl)
 #if defined(TARGET_PPC64)
+
+/*
+ * tlbie[l] helper flags
+ *
+ * RIC, PRS, R and local are passed as flags in the last argument.
+ */
+#define TLBIE_F_RIC_SHIFT   0
+#define TLBIE_F_PRS_SHIFT   2
+#define TLBIE_F_R_SHIFT 3
+#define TLBIE_F_LOCAL_SHIFT 4
+
+#define TLBIE_F_RIC_MASK(3 << TLBIE_F_RIC_SHIFT)
+#define TLBIE_F_PRS (1 << TLBIE_F_PRS_SHIFT)
+#define TLBIE_F_R   (1 << TLBIE_F_R_SHIFT)
+#define TLBIE_F_LOCAL   (1 << TLBIE_F_LOCAL_SHIFT)
+
+DEF_HELPER_FLAGS_4(tlbie_isa300, TCG_CALL_NO_WG, void, \
+env, tl, tl, i32)
 DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl)
 DEF_HELPER_2(load_slb_esid, tl, env, tl)
 DEF_HELPER_2(load_slb_vsid, tl, env, tl)
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 15239dc95b..b881aee23f 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -429,6 +429,160 @@ void helper_tlbie(CPUPPCState *env, target_ulong addr)
 ppc_tlb_invalidate_one(env, addr);
 }
 
+#if defined(TARGET_PPC64)
+
+/* Invalidation Selector */
+#define TLBIE_IS_VA 0
+#define TLBIE_IS_PID1
+#define TLBIE_IS_LPID   2
+#define TLBIE_IS_ALL3
+
+/* Radix Invalidation Control */
+#define TLBIE_RIC_TLB   0
+#define TLBIE_RIC_PWC   1
+#define TLBIE_RIC_ALL   2
+#define TLBIE_RIC_GRP   3
+
+/* Radix Actual Page sizes */
+#define TLBIE_R_AP_4K   0
+#define TLBIE_R_AP_64K  5
+#define TLBIE_R_AP_2M   1
+#define TLBIE_R_AP_1G   2
+
+/* RB field masks */
+#define TLBIE_RB_EPN_MASK   PPC_BITMASK(0, 51)
+#define TLBIE_RB_IS_MASKPPC_BITMASK(52, 53)
+#define TLBIE_RB_AP_MASKPPC_BITMASK(56, 58)
+
+void helper_tlbie_isa300(CPUPPCState *env, target_ulong rb, target_ulong rs,
+ uint32_t flags)
+{
+unsigned ric = (flags & TLBIE_F_RIC_MASK) >> TLBIE_F_RIC_SHIFT;
+/*
+ * With the exception of the checks for invalid instruction forms,
+ * PRS is currently ignored, because we don't know if a given TLB entry
+ * is process or partition scoped.
+ */
+bool prs = flags & TLBIE_F_PRS;
+bool r = flags & TLBIE_F_R;
+bool local = flags & TLBIE_F_LOCAL;
+bool effR;
+unsigned is = extract64(rb, PPC_BIT_NR(53), 2), set;
+unsigned ap;/* actual page size */
+target_ulong addr, pgoffs_mask;
+
+qemu_log_mask(CPU_LOG_MMU,
+"%s: local=%d addr=" TARGET_FMT_lx " ric=%u prs=%d r=%d is=%u\n",
+__func__, local, rb & TARGET_PAGE_MASK, ric, prs, r, is);
+
+effR = FIELD_EX64(env->msr, MSR, HV) ? r : env->spr[SPR_LPCR] & LPCR_HR;
+
+/* Partial TLB invalidation is supported for Radix only for now. */
+if (!effR) {
+goto inval_all;
+}
+
+/* Check for invalid instruction forms (effR=1). */
+if (unlikely(ric == TLBIE_RIC_GRP ||
+ ((ric == TLBIE_RIC_PWC || ric == TLBIE_RIC_ALL) &&
+   is == TLBIE_IS_VA) ||
+ (!prs && is == TLBIE_IS_PID))) {
+qemu_log_mask(LOG_GUEST_ERROR,
+"%s: invalid instruction form: ric=%u prs=%d r=%d is=%u\n",
+__func__, ric, prs, r, is);
+goto invalid;
+}
+
+/* We don't cache Page Walks. */
+if (ric == TLBIE_RIC_PWC) {
+if (local) {
+set = extract64(rb, PPC_BIT_NR(51), 12);
+if (set != 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid set: %d\n",
+  __func__, set);
+goto invalid;
+}
+}
+return;
+}
+
+/*
+ * Invalidation by LPID or PID is not supported, so fallback
+ * to full TLB flush in these cases.
+ */
+if (is != TLBIE_IS_VA) {
+goto inval_all;
+}
+
+/*
+ * The results of an attempt to invalidate a translation outside of
+ * quadrant 0 for Radix Tree translation (effR=1, RIC=0, PRS=1, IS=0,
+ * and EA 0:1 != 0b00) are boundedly undefined.
+ */
+if (unlikely(ric == TLBIE_RIC_TLB && prs && is == TLBIE_IS_VA &&
+ (rb & R_EADDR_QUADRANT) != R_EADDR_QUADRANT0)) {
+  

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

2022-06-20 Thread Vladimir Sementsov-Ogievskiy

On 6/13/22 10:46, Hanna Reitz wrote:

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

To be used in further commit.

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

diff --git a/block.c b/block.c
index be19964f89..1900cdf277 100644
--- a/block.c
+++ b/block.c
@@ -2907,6 +2907,54 @@ static void bdrv_child_free(BdrvChild *child)
  g_free(child);
  }
+typedef struct BdrvTrySetAioContextState {
+    BlockDriverState *bs;
+    AioContext *old_ctx;
+} BdrvTrySetAioContextState;
+
+static void bdrv_try_set_aio_context_abort(void *opaque)
+{
+    BdrvTrySetAioContextState *s = opaque;
+
+    if (bdrv_get_aio_context(s->bs) != s->old_ctx) {
+    bdrv_try_set_aio_context(s->bs, s->old_ctx, _abort);


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

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



Hmm.. Actually, I think that bdrv_try_set_aio_context_abort() should do this 
shuffling by it self. The only hope to correctly rollback a transaction, is 
operation in assumption that on .abort() we are exactly on the same state as on 
.prepare(), regardless of other actions. And this means that old_ctx is 
acquired and new_ctx is not.


--
Best regards,
Vladimir



Re: [PATCH 04/10] bsd-user: Implement freebsd11_mknod, freebsd11_mknodat and mknodat

2022-06-20 Thread Warner Losh
On Mon, Jun 20, 2022 at 1:13 PM Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 6/20/22 10:42, Warner Losh wrote:
> > These implement both the old-pre INO64 mknod variations, as well as the
> > now current INO64 variant. To implement the old stuff, we use some
> > linker magic to bind to the old versions of these functions.
> >
> > Signed-off-by: Stacey Son 
> > Signed-off-by: Michal Meloun 
> > Signed-off-by: Warner Losh 
> > ---
> >   bsd-user/bsd-file.h   | 59 +++
> >   bsd-user/freebsd/os-syscall.c | 15 +
> >   2 files changed, 74 insertions(+)
> >
> > diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h
> > index 0585f6a2a40..3be832b2a74 100644
> > --- a/bsd-user/bsd-file.h
> > +++ b/bsd-user/bsd-file.h
> > @@ -51,6 +51,16 @@ do {\
> >   unlock_user(p1, arg1, 0);   \
> >   } while (0)
> >
> > +#ifndef BSD_HAVE_INO64
> > +#define freebsd11_mknod mknod
> > +#define freebsd11_mknodat   mknodat
> > +#else
> > +int freebsd11_mknod(char *path, mode_t mode, uint32_t dev);
> > +__sym_compat(mknod, freebsd11_mknod, FBSD_1.0);
> > +int freebsd11_mknodat(int fd, char *path, mode_t mode, uint32_t dev);
> > +__sym_compat(mknodat, freebsd11_mknodat, FBSD_1.1);
> > +#endif
>
> Where does BSD_HAVE_INO64 come from?  I can't find it defined in freebsd
> git.
>

It used to be defined conditionally on FreeBSD 12 vs earlier. Now it's
defined unconditionally
in a file that wasn't part of the upstreaming. I'll rework now that it's
unconditional because
there's no way we could run on a FreeBSD 11 system. Normally we'd just
retire these older
system calls to limit the scope of what we need to maintain, but we have to
have the old FreeBSD-11
era pre-INO64 system calls (here and elsewhere) to support rust since it
doesn't use libc at all.


> You should probably avoid the linker tricks and use direct syscalls of
> SYS_freebsd11_mknodat etc
>

Yea, on pre-ino64 systems, there were no system calls like that. Now that
we have them, I think
you are right that we'd be better off just using the system call directly
rather than needing this hack
to get the old system calls. the old symbols will be around forever, but
it's better to be more direct here.
There's nothing hidden in the libc versions of these symbols.

tl;dr: It's always defined now, so I'll unifdef it.

Warner


[PATCH v3] ui/cocoa: Take refresh rate into account

2022-06-20 Thread Akihiko Odaki
Retreieve the refresh rate of the display and reflect it with
dpy_set_ui_info() and update_displaychangelistener(), allowing the
guest and DisplayChangeListener to consume the information.

Signed-off-by: Akihiko Odaki 
---
 meson.build |  3 ++-
 ui/cocoa.m  | 12 
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index 0c2e11ff071..0f83f3730af 100644
--- a/meson.build
+++ b/meson.build
@@ -575,7 +575,8 @@ if get_option('attr').allowed()
   endif
 endif
 
-cocoa = dependency('appleframeworks', modules: 'Cocoa', required: 
get_option('cocoa'))
+cocoa = dependency('appleframeworks', modules: ['Cocoa', 'CoreVideo'],
+   required: get_option('cocoa'))
 if cocoa.found() and get_option('sdl').enabled()
   error('Cocoa and SDL cannot be enabled at the same time')
 endif
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 84c84e98fc5..a3949c6 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -561,8 +561,20 @@ - (void) updateUIInfoLocked
 CGDirectDisplayID display = [[description 
objectForKey:@"NSScreenNumber"] unsignedIntValue];
 NSSize screenSize = [[[self window] screen] frame].size;
 CGSize screenPhysicalSize = CGDisplayScreenSize(display);
+CVDisplayLinkRef displayLink;
 
 frameSize = isFullscreen ? screenSize : [self frame].size;
+
+if (!CVDisplayLinkCreateWithCGDisplay(display, )) {
+CVTime period = 
CVDisplayLinkGetNominalOutputVideoRefreshPeriod(displayLink);
+CVDisplayLinkRelease(displayLink);
+if (!(period.flags & kCVTimeIsIndefinite)) {
+update_displaychangelistener(,
+ 1000 * period.timeValue / 
period.timeScale);
+info.refresh_rate = (int64_t)1000 * period.timeScale / 
period.timeValue;
+}
+}
+
 info.width_mm = frameSize.width / screenSize.width * 
screenPhysicalSize.width;
 info.height_mm = frameSize.height / screenSize.height * 
screenPhysicalSize.height;
 } else {
-- 
2.32.1 (Apple Git-133)




[PATCH 3/3] target/ppc: Check page dir/table base alignment

2022-06-20 Thread Leandro Lupori
Check if each page dir/table base address is properly aligned and
log a guest error if not, as real hardware behave incorrectly in
this case.

These checks are only performed when DEBUG_MMU is defined, to avoid
hurting the performance.

Signed-off-by: Leandro Lupori 
---
 target/ppc/mmu-radix64.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 2f0bcbfe2e..80d945a7c3 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -28,6 +28,8 @@
 #include "mmu-radix64.h"
 #include "mmu-book3s-v3.h"
 
+/* #define DEBUG_MMU */
+
 static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env,
  vaddr eaddr,
  uint64_t *lpid, uint64_t *pid)
@@ -277,6 +279,16 @@ static int ppc_radix64_next_level(AddressSpace *as, vaddr 
eaddr,
 if (!(pde & R_PTE_LEAF)) { /* Prepare for next iteration */
 ++*level;
 *nls = pde & R_PDE_NLS;
+
+#ifdef DEBUG_MMU
+if ((pde & R_PDE_NLB) & MAKE_64BIT_MASK(0, *nls + 3)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+"%s: misaligned page dir/table base: 0x%"VADDR_PRIx
+" page dir size: 0x%"PRIx64" level: %d\n",
+__func__, (pde & R_PDE_NLB), BIT(*nls + 3), *level);
+}
+#endif
+
 index = eaddr >> (*psize - *nls);   /* Shift */
 index &= ((1UL << *nls) - 1);   /* Mask */
 *pte_addr = (pde & R_PDE_NLB) + (index * sizeof(pde));
@@ -297,6 +309,15 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vaddr 
eaddr,
 return 1;
 }
 
+#ifdef DEBUG_MMU
+if (base_addr & MAKE_64BIT_MASK(0, nls + 3)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+"%s: misaligned page dir base: 0x%"VADDR_PRIx
+" page dir size: 0x%"PRIx64"\n",
+__func__, base_addr, BIT(nls + 3));
+}
+#endif
+
 index = eaddr >> (*psize - nls);/* Shift */
 index &= ((1UL << nls) - 1);   /* Mask */
 *pte_addr = base_addr + (index * sizeof(pde));
-- 
2.25.1




[PATCH 2/3] target/ppc: Improve Radix xlate level validation

2022-06-20 Thread Leandro Lupori
Check if the number and size of Radix levels are valid on
POWER9/POWER10 CPUs, according to the supported Radix Tree
Configurations described in their User Manuals.

Signed-off-by: Leandro Lupori 
---
 target/ppc/mmu-radix64.c | 36 +---
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 9a8a2e2875..2f0bcbfe2e 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -236,13 +236,31 @@ static void ppc_radix64_set_rc(PowerPCCPU *cpu, 
MMUAccessType access_type,
 }
 }
 
+static bool ppc_radix64_is_valid_level(int level, int psize, uint64_t nls)
+{
+/*
+ * Check if this is a valid level, according to POWER9 and POWER10
+ * Processor User's Manuals, sections 4.10.4.1 and 5.10.6.1, respectively:
+ * Supported Radix Tree Configurations and Resulting Page Sizes.
+ */
+switch (level) {
+case 0: return psize == 52 && nls == 13;/* Root Page Dir */
+case 1: return psize == 39 && nls == 9;
+case 2: return psize == 30 && nls == 9;
+case 3: return psize == 21 && (nls == 9 || nls == 5);
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "invalid radix level: %d\n", level);
+return false;
+}
+}
+
 static int ppc_radix64_next_level(AddressSpace *as, vaddr eaddr,
-  uint64_t *pte_addr, uint64_t *nls,
+  uint64_t *pte_addr, int *level, uint64_t 
*nls,
   int *psize, uint64_t *pte, int *fault_cause)
 {
 uint64_t index, pde;
 
-if (*nls < 5) { /* Directory maps less than 2**5 entries */
+if (!ppc_radix64_is_valid_level(*level, *psize, *nls)) {
 *fault_cause |= DSISR_R_BADCONFIG;
 return 1;
 }
@@ -257,6 +275,7 @@ static int ppc_radix64_next_level(AddressSpace *as, vaddr 
eaddr,
 *pte = pde;
 *psize -= *nls;
 if (!(pde & R_PTE_LEAF)) { /* Prepare for next iteration */
+++*level;
 *nls = pde & R_PDE_NLS;
 index = eaddr >> (*psize - *nls);   /* Shift */
 index &= ((1UL << *nls) - 1);   /* Mask */
@@ -270,9 +289,10 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vaddr 
eaddr,
  hwaddr *raddr, int *psize, uint64_t *pte,
  int *fault_cause, hwaddr *pte_addr)
 {
-uint64_t index, pde, rpn , mask;
+uint64_t index, pde, rpn, mask;
+int level = 0;
 
-if (nls < 5) { /* Directory maps less than 2**5 entries */
+if (!ppc_radix64_is_valid_level(level, *psize, nls)) {
 *fault_cause |= DSISR_R_BADCONFIG;
 return 1;
 }
@@ -283,8 +303,8 @@ static int ppc_radix64_walk_tree(AddressSpace *as, vaddr 
eaddr,
 do {
 int ret;
 
-ret = ppc_radix64_next_level(as, eaddr, pte_addr, , psize, ,
- fault_cause);
+ret = ppc_radix64_next_level(as, eaddr, pte_addr, , , psize,
+ , fault_cause);
 if (ret) {
 return ret;
 }
@@ -456,6 +476,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
 }
 } else {
 uint64_t rpn, mask;
+int level = 0;
 
 index = (eaddr & R_EADDR_MASK) >> (*g_page_size - nls); /* Shift */
 index &= ((1UL << nls) - 1);/* Mask */
@@ -476,7 +497,8 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
 }
 
 ret = ppc_radix64_next_level(cs->as, eaddr & R_EADDR_MASK, 
_raddr,
- , g_page_size, , 
_cause);
+ , , g_page_size, ,
+ _cause);
 if (ret) {
 /* No valid pte */
 if (guest_visible) {
-- 
2.25.1




[PATCH 1/3] ppc: Check partition and process table alignment

2022-06-20 Thread Leandro Lupori
Check if partition and process tables are properly aligned, in
their size, according to PowerISA 3.1B, Book III 6.7.6 programming
note. Hardware and KVM also raise an exception in these cases.

Signed-off-by: Leandro Lupori 
---
 hw/ppc/spapr.c |  5 +
 hw/ppc/spapr_hcall.c   |  9 +
 target/ppc/mmu-book3s-v3.c |  5 +
 target/ppc/mmu-radix64.c   | 17 +
 4 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index fd4942e881..4b1f346087 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1329,6 +1329,11 @@ static bool spapr_get_pate(PPCVirtualHypervisor *vhyp, 
PowerPCCPU *cpu,
 patb = spapr->nested_ptcr & PTCR_PATB;
 pats = spapr->nested_ptcr & PTCR_PATS;
 
+/* Check if partition table is properly aligned */
+if (patb & MAKE_64BIT_MASK(0, pats + 12)) {
+return false;
+}
+
 /* Calculate number of entries */
 pats = 1ull << (pats + 12 - 4);
 if (pats <= lpid) {
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index d761a7d0c3..2a73ba8a1d 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -920,6 +920,7 @@ static target_ulong h_register_process_table(PowerPCCPU 
*cpu,
 target_ulong page_size = args[2];
 target_ulong table_size = args[3];
 target_ulong update_lpcr = 0;
+target_ulong table_byte_size;
 uint64_t cproc;
 
 if (flags & ~FLAGS_MASK) { /* Check no reserved bits are set */
@@ -927,6 +928,14 @@ static target_ulong h_register_process_table(PowerPCCPU 
*cpu,
 }
 if (flags & FLAG_MODIFY) {
 if (flags & FLAG_REGISTER) {
+/* Check process table alignment */
+table_byte_size = 1ULL << (table_size + 12);
+if (proc_tbl & (table_byte_size - 1)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+"%s: process table not properly aligned: "
+"proc_tbl 0x%lx proc_tbl_size 0x%lx\n",
+__func__, proc_tbl, table_byte_size);
+}
 if (flags & FLAG_RADIX) { /* Register new RADIX process table */
 if (proc_tbl & 0xfff || proc_tbl >> 60) {
 return H_P2;
diff --git a/target/ppc/mmu-book3s-v3.c b/target/ppc/mmu-book3s-v3.c
index f4985bae78..c8f69b3df9 100644
--- a/target/ppc/mmu-book3s-v3.c
+++ b/target/ppc/mmu-book3s-v3.c
@@ -28,6 +28,11 @@ bool ppc64_v3_get_pate(PowerPCCPU *cpu, target_ulong lpid, 
ppc_v3_pate_t *entry)
 uint64_t patb = cpu->env.spr[SPR_PTCR] & PTCR_PATB;
 uint64_t pats = cpu->env.spr[SPR_PTCR] & PTCR_PATS;
 
+/* Check if partition table is properly aligned */
+if (patb & MAKE_64BIT_MASK(0, pats + 12)) {
+return false;
+}
+
 /* Calculate number of entries */
 pats = 1ull << (pats + 12 - 4);
 if (pats <= lpid) {
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 21ac958e48..9a8a2e2875 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -383,7 +383,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
 {
 CPUState *cs = CPU(cpu);
 CPUPPCState *env = >env;
-uint64_t offset, size, prtbe_addr, prtbe0, base_addr, nls, index, pte;
+uint64_t offset, size, prtb, prtbe_addr, prtbe0, base_addr, nls, index, 
pte;
 int fault_cause = 0, h_page_size, h_prot;
 hwaddr h_raddr, pte_addr;
 int ret;
@@ -393,9 +393,18 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU 
*cpu,
   __func__, access_str(access_type),
   eaddr, mmu_idx, pid);
 
+prtb = (pate.dw1 & PATE1_R_PRTB);
+size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
+if (prtb & (size - 1)) {
+/* Process Table not properly aligned */
+if (guest_visible) {
+ppc_radix64_raise_si(cpu, access_type, eaddr, DSISR_R_BADCONFIG);
+}
+return 1;
+}
+
 /* Index Process Table by PID to Find Corresponding Process Table Entry */
 offset = pid * sizeof(struct prtb_entry);
-size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
 if (offset >= size) {
 /* offset exceeds size of the process table */
 if (guest_visible) {
@@ -403,7 +412,7 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,
 }
 return 1;
 }
-prtbe_addr = (pate.dw1 & PATE1_R_PRTB) + offset;
+prtbe_addr = prtb + offset;
 
 if (vhyp_flat_addressing(cpu)) {
 prtbe0 = ldq_phys(cs->as, prtbe_addr);
@@ -568,7 +577,7 @@ static bool ppc_radix64_xlate_impl(PowerPCCPU *cpu, vaddr 
eaddr,
 return false;
 }
 
-/* Get Process Table */
+/* Get Partition Table */
 if (cpu->vhyp) {
 PPCVirtualHypervisorClass *vhc;
 vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
-- 
2.25.1




[PATCH 0/3] ppc: Check for bad Radix configs

2022-06-20 Thread Leandro Lupori
On PowerPC64 using Radix MMU, when partition or process table is not
properly aligned, according to their size, an exception must be raised
(DSI/ISI/HDSI/HISI) and the "Bad Radix Config" bit must be set in the
appropriate register.
Hardware and KVM already do this, but TCG was missing this part.

This patch series also improves the code that validates each Radix Tree
level, by checking the number of levels and the size of each one.

Finally, when DEBUG_MMU is defined, PDE/PTE base address alignment is
also checked and reported, to make it easier to detect invalid
configurations.

Leandro Lupori (3):
  ppc: Check partition and process table alignment
  target/ppc: Improve Radix xlate level validation
  target/ppc: Check page dir/table base alignment

 hw/ppc/spapr.c |  5 +++
 hw/ppc/spapr_hcall.c   |  9 +
 target/ppc/mmu-book3s-v3.c |  5 +++
 target/ppc/mmu-radix64.c   | 74 --
 4 files changed, 82 insertions(+), 11 deletions(-)

-- 
2.25.1




Re: [PATCH 02/10] bsd-user: Implement symlink, symlinkat, readlink and readlinkat

2022-06-20 Thread Warner Losh
On Mon, Jun 20, 2022 at 12:28 PM Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 6/20/22 10:42, Warner Losh wrote:
> > +static abi_long do_bsd_readlink(CPUArchState *env, abi_long arg1,
> > +abi_long arg2, abi_long arg3)
> > +{
> > +abi_long ret;
> > +void *p1, *p2;
> > +
> > +LOCK_PATH(p1, arg1);
> > +p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
> > +if (p2 == NULL) {
> > +UNLOCK_PATH(p1, arg1);
> > +return -TARGET_EFAULT;
> > +}
> > +#ifdef __FreeBSD__
> > +if (strcmp(p1, "/proc/curproc/file") == 0) {
> > +CPUState *cpu = env_cpu(env);
> > +TaskState *ts = (TaskState *)cpu->opaque;
> > +strncpy(p2, ts->bprm->fullpath, arg3);
> > +ret = MIN((abi_long)strlen(ts->bprm->fullpath), arg3);
> > +} else
> > +#endif
>
> Unfortunate ifdef.  Do we really need it while the other bsds are
> presumably still
> non-functional?  I see that HOST_DEFAULT_BSD_TYPE isn't hooked up either...
>

I can remove the ifdef for now and add it to the TODO file as something to
check
when we try to support NetBSD/OpenBSD again.

Warner


Re: [PATCH v4 06/13] accel/tcg: Reorganize tcg_accel_ops_init()

2022-06-20 Thread Richard Henderson

On 3/23/22 10:17, Philippe Mathieu-Daudé wrote:

From: Philippe Mathieu-Daudé 

Reorg TCG AccelOpsClass initialization to emphasis icount
mode share more code with single-threaded TCG.

Signed-off-by: Philippe Mathieu-Daudé 
---
  accel/tcg/tcg-accel-ops.c | 15 ---
  1 file changed, 8 insertions(+), 7 deletions(-)


Queued to tcg-next.


r~



Re: [PATCH v4 05/13] accel/tcg: Init TCG cflags in vCPU thread handler

2022-06-20 Thread Richard Henderson

On 3/23/22 10:17, Philippe Mathieu-Daudé wrote:

From: Philippe Mathieu-Daudé 

Move TCG cflags initialization to thread handler.
Remove the duplicated assert checks.

Signed-off-by: Philippe Mathieu-Daudé 
---
  accel/tcg/tcg-accel-ops-mttcg.c | 5 ++---
  accel/tcg/tcg-accel-ops-rr.c| 7 +++
  2 files changed, 5 insertions(+), 7 deletions(-)


Queued to tcg-next.


r~



Re: [PATCH] target/avr: Drop avr_cpu_memory_rw_debug()

2022-06-20 Thread Richard Henderson

On 3/22/22 02:50, Bin Meng wrote:

CPUClass::memory_rw_debug() holds a callback for GDB memory access.
If not provided, cpu_memory_rw_debug() is used by the GDB stub.
Drop avr_cpu_memory_rw_debug() which does nothing special.

Signed-off-by: Bin Meng 


Queued to tcg-next, for lack of anything better.


r~



Re: [PATCH 05/10] bsd-user: Implement chown, fchown, lchown and fchownat

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

Signed-off-by: Stacey Son
Signed-off-by: Warner Losh
---
  bsd-user/bsd-file.h   | 48 +++
  bsd-user/freebsd/os-syscall.c | 16 
  2 files changed, 64 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 2/2] target/arm: Catch invalid kvm state also for hvf

2022-06-20 Thread Richard Henderson

On 6/20/22 12:22, Alexander Graf wrote:

Some features such as running in EL3 or running M profile code are
incompatible with virtualization as QEMU implements it today. To prevent
users from picking invalid configurations on other virt solutions like
Hvf, let's run the same checks there too.

Resolves:https://gitlab.com/qemu-project/qemu/-/issues/1073
Signed-off-by: Alexander Graf

---

v1 -> v2:

   - Use current_accel_name()
   - Use !tcg_enabled()
---
  target/arm/cpu.c | 11 +++
  1 file changed, 7 insertions(+), 4 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 1/2] accel: Introduce current_accel_name()

2022-06-20 Thread Richard Henderson

On 6/20/22 12:22, Alexander Graf wrote:

We need to fetch the name of the current accelerator in flexible error
messages more going forward. Let's create a helper that gives it to us
without casting in the target code.

Signed-off-by: Alexander Graf
---
  accel/accel-common.c | 8 
  include/qemu/accel.h | 1 +
  softmmu/vl.c | 3 +--
  3 files changed, 10 insertions(+), 2 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 03/10] bsd-user: implement chmod, fchmod, lchmod and fchmodat

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

Signed-off-by: Stacey Son
Signed-off-by: Warner Losh
---
  bsd-user/bsd-file.h   | 46 +++
  bsd-user/freebsd/os-syscall.c | 16 
  2 files changed, 62 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [RFC PATCH v3 00/11] qapi: net: add unix socket type support to netdev backend

2022-06-20 Thread Dr. David Alan Gilbert
* Laurent Vivier (lviv...@redhat.com) wrote:
> "-netdev socket" only supports inet sockets.
> 
> It's not a complex task to add support for unix sockets, but
> the socket netdev parameters are not defined to manage well unix
> socket parameters.
> 
> As discussed in:
> 
>   "socket.c added support for unix domain socket datagram transport"
>   
> https://lore.kernel.org/qemu-devel/1c0e1bc5-904f-46b0-8044-68e43e67b...@gmail.com/
> 
> This series adds support of unix socket type using SocketAddress QAPI 
> structure.
> 
> Two new netdev backends, "stream" and "dgram" are added, that are barely a 
> copy of "socket"
> backend but they use the SocketAddress QAPI to provide socket parameters.
> And then they also implement unix sockets (TCP and UDP).

Had you considered a -netdev chardev?

Dave

> Some examples of CLI syntax:
> 
>   for TCP:
> 
>   -netdev stream,id=socket0,addr.type=inet,addr.host=localhost,addr.port=1234
>   -netdev 
> stream,id=socket0,server=off,addr.type=inet,addr.host=localhost,addr.port=1234
> 
>   -netdev dgram,id=socket0,\
>   local.type=inet,local.host=localhost,local.port=1234,\
>   remote.type=inet,remote.host=localhost,remote.port=1235
> 
>   for UNIX:
> 
>   -netdev stream,id=socket0,addr.type=unix,addr.path=/tmp/qemu0
>   -netdev stream,id=socket0,server=off,addr.type=unix,addr.path=/tmp/qemu0
> 
>   -netdev dgram,id=socket0,\
>   local.type=unix,local.path=/tmp/qemu0,\
>   remote.type=unix,remote.path=/tmp/qemu1
> 
>   for FD:
> 
>   -netdev stream,id=socket0,addr.type=fd,addr.str=4
>   -netdev stream,id=socket0,server=off,addr.type=fd,addr.str=5
> 
>   -netdev dgram,id=socket0,local.type=fd,addr.str=4
> 
> v3:
>   - remove support of "-net" for dgram and stream. They are only
> supported with "-netdev" option.
>   - use _fatal directly in net_client_inits()
>   - update qemu-options.hx
>   - move to QIO for stream socket
> 
> v2:
>   - use "stream" and "dgram" rather than "socket-ng,mode=stream"
> and ""socket-ng,mode=dgram"
>   - extract code to bypass qemu_opts_parse_noisily() to
> a new patch
>   - do not ignore EINVAL (Stefano)
>   - fix "-net" option
> 
> CC: Ralph Schmieder 
> CC: Stefano Brivio 
> CC: Daniel P. Berrangé 
> CC: Markus Armbruster 
> 
> Laurent Vivier (10):
>   net: introduce convert_host_port()
>   net: remove the @errp argument of net_client_inits()
>   qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
>   qapi: net: add stream and dgram netdevs
>   net: stream: add unix socket
>   net: dgram: make dgram_dst generic
>   net: dgram: move mcast specific code from net_socket_fd_init_dgram()
>   net: dgram: add unix socket
>   qemu-sockets: introduce socket_uri()
>   net: stream: move to QIO
> 
> Stefano Brivio (1):
>   net: stream: Don't ignore EINVAL on netdev socket connection
> 
>  hmp-commands.hx|   2 +-
>  include/net/net.h  |   3 +-
>  include/qemu/sockets.h |   4 +-
>  monitor/hmp-cmds.c |  23 +-
>  net/clients.h  |   6 +
>  net/dgram.c| 706 +
>  net/hub.c  |   2 +
>  net/meson.build|   2 +
>  net/net.c  | 149 ++---
>  net/stream.c   | 371 ++
>  qapi/net.json  |  40 ++-
>  qemu-options.hx|  12 +
>  softmmu/vl.c   |   5 +-
>  util/qemu-sockets.c|  20 ++
>  14 files changed, 1277 insertions(+), 68 deletions(-)
>  create mode 100644 net/dgram.c
>  create mode 100644 net/stream.c
> 
> -- 
> 2.36.1
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




Re: [PATCH 01/10] bsd-user: Implement mount, umount and nmount

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

+/*
+ * XXX arg4 should be locked, but it isn't clear how to do that
+ * since it's it may be not be a NULL-terminated string.


it's it.

Unless you meant https://www.itsiticecream.com/  ;-)

Reviewed-by: Richard Henderson 


r~



Re: [PATCH 09/10] bsd-user: Implement pathconf, lpathconf and fpathconf

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

Signed-off-by: Stacey Son
Signed-off-by: Warner Losh
---
  bsd-user/bsd-file.h   | 32 
  bsd-user/freebsd/os-syscall.c | 12 
  2 files changed, 44 insertions(+)


Reviewed-by: Richard Henderson 

r~



[PATCH v2 1/2] accel: Introduce current_accel_name()

2022-06-20 Thread Alexander Graf
We need to fetch the name of the current accelerator in flexible error
messages more going forward. Let's create a helper that gives it to us
without casting in the target code.

Signed-off-by: Alexander Graf 
---
 accel/accel-common.c | 8 
 include/qemu/accel.h | 1 +
 softmmu/vl.c | 3 +--
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/accel/accel-common.c b/accel/accel-common.c
index 7b8ec7e0f7..50035bda55 100644
--- a/accel/accel-common.c
+++ b/accel/accel-common.c
@@ -49,6 +49,14 @@ AccelClass *accel_find(const char *opt_name)
 return ac;
 }
 
+/* Return the name of the current accelerator */
+const char *current_accel_name(void)
+{
+AccelClass *ac = ACCEL_GET_CLASS(current_accel());
+
+return ac->name;
+}
+
 static void accel_init_cpu_int_aux(ObjectClass *klass, void *opaque)
 {
 CPUClass *cc = CPU_CLASS(klass);
diff --git a/include/qemu/accel.h b/include/qemu/accel.h
index 4f4c283f6f..be56da1b99 100644
--- a/include/qemu/accel.h
+++ b/include/qemu/accel.h
@@ -68,6 +68,7 @@ typedef struct AccelClass {
 
 AccelClass *accel_find(const char *opt_name);
 AccelState *current_accel(void);
+const char *current_accel_name(void);
 
 void accel_init_interfaces(AccelClass *ac);
 
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 54e920ada1..3dca5936c7 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2271,8 +2271,7 @@ static void configure_accelerators(const char *progname)
 }
 
 if (init_failed && !qtest_chrdev) {
-AccelClass *ac = ACCEL_GET_CLASS(current_accel());
-error_report("falling back to %s", ac->name);
+error_report("falling back to %s", current_accel_name());
 }
 
 if (icount_enabled() && !tcg_enabled()) {
-- 
2.32.1 (Apple Git-133)




[PATCH v2 2/2] target/arm: Catch invalid kvm state also for hvf

2022-06-20 Thread Alexander Graf
Some features such as running in EL3 or running M profile code are
incompatible with virtualization as QEMU implements it today. To prevent
users from picking invalid configurations on other virt solutions like
Hvf, let's run the same checks there too.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1073
Signed-off-by: Alexander Graf 

---

v1 -> v2:

  - Use current_accel_name()
  - Use !tcg_enabled()
---
 target/arm/cpu.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 1b5d535788..0862dcd63c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1490,7 +1490,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (kvm_enabled()) {
+if (!tcg_enabled()) {
 /*
  * Catch all the cases which might cause us to create more than one
  * address space for the CPU (otherwise we will assert() later in
@@ -1498,17 +1498,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error 
**errp)
  */
 if (arm_feature(env, ARM_FEATURE_M)) {
 error_setg(errp,
-   "Cannot enable KVM when using an M-profile guest CPU");
+   "Cannot enable %s when using an M-profile guest CPU",
+   current_accel_name());
 return;
 }
 if (cpu->has_el3) {
 error_setg(errp,
-   "Cannot enable KVM when guest CPU has EL3 enabled");
+   "Cannot enable %s when guest CPU has EL3 enabled",
+   current_accel_name());
 return;
 }
 if (cpu->tag_memory) {
 error_setg(errp,
-   "Cannot enable KVM when guest CPUs has MTE enabled");
+   "Cannot enable %s when guest CPUs has MTE enabled",
+   current_accel_name());
 return;
 }
 }
-- 
2.32.1 (Apple Git-133)




[PATCH v3 50/51] target/arm: Enable SME for user-only

2022-06-20 Thread Richard Henderson
Enable SME, TPIDR2_EL0, and FA64 if supported by the cpu.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5cb9f9f02c..13b008547e 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -209,6 +209,17 @@ static void arm_cpu_reset(DeviceState *dev)
  CPACR_EL1, ZEN, 3);
 env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
 }
+/* and for SME instructions, with default vector length, and TPIDR2 */
+if (cpu_isar_feature(aa64_sme, cpu)) {
+env->cp15.sctlr_el[1] |= SCTLR_EnTP2;
+env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
+ CPACR_EL1, SMEN, 3);
+env->vfp.smcr_el[1] = cpu->sme_default_vq - 1;
+if (cpu_isar_feature(aa64_sme_fa64, cpu)) {
+env->vfp.smcr_el[1] = FIELD_DP64(env->vfp.smcr_el[1],
+ SMCR, FA64, 1);
+}
+}
 /*
  * Enable 48-bit address space (TODO: take reserved_va into account).
  * Enable TBI0 but not TBI1.
-- 
2.34.1




Re: [PATCH 08/10] bsd-user: Implement mkfifo and mkfifoat

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

Signed-off-by: Stacey Son 
Signed-off-by: Warner Losh 
---
  bsd-user/bsd-file.h   | 27 +++
  bsd-user/freebsd/os-syscall.c |  8 
  2 files changed, 35 insertions(+)


Reviewed-by: Richard Henderson 

r~




Re: [PATCH 07/10] bsd-user: Implement chroot and flock

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

Signed-off-by: Stacey Son
Signed-off-by: Warner Losh
---
  bsd-user/bsd-file.h   | 19 +++
  bsd-user/freebsd/os-syscall.c |  8 
  2 files changed, 27 insertions(+)


Reviewed-by: Richard Henderson 

r~



[PATCH v3 49/51] target/arm: Only set ZEN in reset if SVE present

2022-06-20 Thread Richard Henderson
There's no reason to set CPACR_EL1.ZEN if SVE disabled.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 75295a14a3..5cb9f9f02c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -203,11 +203,10 @@ static void arm_cpu_reset(DeviceState *dev)
 /* and to the FP/Neon instructions */
 env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
  CPACR_EL1, FPEN, 3);
-/* and to the SVE instructions */
-env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
- CPACR_EL1, ZEN, 3);
-/* with reasonable vector length */
+/* and to the SVE instructions, with default vector length */
 if (cpu_isar_feature(aa64_sve, cpu)) {
+env->cp15.cpacr_el1 = FIELD_DP64(env->cp15.cpacr_el1,
+ CPACR_EL1, ZEN, 3);
 env->vfp.zcr_el[1] = cpu->sve_default_vq - 1;
 }
 /*
-- 
2.34.1




Re: [PATCH 10/10] bsd-user: Implement undelete

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

Signed-off-by: Stacey Son
Signed-off-by: Warner Losh
---
  bsd-user/bsd-file.h   | 13 +
  bsd-user/freebsd/os-syscall.c |  4 
  2 files changed, 17 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 06/10] bsd-user: Implement chflags, lchflags and fchflags

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

Signed-off-by: Stacey Son
Signed-off-by: Warner Losh
---
  bsd-user/bsd-file.h   | 32 
  bsd-user/freebsd/os-syscall.c | 12 
  2 files changed, 44 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 04/10] bsd-user: Implement freebsd11_mknod, freebsd11_mknodat and mknodat

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

These implement both the old-pre INO64 mknod variations, as well as the
now current INO64 variant. To implement the old stuff, we use some
linker magic to bind to the old versions of these functions.

Signed-off-by: Stacey Son 
Signed-off-by: Michal Meloun 
Signed-off-by: Warner Losh 
---
  bsd-user/bsd-file.h   | 59 +++
  bsd-user/freebsd/os-syscall.c | 15 +
  2 files changed, 74 insertions(+)

diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h
index 0585f6a2a40..3be832b2a74 100644
--- a/bsd-user/bsd-file.h
+++ b/bsd-user/bsd-file.h
@@ -51,6 +51,16 @@ do {\
  unlock_user(p1, arg1, 0);   \
  } while (0)
  
+#ifndef BSD_HAVE_INO64

+#define freebsd11_mknod mknod
+#define freebsd11_mknodat   mknodat
+#else
+int freebsd11_mknod(char *path, mode_t mode, uint32_t dev);
+__sym_compat(mknod, freebsd11_mknod, FBSD_1.0);
+int freebsd11_mknodat(int fd, char *path, mode_t mode, uint32_t dev);
+__sym_compat(mknodat, freebsd11_mknodat, FBSD_1.1);
+#endif


Where does BSD_HAVE_INO64 come from?  I can't find it defined in freebsd git.

You should probably avoid the linker tricks and use direct syscalls of 
SYS_freebsd11_mknodat etc.



r~



[PATCH v3 47/51] linux-user: Rename sve prctls

2022-06-20 Thread Richard Henderson
Add "sve" to the sve prctl functions, to distinguish
them from the coming "sme" prctls with similar names.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_prctl.h |  8 
 linux-user/syscall.c  | 12 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/linux-user/aarch64/target_prctl.h 
b/linux-user/aarch64/target_prctl.h
index 1d440ffbea..40481e6663 100644
--- a/linux-user/aarch64/target_prctl.h
+++ b/linux-user/aarch64/target_prctl.h
@@ -6,7 +6,7 @@
 #ifndef AARCH64_TARGET_PRCTL_H
 #define AARCH64_TARGET_PRCTL_H
 
-static abi_long do_prctl_get_vl(CPUArchState *env)
+static abi_long do_prctl_sve_get_vl(CPUArchState *env)
 {
 ARMCPU *cpu = env_archcpu(env);
 if (cpu_isar_feature(aa64_sve, cpu)) {
@@ -14,9 +14,9 @@ static abi_long do_prctl_get_vl(CPUArchState *env)
 }
 return -TARGET_EINVAL;
 }
-#define do_prctl_get_vl do_prctl_get_vl
+#define do_prctl_sve_get_vl do_prctl_sve_get_vl
 
-static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
+static abi_long do_prctl_sve_set_vl(CPUArchState *env, abi_long arg2)
 {
 /*
  * We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT.
@@ -47,7 +47,7 @@ static abi_long do_prctl_set_vl(CPUArchState *env, abi_long 
arg2)
 }
 return -TARGET_EINVAL;
 }
-#define do_prctl_set_vl do_prctl_set_vl
+#define do_prctl_sve_set_vl do_prctl_sve_set_vl
 
 static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f55cdebee5..a7f41ef0ac 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6365,11 +6365,11 @@ static abi_long do_prctl_inval1(CPUArchState *env, 
abi_long arg2)
 #ifndef do_prctl_set_fp_mode
 #define do_prctl_set_fp_mode do_prctl_inval1
 #endif
-#ifndef do_prctl_get_vl
-#define do_prctl_get_vl do_prctl_inval0
+#ifndef do_prctl_sve_get_vl
+#define do_prctl_sve_get_vl do_prctl_inval0
 #endif
-#ifndef do_prctl_set_vl
-#define do_prctl_set_vl do_prctl_inval1
+#ifndef do_prctl_sve_set_vl
+#define do_prctl_sve_set_vl do_prctl_inval1
 #endif
 #ifndef do_prctl_reset_keys
 #define do_prctl_reset_keys do_prctl_inval1
@@ -6434,9 +6434,9 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
 case PR_SET_FP_MODE:
 return do_prctl_set_fp_mode(env, arg2);
 case PR_SVE_GET_VL:
-return do_prctl_get_vl(env);
+return do_prctl_sve_get_vl(env);
 case PR_SVE_SET_VL:
-return do_prctl_set_vl(env, arg2);
+return do_prctl_sve_set_vl(env, arg2);
 case PR_PAC_RESET_KEYS:
 if (arg3 || arg4 || arg5) {
 return -TARGET_EINVAL;
-- 
2.34.1




Re: [PATCH 0/7] semihosting: proper QEMU exit on semihosted exit syscall

2022-06-20 Thread Luc Michel
On 08:59 Mon 20 Jun , Richard Henderson wrote:
> On 6/20/22 07:24, Luc Michel wrote:
> > Hi,
> > 
> > This series implements a clean way for semihosted exit syscalls to
> > terminate QEMU with a given return code.
> > 
> > Until now, exit syscalls implementations consisted in calling exit()
> > with the wanted return code. The problem with this approach is that
> > other CPUs are not properly stopped, leading to possible crashes in
> > MTTCG mode, especially when at_exit callbacks have been registered. This
> > can be the case e.g., when plugins are in use. Plugins can register
> > at_exit callbacks. Those will be called on the CPU thread the exit
> > syscall is comming from, while other CPUs can continue to run and thus
> > call other plugin callbacks.
> > 
> > The semihosting_exit_request function provides a mean to cleanly
> > terminate QEMU. It introduces an new exit reason
> > (SHUTDOWN_CAUSE_GUEST_SEMI_EXIT) used in this case. The CPU is stopped
> > and returns to the main CPU loop so that no more instruction get
> > executed (the semihosting_exit_request is declared G_NORETURN).
> > 
> > All targets are converted to use this new function.
> 
> Did you test a complete build?  At a glance I would guess that
> arm-linux-user will no longer link because qemu_set/get_exit_status is
> missing.

You are right I forgot to test build *-linux-user. There is a
compilation issue because I forgot "static inline" on the
semihosting_exit_request function on the CONFIG_USER_ONLY side. I'll fix
that in v2.

qemu_set/get_exit_status is fine though as it is only called from
softmmu-only code (and declared in sysemu/sysemu.h).

thanks,
Luc

> 
> 
> r~
> 
> > 
> > Thanks,
> > Luc
> > 
> > Luc Michel (7):
> >softmmu: add qemu_[set|get]_exit_status functions
> >semihosting: add the semihosting_exit_request function
> >semihosting/arm-compat-semi: use semihosting_exit_request
> >target/m68k: use semihosting_exit_request on semihosted exit syscall
> >target/mips: use semihosting_exit_request on semihosted exit syscall
> >target/nios2: use semihosting_exit_request on semihosted exit syscall
> >target/xtensa: use semihosting_exit_request on semihosted exit syscall
> > 
> >   qapi/run-state.json|  4 +++-
> >   include/semihosting/semihost.h |  4 
> >   include/sysemu/sysemu.h|  2 ++
> >   semihosting/arm-compat-semi.c  |  3 +--
> >   semihosting/config.c   | 17 +
> >   softmmu/main.c |  2 +-
> >   softmmu/runstate.c | 11 +++
> >   target/m68k/m68k-semi.c|  4 ++--
> >   target/mips/tcg/sysemu/mips-semi.c |  2 +-
> >   target/nios2/nios2-semi.c  |  4 ++--
> >   target/xtensa/xtensa-semi.c|  2 +-
> >   11 files changed, 45 insertions(+), 10 deletions(-)
> > 
> 
> 
> 
> To declare a filtering error, please use the following link : 
> https://www.security-mail.net/reporter.php?mid=bb16.62b09954.79e61.0=lmichel%40kalray.eu=richard.henderson%40linaro.org=Re%3A+%5BPATCH+0%2F7%5D+semihosting%3A+proper+QEMU+exit+on+semihosted+exit+syscall=C=d52db680df8df28629e4a26f18787c389730fd78
> 

-- 







[PATCH v3 40/51] linux-user/aarch64: Reset PSTATE.SM on syscalls

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/cpu_loop.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index 3b273f6299..4af6996d57 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -89,6 +89,15 @@ void cpu_loop(CPUARMState *env)
 
 switch (trapnr) {
 case EXCP_SWI:
+/*
+ * On syscall, PSTATE.ZA is preserved, along with the ZA matrix.
+ * PSTATE.SM is cleared, per SMSTOP, which does ResetSVEState.
+ */
+if (FIELD_EX64(env->svcr, SVCR, SM)) {
+env->svcr = FIELD_DP64(env->svcr, SVCR, SM, 0);
+arm_rebuild_hflags(env);
+arm_reset_sve_state(env);
+}
 ret = do_syscall(env,
  env->xregs[8],
  env->xregs[0],
-- 
2.34.1




Re: [PATCH v2 3/9] ppc/pnv: use dev->parent_bus->parent to get the PHB

2022-06-20 Thread Daniel Henrique Barboza




On 6/20/22 04:27, Mark Cave-Ayland wrote:

On 18/06/2022 12:01, Daniel Henrique Barboza wrote:


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

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

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

diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c
index 4ba660f8b9..5e7f827415 100644
--- a/hw/pci-host/pnv_phb3.c
+++ b/hw/pci-host/pnv_phb3.c
@@ -1139,12 +1139,16 @@ static void pnv_phb3_root_port_realize(DeviceState 
*dev, Error **errp)
  {
  PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
  PCIDevice *pci = PCI_DEVICE(dev);
-    PCIBus *bus = pci_get_bus(pci);
  PnvPHB3 *phb = NULL;
  Error *local_err = NULL;
-    phb = (PnvPHB3 *) object_dynamic_cast(OBJECT(bus->qbus.parent),
-  TYPE_PNV_PHB3);
+    /*
+ * dev->parent_bus gives access to the pnv-phb-root bus.
+ * The PnvPHB3 is the owner (parent) of the bus.
+ */
+    if (dev->parent_bus) {


Here dev->parent_bus shouldn't be accessed directly: you should use 
qdev_get_parent_bus() instead.


+    phb = PNV_PHB3(dev->parent_bus->parent);
+    }


This one is a bit trickier, since part of the qdev design is that devices should only 
be aware of their immediate bus, and not the device parenting that bus i.e. 
dev->parent_bus->parent shouldn't be allowed.

What is really needed here is to use QOM links (or embed the device as a 
suitable QOM child) to get the PHB reference which I imagine will be changed as 
part of the follow-up series. So I think this can be left as-is for now, and 
fixed later.



In the previous patch (2) I've put the root port as a child of the bus,
giving us this hierarchy:


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


I did it like this instead of the PHB for no particular reason. If the root 
port of
other PHBs are located as a direct child of the PHB I can change it.


All that said, thinking more about it, since I need to access the PHB just
to set "chassis" and "slot" of the device, and I'm already setting a QOM
parent for it, I guess I'll just set that before root_port_realize() and spare 
us
from having to accessing the parent of the parent bus of the root_port.



Thanks,


Daniel




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


I've had a quick look over the rest of the series and from what I can see this 
is definitely heading in the right direction :)


ATB,

Mark.




Re: [PATCH 02/10] bsd-user: Implement symlink, symlinkat, readlink and readlinkat

2022-06-20 Thread Richard Henderson

On 6/20/22 10:42, Warner Losh wrote:

+static abi_long do_bsd_readlink(CPUArchState *env, abi_long arg1,
+abi_long arg2, abi_long arg3)
+{
+abi_long ret;
+void *p1, *p2;
+
+LOCK_PATH(p1, arg1);
+p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+if (p2 == NULL) {
+UNLOCK_PATH(p1, arg1);
+return -TARGET_EFAULT;
+}
+#ifdef __FreeBSD__
+if (strcmp(p1, "/proc/curproc/file") == 0) {
+CPUState *cpu = env_cpu(env);
+TaskState *ts = (TaskState *)cpu->opaque;
+strncpy(p2, ts->bprm->fullpath, arg3);
+ret = MIN((abi_long)strlen(ts->bprm->fullpath), arg3);
+} else
+#endif


Unfortunate ifdef.  Do we really need it while the other bsds are presumably still 
non-functional?  I see that HOST_DEFAULT_BSD_TYPE isn't hooked up either...



r~



[PATCH v3 38/51] target/arm: Enable SME for -cpu max

2022-06-20 Thread Richard Henderson
Note that SME remains effectively disabled for user-only,
because we do not yet set CPACR_EL1.SMEN.  This needs to
wait until the kernel ABI is implemented.

Signed-off-by: Richard Henderson 
---
 docs/system/arm/emulation.rst |  4 
 target/arm/cpu64.c| 11 +++
 2 files changed, 15 insertions(+)

diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 83b4410065..8e494c8bea 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -65,6 +65,10 @@ the following architecture extensions:
 - FEAT_SHA512 (Advanced SIMD SHA512 instructions)
 - FEAT_SM3 (Advanced SIMD SM3 instructions)
 - FEAT_SM4 (Advanced SIMD SM4 instructions)
+- FEAT_SME (Scalable Matrix Extension)
+- FEAT_SME_FA64 (Full A64 instruction set in Streaming SVE mode)
+- FEAT_SME_F64F64 (Double-precision floating-point outer product instructions)
+- FEAT_SME_I16I64 (16-bit to 64-bit integer widening outer product 
instructions)
 - FEAT_SPECRES (Speculation restriction instructions)
 - FEAT_SSBS (Speculative Store Bypass Safe)
 - FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 19188d6cc2..40a0f043d0 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -1018,6 +1018,7 @@ static void aarch64_max_initfn(Object *obj)
  */
 t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3);   /* FEAT_MTE3 */
 t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0);  /* FEAT_RASv1p1 + 
FEAT_DoubleFault */
+t = FIELD_DP64(t, ID_AA64PFR1, SME, 1);   /* FEAT_SME */
 t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
 cpu->isar.id_aa64pfr1 = t;
 
@@ -1068,6 +1069,16 @@ static void aarch64_max_initfn(Object *obj)
 t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5);/* FEAT_PMUv3p4 */
 cpu->isar.id_aa64dfr0 = t;
 
+t = cpu->isar.id_aa64smfr0;
+t = FIELD_DP64(t, ID_AA64SMFR0, F32F32, 1);   /* FEAT_SME */
+t = FIELD_DP64(t, ID_AA64SMFR0, B16F32, 1);   /* FEAT_SME */
+t = FIELD_DP64(t, ID_AA64SMFR0, F16F32, 1);   /* FEAT_SME */
+t = FIELD_DP64(t, ID_AA64SMFR0, I8I32, 0xf);  /* FEAT_SME */
+t = FIELD_DP64(t, ID_AA64SMFR0, F64F64, 1);   /* FEAT_SME_F64F64 */
+t = FIELD_DP64(t, ID_AA64SMFR0, I16I64, 0xf); /* FEAT_SME_I16I64 */
+t = FIELD_DP64(t, ID_AA64SMFR0, FA64, 1); /* FEAT_SME_FA64 */
+cpu->isar.id_aa64smfr0 = t;
+
 /* Replicate the same data to the 32-bit id registers.  */
 aa32_max_features(cpu);
 
-- 
2.34.1




[PATCH v3 35/51] target/arm: Implement REVD

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper-sve.h|  2 ++
 target/arm/sve.decode  |  1 +
 target/arm/sve_helper.c| 16 
 target/arm/translate-sve.c |  2 ++
 4 files changed, 21 insertions(+)

diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
index ab0333400f..cc4e1d8948 100644
--- a/target/arm/helper-sve.h
+++ b/target/arm/helper-sve.h
@@ -719,6 +719,8 @@ DEF_HELPER_FLAGS_4(sve_revh_d, TCG_CALL_NO_RWG, void, ptr, 
ptr, ptr, i32)
 
 DEF_HELPER_FLAGS_4(sve_revw_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 
+DEF_HELPER_FLAGS_4(sme_revd_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
 DEF_HELPER_FLAGS_4(sve_rbit_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(sve_rbit_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(sve_rbit_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
index bf561c270a..d1e229fd6e 100644
--- a/target/arm/sve.decode
+++ b/target/arm/sve.decode
@@ -652,6 +652,7 @@ REVB0101 .. 1001 00 100 ... . . 
@rd_pg_rn
 REVH0101 .. 1001 01 100 ... . . @rd_pg_rn
 REVW0101 .. 1001 10 100 ... . . @rd_pg_rn
 RBIT0101 .. 1001 11 100 ... . . @rd_pg_rn
+REVD0101 00 1011 10 100 ... . . @rd_pg_rn_e0
 
 # SVE vector splice (predicated, destructive)
 SPLICE  0101 .. 101 100 100 ... . . @rdn_pg_rm
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index 9a26f253e0..5de82696b5 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -931,6 +931,22 @@ DO_ZPZ_D(sve_revh_d, uint64_t, hswap64)
 
 DO_ZPZ_D(sve_revw_d, uint64_t, wswap64)
 
+void HELPER(sme_revd_q)(void *vd, void *vn, void *vg, uint32_t desc)
+{
+intptr_t i, opr_sz = simd_oprsz(desc) / 8;
+uint64_t *d = vd, *n = vn;
+uint8_t *pg = vg;
+
+for (i = 0; i < opr_sz; i += 2) {
+if (pg[H1(i)] & 1) {
+uint64_t n0 = n[i + 0];
+uint64_t n1 = n[i + 1];
+d[i + 0] = n1;
+d[i + 1] = n0;
+}
+}
+}
+
 DO_ZPZ(sve_rbit_b, uint8_t, H1, revbit8)
 DO_ZPZ(sve_rbit_h, uint16_t, H1_2, revbit16)
 DO_ZPZ(sve_rbit_s, uint32_t, H1_4, revbit32)
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 58d0894e15..1129f1fc56 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -2896,6 +2896,8 @@ TRANS_FEAT(REVH, aa64_sve, gen_gvec_ool_arg_zpz, 
revh_fns[a->esz], a, 0)
 TRANS_FEAT(REVW, aa64_sve, gen_gvec_ool_arg_zpz,
a->esz == 3 ? gen_helper_sve_revw_d : NULL, a, 0)
 
+TRANS_FEAT(REVD, aa64_sme, gen_gvec_ool_arg_zpz, gen_helper_sme_revd_q, a, 0)
+
 TRANS_FEAT(SPLICE, aa64_sve, gen_gvec_ool_arg_zpzz,
gen_helper_sve_splice, a, a->esz)
 
-- 
2.34.1




[PATCH v3 48/51] linux-user/aarch64: Implement PR_SME_GET_VL, PR_SME_SET_VL

2022-06-20 Thread Richard Henderson
These prctl set the Streaming SVE vector length, which may
be completely different from the Normal SVE vector length.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_prctl.h | 48 +++
 linux-user/syscall.c  | 16 +++
 2 files changed, 64 insertions(+)

diff --git a/linux-user/aarch64/target_prctl.h 
b/linux-user/aarch64/target_prctl.h
index 40481e6663..f8f8f88992 100644
--- a/linux-user/aarch64/target_prctl.h
+++ b/linux-user/aarch64/target_prctl.h
@@ -10,6 +10,7 @@ static abi_long do_prctl_sve_get_vl(CPUArchState *env)
 {
 ARMCPU *cpu = env_archcpu(env);
 if (cpu_isar_feature(aa64_sve, cpu)) {
+/* PSTATE.SM is always unset on syscall entry. */
 return sve_vq(env) * 16;
 }
 return -TARGET_EINVAL;
@@ -27,6 +28,7 @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, 
abi_long arg2)
 && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
 uint32_t vq, old_vq;
 
+/* PSTATE.SM is always unset on syscall entry. */
 old_vq = sve_vq(env);
 
 /*
@@ -49,6 +51,52 @@ static abi_long do_prctl_sve_set_vl(CPUArchState *env, 
abi_long arg2)
 }
 #define do_prctl_sve_set_vl do_prctl_sve_set_vl
 
+static abi_long do_prctl_sme_get_vl(CPUArchState *env)
+{
+ARMCPU *cpu = env_archcpu(env);
+if (cpu_isar_feature(aa64_sme, cpu)) {
+return sme_vq(env) * 16;
+}
+return -TARGET_EINVAL;
+}
+#define do_prctl_sme_get_vl do_prctl_sme_get_vl
+
+static abi_long do_prctl_sme_set_vl(CPUArchState *env, abi_long arg2)
+{
+/*
+ * We cannot support either PR_SME_SET_VL_ONEXEC or PR_SME_VL_INHERIT.
+ * Note the kernel definition of sve_vl_valid allows for VQ=512,
+ * i.e. VL=8192, even though the architectural maximum is VQ=16.
+ */
+if (cpu_isar_feature(aa64_sme, env_archcpu(env))
+&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
+int vq, old_vq;
+
+old_vq = sme_vq(env);
+
+/*
+ * Bound the value of vq, so that we know that it fits into
+ * the 4-bit field in SMCR_EL1.  Because PSTATE.SM is cleared
+ * on syscall entry, we are not modifying the current SVE
+ * vector length.
+ */
+vq = MAX(arg2 / 16, 1);
+vq = MIN(vq, 16);
+env->vfp.smcr_el[1] =
+FIELD_DP64(env->vfp.smcr_el[1], SMCR, LEN, vq - 1);
+vq = sme_vq(env);
+
+if (old_vq != vq) {
+/* PSTATE.ZA state is cleared on any change to VQ. */
+env->svcr = FIELD_DP64(env->svcr, SVCR, ZA, 0);
+arm_rebuild_hflags(env);
+}
+return vq * 16;
+}
+return -TARGET_EINVAL;
+}
+#define do_prctl_sme_set_vl do_prctl_sme_set_vl
+
 static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
 {
 ARMCPU *cpu = env_archcpu(env);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a7f41ef0ac..e8d6e20b85 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6346,6 +6346,12 @@ abi_long do_arch_prctl(CPUX86State *env, int code, 
abi_ulong addr)
 #ifndef PR_SET_SYSCALL_USER_DISPATCH
 # define PR_SET_SYSCALL_USER_DISPATCH 59
 #endif
+#ifndef PR_SME_SET_VL
+# define PR_SME_SET_VL  63
+# define PR_SME_GET_VL  64
+# define PR_SME_VL_LEN_MASK  0x
+# define PR_SME_VL_INHERIT   (1 << 17)
+#endif
 
 #include "target_prctl.h"
 
@@ -6386,6 +6392,12 @@ static abi_long do_prctl_inval1(CPUArchState *env, 
abi_long arg2)
 #ifndef do_prctl_set_unalign
 #define do_prctl_set_unalign do_prctl_inval1
 #endif
+#ifndef do_prctl_sme_get_vl
+#define do_prctl_sme_get_vl do_prctl_inval0
+#endif
+#ifndef do_prctl_sme_set_vl
+#define do_prctl_sme_set_vl do_prctl_inval1
+#endif
 
 static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
  abi_long arg3, abi_long arg4, abi_long arg5)
@@ -6437,6 +6449,10 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
 return do_prctl_sve_get_vl(env);
 case PR_SVE_SET_VL:
 return do_prctl_sve_set_vl(env, arg2);
+case PR_SME_GET_VL:
+return do_prctl_sme_get_vl(env);
+case PR_SME_SET_VL:
+return do_prctl_sme_set_vl(env, arg2);
 case PR_PAC_RESET_KEYS:
 if (arg3 || arg4 || arg5) {
 return -TARGET_EINVAL;
-- 
2.34.1




[PATCH v3 36/51] target/arm: Implement SCLAMP, UCLAMP

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h|  18 +++
 target/arm/sve.decode  |   5 ++
 target/arm/translate-sve.c | 102 +
 target/arm/vec_helper.c|  24 +
 4 files changed, 149 insertions(+)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 3a8ce42ab0..92f36d9dbb 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -1019,6 +1019,24 @@ DEF_HELPER_FLAGS_6(gvec_bfmlal, TCG_CALL_NO_RWG,
 DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, i32)
 
+DEF_HELPER_FLAGS_5(gvec_sclamp_b, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sclamp_h, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sclamp_s, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_sclamp_d, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_5(gvec_uclamp_b, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uclamp_h, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uclamp_s, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_uclamp_d, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
+
 #ifdef TARGET_AARCH64
 #include "helper-a64.h"
 #include "helper-sve.h"
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
index d1e229fd6e..ad411b5790 100644
--- a/target/arm/sve.decode
+++ b/target/arm/sve.decode
@@ -1695,3 +1695,8 @@ PSEL00100101 .. 1 100 .. 01  0  0 
  \
 @psel esz=2 imm=%psel_imm_s
 PSEL00100101 .1 1 000 .. 01  0  0   \
 @psel esz=3 imm=%psel_imm_d
+
+### SVE clamp
+
+SCLAMP  01000100 .. 0 . 11 . .  @rda_rn_rm
+UCLAMP  01000100 .. 0 . 110001 . .  @rda_rn_rm
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 1129f1fc56..40c5bf1a55 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -7438,3 +7438,105 @@ static bool trans_PSEL(DisasContext *s, arg_psel *a)
 tcg_temp_free_ptr(ptr);
 return true;
 }
+
+static void gen_sclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
+{
+tcg_gen_smax_i32(d, a, n);
+tcg_gen_smin_i32(d, d, m);
+}
+
+static void gen_sclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
+{
+tcg_gen_smax_i64(d, a, n);
+tcg_gen_smin_i64(d, d, m);
+}
+
+static void gen_sclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
+   TCGv_vec m, TCGv_vec a)
+{
+tcg_gen_smax_vec(vece, d, a, n);
+tcg_gen_smin_vec(vece, d, d, m);
+}
+
+static void gen_sclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
+   uint32_t a, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop[] = {
+INDEX_op_smin_vec, INDEX_op_smax_vec, 0
+};
+static const GVecGen4 ops[4] = {
+{ .fniv = gen_sclamp_vec,
+  .fno  = gen_helper_gvec_sclamp_b,
+  .opt_opc = vecop,
+  .vece = MO_8 },
+{ .fniv = gen_sclamp_vec,
+  .fno  = gen_helper_gvec_sclamp_h,
+  .opt_opc = vecop,
+  .vece = MO_16 },
+{ .fni4 = gen_sclamp_i32,
+  .fniv = gen_sclamp_vec,
+  .fno  = gen_helper_gvec_sclamp_s,
+  .opt_opc = vecop,
+  .vece = MO_32 },
+{ .fni8 = gen_sclamp_i64,
+  .fniv = gen_sclamp_vec,
+  .fno  = gen_helper_gvec_sclamp_d,
+  .opt_opc = vecop,
+  .vece = MO_64,
+  .prefer_i64 = TCG_TARGET_REG_BITS == 64 }
+};
+tcg_gen_gvec_4(d, n, m, a, oprsz, maxsz, [vece]);
+}
+
+TRANS_FEAT(SCLAMP, aa64_sme, gen_gvec_fn_arg_, gen_sclamp, a)
+
+static void gen_uclamp_i32(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m, TCGv_i32 a)
+{
+tcg_gen_umax_i32(d, a, n);
+tcg_gen_umin_i32(d, d, m);
+}
+
+static void gen_uclamp_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m, TCGv_i64 a)
+{
+tcg_gen_umax_i64(d, a, n);
+tcg_gen_umin_i64(d, d, m);
+}
+
+static void gen_uclamp_vec(unsigned vece, TCGv_vec d, TCGv_vec n,
+   TCGv_vec m, TCGv_vec a)
+{
+tcg_gen_umax_vec(vece, d, a, n);
+tcg_gen_umin_vec(vece, d, d, m);
+}
+
+static void gen_uclamp(unsigned vece, uint32_t d, uint32_t n, uint32_t m,
+   uint32_t a, uint32_t oprsz, uint32_t maxsz)
+{
+static const TCGOpcode vecop[] = {
+INDEX_op_umin_vec, INDEX_op_umax_vec, 0
+};
+static const GVecGen4 ops[4] = {
+{ .fniv = gen_uclamp_vec,
+  .fno  = gen_helper_gvec_uclamp_b,
+  .opt_opc = vecop,
+  .vece = MO_8 },
+{ .fniv = gen_uclamp_vec,
+  .fno  = gen_helper_gvec_uclamp_h,
+  .opt_opc = vecop,
+  .vece = MO_16 },
+  

[PATCH v3 44/51] linux-user/aarch64: Verify extra record lock succeeded

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/signal.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index 8fbe98d72f..9ff79da4be 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -340,6 +340,9 @@ static int target_restore_sigframe(CPUARMState *env,
 __get_user(extra_size,
&((struct target_extra_context *)ctx)->size);
 extra = lock_user(VERIFY_READ, extra_datap, extra_size, 0);
+if (!extra) {
+return 1;
+}
 break;
 
 default:
-- 
2.34.1




Re: [PATCH v5 4/5] i386/pc: relocate 4g start to 1T where applicable

2022-06-20 Thread Joao Martins
On 6/20/22 17:36, Joao Martins wrote:
> On 6/20/22 15:27, Igor Mammedov wrote:
>> On Fri, 17 Jun 2022 14:33:02 +0100
>> Joao Martins  wrote:
>>> On 6/17/22 13:32, Igor Mammedov wrote:
 On Fri, 17 Jun 2022 13:18:38 +0100
 Joao Martins  wrote:  
> On 6/16/22 15:23, Igor Mammedov wrote:  
>> On Fri, 20 May 2022 11:45:31 +0100
>> Joao Martins  wrote:  
>>> +hwaddr above_4g_mem_start,
>>> +uint64_t pci_hole64_size)
>>> +{
>>> +PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
>>> +X86MachineState *x86ms = X86_MACHINE(pcms);
>>> +MachineState *machine = MACHINE(pcms);
>>> +ram_addr_t device_mem_size = 0;
>>> +hwaddr base;
>>> +
>>> +if (!x86ms->above_4g_mem_size) {
>>> +   /*
>>> +* 32-bit pci hole goes from
>>> +* end-of-low-ram (@below_4g_mem_size) to IOAPIC.
>>> +*/
>>> +return IO_APIC_DEFAULT_ADDRESS - 1;
>>
>> lack of above_4g_mem, doesn't mean absence of device_mem_size or 
>> anything else
>> that's located above it.
>> 
>
> True. But the intent is to fix 32-bit boundaries as one of the qtests was 
> failing
> otherwise. We won't hit the 1T hole, hence a nop.  

 I don't get the reasoning, can you clarify it pls?
   
>>>
>>> I was trying to say that what lead me here was a couple of qtests failures 
>>> (from v3->v4).
>>>
>>> I was doing this before based on pci_hole64. phys-bits=32 was for example 
>>> one
>>> of the test failures, and pci-hole64 sits above what 32-bit can reference.
>>
>> if user sets phys-bits=32, then nothing above 4Gb should work (be usable)
>> (including above-4g-ram, hotplug region or pci64 hole or sgx or cxl)
>>
>> and this doesn't look to me as AMD specific issue
>>
>> perhaps do a phys-bits check as a separate patch
>> that will error out if max_used_gpa is above phys-bits limit
>> (maybe at machine_done time)
>> (i.e. defining max_gpa and checking if compatible with configured cpu
>> are 2 different things)
>>
>> (it might be possible that tests need to be fixed too to account for it)
>>
> 
> My old notes (from v3) tell me with such a check these tests were exiting 
> early thanks to
> that error:
> 
>  1/56 qemu:qtest+qtest-x86_64 / qtest-x86_64/qom-test   ERROR 
>   0.07s
>   killed by signal 6 SIGABRT
>  4/56 qemu:qtest+qtest-x86_64 / qtest-x86_64/test-hmp   ERROR 
>   0.07s
>   killed by signal 6 SIGABRT
>  7/56 qemu:qtest+qtest-x86_64 / qtest-x86_64/boot-serial-test   ERROR 
>   0.07s
>   killed by signal 6 SIGABRT
> 44/56 qemu:qtest+qtest-x86_64 / qtest-x86_64/test-x86-cpuid-compat  ERROR 
>   0.09s
>   killed by signal 6 SIGABRT
> 45/56 qemu:qtest+qtest-x86_64 / qtest-x86_64/numa-test  ERROR 
>   0.17s
>   killed by signal 6 SIGABRT
> 
> But the real reason these fail is not at all related to CPU phys bits,
> but because we just don't handle the case where no pci_hole64 is supposed to 
> exist (which
> is what that other check is trying to do) e.g. A VM with -m 1G would
> observe the same thing i.e. the computations after that conditional are all 
> for the pci
> hole64, which acounts for SGX/CXL/hotplug or etc which consequently means 
> it's *errousnly*
> bigger than phys-bits=32 (by definition). So the error_report is just telling 
> me that
> pc_max_used_gpa() is just incorrect without the !x86ms->above_4g_mem_size 
> check.
> 
> If you're not fond of:
> 
> +if (!x86ms->above_4g_mem_size) {
> +   /*
> +* 32-bit pci hole goes from
> +* end-of-low-ram (@below_4g_mem_size) to IOAPIC.
> + */
> +return IO_APIC_DEFAULT_ADDRESS - 1;
> +}
> 
> Then what should I use instead of the above?
> 
> 'IO_APIC_DEFAULT_ADDRESS - 1' is the size of the 32-bit PCI hole, which is
> also what is used for i440fx/q35 code. I could move it to a macro (e.g.
> PCI_HOST_HOLE32_SIZE) to make it a bit readable and less hardcoded. Or
> perhaps your problem is on !x86ms->above_4g_mem_size and maybe I should check
> in addition for hotplug/CXL/etc existence?
> 
>  Unless we plan on using
> pc_max_used_gpa() for something else other than this.  

 Even if '!above_4g_mem_sizem', we can still have hotpluggable memory region
 present and that can  hit 1Tb. The same goes for pci64_hole if it's 
 configured
 large enough on CLI.
   
>>> So hotpluggable memory seems to assume it sits above 4g mem.
>>>
>>> pci_hole64 likewise as it uses similar computations as hotplug.
>>>
>>> Unless I am misunderstanding something here.
>>>
 Looks like guesstimate we could use is taking pci64_hole_end as max used 
 GPA
   
>>> I think this was what I had before (v3[0]) and did not work.
>>
>> that had been tied to host's phys-bits directly, all in one patch
>> and duplicating existing 

[PATCH v3 30/51] target/arm: Implement FMOPA, FMOPS (non-widening)

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h|  5 +++
 target/arm/sme.decode  |  9 +
 target/arm/sme_helper.c| 67 ++
 target/arm/translate-sme.c | 33 +++
 4 files changed, 114 insertions(+)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index 6f0fce7e2c..727095a3eb 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -119,3 +119,8 @@ DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, 
ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index 8cb6c4053c..ba4774d174 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -64,3 +64,12 @@ ADDHA_s 1100 10 01000 0 ... ... . 000 .. 
   @adda_32
 ADDVA_s 1100 10 01000 1 ... ... . 000 ..@adda_32
 ADDHA_d 1100 11 01000 0 ... ... . 00 ...@adda_64
 ADDVA_d 1100 11 01000 1 ... ... . 00 ...@adda_64
+
+### SME Outer Product
+
+ zad zn zm pm pn sub:bool
+@op_32   ... zm:5 pm:3 pn:3 zn:5 sub:1 .. zad:2 
+@op_64   ... zm:5 pm:3 pn:3 zn:5 sub:1 .  zad:3 
+
+FMOPA_s 1000 100 . ... ... . . 00 ..@op_32
+FMOPA_d 1000 110 . ... ... . . 0 ...@op_64
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
index 799e44c047..62d9690cae 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/sme_helper.c
@@ -25,6 +25,7 @@
 #include "exec/cpu_ldst.h"
 #include "exec/exec-all.h"
 #include "qemu/int128.h"
+#include "fpu/softfloat.h"
 #include "vec_internal.h"
 #include "sve_ldst_internal.h"
 
@@ -897,3 +898,69 @@ void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
 }
 }
 }
+
+void HELPER(sme_fmopa_s)(void *vza, void *vzn, void *vzm, void *vpn,
+ void *vpm, void *vst, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_maxsz(desc);
+uint32_t neg = simd_data(desc) << 31;
+uint16_t *pn = vpn, *pm = vpm;
+
+bool save_dn = get_default_nan_mode(vst);
+set_default_nan_mode(true, vst);
+
+for (row = 0; row < oprsz; ) {
+uint16_t pa = pn[H2(row >> 4)];
+do {
+if (pa & 1) {
+void *vza_row = vza + row * sizeof(ARMVectorReg);
+uint32_t n = *(uint32_t *)(vzn + row) ^ neg;
+
+for (col = 0; col < oprsz; ) {
+uint16_t pb = pm[H2(col >> 4)];
+do {
+if (pb & 1) {
+uint32_t *a = vza_row + col;
+uint32_t *m = vzm + col;
+*a = float32_muladd(n, *m, *a, 0, vst);
+}
+col += 4;
+pb >>= 4;
+} while (col & 15);
+}
+}
+row += 4;
+pa >>= 4;
+} while (row & 15);
+}
+
+set_default_nan_mode(save_dn, vst);
+}
+
+void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, void *vpn,
+ void *vpm, void *vst, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
+uint64_t neg = (uint64_t)simd_data(desc) << 63;
+uint64_t *za = vza, *zn = vzn, *zm = vzm;
+uint8_t *pn = vpn, *pm = vpm;
+
+bool save_dn = get_default_nan_mode(vst);
+set_default_nan_mode(true, vst);
+
+for (row = 0; row < oprsz; ++row) {
+if (pn[H1(row)] & 1) {
+uint64_t *za_row = [row * sizeof(ARMVectorReg)];
+uint64_t n = zn[row] ^ neg;
+
+for (col = 0; col < oprsz; ++col) {
+if (pm[H1(col)] & 1) {
+uint64_t *a = _row[col];
+*a = float64_muladd(n, zm[col], *a, 0, vst);
+}
+}
+}
+}
+
+set_default_nan_mode(save_dn, vst);
+}
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
index e9676b2415..e6e4541e76 100644
--- a/target/arm/translate-sme.c
+++ b/target/arm/translate-sme.c
@@ -273,3 +273,36 @@ TRANS_FEAT(ADDHA_s, aa64_sme, do_adda, a, MO_32, 
gen_helper_sme_addha_s)
 TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, gen_helper_sme_addva_s)
 TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
 TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
+
+static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
+   

[PATCH v3 33/51] target/arm: Implement SME integer outer product

2022-06-20 Thread Richard Henderson
This is SMOPA, SUMOPA, USMOPA_s, UMOPA, for both Int8 and Int16.

Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h| 16 
 target/arm/sme.decode  | 10 +
 target/arm/sme_helper.c| 82 ++
 target/arm/translate-sme.c | 14 +++
 4 files changed, 122 insertions(+)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index ecc957be14..31562551ee 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -128,3 +128,19 @@ DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_smopa_s, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_umopa_s, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_sumopa_s, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_usmopa_s, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_smopa_d, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_umopa_d, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_sumopa_d, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_usmopa_d, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index e8d27fd8a0..628804e37a 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -76,3 +76,13 @@ FMOPA_d 1000 110 . ... ... . . 0 ... 
   @op_64
 
 BFMOPA  1001 100 . ... ... . . 00 ..@op_32
 FMOPA_h 1001 101 . ... ... . . 00 ..@op_32
+
+SMOPA_s 101 0 10 0 . ... ... . . 00 ..  @op_32
+SUMOPA_s101 0 10 1 . ... ... . . 00 ..  @op_32
+USMOPA_s101 1 10 0 . ... ... . . 00 ..  @op_32
+UMOPA_s 101 1 10 1 . ... ... . . 00 ..  @op_32
+
+SMOPA_d 101 0 11 0 . ... ... . . 0 ...  @op_64
+SUMOPA_d101 0 11 1 . ... ... . . 0 ...  @op_64
+USMOPA_d101 1 11 0 . ... ... . . 0 ...  @op_64
+UMOPA_d 101 1 11 1 . ... ... . . 0 ...  @op_64
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
index 6863a204d4..f1c7e6ae56 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/sme_helper.c
@@ -1090,3 +1090,85 @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, 
void *vpn,
 } while (row & 15);
 }
 }
+
+typedef uint64_t IMOPFn(uint64_t, uint64_t, uint64_t, uint8_t, bool);
+
+static inline void do_imopa(uint64_t *za, uint64_t *zn, uint64_t *zm,
+uint8_t *pn, uint8_t *pm,
+uint32_t desc, IMOPFn *fn)
+{
+intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
+bool neg = simd_data(desc);
+
+for (row = 0; row < oprsz; ++row) {
+uint8_t pa = pn[H1(row)];
+uint64_t *za_row = [row * sizeof(ARMVectorReg)];
+uint64_t n = zn[row];
+
+for (col = 0; col < oprsz; ++col) {
+uint8_t pb = pm[H1(col)];
+uint64_t *a = _row[col];
+
+*a = fn(n, zm[col], *a, pa & pb, neg);
+}
+}
+}
+
+#define DEF_IMOP_32(NAME, NTYPE, MTYPE) \
+static uint64_t NAME(uint64_t n, uint64_t m, uint64_t a, uint8_t p, bool neg) \
+{   \
+uint32_t sum0 = 0, sum1 = 0;\
+/* Apply P to N as a mask, making the inactive elements 0. */   \
+n &= expand_pred_b(p);  \
+sum0 += (NTYPE)(n >> 0) * (MTYPE)(m >> 0);  \
+sum0 += (NTYPE)(n >> 8) * (MTYPE)(m >> 8);  \
+sum0 += (NTYPE)(n >> 16) * (MTYPE)(m >> 16);\
+sum0 += (NTYPE)(n >> 24) * (MTYPE)(m >> 24);\
+sum1 += (NTYPE)(n >> 32) * (MTYPE)(m >> 32);\
+sum1 += (NTYPE)(n >> 40) * (MTYPE)(m >> 40);\
+sum1 += (NTYPE)(n >> 48) * (MTYPE)(m >> 48);\
+sum1 += (NTYPE)(n >> 56) * (MTYPE)(m >> 56);\
+if (neg) {  \
+sum0 = (uint32_t)a - sum0, sum1 = (uint32_t)(a >> 32) - sum1;   \
+} else {\
+sum0 = (uint32_t)a + sum0, sum1 = (uint32_t)(a >> 32) + sum1;   \
+}  

[PATCH v3 26/51] target/arm: Implement SME LD1, ST1

2022-06-20 Thread Richard Henderson
We cannot reuse the SVE functions for LD[1-4] and ST[1-4],
because those functions accept only a Zreg register number.
For SME, we want to pass a pointer into ZA storage.

Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h|  82 +
 target/arm/sme.decode  |   9 +
 target/arm/sme_helper.c| 615 +
 target/arm/translate-sme.c |  69 +
 4 files changed, 775 insertions(+)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index 600346e08c..5cca01f372 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -32,3 +32,85 @@ DEF_HELPER_FLAGS_4(sme_mova_avz_d, TCG_CALL_NO_RWG, void, 
ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(sme_mova_zav_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(sme_mova_avz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(sme_mova_zav_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_5(sme_ld1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1s_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1s_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1s_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1s_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1d_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1d_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1d_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1d_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_ld1q_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_ld1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_st1b_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_st1b_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_st1b_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_st1b_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_st1h_be_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_st1h_le_h, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_st1h_be_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_st1h_le_v, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, i32)
+DEF_HELPER_FLAGS_5(sme_st1h_be_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_st1h_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_st1h_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+DEF_HELPER_FLAGS_5(sme_st1h_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_st1s_be_h, TCG_CALL_NO_WG, void, env, ptr, 

[PATCH v3 39/51] linux-user/aarch64: Clear tpidr2_el0 if CLONE_SETTLS

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h
index 97a477bd3e..f90359faf2 100644
--- a/linux-user/aarch64/target_cpu.h
+++ b/linux-user/aarch64/target_cpu.h
@@ -34,10 +34,13 @@ static inline void cpu_clone_regs_parent(CPUARMState *env, 
unsigned flags)
 
 static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls)
 {
-/* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
+/*
+ * Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is
  * different from AArch32 Linux, which uses TPIDRRO.
  */
 env->cp15.tpidr_el[0] = newtls;
+/* TPIDR2_EL0 is cleared with CLONE_SETTLS. */
+env->cp15.tpidr2_el0 = 0;
 }
 
 static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
-- 
2.34.1




[PATCH v3 45/51] linux-user/aarch64: Move sve record checks into restore

2022-06-20 Thread Richard Henderson
Move the checks out of the parsing loop and into the
restore function.  This more closely mirrors the code
structure in the kernel, and is slightly clearer.

Reject rather than silently skip incorrect VL and SVE record sizes.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/signal.c | 51 +
 1 file changed, 35 insertions(+), 16 deletions(-)

diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index 9ff79da4be..22d0b8b4ec 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -250,12 +250,36 @@ static void target_restore_fpsimd_record(CPUARMState *env,
 }
 }
 
-static void target_restore_sve_record(CPUARMState *env,
-  struct target_sve_context *sve, int vq)
+static bool target_restore_sve_record(CPUARMState *env,
+  struct target_sve_context *sve,
+  int size)
 {
-int i, j;
+int i, j, vl, vq;
 
-/* Note that SVE regs are stored as a byte stream, with each byte element
+if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
+return false;
+}
+
+__get_user(vl, >vl);
+vq = sve_vq(env);
+
+/* Reject mismatched VL. */
+if (vl != vq * TARGET_SVE_VQ_BYTES) {
+return false;
+}
+
+/* Accept empty record -- used to clear PSTATE.SM. */
+if (size <= sizeof(*sve)) {
+return true;
+}
+
+/* Reject non-empty but incomplete record. */
+if (size < TARGET_SVE_SIG_CONTEXT_SIZE(vq)) {
+return false;
+}
+
+/*
+ * Note that SVE regs are stored as a byte stream, with each byte element
  * at a subsequent address.  This corresponds to a little-endian load
  * of our 64-bit hunks.
  */
@@ -277,6 +301,7 @@ static void target_restore_sve_record(CPUARMState *env,
 }
 }
 }
+return true;
 }
 
 static int target_restore_sigframe(CPUARMState *env,
@@ -287,7 +312,7 @@ static int target_restore_sigframe(CPUARMState *env,
 struct target_sve_context *sve = NULL;
 uint64_t extra_datap = 0;
 bool used_extra = false;
-int vq = 0, sve_size = 0;
+int sve_size = 0;
 
 target_restore_general_frame(env, sf);
 
@@ -321,15 +346,9 @@ static int target_restore_sigframe(CPUARMState *env,
 if (sve || size < sizeof(struct target_sve_context)) {
 goto err;
 }
-if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
-vq = sve_vq(env);
-sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
-if (size == sve_size) {
-sve = (struct target_sve_context *)ctx;
-break;
-}
-}
-goto err;
+sve = (struct target_sve_context *)ctx;
+sve_size = size;
+break;
 
 case TARGET_EXTRA_MAGIC:
 if (extra || size != sizeof(struct target_extra_context)) {
@@ -362,8 +381,8 @@ static int target_restore_sigframe(CPUARMState *env,
 }
 
 /* SVE data, if present, overwrites FPSIMD data.  */
-if (sve) {
-target_restore_sve_record(env, sve, vq);
+if (sve && !target_restore_sve_record(env, sve, sve_size)) {
+goto err;
 }
 unlock_user(extra, extra_datap, 0);
 return 0;
-- 
2.34.1




[PATCH v3 51/51] linux-user/aarch64: Add SME related hwcap entries

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 linux-user/elfload.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f7eae357f4..8135960305 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -601,6 +601,18 @@ enum {
 ARM_HWCAP2_A64_RNG  = 1 << 16,
 ARM_HWCAP2_A64_BTI  = 1 << 17,
 ARM_HWCAP2_A64_MTE  = 1 << 18,
+ARM_HWCAP2_A64_ECV  = 1 << 19,
+ARM_HWCAP2_A64_AFP  = 1 << 20,
+ARM_HWCAP2_A64_RPRES= 1 << 21,
+ARM_HWCAP2_A64_MTE3 = 1 << 22,
+ARM_HWCAP2_A64_SME  = 1 << 23,
+ARM_HWCAP2_A64_SME_I16I64   = 1 << 24,
+ARM_HWCAP2_A64_SME_F64F64   = 1 << 25,
+ARM_HWCAP2_A64_SME_I8I32= 1 << 26,
+ARM_HWCAP2_A64_SME_F16F32   = 1 << 27,
+ARM_HWCAP2_A64_SME_B16F32   = 1 << 28,
+ARM_HWCAP2_A64_SME_F32F32   = 1 << 29,
+ARM_HWCAP2_A64_SME_FA64 = 1 << 30,
 };
 
 #define ELF_HWCAP   get_elf_hwcap()
@@ -670,6 +682,14 @@ static uint32_t get_elf_hwcap2(void)
 GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
 GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
 GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
+GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME |
+  ARM_HWCAP2_A64_SME_F32F32 |
+  ARM_HWCAP2_A64_SME_B16F32 |
+  ARM_HWCAP2_A64_SME_F16F32 |
+  ARM_HWCAP2_A64_SME_I8I32));
+GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
+GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
+GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
 
 return hwcaps;
 }
-- 
2.34.1




[PATCH v3 42/51] linux-user/aarch64: Tidy target_restore_sigframe error return

2022-06-20 Thread Richard Henderson
Fold the return value setting into the goto, so each
point of failure need not do both.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/signal.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index 3cef2f44cf..8b352abb97 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -287,7 +287,6 @@ static int target_restore_sigframe(CPUARMState *env,
 struct target_sve_context *sve = NULL;
 uint64_t extra_datap = 0;
 bool used_extra = false;
-bool err = false;
 int vq = 0, sve_size = 0;
 
 target_restore_general_frame(env, sf);
@@ -301,8 +300,7 @@ static int target_restore_sigframe(CPUARMState *env,
 switch (magic) {
 case 0:
 if (size != 0) {
-err = true;
-goto exit;
+goto err;
 }
 if (used_extra) {
 ctx = NULL;
@@ -314,8 +312,7 @@ static int target_restore_sigframe(CPUARMState *env,
 
 case TARGET_FPSIMD_MAGIC:
 if (fpsimd || size != sizeof(struct target_fpsimd_context)) {
-err = true;
-goto exit;
+goto err;
 }
 fpsimd = (struct target_fpsimd_context *)ctx;
 break;
@@ -329,13 +326,11 @@ static int target_restore_sigframe(CPUARMState *env,
 break;
 }
 }
-err = true;
-goto exit;
+goto err;
 
 case TARGET_EXTRA_MAGIC:
 if (extra || size != sizeof(struct target_extra_context)) {
-err = true;
-goto exit;
+goto err;
 }
 __get_user(extra_datap,
&((struct target_extra_context *)ctx)->datap);
@@ -348,8 +343,7 @@ static int target_restore_sigframe(CPUARMState *env,
 /* Unknown record -- we certainly didn't generate it.
  * Did we in fact get out of sync?
  */
-err = true;
-goto exit;
+goto err;
 }
 ctx = (void *)ctx + size;
 }
@@ -358,17 +352,19 @@ static int target_restore_sigframe(CPUARMState *env,
 if (fpsimd) {
 target_restore_fpsimd_record(env, fpsimd);
 } else {
-err = true;
+goto err;
 }
 
 /* SVE data, if present, overwrites FPSIMD data.  */
 if (sve) {
 target_restore_sve_record(env, sve, vq);
 }
-
- exit:
 unlock_user(extra, extra_datap, 0);
-return err;
+return 0;
+
+ err:
+unlock_user(extra, extra_datap, 0);
+return 1;
 }
 
 static abi_ulong get_sigframe(struct target_sigaction *ka,
-- 
2.34.1




[PATCH v3 28/51] target/arm: Implement SME LDR, STR

2022-06-20 Thread Richard Henderson
We can reuse the SVE functions for LDR and STR, passing in the
base of the ZA vector and a zero offset.

Signed-off-by: Richard Henderson 
---
 target/arm/sme.decode  |  7 +++
 target/arm/translate-sme.c | 23 +++
 2 files changed, 30 insertions(+)

diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index 900e3f2a07..f1ebd857a5 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -46,3 +46,10 @@ LDST1   111 0 esz:2 st:1 rm:5 v:1 .. pg:3 rn:5 0 
za_imm:4  \
  rs=%mova_rs
 LDST1   111 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 za_imm:4  \
  esz=4 rs=%mova_rs
+
+  rv rn imm
+@ldstr  ... ... . .. .. ... rn:5 . imm:4 \
+ rv=%mova_rs
+
+LDR 111 100 0 00 .. 000 . 0 @ldstr
+STR 111 100 1 00 .. 000 . 0 @ldstr
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
index 978af74d1d..c3e544d69c 100644
--- a/target/arm/translate-sme.c
+++ b/target/arm/translate-sme.c
@@ -220,3 +220,26 @@ static bool trans_LDST1(DisasContext *s, arg_LDST1 *a)
 tcg_temp_free_i64(addr);
 return true;
 }
+
+typedef void GenLdStR(DisasContext *, TCGv_ptr, int, int, int, int);
+
+static bool do_ldst_r(DisasContext *s, arg_ldstr *a, GenLdStR *fn)
+{
+int imm = a->imm;
+TCGv_ptr base;
+
+if (!sme_za_enabled_check(s)) {
+return true;
+}
+
+/* ZA[n] equates to ZA0H.B[n]. */
+base = get_tile_rowcol(s, MO_8, a->rv, imm, false);
+
+fn(s, base, 0, s->svl, a->rn, imm * s->svl);
+
+tcg_temp_free_ptr(base);
+return true;
+}
+
+TRANS_FEAT(LDR, aa64_sme, do_ldst_r, a, gen_sve_ldr)
+TRANS_FEAT(STR, aa64_sme, do_ldst_r, a, gen_sve_str)
-- 
2.34.1




[PATCH v3 22/51] target/arm: Trap AdvSIMD usage when Streaming SVE is active

2022-06-20 Thread Richard Henderson
This new behaviour is in the ARM pseudocode function
AArch64.CheckFPAdvSIMDEnabled, which applies to AArch32
via AArch32.CheckAdvSIMDOrFPEnabled when the EL to which
the trap would be delivered is in AArch64 mode.

Given that ARMv9 drops support for AArch32 outside EL0,
the trap EL detection ought to be trivially true, but
the pseudocode still contains a number of conditions,
and QEMU has not yet committed to dropping A32 support
for EL[12] when v9 features are present.

Since the computation of SME_TRAP_SIMD is necessarily
different for the two modes, we might as well preserve
bits within TBFLAG_ANY and allocate separate bits within
TBFLAG_A32 and TBFLAG_A64 instead.

Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   |  6 +++
 target/arm/translate.h |  3 ++
 target/arm/sme-fa64.decode | 89 ++
 target/arm/helper.c| 42 ++
 target/arm/translate-a64.c | 40 -
 target/arm/translate-vfp.c | 12 +
 target/arm/translate.c |  1 +
 target/arm/meson.build |  1 +
 8 files changed, 192 insertions(+), 2 deletions(-)
 create mode 100644 target/arm/sme-fa64.decode

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 068877323c..da1c036fa0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3132,6 +3132,11 @@ FIELD(TBFLAG_A32, HSTR_ACTIVE, 9, 1)
  * the same thing as the current security state of the processor!
  */
 FIELD(TBFLAG_A32, NS, 10, 1)
+/*
+ * Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not.
+ * This requires an SME trap from AArch32 mode when using NEON.
+ */
+FIELD(TBFLAG_A32, SME_TRAP_SIMD, 11, 1)
 
 /*
  * Bit usage when in AArch32 state, for M-profile only.
@@ -3169,6 +3174,7 @@ FIELD(TBFLAG_A64, SMEEXC_EL, 20, 2)
 FIELD(TBFLAG_A64, PSTATE_SM, 22, 1)
 FIELD(TBFLAG_A64, PSTATE_ZA, 23, 1)
 FIELD(TBFLAG_A64, SVL, 24, 4)
+FIELD(TBFLAG_A64, SME_TRAP_SIMD, 28, 1)
 
 /*
  * Helpers for using the above.
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 22fd882368..ef158a75c6 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -102,6 +102,9 @@ typedef struct DisasContext {
 bool pstate_sm;
 /* True if PSTATE.ZA is set. */
 bool pstate_za;
+/* True if AdvSIMD insns should raise an SME Streaming exception. */
+bool sme_trap_simd;
+bool sme_trap_this_insn;
 /* True if MVE insns are definitely not predicated by VPR or LTPSIZE */
 bool mve_no_pred;
 /*
diff --git a/target/arm/sme-fa64.decode b/target/arm/sme-fa64.decode
new file mode 100644
index 00..4c2569477d
--- /dev/null
+++ b/target/arm/sme-fa64.decode
@@ -0,0 +1,89 @@
+# AArch64 SME allowed instruction decoding
+#
+#  Copyright (c) 2022 Linaro, Ltd
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see .
+
+#
+# This file is processed by scripts/decodetree.py
+#
+
+# These patterns are taken from Appendix E1.1 of DDI0616 A.a,
+# Arm Architecture Reference Manual Supplement,
+# The Scalable Matrix Extension (SME), for Armv9-A
+
+{
+  [
+OK  0-00 1110  0001 0010 11--     # SMOV W|Xd,Vn.B[0]
+OK  0-00 1110  0010 0010 11--     # SMOV W|Xd,Vn.H[0]
+OK  0100 1110  0100 0010 11--     # SMOV Xd,Vn.S[0]
+OK   1110  0001 0011 11--     # UMOV Wd,Vn.B[0]
+OK   1110  0010 0011 11--     # UMOV Wd,Vn.H[0]
+OK   1110  0100 0011 11--     # UMOV Wd,Vn.S[0]
+OK  0100 1110  1000 0011 11--     # UMOV Xd,Vn.D[0]
+  ]
+  FAIL  0--0 111-         # Advanced SIMD vector 
operations
+}
+
+{
+  [
+OK  0101 1110 --1-  11-1 11--     # FMULX/FRECPS/FRSQRTS 
(scalar)
+OK  0101 1110 -10-  00-1 11--     # FMULX/FRECPS/FRSQRTS 
(scalar, FP16)
+OK  01-1 1110 1-10 0001 11-1 10--     # FRECPE/FRSQRTE/FRECPX 
(scalar)
+OK  01-1 1110  1001 11-1 10--     # FRECPE/FRSQRTE/FRECPX 
(scalar, FP16)
+  ]
+  FAIL  01-1 111-         # Advanced SIMD 
single-element operations
+}
+
+FAIL0-00 110-         # Advanced SIMD structure 
load/store
+FAIL1100 1110         # Advanced SIMD cryptography 
extensions
+
+# These are the "avoidance of doubt" final table of Illegal Advanced SIMD 
instructions
+# We don't actually need 

[PATCH v3 46/51] linux-user/aarch64: Implement SME signal handling

2022-06-20 Thread Richard Henderson
Set the SM bit in the SVE record on signal delivery, create the ZA record.
Restore SM and ZA state according to the records present on return.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/signal.c | 162 +---
 1 file changed, 151 insertions(+), 11 deletions(-)

diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index 22d0b8b4ec..1ad125d3d9 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -104,6 +104,22 @@ struct target_sve_context {
 
 #define TARGET_SVE_SIG_FLAG_SM  1
 
+#define TARGET_ZA_MAGIC0x54366345
+
+struct target_za_context {
+struct target_aarch64_ctx head;
+uint16_t vl;
+uint16_t reserved[3];
+/* The actual ZA data immediately follows. */
+};
+
+#define TARGET_ZA_SIG_REGS_OFFSET \
+QEMU_ALIGN_UP(sizeof(struct target_za_context), TARGET_SVE_VQ_BYTES)
+#define TARGET_ZA_SIG_ZAV_OFFSET(VQ, N) \
+(TARGET_ZA_SIG_REGS_OFFSET + (VQ) * TARGET_SVE_VQ_BYTES * (N))
+#define TARGET_ZA_SIG_CONTEXT_SIZE(VQ) \
+TARGET_ZA_SIG_ZAV_OFFSET(VQ, VQ * TARGET_SVE_VQ_BYTES)
+
 struct target_rt_sigframe {
 struct target_siginfo info;
 struct target_ucontext uc;
@@ -176,9 +192,9 @@ static void target_setup_end_record(struct 
target_aarch64_ctx *end)
 }
 
 static void target_setup_sve_record(struct target_sve_context *sve,
-CPUARMState *env, int vq, int size)
+CPUARMState *env, int size)
 {
-int i, j;
+int i, j, vq = sme_vq(env);
 
 memset(sve, 0, sizeof(*sve));
 __put_user(TARGET_SVE_MAGIC, >head.magic);
@@ -207,6 +223,34 @@ static void target_setup_sve_record(struct 
target_sve_context *sve,
 }
 }
 
+static void target_setup_za_record(struct target_za_context *za,
+   CPUARMState *env, int size)
+{
+int vq = sme_vq(env);
+int vl = vq * TARGET_SVE_VQ_BYTES;
+int i, j;
+
+memset(za, 0, sizeof(*za));
+__put_user(TARGET_ZA_MAGIC, >head.magic);
+__put_user(size, >head.size);
+__put_user(vl, >vl);
+
+if (size == TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
+return;
+}
+
+/*
+ * Note that ZA vectors are stored as a byte stream,
+ * with each byte element at a subsequent address.
+ */
+for (i = 0; i < vl; ++i) {
+uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
+for (j = 0; j < vq * 2; ++j) {
+__put_user_e(env->zarray[i].d[j], z + j, le);
+}
+}
+}
+
 static void target_restore_general_frame(CPUARMState *env,
  struct target_rt_sigframe *sf)
 {
@@ -252,16 +296,28 @@ static void target_restore_fpsimd_record(CPUARMState *env,
 
 static bool target_restore_sve_record(CPUARMState *env,
   struct target_sve_context *sve,
-  int size)
+  int size, int *svcr)
 {
-int i, j, vl, vq;
+int i, j, vl, vq, flags;
+bool sm;
 
+/* ??? Kernel tests SVE && (!sm || SME); suggest (sm ? SME : SVE). */
 if (!cpu_isar_feature(aa64_sve, env_archcpu(env))) {
 return false;
 }
 
 __get_user(vl, >vl);
-vq = sve_vq(env);
+__get_user(flags, >flags);
+
+sm = flags & TARGET_SVE_SIG_FLAG_SM;
+if (sm) {
+if (!cpu_isar_feature(aa64_sme, env_archcpu(env))) {
+return false;
+}
+vq = sme_vq(env);
+} else {
+vq = sve_vq(env);
+}
 
 /* Reject mismatched VL. */
 if (vl != vq * TARGET_SVE_VQ_BYTES) {
@@ -278,6 +334,8 @@ static bool target_restore_sve_record(CPUARMState *env,
 return false;
 }
 
+*svcr = FIELD_DP64(*svcr, SVCR, SM, sm);
+
 /*
  * Note that SVE regs are stored as a byte stream, with each byte element
  * at a subsequent address.  This corresponds to a little-endian load
@@ -304,15 +362,57 @@ static bool target_restore_sve_record(CPUARMState *env,
 return true;
 }
 
+static bool target_restore_za_record(CPUARMState *env,
+ struct target_za_context *za,
+ int size, int *svcr)
+{
+int i, j, vl, vq;
+
+if (!cpu_isar_feature(aa64_sme, env_archcpu(env))) {
+return false;
+}
+
+__get_user(vl, >vl);
+vq = sme_vq(env);
+
+/* Reject mismatched VL. */
+if (vl != vq * TARGET_SVE_VQ_BYTES) {
+return false;
+}
+
+/* Accept empty record -- used to clear PSTATE.ZA. */
+if (size <= TARGET_ZA_SIG_CONTEXT_SIZE(0)) {
+return true;
+}
+
+/* Reject non-empty but incomplete record. */
+if (size < TARGET_ZA_SIG_CONTEXT_SIZE(vq)) {
+return false;
+}
+
+*svcr = FIELD_DP64(*svcr, SVCR, ZA, 1);
+
+for (i = 0; i < vl; ++i) {
+uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i);
+for (j = 0; j < vq * 2; ++j) {
+

[PATCH v3 34/51] target/arm: Implement PSEL

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/sve.decode  | 20 +
 target/arm/translate-sve.c | 57 ++
 2 files changed, 77 insertions(+)

diff --git a/target/arm/sve.decode b/target/arm/sve.decode
index bbdaac6ac7..bf561c270a 100644
--- a/target/arm/sve.decode
+++ b/target/arm/sve.decode
@@ -1674,3 +1674,23 @@ BFMLALT_zzxw01100100 11 1 . 0100.1 . .   
  @rrxr_3a esz=2
 
 ### SVE2 floating-point bfloat16 dot-product (indexed)
 BFDOT_zzxz  01100100 01 1 . 01 . . @rrxr_2 esz=2
+
+### SVE broadcast predicate element
+
+   esz pd pn pm rv imm
+%psel_rv16:2 !function=plus_12
+%psel_imm_b 22:2 19:2
+%psel_imm_h 22:2 20:1
+%psel_imm_s 22:2
+%psel_imm_d 23:1
+@psel    .. . ... .. .. pn:4 . pm:4 . pd:4  \
+ rv=%psel_rv
+
+PSEL00100101 .. 1 ..1 .. 01  0  0   \
+@psel esz=0 imm=%psel_imm_b
+PSEL00100101 .. 1 .10 .. 01  0  0   \
+@psel esz=1 imm=%psel_imm_h
+PSEL00100101 .. 1 100 .. 01  0  0   \
+@psel esz=2 imm=%psel_imm_s
+PSEL00100101 .1 1 000 .. 01  0  0   \
+@psel esz=3 imm=%psel_imm_d
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index adf0cd3e68..58d0894e15 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -7379,3 +7379,60 @@ static bool do_BFMLAL_zzxw(DisasContext *s, arg_rrxr_esz 
*a, bool sel)
 
 TRANS_FEAT(BFMLALB_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, false)
 TRANS_FEAT(BFMLALT_zzxw, aa64_sve_bf16, do_BFMLAL_zzxw, a, true)
+
+static bool trans_PSEL(DisasContext *s, arg_psel *a)
+{
+int vl = vec_full_reg_size(s);
+int pl = pred_gvec_reg_size(s);
+int elements = vl >> a->esz;
+TCGv_i64 tmp, didx, dbit;
+TCGv_ptr ptr;
+
+if (!dc_isar_feature(aa64_sme, s)) {
+return false;
+}
+if (!sve_access_check(s)) {
+return true;
+}
+
+tmp = tcg_temp_new_i64();
+dbit = tcg_temp_new_i64();
+didx = tcg_temp_new_i64();
+ptr = tcg_temp_new_ptr();
+
+/* Compute the predicate element. */
+tcg_gen_addi_i64(tmp, cpu_reg(s, a->rv), a->imm);
+if (is_power_of_2(elements)) {
+tcg_gen_andi_i64(tmp, tmp, elements - 1);
+} else {
+tcg_gen_remu_i64(tmp, tmp, tcg_constant_i64(elements));
+}
+
+/* Extract the predicate byte and bit indices. */
+tcg_gen_shli_i64(tmp, tmp, a->esz);
+tcg_gen_andi_i64(dbit, tmp, 7);
+tcg_gen_shri_i64(didx, tmp, 3);
+if (HOST_BIG_ENDIAN) {
+tcg_gen_xori_i64(didx, didx, 7);
+}
+
+/* Load the predicate word. */
+tcg_gen_trunc_i64_ptr(ptr, didx);
+tcg_gen_add_ptr(ptr, ptr, cpu_env);
+tcg_gen_ld8u_i64(tmp, ptr, pred_full_reg_offset(s, a->pm));
+
+/* Extract the predicate bit and replicate to MO_64. */
+tcg_gen_shr_i64(tmp, tmp, dbit);
+tcg_gen_andi_i64(tmp, tmp, 1);
+tcg_gen_neg_i64(tmp, tmp);
+
+/* Apply to either copy the source, or write zeros. */
+tcg_gen_gvec_ands(MO_64, pred_full_reg_offset(s, a->pd),
+  pred_full_reg_offset(s, a->pn), tmp, pl, pl);
+
+tcg_temp_free_i64(tmp);
+tcg_temp_free_i64(dbit);
+tcg_temp_free_i64(didx);
+tcg_temp_free_ptr(ptr);
+return true;
+}
-- 
2.34.1




[PATCH v3 17/51] target/arm: Add cpu properties for SME

2022-06-20 Thread Richard Henderson
Mirror the properties for SVE.  The main difference is
that any arbitrary set of powers of 2 may be supported,
and not the stricter constraints that apply to SVE.

Include a property to control FEAT_SME_FA64, as failing
to restrict the runtime to the proper subset of insns
could be a major point for bugs.

Signed-off-by: Richard Henderson 
---
 docs/system/arm/cpu-features.rst |  56 +++
 target/arm/cpu.h |   2 +
 target/arm/internals.h   |   1 +
 target/arm/cpu.c |  14 +++-
 target/arm/cpu64.c   | 114 +--
 5 files changed, 180 insertions(+), 7 deletions(-)

diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst
index 3e626c4b68..3fd76fa0b4 100644
--- a/docs/system/arm/cpu-features.rst
+++ b/docs/system/arm/cpu-features.rst
@@ -372,6 +372,31 @@ verbose command lines.  However, the recommended way to 
select vector
 lengths is to explicitly enable each desired length.  Therefore only
 example's (1), (4), and (6) exhibit recommended uses of the properties.
 
+SME CPU Property Examples
+-
+
+  1) Disable SME::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sme=off
+
+  2) Implicitly enable all vector lengths for the ``max`` CPU type::
+
+ $ qemu-system-aarch64 -M virt -cpu max
+
+  3) Only enable the 256-bit vector length::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sme256=on
+
+  3) Enable the 256-bit and 1024-bit vector lengths::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sme256=on,sme1024=on
+
+  4) Disable the 512-bit vector length.  This results in all the other
+ lengths supported by ``max`` defaulting to enabled
+ (128, 256, 1024 and 2048)::
+
+ $ qemu-system-aarch64 -M virt -cpu max,sve512=off
+
 SVE User-mode Default Vector Length Property
 
 
@@ -387,3 +412,34 @@ length supported by QEMU is 256.
 
 If this property is set to ``-1`` then the default vector length
 is set to the maximum possible length.
+
+SME CPU Properties
+==
+
+The SME CPU properties are much like the SVE properties: ``sme`` is
+used to enable or disable the entire SME feature, and ``sme`` is
+used to enable or disable specific vector lengths.  Finally,
+``sme_fa64`` is used to enable or disable ``FEAT_SME_FA64``, which
+allows execution of the "full a64" instruction set while Streaming
+SVE mode is enabled.
+
+SME is not supported by KVM at this time.
+
+At least one vector length must be enabled when ``sme`` is enabled,
+and all vector lengths must be powers of 2.  The maximum vector
+length supported by qemu is 2048 bits.  Otherwise, there are no
+additional constraints on the set of vector lengths supported by SME.
+
+SME User-mode Default Vector Length Property
+
+
+For qemu-aarch64, the cpu propery ``sme-default-vector-length=N`` is
+defined to mirror the Linux kernel parameter file
+``/proc/sys/abi/sme_default_vector_length``.  The default length, ``N``,
+is in units of bytes and must be between 16 and 8192.
+If not specified, the default vector length is 32.
+
+As with ``sve-default-vector-length``, if the default length is larger
+than the maximum vector length enabled, the actual vector length will
+be reduced.  If this property is set to ``-1`` then the default vector
+length is set to the maximum possible length.
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c73f289125..8b00d29af4 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1046,9 +1046,11 @@ struct ArchCPU {
 #ifdef CONFIG_USER_ONLY
 /* Used to set the default vector length at process start. */
 uint32_t sve_default_vq;
+uint32_t sme_default_vq;
 #endif
 
 ARMVQMap sve_vq;
+ARMVQMap sme_vq;
 
 /* Generic timer counter frequency, in Hz */
 uint64_t gt_cntfrq_hz;
diff --git a/target/arm/internals.h b/target/arm/internals.h
index aef568adf7..c66f74a0db 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1289,6 +1289,7 @@ int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, 
int reg);
 int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
 void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
 void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b5276fa944..75295a14a3 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1122,11 +1122,13 @@ static void arm_cpu_initfn(Object *obj)
 #ifdef CONFIG_USER_ONLY
 # ifdef TARGET_AARCH64
 /*
- * The linux kernel defaults to 512-bit vectors, when sve is supported.
- * See documentation for /proc/sys/abi/sve_default_vector_length, and
- * our corresponding sve-default-vector-length cpu property.
+ * The linux kernel 

[PATCH v3 24/51] target/arm: Implement SME ZERO

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h|  2 ++
 target/arm/translate-a64.h |  1 +
 target/arm/sme.decode  |  4 
 target/arm/sme_helper.c| 25 +
 target/arm/translate-a64.c | 14 ++
 target/arm/translate-sme.c | 13 +
 6 files changed, 59 insertions(+)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index 3bd48c235f..c4ee1f09e4 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -19,3 +19,5 @@
 
 DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
+
+DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
index 6bd1b2eb4b..ec5d580ba0 100644
--- a/target/arm/translate-a64.h
+++ b/target/arm/translate-a64.h
@@ -30,6 +30,7 @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int 
immn,
 unsigned int imms, unsigned int immr);
 bool sve_access_check(DisasContext *s);
 bool sme_enabled_check(DisasContext *s);
+bool sme_za_enabled_check(DisasContext *s);
 TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
 TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
 bool tag_checked, int log2_size);
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index c25c031a71..6e4483fdce 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -18,3 +18,7 @@
 #
 # This file is processed by scripts/decodetree.py
 #
+
+### SME Misc
+
+ZERO1100 00 001 000 imm:8
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
index b215725594..e5b5723a15 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/sme_helper.c
@@ -59,3 +59,28 @@ void helper_set_pstate_za(CPUARMState *env, uint32_t i)
 memset(env->zarray, 0, sizeof(env->zarray));
 }
 }
+
+void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl)
+{
+uint32_t i;
+
+/*
+ * Special case clearing the entire ZA space.
+ * This falls into the CONSTRAINED UNPREDICTABLE zeroing of any
+ * parts of the ZA storage outside of SVL.
+ */
+if (imm == 0xff) {
+memset(env->zarray, 0, sizeof(env->zarray));
+return;
+}
+
+/*
+ * Recall that ZAnH.D[m] is spread across ZA[n+8*m].
+ * Unless SVL == ARM_MAX_VQ, each row is discontiguous.
+ */
+for (i = 0; i < svl; i++) {
+if (imm & (1 << (i % 8))) {
+memset(>zarray[i], 0, svl);
+}
+}
+}
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 498970f653..df9fc42635 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1231,6 +1231,20 @@ bool sme_enabled_check(DisasContext *s)
 return fp_access_check_only(s);
 }
 
+/* Note that this function corresponds to CheckSMEAndZAEnabled. */
+bool sme_za_enabled_check(DisasContext *s)
+{
+if (!sme_enabled_check(s)) {
+return false;
+}
+if (!s->pstate_za) {
+gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
+   syn_smetrap(SME_ET_InactiveZA, false));
+return false;
+}
+return true;
+}
+
 /*
  * This utility function is for doing register extension with an
  * optional shift. You will likely want to pass a temporary for the
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
index 786c93fb2d..d526c74456 100644
--- a/target/arm/translate-sme.c
+++ b/target/arm/translate-sme.c
@@ -33,3 +33,16 @@
  */
 
 #include "decode-sme.c.inc"
+
+
+static bool trans_ZERO(DisasContext *s, arg_ZERO *a)
+{
+if (!dc_isar_feature(aa64_sme, s)) {
+return false;
+}
+if (sme_za_enabled_check(s)) {
+gen_helper_sme_zero(cpu_env, tcg_constant_i32(a->imm),
+tcg_constant_i32(s->svl));
+}
+return true;
+}
-- 
2.34.1




[PATCH v3 43/51] linux-user/aarch64: Do not allow duplicate or short sve records

2022-06-20 Thread Richard Henderson
In parse_user_sigframe, the kernel rejects duplicate sve records,
or records that are smaller than the header.  We were silently
allowing these cases to pass, dropping the record.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/signal.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index 8b352abb97..8fbe98d72f 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -318,10 +318,13 @@ static int target_restore_sigframe(CPUARMState *env,
 break;
 
 case TARGET_SVE_MAGIC:
+if (sve || size < sizeof(struct target_sve_context)) {
+goto err;
+}
 if (cpu_isar_feature(aa64_sve, env_archcpu(env))) {
 vq = sve_vq(env);
 sve_size = QEMU_ALIGN_UP(TARGET_SVE_SIG_CONTEXT_SIZE(vq), 16);
-if (!sve && size == sve_size) {
+if (size == sve_size) {
 sve = (struct target_sve_context *)ctx;
 break;
 }
-- 
2.34.1




[PATCH v3 37/51] target/arm: Reset streaming sve state on exception boundaries

2022-06-20 Thread Richard Henderson
We can handle both exception entry and exception return by
hooking into aarch64_sve_change_el.

Signed-off-by: Richard Henderson 
---
 target/arm/helper.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 26f4a4bc26..9c5b1a10eb 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11754,6 +11754,19 @@ void aarch64_sve_change_el(CPUARMState *env, int 
old_el,
 return;
 }
 
+old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
+new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
+
+/*
+ * Both AArch64.TakeException and AArch64.ExceptionReturn
+ * invoke ResetSVEState when taking an exception from, or
+ * returning to, AArch32 state when PSTATE.SM is enabled.
+ */
+if (old_a64 != new_a64 && FIELD_EX64(env->svcr, SVCR, SM)) {
+arm_reset_sve_state(env);
+return;
+}
+
 /*
  * DDI0584A.d sec 3.2: "If SVE instructions are disabled or trapped
  * at ELx, or not available because the EL is in AArch32 state, then
@@ -11766,10 +11779,8 @@ void aarch64_sve_change_el(CPUARMState *env, int 
old_el,
  * we already have the correct register contents when encountering the
  * vq0->vq0 transition between EL0->EL1.
  */
-old_a64 = old_el ? arm_el_is_aa64(env, old_el) : el0_a64;
 old_len = (old_a64 && !sve_exception_el(env, old_el)
? sve_vqm1_for_el(env, old_el) : 0);
-new_a64 = new_el ? arm_el_is_aa64(env, new_el) : el0_a64;
 new_len = (new_a64 && !sve_exception_el(env, new_el)
? sve_vqm1_for_el(env, new_el) : 0);
 
-- 
2.34.1




[PATCH v3 25/51] target/arm: Implement SME MOVA

2022-06-20 Thread Richard Henderson
We can reuse the SVE functions for implementing moves to/from
horizontal tile slices, but we need new ones for moves to/from
vertical tile slices.

Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h|  11 
 target/arm/helper-sve.h|   2 +
 target/arm/translate-a64.h |   9 +++
 target/arm/translate.h |   5 ++
 target/arm/sme.decode  |  15 +
 target/arm/sme_helper.c| 110 -
 target/arm/sve_helper.c|  12 
 target/arm/translate-a64.c |  19 +++
 target/arm/translate-sme.c | 105 +++
 9 files changed, 287 insertions(+), 1 deletion(-)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index c4ee1f09e4..600346e08c 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -21,3 +21,14 @@ DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, 
env, i32)
 DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
 
 DEF_HELPER_FLAGS_3(sme_zero, TCG_CALL_NO_RWG, void, env, i32, i32)
+
+DEF_HELPER_FLAGS_4(sme_mova_avz_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_zav_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_avz_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_zav_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_avz_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_zav_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_avz_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_zav_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_avz_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(sme_mova_zav_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
index dc629f851a..ab0333400f 100644
--- a/target/arm/helper-sve.h
+++ b/target/arm/helper-sve.h
@@ -325,6 +325,8 @@ DEF_HELPER_FLAGS_5(sve_sel_zpzz_s, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_5(sve_sel_zpzz_d, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sve_sel_zpzz_q, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, i32)
 
 DEF_HELPER_FLAGS_5(sve2_addp_zpzz_b, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
index ec5d580ba0..c341c95582 100644
--- a/target/arm/translate-a64.h
+++ b/target/arm/translate-a64.h
@@ -31,6 +31,7 @@ bool logic_imm_decode_wmask(uint64_t *result, unsigned int 
immn,
 bool sve_access_check(DisasContext *s);
 bool sme_enabled_check(DisasContext *s);
 bool sme_za_enabled_check(DisasContext *s);
+bool sme_smza_enabled_check(DisasContext *s);
 TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
 TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
 bool tag_checked, int log2_size);
@@ -147,6 +148,14 @@ static inline int pred_gvec_reg_size(DisasContext *s)
 return size_for_gvec(pred_full_reg_size(s));
 }
 
+/* Return a newly allocated pointer to the predicate register.  */
+static inline TCGv_ptr pred_full_reg_ptr(DisasContext *s, int regno)
+{
+TCGv_ptr ret = tcg_temp_new_ptr();
+tcg_gen_addi_ptr(ret, cpu_env, pred_full_reg_offset(s, regno));
+return ret;
+}
+
 bool disas_sve(DisasContext *, uint32_t);
 bool disas_sme(DisasContext *, uint32_t);
 
diff --git a/target/arm/translate.h b/target/arm/translate.h
index ef158a75c6..0c0c6641bb 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -155,6 +155,11 @@ static inline int plus_2(DisasContext *s, int x)
 return x + 2;
 }
 
+static inline int plus_12(DisasContext *s, int x)
+{
+return x + 12;
+}
+
 static inline int times_2(DisasContext *s, int x)
 {
 return x * 2;
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index 6e4483fdce..241b4895b7 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -22,3 +22,18 @@
 ### SME Misc
 
 ZERO1100 00 001 000 imm:8
+
+### SME Move into/from Array
+
+%mova_rs13:2 !function=plus_12
+   esz rs pg zr za_imm v:bool to_vec:bool
+
+MOVA1100 esz:2 0 0 v:1 .. pg:3 zr:5 0 za_imm:4  \
+ to_vec=0 rs=%mova_rs
+MOVA1100 110 1 v:1 .. pg:3 zr:5 0 za_imm:4  \
+ to_vec=0 rs=%mova_rs esz=4
+
+MOVA1100 esz:2 1 0 v:1 .. pg:3 0 za_imm:4 zr:5  \
+ to_vec=1 rs=%mova_rs
+MOVA1100 111 1 v:1 .. pg:3 0 za_imm:4 zr:5  \
+ to_vec=1 rs=%mova_rs esz=4
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
index e5b5723a15..99524ead4d 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/sme_helper.c
@@ -19,8 +19,10 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
-#include 

[PATCH v3 15/51] target/arm: Move arm_cpu_*_finalize to internals.h

2022-06-20 Thread Richard Henderson
Drop the aa32-only inline fallbacks,
and just use a couple of ifdefs.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   | 6 --
 target/arm/internals.h | 3 +++
 target/arm/cpu.c   | 2 ++
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index ece720a757..d8ff78d96d 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -205,14 +205,8 @@ typedef struct {
 
 #ifdef TARGET_AARCH64
 # define ARM_MAX_VQ16
-void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
-void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
-void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #else
 # define ARM_MAX_VQ1
-static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
-static inline void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) { }
-static inline void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) { }
 #endif
 
 typedef struct ARMVectorReg {
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6f94f3019d..aef568adf7 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1288,6 +1288,9 @@ int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, 
int reg);
 int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg);
 int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg);
 int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg);
+void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
 #endif
 
 #ifdef CONFIG_USER_ONLY
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 1b5d535788..b5276fa944 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1421,6 +1421,7 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
 {
 Error *local_err = NULL;
 
+#ifdef TARGET_AARCH64
 if (arm_feature(>env, ARM_FEATURE_AARCH64)) {
 arm_cpu_sve_finalize(cpu, _err);
 if (local_err != NULL) {
@@ -1440,6 +1441,7 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
 return;
 }
 }
+#endif
 
 if (kvm_enabled()) {
 kvm_arm_steal_time_finalize(cpu, _err);
-- 
2.34.1




[PATCH v3 29/51] target/arm: Implement SME ADDHA, ADDVA

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h|  5 +++
 target/arm/sme.decode  | 11 +
 target/arm/sme_helper.c| 90 ++
 target/arm/translate-sme.c | 30 +
 4 files changed, 136 insertions(+)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index 5cca01f372..6f0fce7e2c 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -114,3 +114,8 @@ DEF_HELPER_FLAGS_5(sme_st1q_be_h_mte, TCG_CALL_NO_WG, void, 
env, ptr, ptr, tl, i
 DEF_HELPER_FLAGS_5(sme_st1q_le_h_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
 DEF_HELPER_FLAGS_5(sme_st1q_be_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
 DEF_HELPER_FLAGS_5(sme_st1q_le_v_mte, TCG_CALL_NO_WG, void, env, ptr, ptr, tl, 
i32)
+
+DEF_HELPER_FLAGS_5(sme_addha_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index f1ebd857a5..8cb6c4053c 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -53,3 +53,14 @@ LDST1   111 111 st:1 rm:5 v:1 .. pg:3 rn:5 0 
za_imm:4  \
 
 LDR 111 100 0 00 .. 000 . 0 @ldstr
 STR 111 100 1 00 .. 000 . 0 @ldstr
+
+### SME Add Vector to Array
+
+   zad zn pm pn
+@adda_32 .. . . pm:3 pn:3 zn:5 ... zad:2
+@adda_64 .. . . pm:3 pn:3 zn:5 ..  zad:3
+
+ADDHA_s 1100 10 01000 0 ... ... . 000 ..@adda_32
+ADDVA_s 1100 10 01000 1 ... ... . 000 ..@adda_32
+ADDHA_d 1100 11 01000 0 ... ... . 00 ...@adda_64
+ADDVA_d 1100 11 01000 1 ... ... . 00 ...@adda_64
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
index 0c51fbbd49..799e44c047 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/sme_helper.c
@@ -807,3 +807,93 @@ DO_ST(q, _be, MO_128)
 DO_ST(q, _le, MO_128)
 
 #undef DO_ST
+
+void HELPER(sme_addha_s)(void *vzda, void *vzn, void *vpn,
+ void *vpm, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
+uint64_t *pn = vpn, *pm = vpm;
+uint32_t * restrict zda = vzda, * restrict zn = vzn;
+
+for (row = 0; row < oprsz; ) {
+uint64_t pa = pn[row >> 4];
+do {
+if (pa & 1) {
+for (col = 0; col < oprsz; ) {
+uint64_t pb = pm[col >> 4];
+do {
+if (pb & 1) {
+zda[row * sizeof(ARMVectorReg) + col] += zn[col];
+}
+pb >>= 4;
+} while (++col & 15);
+}
+}
+pa >>= 4;
+} while (++row & 15);
+}
+}
+
+void HELPER(sme_addha_d)(void *vzda, void *vzn, void *vpn,
+ void *vpm, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
+uint8_t *pn = vpn, *pm = vpm;
+uint64_t * restrict zda = vzda, * restrict zn = vzn;
+
+for (row = 0; row < oprsz; ++row) {
+if (pn[H1(row)] & 1) {
+for (col = 0; col < oprsz; ++col) {
+if (pm[H1(col)] & 1) {
+zda[row * sizeof(ARMVectorReg) + col] += zn[col];
+}
+}
+}
+}
+}
+
+void HELPER(sme_addva_s)(void *vzda, void *vzn, void *vpn,
+ void *vpm, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_oprsz(desc) / 4;
+uint64_t *pn = vpn, *pm = vpm;
+uint32_t * restrict zda = vzda, * restrict zn = vzn;
+
+for (row = 0; row < oprsz; ) {
+uint64_t pa = pn[row >> 4];
+do {
+if (pa & 1) {
+uint32_t zn_row = zn[row];
+for (col = 0; col < oprsz; ) {
+uint64_t pb = pm[col >> 4];
+do {
+if (pb & 1) {
+zda[row * sizeof(ARMVectorReg) + col] += zn_row;
+}
+pb >>= 4;
+} while (++col & 15);
+}
+}
+pa >>= 4;
+} while (++row & 15);
+}
+}
+
+void HELPER(sme_addva_d)(void *vzda, void *vzn, void *vpn,
+ void *vpm, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_oprsz(desc) / 8;
+uint8_t *pn = vpn, *pm = vpm;
+uint64_t * restrict zda = vzda, * restrict zn = vzn;
+
+for (row = 0; row < oprsz; ++row) {
+if (pn[H1(row)] & 1) {
+uint64_t zn_row = zn[row];
+for (col = 0; col < oprsz; ++col) {
+if (pm[H1(col)] & 1) {
+zda[row * 

[PATCH v3 41/51] linux-user/aarch64: Add SM bit to SVE signal context

2022-06-20 Thread Richard Henderson
Make sure to zero the currently reserved fields.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/signal.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index 7da0e36c6d..3cef2f44cf 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -78,7 +78,8 @@ struct target_extra_context {
 struct target_sve_context {
 struct target_aarch64_ctx head;
 uint16_t vl;
-uint16_t reserved[3];
+uint16_t flags;
+uint16_t reserved[2];
 /* The actual SVE data immediately follows.  It is laid out
  * according to TARGET_SVE_SIG_{Z,P}REG_OFFSET, based off of
  * the original struct pointer.
@@ -101,6 +102,8 @@ struct target_sve_context {
 #define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \
 (TARGET_SVE_SIG_PREG_OFFSET(VQ, 17))
 
+#define TARGET_SVE_SIG_FLAG_SM  1
+
 struct target_rt_sigframe {
 struct target_siginfo info;
 struct target_ucontext uc;
@@ -177,9 +180,13 @@ static void target_setup_sve_record(struct 
target_sve_context *sve,
 {
 int i, j;
 
+memset(sve, 0, sizeof(*sve));
 __put_user(TARGET_SVE_MAGIC, >head.magic);
 __put_user(size, >head.size);
 __put_user(vq * TARGET_SVE_VQ_BYTES, >vl);
+if (FIELD_EX64(env->svcr, SVCR, SM)) {
+__put_user(TARGET_SVE_SIG_FLAG_SM, >flags);
+}
 
 /* Note that SVE regs are stored as a byte stream, with each byte element
  * at a subsequent address.  This corresponds to a little-endian store
-- 
2.34.1




[PATCH v3 23/51] target/arm: Implement SME RDSVL, ADDSVL, ADDSPL

2022-06-20 Thread Richard Henderson
These SME instructions are nominally within the SVE decode space,
so we add them to sve.decode and translate-sve.c.

Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.h |  1 +
 target/arm/sve.decode  |  5 -
 target/arm/translate-a64.c | 15 +++
 target/arm/translate-sve.c | 38 ++
 4 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
index 789b6e8e78..6bd1b2eb4b 100644
--- a/target/arm/translate-a64.h
+++ b/target/arm/translate-a64.h
@@ -29,6 +29,7 @@ void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v);
 bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
 unsigned int imms, unsigned int immr);
 bool sve_access_check(DisasContext *s);
+bool sme_enabled_check(DisasContext *s);
 TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
 TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
 bool tag_checked, int log2_size);
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
index a54feb2f61..bbdaac6ac7 100644
--- a/target/arm/sve.decode
+++ b/target/arm/sve.decode
@@ -449,14 +449,17 @@ INDEX_ri0100 esz:2 1 imm:s5 010001 rn:5 rd:5
 # SVE index generation (register start, register increment)
 INDEX_rr0100 .. 1 . 010011 . .  @rd_rn_rm
 
-### SVE Stack Allocation Group
+### SVE / Streaming SVE Stack Allocation Group
 
 # SVE stack frame adjustment
 ADDVL   0100 001 . 01010 .. .   @rd_rn_i6
+ADDSVL  0100 001 . 01011 .. .   @rd_rn_i6
 ADDPL   0100 011 . 01010 .. .   @rd_rn_i6
+ADDSPL  0100 011 . 01011 .. .   @rd_rn_i6
 
 # SVE stack frame size
 RDVL0100 101 1 01010 imm:s6 rd:5
+RDSVL   0100 101 1 01011 imm:s6 rd:5
 
 ### SVE Bitwise Shift - Unpredicated Group
 
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index efcfb919ff..498970f653 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1216,6 +1216,21 @@ static bool sme_access_check(DisasContext *s)
 return true;
 }
 
+/* Note that this function corresponds to CheckSMEEnabled. */
+bool sme_enabled_check(DisasContext *s)
+{
+/*
+ * Note that unlike sve_excp_el, we have not constrained sme_excp_el
+ * to be zero when fp_excp_el has priority.  This is because we need
+ * sme_excp_el by itself for cpregs access checks.
+ */
+if (!s->fp_excp_el || s->sme_excp_el < s->fp_excp_el) {
+s->fp_access_checked = true;
+return sme_access_check(s);
+}
+return fp_access_check_only(s);
+}
+
 /*
  * This utility function is for doing register extension with an
  * optional shift. You will likely want to pass a temporary for the
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 62b5f3040c..13bdd027a5 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -1286,6 +1286,19 @@ static bool trans_ADDVL(DisasContext *s, arg_ADDVL *a)
 return true;
 }
 
+static bool trans_ADDSVL(DisasContext *s, arg_ADDSVL *a)
+{
+if (!dc_isar_feature(aa64_sme, s)) {
+return false;
+}
+if (sme_enabled_check(s)) {
+TCGv_i64 rd = cpu_reg_sp(s, a->rd);
+TCGv_i64 rn = cpu_reg_sp(s, a->rn);
+tcg_gen_addi_i64(rd, rn, a->imm * s->svl);
+}
+return true;
+}
+
 static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
 {
 if (!dc_isar_feature(aa64_sve, s)) {
@@ -1299,6 +1312,19 @@ static bool trans_ADDPL(DisasContext *s, arg_ADDPL *a)
 return true;
 }
 
+static bool trans_ADDSPL(DisasContext *s, arg_ADDSPL *a)
+{
+if (!dc_isar_feature(aa64_sme, s)) {
+return false;
+}
+if (sme_enabled_check(s)) {
+TCGv_i64 rd = cpu_reg_sp(s, a->rd);
+TCGv_i64 rn = cpu_reg_sp(s, a->rn);
+tcg_gen_addi_i64(rd, rn, a->imm * (s->svl / 8));
+}
+return true;
+}
+
 static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
 {
 if (!dc_isar_feature(aa64_sve, s)) {
@@ -1311,6 +1337,18 @@ static bool trans_RDVL(DisasContext *s, arg_RDVL *a)
 return true;
 }
 
+static bool trans_RDSVL(DisasContext *s, arg_RDSVL *a)
+{
+if (!dc_isar_feature(aa64_sme, s)) {
+return false;
+}
+if (sme_enabled_check(s)) {
+TCGv_i64 reg = cpu_reg(s, a->rd);
+tcg_gen_movi_i64(reg, a->imm * s->svl);
+}
+return true;
+}
+
 /*
  *** SVE Compute Vector Address Group
  */
-- 
2.34.1




[PATCH v3 12/51] target/arm: Create ARMVQMap

2022-06-20 Thread Richard Henderson
Pull the three sve_vq_* values into a structure.
This will be reused for SME.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h| 29 ++---
 target/arm/cpu64.c  | 22 +++---
 target/arm/helper.c |  2 +-
 target/arm/kvm64.c  |  2 +-
 4 files changed, 27 insertions(+), 28 deletions(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 2e049291da..ece720a757 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -793,6 +793,19 @@ typedef enum ARMPSCIState {
 
 typedef struct ARMISARegisters ARMISARegisters;
 
+/*
+ * In map, each set bit is a supported vector length of (bit-number + 1) * 16
+ * bytes, i.e. each bit number + 1 is the vector length in quadwords.
+ *
+ * While processing properties during initialization, corresponding init bits
+ * are set for bits in sve_vq_map that have been set by properties.
+ *
+ * Bits set in supported represent valid vector lengths for the CPU type.
+ */
+typedef struct {
+uint32_t map, init, supported;
+} ARMVQMap;
+
 /**
  * ARMCPU:
  * @env: #CPUARMState
@@ -1041,21 +1054,7 @@ struct ArchCPU {
 uint32_t sve_default_vq;
 #endif
 
-/*
- * In sve_vq_map each set bit is a supported vector length of
- * (bit-number + 1) * 16 bytes, i.e. each bit number + 1 is the vector
- * length in quadwords.
- *
- * While processing properties during initialization, corresponding
- * sve_vq_init bits are set for bits in sve_vq_map that have been
- * set by properties.
- *
- * Bits set in sve_vq_supported represent valid vector lengths for
- * the CPU type.
- */
-uint32_t sve_vq_map;
-uint32_t sve_vq_init;
-uint32_t sve_vq_supported;
+ARMVQMap sve_vq;
 
 /* Generic timer counter frequency, in Hz */
 uint64_t gt_cntfrq_hz;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index a46e40f4f2..cadc401c7e 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -355,8 +355,8 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
  * any of the above.  Finally, if SVE is not disabled, then at least one
  * vector length must be enabled.
  */
-uint32_t vq_map = cpu->sve_vq_map;
-uint32_t vq_init = cpu->sve_vq_init;
+uint32_t vq_map = cpu->sve_vq.map;
+uint32_t vq_init = cpu->sve_vq.init;
 uint32_t vq_supported;
 uint32_t vq_mask = 0;
 uint32_t tmp, vq, max_vq = 0;
@@ -369,14 +369,14 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
  */
 if (kvm_enabled()) {
 if (kvm_arm_sve_supported()) {
-cpu->sve_vq_supported = kvm_arm_sve_get_vls(CPU(cpu));
-vq_supported = cpu->sve_vq_supported;
+cpu->sve_vq.supported = kvm_arm_sve_get_vls(CPU(cpu));
+vq_supported = cpu->sve_vq.supported;
 } else {
 assert(!cpu_isar_feature(aa64_sve, cpu));
 vq_supported = 0;
 }
 } else {
-vq_supported = cpu->sve_vq_supported;
+vq_supported = cpu->sve_vq.supported;
 }
 
 /*
@@ -534,7 +534,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
 
 /* From now on sve_max_vq is the actual maximum supported length. */
 cpu->sve_max_vq = max_vq;
-cpu->sve_vq_map = vq_map;
+cpu->sve_vq.map = vq_map;
 }
 
 static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
@@ -595,7 +595,7 @@ static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, 
const char *name,
 if (!cpu_isar_feature(aa64_sve, cpu)) {
 value = false;
 } else {
-value = extract32(cpu->sve_vq_map, vq - 1, 1);
+value = extract32(cpu->sve_vq.map, vq - 1, 1);
 }
 visit_type_bool(v, name, , errp);
 }
@@ -611,8 +611,8 @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, 
const char *name,
 return;
 }
 
-cpu->sve_vq_map = deposit32(cpu->sve_vq_map, vq - 1, 1, value);
-cpu->sve_vq_init |= 1 << (vq - 1);
+cpu->sve_vq.map = deposit32(cpu->sve_vq.map, vq - 1, 1, value);
+cpu->sve_vq.init |= 1 << (vq - 1);
 }
 
 static bool cpu_arm_get_sve(Object *obj, Error **errp)
@@ -974,7 +974,7 @@ static void aarch64_max_initfn(Object *obj)
 cpu->dcz_blocksize = 7; /*  512 bytes */
 #endif
 
-cpu->sve_vq_supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
+cpu->sve_vq.supported = MAKE_64BIT_MASK(0, ARM_MAX_VQ);
 
 aarch64_add_pauth_properties(obj);
 aarch64_add_sve_properties(obj);
@@ -1023,7 +1023,7 @@ static void aarch64_a64fx_initfn(Object *obj)
 
 /* The A64FX supports only 128, 256 and 512 bit vector lengths */
 aarch64_add_sve_properties(obj);
-cpu->sve_vq_supported = (1 << 0)  /* 128bit */
+cpu->sve_vq.supported = (1 << 0)  /* 128bit */
   | (1 << 1)  /* 256bit */
   | (1 << 3); /* 512bit */
 
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 88d96f7991..a80ca461e5 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6287,7 +6287,7 @@ 

[PATCH v3 32/51] target/arm: Implement FMOPA, FMOPS (widening)

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h|  2 ++
 target/arm/sme.decode  |  1 +
 target/arm/sme_helper.c| 74 ++
 target/arm/translate-sme.c |  2 ++
 4 files changed, 79 insertions(+)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index 6b36542133..ecc957be14 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -120,6 +120,8 @@ DEF_HELPER_FLAGS_5(sme_addva_s, TCG_CALL_NO_RWG, void, ptr, 
ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_5(sme_addha_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_5(sme_addva_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
 
+DEF_HELPER_FLAGS_7(sme_fmopa_h, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index afd9c0dffd..e8d27fd8a0 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -75,3 +75,4 @@ FMOPA_s 1000 100 . ... ... . . 00 ..  
  @op_32
 FMOPA_d 1000 110 . ... ... . . 0 ...@op_64
 
 BFMOPA  1001 100 . ... ... . . 00 ..@op_32
+FMOPA_h 1001 101 . ... ... . . 00 ..@op_32
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
index 61bab73cb7..6863a204d4 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/sme_helper.c
@@ -981,6 +981,80 @@ static inline uint32_t f16mop_adj_pair(uint32_t pair, 
uint32_t pg, uint32_t neg)
 return pair;
 }
 
+static float32 f16_dotadd(float32 sum, uint32_t e1, uint32_t e2,
+  float_status *s)
+{
+float64 e1r = float16_to_float64(e1 & 0x, true, s);
+float64 e1c = float16_to_float64(e1 >> 16, true, s);
+float64 e2r = float16_to_float64(e2 & 0x, true, s);
+float64 e2c = float16_to_float64(e2 >> 16, true, s);
+float64 t64;
+float32 t32;
+
+/*
+ * The ARM pseudocode function FPDot performs both multiplies
+ * and the add with a single rounding operation.  Emulate this
+ * by performing the first multiply in round-to-odd, then doing
+ * the second multiply as fused multiply-add, and rounding to
+ * float32 all in one step.
+ */
+FloatRoundMode old_rm = get_float_rounding_mode(s);
+set_float_rounding_mode(float_round_to_odd, s);
+
+t64 = float64_mul(e1r, e2r, s);
+
+set_float_rounding_mode(old_rm, s);
+
+t64 = float64r32_muladd(e1c, e2c, t64, 0, s);
+
+/* This conversion is exact, because we've already rounded. */
+t32 = float64_to_float32(t64, s);
+
+/* The final accumulation step is not fused. */
+return float32_add(sum, t32, s);
+}
+
+void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn,
+ void *vpm, void *vst, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_maxsz(desc);
+uint32_t neg = simd_data(desc) << 15;
+uint16_t *pn = vpn, *pm = vpm;
+
+bool save_dn = get_default_nan_mode(vst);
+set_default_nan_mode(true, vst);
+
+for (row = 0; row < oprsz; ) {
+uint16_t pa = pn[H2(row >> 4)];
+do {
+void *vza_row = vza + row * sizeof(ARMVectorReg);
+uint32_t n = *(uint32_t *)(vzn + row);
+
+n = f16mop_adj_pair(n, pa, neg);
+
+for (col = 0; col < oprsz; ) {
+uint16_t pb = pm[H2(col >> 4)];
+do {
+if ((pa & 0b0101) == 0b0101 || (pb & 0b0101) == 0b0101) {
+uint32_t *a = vza_row + col;
+uint32_t m = *(uint32_t *)(vzm + col);
+
+m = f16mop_adj_pair(m, pb, neg);
+*a = f16_dotadd(*a, n, m, vst);
+
+col += 4;
+pb >>= 4;
+}
+} while (col & 15);
+}
+row += 4;
+pa >>= 4;
+} while (row & 15);
+}
+
+set_default_nan_mode(save_dn, vst);
+}
+
 void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
 void *vpm, uint32_t desc)
 {
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
index 581bf9174f..847f2274b1 100644
--- a/target/arm/translate-sme.c
+++ b/target/arm/translate-sme.c
@@ -328,6 +328,8 @@ static bool do_outprod_fpst(DisasContext *s, arg_op *a, 
MemOp esz,
 return true;
 }
 
+TRANS_FEAT(FMOPA_h, aa64_sme, do_outprod_fpst,
+   a, MO_32, gen_helper_sme_fmopa_h)
 TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst,
a, MO_32, gen_helper_sme_fmopa_s)
 TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst,
-- 
2.34.1




[PATCH v3 27/51] target/arm: Export unpredicated ld/st from translate-sve.c

2022-06-20 Thread Richard Henderson
Add a TCGv_ptr base argument, which will be cpu_env for SVE.
We will reuse this for SME save and restore array insns.

Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.h |  3 +++
 target/arm/translate-sve.c | 48 --
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
index c341c95582..54503745a9 100644
--- a/target/arm/translate-a64.h
+++ b/target/arm/translate-a64.h
@@ -165,4 +165,7 @@ void gen_gvec_xar(unsigned vece, uint32_t rd_ofs, uint32_t 
rn_ofs,
   uint32_t rm_ofs, int64_t shift,
   uint32_t opr_sz, uint32_t max_sz);
 
+void gen_sve_ldr(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int 
imm);
+void gen_sve_str(DisasContext *s, TCGv_ptr, int vofs, int len, int rn, int 
imm);
+
 #endif /* TARGET_ARM_TRANSLATE_A64_H */
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 13bdd027a5..adf0cd3e68 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -4294,7 +4294,8 @@ TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz,
  * The load should begin at the address Rn + IMM.
  */
 
-static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
+void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
+ int len, int rn, int imm)
 {
 int len_align = QEMU_ALIGN_DOWN(len, 8);
 int len_remain = len % 8;
@@ -4320,7 +4321,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 t0 = tcg_temp_new_i64();
 for (i = 0; i < len_align; i += 8) {
 tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
-tcg_gen_st_i64(t0, cpu_env, vofs + i);
+tcg_gen_st_i64(t0, base, vofs + i);
 tcg_gen_addi_i64(clean_addr, clean_addr, 8);
 }
 tcg_temp_free_i64(t0);
@@ -4333,6 +4334,12 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 clean_addr = new_tmp_a64_local(s);
 tcg_gen_mov_i64(clean_addr, t0);
 
+if (base != cpu_env) {
+TCGv_ptr b = tcg_temp_local_new_ptr();
+tcg_gen_mov_ptr(b, base);
+base = b;
+}
+
 gen_set_label(loop);
 
 t0 = tcg_temp_new_i64();
@@ -4340,7 +4347,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 tcg_gen_addi_i64(clean_addr, clean_addr, 8);
 
 tp = tcg_temp_new_ptr();
-tcg_gen_add_ptr(tp, cpu_env, i);
+tcg_gen_add_ptr(tp, base, i);
 tcg_gen_addi_ptr(i, i, 8);
 tcg_gen_st_i64(t0, tp, vofs);
 tcg_temp_free_ptr(tp);
@@ -4348,6 +4355,11 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 
 tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
 tcg_temp_free_ptr(i);
+
+if (base != cpu_env) {
+tcg_temp_free_ptr(base);
+assert(len_remain == 0);
+}
 }
 
 /*
@@ -4376,13 +4388,14 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 default:
 g_assert_not_reached();
 }
-tcg_gen_st_i64(t0, cpu_env, vofs + len_align);
+tcg_gen_st_i64(t0, base, vofs + len_align);
 tcg_temp_free_i64(t0);
 }
 }
 
 /* Similarly for stores.  */
-static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm)
+void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
+ int len, int rn, int imm)
 {
 int len_align = QEMU_ALIGN_DOWN(len, 8);
 int len_remain = len % 8;
@@ -4408,7 +4421,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 
 t0 = tcg_temp_new_i64();
 for (i = 0; i < len_align; i += 8) {
-tcg_gen_ld_i64(t0, cpu_env, vofs + i);
+tcg_gen_ld_i64(t0, base, vofs + i);
 tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ);
 tcg_gen_addi_i64(clean_addr, clean_addr, 8);
 }
@@ -4422,11 +4435,17 @@ static void do_str(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 clean_addr = new_tmp_a64_local(s);
 tcg_gen_mov_i64(clean_addr, t0);
 
+if (base != cpu_env) {
+TCGv_ptr b = tcg_temp_local_new_ptr();
+tcg_gen_mov_ptr(b, base);
+base = b;
+}
+
 gen_set_label(loop);
 
 t0 = tcg_temp_new_i64();
 tp = tcg_temp_new_ptr();
-tcg_gen_add_ptr(tp, cpu_env, i);
+tcg_gen_add_ptr(tp, base, i);
 tcg_gen_ld_i64(t0, tp, vofs);
 tcg_gen_addi_ptr(i, i, 8);
 tcg_temp_free_ptr(tp);
@@ -4437,12 +4456,17 @@ static void do_str(DisasContext *s, uint32_t vofs, int 
len, int rn, int imm)
 
 tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
 tcg_temp_free_ptr(i);
+
+if (base != cpu_env) {
+tcg_temp_free_ptr(base);
+

[PATCH v3 10/51] target/arm: Implement SMSTART, SMSTOP

2022-06-20 Thread Richard Henderson
These two instructions are aliases of MSR (immediate).
Use the two helpers to properly implement svcr_write.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h   |  1 +
 target/arm/helper-sme.h| 21 +
 target/arm/helper.h|  1 +
 target/arm/helper.c|  6 ++--
 target/arm/sme_helper.c| 61 ++
 target/arm/translate-a64.c | 24 +++
 target/arm/meson.build |  1 +
 7 files changed, 112 insertions(+), 3 deletions(-)
 create mode 100644 target/arm/helper-sme.h
 create mode 100644 target/arm/sme_helper.c

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c3c7ec697d..2e049291da 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1106,6 +1106,7 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
int new_el, bool el0_a64);
 void aarch64_add_sve_properties(Object *obj);
 void aarch64_add_pauth_properties(Object *obj);
+void arm_reset_sve_state(CPUARMState *env);
 
 /*
  * SVE registers are encoded in KVM's memory in an endianness-invariant format.
diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
new file mode 100644
index 00..3bd48c235f
--- /dev/null
+++ b/target/arm/helper-sme.h
@@ -0,0 +1,21 @@
+/*
+ *  AArch64 SME specific helper definitions
+ *
+ *  Copyright (c) 2022 Linaro, Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+DEF_HELPER_FLAGS_2(set_pstate_sm, TCG_CALL_NO_RWG, void, env, i32)
+DEF_HELPER_FLAGS_2(set_pstate_za, TCG_CALL_NO_RWG, void, env, i32)
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 07d45faf49..3a8ce42ab0 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -1022,6 +1022,7 @@ DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
 #ifdef TARGET_AARCH64
 #include "helper-a64.h"
 #include "helper-sve.h"
+#include "helper-sme.h"
 #endif
 
 #include "helper-mve.h"
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e06c054c3d..88d96f7991 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6366,9 +6366,9 @@ static CPAccessResult access_esm(CPUARMState *env, const 
ARMCPRegInfo *ri,
 static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
 {
-value &= R_SVCR_SM_MASK | R_SVCR_ZA_MASK;
-/* TODO: Side effects. */
-env->svcr = value;
+helper_set_pstate_sm(env, FIELD_EX64(value, SVCR, SM));
+helper_set_pstate_za(env, FIELD_EX64(value, SVCR, ZA));
+arm_rebuild_hflags(env);
 }
 
 static void smcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
new file mode 100644
index 00..b215725594
--- /dev/null
+++ b/target/arm/sme_helper.c
@@ -0,0 +1,61 @@
+/*
+ * ARM SME Operations
+ *
+ * Copyright (c) 2022 Linaro, Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internals.h"
+#include "exec/helper-proto.h"
+
+/* ResetSVEState */
+void arm_reset_sve_state(CPUARMState *env)
+{
+memset(env->vfp.zregs, 0, sizeof(env->vfp.zregs));
+/* Recall that FFR is stored as pregs[16]. */
+memset(env->vfp.pregs, 0, sizeof(env->vfp.pregs));
+vfp_set_fpcr(env, 0x089f);
+}
+
+void helper_set_pstate_sm(CPUARMState *env, uint32_t i)
+{
+if (i == FIELD_EX64(env->svcr, SVCR, SM)) {
+return;
+}
+env->svcr ^= R_SVCR_SM_MASK;
+arm_reset_sve_state(env);
+}
+
+void helper_set_pstate_za(CPUARMState *env, uint32_t i)
+{
+if (i == FIELD_EX64(env->svcr, SVCR, ZA)) {
+return;
+}
+env->svcr ^= R_SVCR_ZA_MASK;
+
+/*
+ * ResetSMEState.
+ *
+ * SetPSTATE_ZA zeros on enable and 

[PATCH v3 20/51] target/arm: Move pred_{full, gvec}_reg_{offset, size} to translate-a64.h

2022-06-20 Thread Richard Henderson
We will need these functions in translate-sme.c.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.h | 38 ++
 target/arm/translate-sve.c | 36 
 2 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
index dbc917ee65..f0970c6b8c 100644
--- a/target/arm/translate-a64.h
+++ b/target/arm/translate-a64.h
@@ -107,6 +107,44 @@ static inline int vec_full_reg_size(DisasContext *s)
 return s->vl;
 }
 
+/*
+ * Return the offset info CPUARMState of the predicate vector register Pn.
+ * Note for this purpose, FFR is P16.
+ */
+static inline int pred_full_reg_offset(DisasContext *s, int regno)
+{
+return offsetof(CPUARMState, vfp.pregs[regno]);
+}
+
+/* Return the byte size of the whole predicate register, VL / 64.  */
+static inline int pred_full_reg_size(DisasContext *s)
+{
+return s->vl >> 3;
+}
+
+/*
+ * Round up the size of a register to a size allowed by
+ * the tcg vector infrastructure.  Any operation which uses this
+ * size may assume that the bits above pred_full_reg_size are zero,
+ * and must leave them the same way.
+ *
+ * Note that this is not needed for the vector registers as they
+ * are always properly sized for tcg vectors.
+ */
+static inline int size_for_gvec(int size)
+{
+if (size <= 8) {
+return 8;
+} else {
+return QEMU_ALIGN_UP(size, 16);
+}
+}
+
+static inline int pred_gvec_reg_size(DisasContext *s)
+{
+return size_for_gvec(pred_full_reg_size(s));
+}
+
 bool disas_sve(DisasContext *, uint32_t);
 
 void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 67761bf2cc..62b5f3040c 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -100,42 +100,6 @@ static inline int msz_dtype(DisasContext *s, int msz)
  * Implement all of the translator functions referenced by the decoder.
  */
 
-/* Return the offset info CPUARMState of the predicate vector register Pn.
- * Note for this purpose, FFR is P16.
- */
-static inline int pred_full_reg_offset(DisasContext *s, int regno)
-{
-return offsetof(CPUARMState, vfp.pregs[regno]);
-}
-
-/* Return the byte size of the whole predicate register, VL / 64.  */
-static inline int pred_full_reg_size(DisasContext *s)
-{
-return s->vl >> 3;
-}
-
-/* Round up the size of a register to a size allowed by
- * the tcg vector infrastructure.  Any operation which uses this
- * size may assume that the bits above pred_full_reg_size are zero,
- * and must leave them the same way.
- *
- * Note that this is not needed for the vector registers as they
- * are always properly sized for tcg vectors.
- */
-static int size_for_gvec(int size)
-{
-if (size <= 8) {
-return 8;
-} else {
-return QEMU_ALIGN_UP(size, 16);
-}
-}
-
-static int pred_gvec_reg_size(DisasContext *s)
-{
-return size_for_gvec(pred_full_reg_size(s));
-}
-
 /* Invoke an out-of-line helper on 2 Zregs. */
 static bool gen_gvec_ool_zz(DisasContext *s, gen_helper_gvec_2 *fn,
 int rd, int rn, int data)
-- 
2.34.1




[PATCH v3 31/51] target/arm: Implement BFMOPA, BFMOPS

2022-06-20 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper-sme.h|  2 ++
 target/arm/sme.decode  |  2 ++
 target/arm/sme_helper.c| 52 ++
 target/arm/translate-sme.c | 29 +
 4 files changed, 85 insertions(+)

diff --git a/target/arm/helper-sme.h b/target/arm/helper-sme.h
index 727095a3eb..6b36542133 100644
--- a/target/arm/helper-sme.h
+++ b/target/arm/helper-sme.h
@@ -124,3 +124,5 @@ DEF_HELPER_FLAGS_7(sme_fmopa_s, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_7(sme_fmopa_d, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_6(sme_bfmopa, TCG_CALL_NO_RWG,
+   void, ptr, ptr, ptr, ptr, ptr, i32)
diff --git a/target/arm/sme.decode b/target/arm/sme.decode
index ba4774d174..afd9c0dffd 100644
--- a/target/arm/sme.decode
+++ b/target/arm/sme.decode
@@ -73,3 +73,5 @@ ADDVA_d 1100 11 01000 1 ... ... . 00 ...  
  @adda_64
 
 FMOPA_s 1000 100 . ... ... . . 00 ..@op_32
 FMOPA_d 1000 110 . ... ... . . 0 ...@op_64
+
+BFMOPA  1001 100 . ... ... . . 00 ..@op_32
diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c
index 62d9690cae..61bab73cb7 100644
--- a/target/arm/sme_helper.c
+++ b/target/arm/sme_helper.c
@@ -964,3 +964,55 @@ void HELPER(sme_fmopa_d)(void *vza, void *vzn, void *vzm, 
void *vpn,
 
 set_default_nan_mode(save_dn, vst);
 }
+
+/*
+ * Alter PAIR as needed for controlling predicates being false,
+ * and for NEG on an enabled row element.
+ */
+static inline uint32_t f16mop_adj_pair(uint32_t pair, uint32_t pg, uint32_t 
neg)
+{
+pair ^= neg;
+if (!(pg & 1)) {
+pair &= 0xu;
+}
+if (!(pg & 4)) {
+pair &= 0xu;
+}
+return pair;
+}
+
+void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn,
+void *vpm, uint32_t desc)
+{
+intptr_t row, col, oprsz = simd_maxsz(desc);
+uint32_t neg = simd_data(desc) << 15;
+uint16_t *pn = vpn, *pm = vpm;
+
+for (row = 0; row < oprsz; ) {
+uint16_t pa = pn[H2(row >> 4)];
+do {
+void *vza_row = vza + row * sizeof(ARMVectorReg);
+uint32_t n = *(uint32_t *)(vzn + row);
+
+n = f16mop_adj_pair(n, pa, neg);
+
+for (col = 0; col < oprsz; ) {
+uint16_t pb = pm[H2(col >> 4)];
+do {
+if ((pa & 0b0101) == 0b0101 || (pb & 0b0101) == 0b0101) {
+uint32_t *a = vza_row + col;
+uint32_t m = *(uint32_t *)(vzm + col);
+
+m = f16mop_adj_pair(m, pb, neg);
+*a = bfdotadd(*a, n, m);
+
+col += 4;
+pb >>= 4;
+}
+} while (col & 15);
+}
+row += 4;
+pa >>= 4;
+} while (row & 15);
+}
+}
diff --git a/target/arm/translate-sme.c b/target/arm/translate-sme.c
index e6e4541e76..581bf9174f 100644
--- a/target/arm/translate-sme.c
+++ b/target/arm/translate-sme.c
@@ -274,6 +274,32 @@ TRANS_FEAT(ADDVA_s, aa64_sme, do_adda, a, MO_32, 
gen_helper_sme_addva_s)
 TRANS_FEAT(ADDHA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addha_d)
 TRANS_FEAT(ADDVA_d, aa64_sme_i16i64, do_adda, a, MO_64, gen_helper_sme_addva_d)
 
+static bool do_outprod(DisasContext *s, arg_op *a, MemOp esz,
+   gen_helper_gvec_5 *fn)
+{
+uint32_t desc = simd_desc(s->svl, s->svl, a->sub);
+TCGv_ptr za, zn, zm, pn, pm;
+
+if (!sme_smza_enabled_check(s)) {
+return true;
+}
+
+/* Sum XZR+zad to find ZAd. */
+za = get_tile_rowcol(s, esz, 31, a->zad, false);
+zn = vec_full_reg_ptr(s, a->zn);
+zm = vec_full_reg_ptr(s, a->zm);
+pn = pred_full_reg_ptr(s, a->pn);
+pm = pred_full_reg_ptr(s, a->pm);
+
+fn(za, zn, zm, pn, pm, tcg_constant_i32(desc));
+
+tcg_temp_free_ptr(za);
+tcg_temp_free_ptr(zn);
+tcg_temp_free_ptr(pn);
+tcg_temp_free_ptr(pm);
+return true;
+}
+
 static bool do_outprod_fpst(DisasContext *s, arg_op *a, MemOp esz,
 gen_helper_gvec_5_ptr *fn)
 {
@@ -306,3 +332,6 @@ TRANS_FEAT(FMOPA_s, aa64_sme, do_outprod_fpst,
a, MO_32, gen_helper_sme_fmopa_s)
 TRANS_FEAT(FMOPA_d, aa64_sme_f64f64, do_outprod_fpst,
a, MO_64, gen_helper_sme_fmopa_d)
+
+/* TODO: FEAT_EBF16 */
+TRANS_FEAT(BFMOPA, aa64_sme, do_outprod, a, MO_32, gen_helper_sme_bfmopa)
-- 
2.34.1




[PATCH v3 09/51] target/arm: Add the SME ZA storage to CPUARMState

2022-06-20 Thread Richard Henderson
Place this late in the resettable section of the structure,
to keep the most common element offsets from being > 64k.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.h |  8 
 target/arm/machine.c | 34 ++
 2 files changed, 42 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 05d369e690..c3c7ec697d 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -694,6 +694,14 @@ typedef struct CPUArchState {
 } keys;
 
 uint64_t scxtnum_el[4];
+
+/*
+ * SME ZA storage -- 256 x 256 byte array, with bytes in host word order,
+ * as we do with vfp.zregs[].  Because this is so large, keep this toward
+ * the end of the reset area, to keep the offsets into the rest of the
+ * structure smaller.
+ */
+ARMVectorReg zarray[ARM_MAX_VQ * 16];
 #endif
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 285e387d2c..54c5c62433 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -167,6 +167,39 @@ static const VMStateDescription vmstate_sve = {
 VMSTATE_END_OF_LIST()
 }
 };
+
+static const VMStateDescription vmstate_vreg = {
+.name = "vreg",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT64_ARRAY(d, ARMVectorReg, ARM_MAX_VQ * 2),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static bool za_needed(void *opaque)
+{
+ARMCPU *cpu = opaque;
+
+/*
+ * When ZA storage is disabled, its contents are discarded.
+ * It will be zeroed when ZA storage is re-enabled.
+ */
+return FIELD_EX64(cpu->env.svcr, SVCR, ZA);
+}
+
+static const VMStateDescription vmstate_za = {
+.name = "cpu/sme",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = za_needed,
+.fields = (VMStateField[]) {
+VMSTATE_STRUCT_ARRAY(env.zarray, ARMCPU, ARM_MAX_VQ * 16, 0,
+ vmstate_vreg, ARMVectorReg),
+VMSTATE_END_OF_LIST()
+}
+};
 #endif /* AARCH64 */
 
 static bool serror_needed(void *opaque)
@@ -884,6 +917,7 @@ const VMStateDescription vmstate_arm_cpu = {
 _m_security,
 #ifdef TARGET_AARCH64
 _sve,
+_za,
 #endif
 _serror,
 _irq_line_state,
-- 
2.34.1




  1   2   3   4   >