Re: [PATCH] virtio-blk: drop deprecated scsi=on|off property

2021-04-29 Thread Michal Prívozník
On 4/29/21 5:52 PM, Stefan Hajnoczi wrote:
> The scsi=on|off property was deprecated in QEMU 5.0 and can be removed
> completely at this point.
> 
> Drop the scsi=on|off option. It was only available on Legacy virtio-blk
> devices. Linux v5.6 already dropped support for it.
> 
> Remove the hw_compat_2_4[] property assignment since scsi=on|off no
> longer exists. Old guests with Legacy virtio-blk devices no longer see
> the SCSI host features bit.
> 
> Live migrating old guests from an old QEMU with the SCSI feature bit
> enabled will fail with "Features 0x... unsupported. Allowed features:
> 0x...". We've followed the QEMU deprecation policy so users have been
> warned...
> 
> I have tested that libvirt still works when the property is absent. It
> no longer adds scsi=on|off to the command-line.
> 
> Cc: Markus Armbruster 
> Cc: Christoph Hellwig 
> Cc: Peter Krempa 
> Cc: Dr. David Alan Gilbert 
> Signed-off-by: Stefan Hajnoczi 
> ---
>  docs/specs/tpm.rst   |   2 +-
>  docs/system/deprecated.rst   |  13 ---
>  docs/pci_expander_bridge.txt |   2 +-
>  hw/block/virtio-blk.c| 192 +--
>  hw/core/machine.c|   2 -
>  5 files changed, 3 insertions(+), 208 deletions(-)

Reviewed-by: Michal Privoznik 

Michal




Re: [RFC PATCH v2 2/4] hw/arm/virt: Parse -smp cluster parameter in virt_smp_parse

2021-04-29 Thread wangyanan (Y)

Hi Drew,

On 2021/4/29 19:02, Andrew Jones wrote:

On Thu, Apr 29, 2021 at 04:56:06PM +0800, wangyanan (Y) wrote:

On 2021/4/29 15:16, Andrew Jones wrote:

On Thu, Apr 29, 2021 at 10:14:37AM +0800, wangyanan (Y) wrote:

On 2021/4/28 18:31, Andrew Jones wrote:

On Tue, Apr 13, 2021 at 04:31:45PM +0800, Yanan Wang wrote:

} else if (sockets == 0) {
threads = threads > 0 ? threads : 1;
-sockets = cpus / (cores * threads);
+sockets = cpus / (clusters * cores * threads);
sockets = sockets > 0 ? sockets : 1;

If we initialize clusters to zero instead of one and add lines in
'cpus == 0 || cores == 0' and 'sockets == 0' like
'clusters = clusters > 0 ? clusters : 1' as needed, then I think we can
add

} else if (clusters == 0) {
threads = threads > 0 ? threads : 1;
clusters = cpus / (sockets * cores * thread);
clusters = clusters > 0 ? clusters : 1;
}

here.

I have thought about this kind of format before, but there is a little bit
difference between these two ways. Let's chose the better and more
reasonable one of the two.

Way A currently in this patch:
If value of clusters is not explicitly specified in -smp command line, we
assume
that users don't want to support clusters, for compatibility we initialized
the
value to 1. So that with cmdline "-smp cpus=24, sockets=2, cores=6", we will
parse out the topology description like below:
cpus=24, sockets=2, clusters=1, cores=6, threads=2

Way B that you suggested for this patch:
Whether value of clusters is explicitly specified in -smp command line or
not,
we assume that clusters are supported and calculate the value. So that with
cmdline "-smp cpus=24, sockets=2, cores=6", we will parse out the topology
description like below:
cpus =24, sockets=2, clusters=2, cores=6, threads=1

But I think maybe we should not assume too much about what users think
through the -smp command line. We should just assume that all levels of
cpu topology are supported and calculate them, and users should be more
careful if they want to get the expected results with not so complete
cmdline.
If I'm right, then Way B should be better. :)


Hi Yanan,

We're already assuming the user wants to describe clusters to the guest
because we require at least one per socket. If we want the user to have a
choice between using clusters or not, then I guess we need to change the
logic in the PPTT and the cpu-map to only generate the cluster level when
the number of clusters is not zero. And then change this parser to not
require clusters at all.

Hi Drew,

I think this kind of change will introduce more complexity and actually is
not necessary.
Not generating cluster level at all and generating cluster level (one per
socket) are same
to kernel. Without cluster description provided, kernel will initialize all
cores in the same
cluster which also means one cluster per socket.

Which kernel? All kernels? One without the cluster support patches [1]?

[1] 
https://lore.kernel.org/lkml/20210420001844.9116-1-song.bao@hisilicon.com/#t

I'm sorry, I didn't make it clear. :)
I actually mean the ARM64 kernel, with or without [1].

Without [1]: Kernel doesn't care about cluster. When populating cpu 
topology, it directly
finds the hierarchy node with "physical package flag" as package when 
parsing ACPI, and
finds the core node's parent as package when parsing DT. So even we 
provide cluster level
description (one per socket), the parsing results will be the same as 
not providing at all.


With [1]: Kernel finds the core hierarchy node's parent as cluster when 
parsing ACPI. So if
we don't provide cluster level description, package will be taken as 
cluster. And if we provide

the description (one per socket), the parsing result will also be the same.

That's why I said that we just need to provide description of cluster 
(one per socket) if we

don't want to make use of it in VMs.

[1] 
https://lore.kernel.org/lkml/20210420001844.9116-1-song.bao@hisilicon.com/#t

So we should only ensure value of clusters per socket is one if we don't
want to use clusters,
and don't need to care about whether or not to generate description in PPTT
and cpu-map.
Is this right?

Depends on your answer to my 'which kernel' questions.


I'm not a big fan of these auto-calculated values either, but the
documentation says that it'll do that, and it's been done that way
forever, so I think we're stuck with it for the -smp option. Hmm, I was
just about to say that x86 computes all its values, but I see the most
recently added one, 'dies', is implemented the way you're proposing we
implement 'clusters', i.e. default to one and don't calculate it when it's
missing. I actually consider that either a documentation bug or an smp
parsing bug, though.

My propose originally came from implementation of x86.

Another possible option, for Arm, because only the cpus and maxcpus
parameters of -smp have ever worked, is to document, for Arm, that 

Re: [PATCH RFC v5 07/12] hw/riscv: PLIC update external interrupt by KVM when kvm enabled

2021-04-29 Thread Anup Patel
On Mon, Apr 12, 2021 at 12:24 PM Yifei Jiang  wrote:
>
> Only support supervisor external interrupt currently.
>
> Signed-off-by: Yifei Jiang 
> Signed-off-by: Yipeng Yin 
> ---
>  hw/intc/sifive_plic.c| 29 -
>  target/riscv/kvm-stub.c  |  5 +
>  target/riscv/kvm.c   | 20 
>  target/riscv/kvm_riscv.h |  1 +
>  4 files changed, 46 insertions(+), 9 deletions(-)
>
> diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
> index 97a1a27a9a..2746eb7a05 100644
> --- a/hw/intc/sifive_plic.c
> +++ b/hw/intc/sifive_plic.c
> @@ -31,6 +31,8 @@
>  #include "target/riscv/cpu.h"
>  #include "sysemu/sysemu.h"
>  #include "migration/vmstate.h"
> +#include "sysemu/kvm.h"
> +#include "kvm_riscv.h"
>
>  #define RISCV_DEBUG_PLIC 0
>
> @@ -147,15 +149,24 @@ static void sifive_plic_update(SiFivePLICState *plic)
>  continue;
>  }
>  int level = sifive_plic_irqs_pending(plic, addrid);
> -switch (mode) {
> -case PLICMode_M:
> -riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_MEIP, 
> BOOL_TO_MASK(level));
> -break;
> -case PLICMode_S:
> -riscv_cpu_update_mip(RISCV_CPU(cpu), MIP_SEIP, 
> BOOL_TO_MASK(level));
> -break;
> -default:
> -break;
> +if (kvm_enabled()) {
> +if (mode == PLICMode_M) {
> +continue;
> +}
> +kvm_riscv_set_irq(RISCV_CPU(cpu), IRQ_S_EXT, level);
> +} else {
> +switch (mode) {
> +case PLICMode_M:
> +riscv_cpu_update_mip(RISCV_CPU(cpu),
> + MIP_MEIP, BOOL_TO_MASK(level));
> +break;
> +case PLICMode_S:
> +riscv_cpu_update_mip(RISCV_CPU(cpu),
> + MIP_SEIP, BOOL_TO_MASK(level));
> +break;
> +default:
> +break;
> +}

I am not comfortable with this patch.

This way we will endup calling kvm_riscv_set_irq() from various
places in hw/intc and hw/riscv.

I suggest to extend riscv_cpu_update_mip() such that when kvm is
enabled riscv_cpu_update_mip() will:
1) Consider only MIP_SEIP bit in "mask" parameter and all other
bits in "mask" parameter will be ignored probably with warning
2) When the MIP_SEIP bit is set in "mask" call kvm_riscv_set_irq()
to change the IRQ state in the KVM module.

Regards,
Anup

>  }
>  }
>
> diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm-stub.c
> index 39b96fe3f4..4e8fc31a21 100644
> --- a/target/riscv/kvm-stub.c
> +++ b/target/riscv/kvm-stub.c
> @@ -23,3 +23,8 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
>  {
>  abort();
>  }
> +
> +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
> +{
> +abort();
> +}
> diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
> index 79c931acb4..da63535812 100644
> --- a/target/riscv/kvm.c
> +++ b/target/riscv/kvm.c
> @@ -453,6 +453,26 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu)
>  env->gpr[11] = cpu->env.fdt_addr;  /* a1 */
>  }
>
> +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
> +{
> +int ret;
> +unsigned virq = level ? KVM_INTERRUPT_SET : KVM_INTERRUPT_UNSET;
> +
> +if (irq != IRQ_S_EXT) {
> +return;
> +}
> +
> +if (!kvm_enabled()) {
> +return;
> +}
> +
> +ret = kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, );
> +if (ret < 0) {
> +perror("Set irq failed");
> +abort();
> +}
> +}
> +
>  bool kvm_arch_cpu_check_are_resettable(void)
>  {
>  return true;
> diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h
> index f38c82bf59..ed281bdce0 100644
> --- a/target/riscv/kvm_riscv.h
> +++ b/target/riscv/kvm_riscv.h
> @@ -20,5 +20,6 @@
>  #define QEMU_KVM_RISCV_H
>
>  void kvm_riscv_reset_vcpu(RISCVCPU *cpu);
> +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level);
>
>  #endif
> --
> 2.19.1
>
>
> --
> kvm-riscv mailing list
> kvm-ri...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kvm-riscv



Re: [PATCH v2 4/7] target/ppc: turned SPR R/W callbacks not static

2021-04-29 Thread Richard Henderson

On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote:

To be able to compile translate_init.c.inc as a standalone file,
we have to make the callbacks accessible outside of translate.c;
This patch does that, making the callbacks not static and creating
a new .h file

Signed-off-by: Bruno Larsen (billionai)
---
  target/ppc/spr_tcg.c.inc | 203 ---
  target/ppc/spr_tcg.h | 121 +++
  2 files changed, 223 insertions(+), 101 deletions(-)
  create mode 100644 target/ppc/spr_tcg.h


FWIW, a good follow-up would be to separately compile this.


r~



Re: [PATCH v2 7/7] target/ppc: isolated cpu init from translation logic

2021-04-29 Thread Richard Henderson

On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote:

@@ -49,7 +54,12 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val)
  {
  /* Altivec always uses round-to-nearest */
  set_float_rounding_mode(float_round_nearest_even, >vec_status);
-helper_mtvscr(env, val);
+/*
+ * This comment is here just so the project will build.
+ * The current solution is in another patch and will be
+ * added when we figure out an internal fork of qemu
+ */
+/* helper_mtvscr(env, val); */
  }


(1) this is a separate change to splitting out cpu_init.c.
(2) you can't even do this without introducing a regression.


r~



Re: [PATCH v2 6/7] target/ttc: renamed SPR registration functions

2021-04-29 Thread Richard Henderson

On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote:

Renamed all gen_spr_* and gen_* functions specifically related to
registering SPRs to register_*_sprs and register_*, to avoid future
confusion with other TCG related code.

Signed-off-by: Bruno Larsen (billionai)
---
  target/ppc/translate_init.c.inc | 860 
  1 file changed, 430 insertions(+), 430 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 4/7] target/ppc: turned SPR R/W callbacks not static

2021-04-29 Thread Richard Henderson

On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote:

@@ -234,19 +235,19 @@ static void spr_read_tbu(DisasContext *ctx, int gprn, int 
sprn)
  }
  
  ATTRIBUTE_UNUSED

-static void spr_read_atbl(DisasContext *ctx, int gprn, int sprn)
+void spr_read_atbl(DisasContext *ctx, int gprn, int sprn)
  {


You can drop the ATTRIBUTE_UNUSED at the same time.

It was only there to stop the static symbol from being signaled as unused; for 
a non-static symbol, the compiler obviously can't tell.



diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h
new file mode 100644
index 00..b573a23e7b
--- /dev/null
+++ b/target/ppc/spr_tcg.h
@@ -0,0 +1,121 @@
+#ifndef SPR_TCG_H
+#define SPR_TCG_H
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/translator.h"
+#include "tcg/tcg.h"


All new files get copyright headers.  No headers include osdep.h.  It doesn't 
appear that you need any headers for this file; just add


typedef struct DisasContext DisasContext;

to the top of the file.


r~



Re: [PATCH v2 3/7] target/ppc: Isolated SPR read/write callbacks

2021-04-29 Thread Richard Henderson

On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote:

diff --git a/target/ppc/spr_tcg.c.inc b/target/ppc/spr_tcg.c.inc
new file mode 100644
index 00..48274dd52b
--- /dev/null
+++ b/target/ppc/spr_tcg.c.inc
@@ -0,0 +1,1033 @@
+#include "exec/translator.h"


All new files must have copyright header.


+/* I really see no reason to keep these gen_*_xer */
+/* instead of just leaving the code in the spr_*_xer */


Then just do that, as a separate patch, before or after.


@@ -8515,3 +8471,4 @@ void restore_state_to_opc(CPUPPCState *env, 
TranslationBlock *tb,
  {
  env->nip = data[0];
  }
+


Watch the extra whitespace at end of file.


r~



Re: Let's remove some deprecated stuff

2021-04-29 Thread Robert Hoo
On Thu, 2021-04-29 at 11:59 +0200, Markus Armbruster wrote:
> If you're cc'ed, you added a section to docs/system/deprecated.rst
> that
> is old enough to permit removal.  This is *not* a demand to remove,
> it's
> a polite request to consider whether the time for removal has come.
> Extra points for telling us in a reply.  "We should remove, but I
> can't
> do it myself right now" is a valid answer.  Let's review the file:
> 
> System emulator command line arguments
> --
> 
[...]
> 
> Robert Hoo:
> 
> ``Icelake-Client`` CPU Model (since 5.2.0)
> ''
> 
> ``Icelake-Client`` CPU Models are deprecated. Use ``Icelake-
> Server`` CPU
> Models instead.
> 
Yeah, please drop this entry.
Actually I've sent patches for this.
https://lore.kernel.org/qemu-devel/1619660147-136679-1-git-send-email-robert...@linux.intel.com/




Re: [PATCH v2] target/i386: add "-cpu, lbr-fmt=*" support to enable guest LBR

2021-04-29 Thread Like Xu

Hi Eduardo,

Thanks for your detailed comments.

On 2021/4/29 5:19, Eduardo Habkost wrote:

On Tue, Apr 27, 2021 at 04:09:48PM +0800, Like Xu wrote:

The last branch recording (LBR) is a performance monitor unit (PMU)
feature on Intel processors that records a running trace of the most
recent branches taken by the processor in the LBR stack. The QEMU
could configure whether it's enabled or not for each guest via CLI.

The LBR feature would be enabled on the guest if:
- the KVM is enabled and the PMU is enabled and,
- the msr-based-feature IA32_PERF_CAPABILITIES is supporterd on KVM and,
- the supported returned value for lbr_fmt from this msr is not zero and,
- the requested guest vcpu model does support FEAT_1_ECX.CPUID_EXT_PDCM,
- the configured lbr-fmt value is the same as the host lbr_fmt value
   OR use the QEMU option "-cpu host,migratable=no".


I don't understand why "migratable" matters here.  "migratable"
is just a convenience property to get better defaults when using
"-cpu host".  I don't know why it would change the lbr-fmt
validation rules.


Your comments bevlow help me understand why we introduced "migratable"
and I'll fllow it.





Signed-off-by: Like Xu 
---


A changelog explaining what you changed since v1 would have been
useful here.


Sorry for inconvenience.




  target/i386/cpu.c | 34 ++
  target/i386/cpu.h | 10 ++
  target/i386/kvm/kvm.c | 10 --
  3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index ad99cad0e7..9c8e54aa6f 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6623,6 +6623,10 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool 
verbose)
  }
  
  for (w = 0; w < FEATURE_WORDS; w++) {

+if (w == FEAT_PERF_CAPABILITIES) {
+continue;
+}
+


Why exactly is this necessary?  I expected to be completely OK to
call mark_unavailable_features() multiple times for the same
FeatureWord.



OK.


If there's a reason why this is necessary, I suggest adding a
comment explaining why.


  uint64_t host_feat =
  x86_cpu_get_supported_feature_word(w, false);
  uint64_t requested_features = env->features[w];
@@ -6630,6 +6634,27 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool 
verbose)
  mark_unavailable_features(cpu, w, unavailable_features, prefix);
  }
  
+uint64_t host_perf_cap =

+x86_cpu_get_supported_feature_word(FEAT_PERF_CAPABILITIES, false);
+if (!cpu->lbr_fmt && !cpu->migratable) {
+cpu->lbr_fmt = host_perf_cap & PERF_CAP_LBR_FMT;


"migratable=no" is not a request to override explicit user
settings.  This is why we have the ~env->user_features masking
inside x86_cpu_expand_features() when initializing
env->features[].

In either case, I don't understand why you need the lines above.
"migratable=no" should already trigger the x86_cpu_get_supported_feature_word()
loop inside x86_cpu_expand_features(), and it should initialize
env->features[FEAT_PERF_CAPABILITIES] with the host value.  Isn't
that code working for you?



+if (cpu->lbr_fmt) {
+info_report("vPMU: The value of lbr-fmt has been adjusted "
+"to 0x%lx and guest LBR is enabled.",
+host_perf_cap & PERF_CAP_LBR_FMT);




From your other message:


(I'm assuming your examples are for a lbr-fmt=5 host)


"-cpu host,migratable=no" --> "Enable guest LBR and show warning"


Enabling guest LBR in this case is 100% OK, isn't it?  I don't
think you need to show a warning.



"-cpu host,migratable=no,lbr-fmt=0" --> "Enable guest LBR and show warning"


Why?  In this case, we should do what the user asked for whenever
possible, and the user is explicitly asking lbr-fmt to be 0.


"-cpu host,migratable=no,lbr-fmt=5" --> "Enable guest LBR"


Looks OK.


"-cpu host,migratable=no,lbr-fmt=6" --> "Disable guest LBR and show warning"


Makes sense to me[1].



+}
+} else {
+uint64_t requested_lbr_fmt = cpu->lbr_fmt & PERF_CAP_LBR_FMT;
+if (requested_lbr_fmt && kvm_enabled()) {




From your other message:



"-cpu host,lbr-fmt=0" --> "Disable guest LBR"


Makes sense to me.  I understand this as a confirmation that it's
OK to have a guest/host mismatch if guest LBR=0.


"-cpu host,lbr-fmt=5" --> "Enable guest LBR"


Makes sense to me.


"-cpu host,lbr-fmt=6" --> "Disable guest LBR and show warning"


Makes sense to me[1].


[1] As long as "show warning" becomes "fatal error" if enforce=1.
 mark_unavailable_features() should make sure this happens.

 Or maybe we should make this an error?  It would be even
 better.  The example code below makes it an error.



+if (requested_lbr_fmt != (host_perf_cap & PERF_CAP_LBR_FMT)) {
+cpu->lbr_fmt = 0;
+warn_report("vPMU: The supported lbr-fmt value on the host "
+"is 0x%lx and guest LBR is 

Re: [PATCH v2 1/7] target/ppc: move opcode table logic to translate.c

2021-04-29 Thread Richard Henderson

On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote:

code motion to remove opcode callback table from
translate_init.c.inc to translate.c in preparation to remove
the #include  from translate.c. Also created
destroy_ppc_opcodes and removed that logic from ppc_cpu_unrealize

Signed-off-by: Bruno Larsen (billionai)
---
  target/ppc/internal.h   |   8 +
  target/ppc/translate.c  | 394 
  target/ppc/translate_init.c.inc | 391 +--
  3 files changed, 403 insertions(+), 390 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 0/7] target/ppc: untangle cpu init from translation

2021-04-29 Thread Richard Henderson

On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote:

This series requires the patch proposed in
<20210426184706.48040-1-bruno.lar...@eldorado.org.br>


FYI, for the benefit of tooling, use "Based-on: message-id" which will allow 
patchew to construct a patch repository.


As is,

https://patchew.org/QEMU/20210429162130.2412-1-bruno.lar...@eldorado.org.br/

reports "Failed in applying to current master". Compare that to

https://patchew.org/QEMU/20210416210240.1591291-1-richard.hender...@linaro.org/

(which, no coincidence, is the first one I could think of that uses Based-on).


r~



[PATCH v2] Set the correct env->fpip for x86 float instructions

2021-04-29 Thread Ziqiao Kong
Thanks the review for v1 from Richard Henderson!

Changes since v1:
  - Don't update FCS, FIP, FDS and FDP for x87 control instruction.
  - Also write FCS, FDS and FDP for FSTENV.
  - Clear FCS, FIP, FDS and FDP for FXSAVE as intel manual says.

Note:
  During my test, I find that the implementation between some intel cpus
  differs on updating FDS and FDP while the AMD Ryzen always update the 
  two registers correctly. Not sure wthether it's a bug or not.

Ziqiao

Signed-off-by: Ziqiao Kong 
---
 target/i386/cpu.h|  4 +++
 target/i386/tcg/fpu_helper.c | 50 ++--
 target/i386/tcg/translate.c  | 45 +++-
 3 files changed, 79 insertions(+), 20 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 570f916878..ba43ceb4ad 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -705,6 +705,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EBX_INVPCID   (1U << 10)
 /* Restricted Transactional Memory */
 #define CPUID_7_0_EBX_RTM   (1U << 11)
+/* Deprecates FPU CS and FPU DS values */
+#define CPUID_7_0_EBX_FCS_FDS   (1U << 13)
 /* Memory Protection Extension */
 #define CPUID_7_0_EBX_MPX   (1U << 14)
 /* AVX-512 Foundation */
@@ -1440,7 +1442,9 @@ typedef struct CPUX86State {
 FPReg fpregs[8];
 /* KVM-only so far */
 uint16_t fpop;
+uint16_t fpcs;
 uint64_t fpip;
+uint16_t fpds;
 uint64_t fpdp;
 
 /* emulator internal variables */
diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c
index 60ed93520a..97cf68542b 100644
--- a/target/i386/tcg/fpu_helper.c
+++ b/target/i386/tcg/fpu_helper.c
@@ -766,6 +766,10 @@ void helper_fninit(CPUX86State *env)
 {
 env->fpus = 0;
 env->fpstt = 0;
+env->fpcs = 0;
+env->fpip = 0;
+env->fpds = 0;
+env->fpdp = 0;
 cpu_set_fpuc(env, 0x37f);
 env->fptags[0] = 1;
 env->fptags[1] = 1;
@@ -2368,6 +2372,7 @@ static void do_fstenv(CPUX86State *env, target_ulong ptr, 
int data32,
 {
 int fpus, fptag, exp, i;
 uint64_t mant;
+uint16_t fpcs, fpds;
 CPU_LDoubleU tmp;
 
 fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
@@ -2390,24 +2395,41 @@ static void do_fstenv(CPUX86State *env, target_ulong 
ptr, int data32,
 }
 }
 }
+
+/*
+ * If CR0.PE = 1, each instruction saves FCS and FDS into memory. If
+ * CPUID.(EAX=07H,ECX=0H):EBX[bit 13] = 1, the processor deprecates
+ * FCS and FDS; it saves each as H.
+ */
+if (!(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_FCS_FDS)
+&& (env->cr[0] & CR0_PE_MASK)) {
+fpcs = env->fpcs;
+fpds = env->fpds;
+} else {
+fpcs = 0;
+fpds = 0;
+}
+
 if (data32) {
 /* 32 bit */
 cpu_stl_data_ra(env, ptr, env->fpuc, retaddr);
 cpu_stl_data_ra(env, ptr + 4, fpus, retaddr);
 cpu_stl_data_ra(env, ptr + 8, fptag, retaddr);
-cpu_stl_data_ra(env, ptr + 12, 0, retaddr); /* fpip */
-cpu_stl_data_ra(env, ptr + 16, 0, retaddr); /* fpcs */
-cpu_stl_data_ra(env, ptr + 20, 0, retaddr); /* fpoo */
-cpu_stl_data_ra(env, ptr + 24, 0, retaddr); /* fpos */
+cpu_stl_data_ra(env, ptr + 12, env->fpip, retaddr); /* fpip */
+cpu_stw_data_ra(env, ptr + 16, fpcs, retaddr); /* fpcs */
+cpu_stw_data_ra(env, ptr + 18, 0, retaddr);
+cpu_stl_data_ra(env, ptr + 20, env->fpdp, retaddr); /* fpdp */
+cpu_stw_data_ra(env, ptr + 24, fpds, retaddr); /* fpds */
+cpu_stw_data_ra(env, ptr + 26, 0, retaddr);
 } else {
 /* 16 bit */
 cpu_stw_data_ra(env, ptr, env->fpuc, retaddr);
 cpu_stw_data_ra(env, ptr + 2, fpus, retaddr);
 cpu_stw_data_ra(env, ptr + 4, fptag, retaddr);
-cpu_stw_data_ra(env, ptr + 6, 0, retaddr);
-cpu_stw_data_ra(env, ptr + 8, 0, retaddr);
-cpu_stw_data_ra(env, ptr + 10, 0, retaddr);
-cpu_stw_data_ra(env, ptr + 12, 0, retaddr);
+cpu_stw_data_ra(env, ptr + 6, env->fpip, retaddr);
+cpu_stw_data_ra(env, ptr + 8, fpcs, retaddr);
+cpu_stw_data_ra(env, ptr + 10, env->fpdp, retaddr);
+cpu_stw_data_ra(env, ptr + 12, fpds, retaddr);
 }
 }
 
@@ -2473,17 +2495,7 @@ void helper_fsave(CPUX86State *env, target_ulong ptr, 
int data32)
 }
 
 /* fninit */
-env->fpus = 0;
-env->fpstt = 0;
-cpu_set_fpuc(env, 0x37f);
-env->fptags[0] = 1;
-env->fptags[1] = 1;
-env->fptags[2] = 1;
-env->fptags[3] = 1;
-env->fptags[4] = 1;
-env->fptags[5] = 1;
-env->fptags[6] = 1;
-env->fptags[7] = 1;
+helper_fninit(env);
 }
 
 void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 880bc45561..c26d343ab8 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -4486,6 +4486,11 @@ static 

Re: [PATCH] spapr: Modify ibm, get-config-addr-info2 to set DEVNUM in PE config address.

2021-04-29 Thread Oliver O'Halloran
On Thu, Apr 29, 2021 at 7:02 PM Mahesh J Salgaonkar
 wrote:
>
> On 2021-04-28 22:33:45 Wed, Oliver O'Halloran wrote:
> > On Tue, Apr 27, 2021 at 9:56 PM Mahesh Salgaonkar  
> > wrote:
> > >
> > > With upstream kernel, especially after commit 98ba956f6a389
> > > ("powerpc/pseries/eeh: Rework device EEH PE determination") we see that 
> > > KVM
> > > guest isn't able to enable EEH option for PCI pass-through devices 
> > > anymore.
> >
> > How are you passing the devices through to the guest?
>
> I am using libvirt with below xml section to add pass-through:
>
> 
>   
>   
> 
>   
>function='0x0' multifunction='on'/>
> 
> 
>   
>   
> 
>   
>function='0x1' multifunction='on'/>
> 
>
> Looks like libvirt does not allow pass through device in slot zero, and
> throws following error.
>
> error: XML error: Invalid PCI address :01:00.0. slot must be >= 1
> Failed. Try again? [y,n,i,f,?]:

That's pretty odd and I have no idea why that's happening. I seem to
remember being able to use slot 0 for vfio devices when doing the
passthru manually with the qemu command line so this might be a
libvirt quirk.

> *snip*
>
> Agree. I realize my fix is not correctly handling this. The current code
> under ibm,set-eeh-option is checking for individual PCI device presence.
> Better fix should be to check if there is any PCI device (vfio-pci)
> present under specified bus and enable the EEH if found. And no change
> in return value of get-config-addr-info2. What do you say ?

That sounds reasonable. You would however need to verify that all the
devices on that bus are within the same PE on the hypervisor side.



Re: [PATCH v3 00/30] Base for adding PowerPC 64-bit instructions

2021-04-29 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20210430011543.1017113-1-richard.hender...@linaro.org/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210430011543.1017113-1-richard.hender...@linaro.org
Subject: [PATCH v3 00/30] Base for adding PowerPC 64-bit instructions

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag] 
patchew/20210430011543.1017113-1-richard.hender...@linaro.org -> 
patchew/20210430011543.1017113-1-richard.hender...@linaro.org
Switched to a new branch 'test'
94d954b target/ppc: Implement prefixed integer store instructions
d2b6c00 target/ppc: Move D/DS/X-form integer stores to decodetree
3b6ae7e target/ppc: Implement prefixed integer load instructions
7785d8b target/ppc: Move D/DS/X-form integer loads to decodetree
60fd320 target/ppc: Implement PNOP
6d3431c target/ppc: Move ADDI, ADDIS to decodetree, implement PADDI
9cbf606 target/ppc: Move page crossing check to ppc_tr_translate_insn
f04f977 target/ppc: Add infrastructure for prefixed insns
efe0f1b target/ppc: Introduce macros to check isa extensions
69d9dd3 target/ppc: Use translator_loop_temp_check
2aba16a target/ppc: Mark helper_raise_exception* as noreturn
3b0336d target/ppc: Tidy exception vs exit_tb
d9e4ef4 target/ppc: Move single-step check to ppc_tr_tb_stop
27cd7b1 target/ppc: Remove DisasContext.exception
1241c8b target/ppc: Replace POWERPC_EXCP_BRANCH with DISAS_NORETURN
79906ac target/ppc: Replace POWERPC_EXCP_STOP with DISAS_EXIT_UPDATE
cf2d292 target/ppc: Introduce gen_icount_io_start
434992b target/ppc: Remove unnecessary gen_io_end calls
4c7c9fe target/ppc: Replace POWERPC_EXCP_SYNC with DISAS_EXIT
e4f28a4 target/ppc: Introduce DISAS_{EXIT,CHAIN}{,_UPDATE}
59c8dec target/ppc: Simplify gen_debug_exception
33ef476 target/ppc: Remove special case for POWERPC_EXCP_TRAP
a899437 target/ppc: Remove special case for POWERPC_SYSCALL
65217f2 target/ppc: Move DISAS_NORETURN setting into gen_exception*
68b60d8 target/ppc: Split out decode_legacy
91d5d66 target/ppc: Add cia field to DisasContext
8b45cf3 decodetree: Extend argument set syntax to allow types
2797541 decodetree: Add support for 64-bit instructions
1b1c946 decodetree: More use of f-strings
fd4892f decodetree: Introduce whex and whexC helpers

=== OUTPUT BEGIN ===
1/30 Checking commit fd4892f09eff (decodetree: Introduce whex and whexC helpers)
ERROR: line over 90 characters
#51: FILE: scripts/decodetree.py:495:
+output(ind, f'if ((insn & {whexC(innermask)}) == 
{whexC(innerbits)}) {{\n')

WARNING: line over 80 characters
#52: FILE: scripts/decodetree.py:496:
+output(ind, f'/* {str_match_bits(p.fixedbits, 
p.fixedmask)} */\n')

total: 1 errors, 1 warnings, 136 lines checked

Patch 1/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

2/30 Checking commit 1b1c946ade32 (decodetree: More use of f-strings)
3/30 Checking commit 279754143f3b (decodetree: Add support for 64-bit 
instructions)
WARNING: line over 80 characters
#74: FILE: scripts/decodetree.py:236:
+ret = f'deposit{bitop_width}({ret}, {pos}, {bitop_width - 
pos}, {ext})'

total: 0 errors, 1 warnings, 63 lines checked

Patch 3/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/30 Checking commit 8b45cf3a2c2d (decodetree: Extend argument set syntax to 
allow types)
Use of uninitialized value $acpi_testexpected in string eq at 
./scripts/checkpatch.pl line 1529.
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#155: 
new file mode 100644

total: 0 errors, 1 warnings, 121 lines checked

Patch 4/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/30 Checking commit 91d5d66281c8 (target/ppc: Add cia field to DisasContext)
6/30 Checking commit 68b60d843565 (target/ppc: Split out decode_legacy)
7/30 Checking commit 65217f275156 (target/ppc: Move DISAS_NORETURN setting into 
gen_exception*)
8/30 Checking commit a899437b0743 (target/ppc: Remove special case for 
POWERPC_SYSCALL)
9/30 Checking commit 33ef476619c9 (target/ppc: Remove special case for 
POWERPC_EXCP_TRAP)
10/30 Checking commit 59c8dec6fc93 (target/ppc: Simplify gen_debug_exception)
11/30 Checking commit e4f28a4f9529 (target/ppc: Introduce 
DISAS_{EXIT,CHAIN}{,_UPDATE})
12/30 Checking commit 4c7c9fedf741 (target/ppc: Replace POWERPC_EXCP_SYNC with 
DISAS_EXIT)
13/30 Checking commit 434992beb095 (target/ppc: Remove 

[PATCH v3 29/30] target/ppc: Move D/DS/X-form integer stores to decodetree

2021-04-29 Thread Richard Henderson
These are all connected by macros in the legacy decoding.

Signed-off-by: Richard Henderson 
---
 target/ppc/insn32.decode   | 22 ++
 target/ppc/translate.c | 83 +-
 target/ppc/translate/fixedpoint-impl.c.inc | 24 +++
 3 files changed, 48 insertions(+), 81 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 1c1b4620fc..7d35f61e45 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -63,6 +63,28 @@ LDU 111010 . . ..01 
@PLS_DS
 LDX 01 . . . 010101 -   @X
 LDUX01 . . . 110101 -   @X
 
+### Fixed-Point Store Instructions
+
+STB 100110 . .  @PLS_D
+STBU100111 . .  @PLS_D
+STBX01 . . . 0011010111 -   @X
+STBUX   01 . . . 000111 -   @X
+
+STH 101100 . .  @PLS_D
+STHU101101 . .  @PLS_D
+STHX01 . . . 0110010111 -   @X
+STHUX   01 . . . 0110110111 -   @X
+
+STW 100100 . .  @PLS_D
+STWU100101 . .  @PLS_D
+STWX01 . . . 0010010111 -   @X
+STWUX   01 . . . 0010110111 -   @X
+
+STD 10 . . ..00 @PLS_DS
+STDU10 . . ..01 @PLS_DS
+STDX01 . . . 0010010101 -   @X
+STDUX   01 . . . 0010110101 -   @X
+
 ### Fixed-Point Arithmetic Instructions
 
 ADDI001110 . .  @PLS_D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 1fdb501ee9..ad32fcc740 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2463,7 +2463,9 @@ static void glue(gen_qemu_, stop)(DisasContext *ctx,  
  \
 tcg_gen_qemu_st_tl(val, addr, ctx->mem_idx, op);\
 }
 
+#if defined(TARGET_PPC64) || !defined(CONFIG_USER_ONLY)
 GEN_QEMU_STORE_TL(st8,  DEF_MEMOP(MO_UB))
+#endif
 GEN_QEMU_STORE_TL(st16, DEF_MEMOP(MO_UW))
 GEN_QEMU_STORE_TL(st32, DEF_MEMOP(MO_UL))
 
@@ -2596,52 +2598,6 @@ static void gen_lq(DisasContext *ctx)
 #endif
 
 /***  Integer store***/
-#define GEN_ST(name, stop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx)   \
-{ \
-TCGv EA;  \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);   \
-tcg_temp_free(EA);\
-}
-
-#define GEN_STU(name, stop, opc, type)\
-static void glue(gen_, stop##u)(DisasContext *ctx)\
-{ \
-TCGv EA;  \
-if (unlikely(rA(ctx->opcode) == 0)) { \
-gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);   \
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-if (type == PPC_64B)  \
-gen_addr_imm_index(ctx, EA, 0x03);\
-else  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA);   \
-tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
-tcg_temp_free(EA);\
-}
-
-#define GEN_STUX(name, stop, opc2, opc3, type)\
-static void glue(gen_, name##ux)(DisasContext *ctx)   \
-{ \
-TCGv EA;  \
-if 

Re: [PATCH v3 24/30] target/ppc: Move page crossing check to ppc_tr_translate_insn

2021-04-29 Thread Richard Henderson

On 4/29/21 6:15 PM, Richard Henderson wrote:

With prefixed instructions, the number of instructions
remaining until the page crossing is no longer constant.

Signed-off-by: Richard Henderson
---
  target/ppc/translate.c | 8 +---
  1 file changed, 5 insertions(+), 3 deletions(-)


Oops, this was supposed to be ordered before the previous patch.


r~



[PATCH v3 25/30] target/ppc: Move ADDI, ADDIS to decodetree, implement PADDI

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/ppc/insn32.decode   | 12 +++
 target/ppc/insn64.decode   | 15 +
 target/ppc/translate.c | 29 
 target/ppc/translate/fixedpoint-impl.c.inc | 39 ++
 4 files changed, 66 insertions(+), 29 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index b175441209..52d9b355d4 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -16,3 +16,15 @@
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library; if not, see .
 #
+
+  rt ra si
+@D  .. rt:5 ra:5 si:s16 
+
+# If a prefix is allowed, decode with default values.
+_D  rt ra si:int64_t r:bool
+@PLS_D  .. rt:5 ra:5 si:s16 _D r=0
+
+### Fixed-Point Arithmetic Instructions
+
+ADDI001110 . .  @PLS_D
+ADDIS   00 . .  @D
diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index 9fc45d0614..f4272df724 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -16,3 +16,18 @@
 # You should have received a copy of the GNU Lesser General Public
 # License along with this library; if not, see .
 #
+
+# Many all of these instruction names would be prefixed by "P",
+# but we share code with the non-prefixed instruction.
+
+# Format MLS:D and 8LS:D
+_D  rt ra si:int64_t r:bool  !extern
+%pls_si 32:s18 0:16
+@PLS_D  .. .. ... r:1 .. .. \
+.. rt:5 ra:5    \
+_D si=%pls_si
+
+### Fixed-Point Arithmetic Instructions
+
+ADDI01 10 0--.-- .. \
+001110 . .  @PLS_D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index d782a13d27..5a8a3c39c3 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -924,19 +924,6 @@ GEN_INT_ARITH_ADD(addex, 0x05, cpu_ov, 1, 1, 0);
 /* addze  addze.  addzeo  addzeo.*/
 GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, cpu_ca, 1, 1, 0)
 GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, cpu_ca, 1, 1, 1)
-/* addi */
-static void gen_addi(DisasContext *ctx)
-{
-target_long simm = SIMM(ctx->opcode);
-
-if (rA(ctx->opcode) == 0) {
-/* li case */
-tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
-} else {
-tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
-cpu_gpr[rA(ctx->opcode)], simm);
-}
-}
 /* addic  addic.*/
 static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
 {
@@ -956,20 +943,6 @@ static void gen_addic_(DisasContext *ctx)
 gen_op_addic(ctx, 1);
 }
 
-/* addis */
-static void gen_addis(DisasContext *ctx)
-{
-target_long simm = SIMM(ctx->opcode);
-
-if (rA(ctx->opcode) == 0) {
-/* lis case */
-tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
-} else {
-tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)],
-cpu_gpr[rA(ctx->opcode)], simm << 16);
-}
-}
-
 /* addpcis */
 static void gen_addpcis(DisasContext *ctx)
 {
@@ -7029,10 +7002,8 @@ GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x0060, 
PPC_NONE, PPC2_ISA300),
 GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x0001, PPC_NONE, PPC2_ISA205),
 GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x0041, PPC_NONE, PPC2_ISA300),
 GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x0001, PPC_ISEL),
-GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x, PPC_INTEGER),
 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x, PPC_INTEGER),
 GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x, PPC_INTEGER),
-GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x, PPC_INTEGER),
 GEN_HANDLER_E(addpcis, 0x13, 0x2, 0xFF, 0x, PPC_NONE, PPC2_ISA300),
 GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x0400, PPC_INTEGER),
 GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x0400, PPC_INTEGER),
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index b740083605..7af1b3bcf5 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -16,3 +16,42 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see .
  */
+
+/*
+ * Incorporate CIA into the constant when R=1.
+ * Validate that when R=1, RA=0.
+ */
+static bool resolve_PLS_D(DisasContext *ctx, arg_PLS_D *a)
+{
+if (a->r) {
+if (unlikely(a->ra != 0)) {
+gen_invalid(ctx);
+return false;
+}
+a->si += ctx->cia;
+}
+return true;
+}
+
+static bool trans_ADDI(DisasContext *ctx, arg_PLS_D *a)
+{
+if (resolve_PLS_D(ctx, a)) {
+if (a->ra) {
+tcg_gen_addi_tl(cpu_gpr[a->rt], 

[PATCH v3 28/30] target/ppc: Implement prefixed integer load instructions

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/ppc/insn64.decode | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index 5a82ce375e..4198e5c8f3 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -29,6 +29,21 @@
 .. rt:5 ra:5    \
 _D si=%pls_si
 
+### Fixed-Point Load Instructions
+
+LBZ 01 10 0--.-- .. \
+100010 . .  @PLS_D
+LHZ 01 10 0--.-- .. \
+101000 . .  @PLS_D
+LHA 01 10 0--.-- .. \
+101010 . .  @PLS_D
+LWZ 01 10 0--.-- .. \
+10 . .  @PLS_D
+LWA 01 00 0--.-- .. \
+101001 . .  @PLS_D
+LD  01 00 0--.-- .. \
+111001 . .  @PLS_D
+
 ### Fixed-Point Arithmetic Instructions
 
 ADDI01 10 0--.-- .. \
-- 
2.25.1




[PATCH v3 27/30] target/ppc: Move D/DS/X-form integer loads to decodetree

2021-04-29 Thread Richard Henderson
These are all connected by macros in the legacy decoding.
Decode the D and DS forms into the PLS_D argument set so
that prefixed insns can share code.

Signed-off-by: Richard Henderson 
---
 target/ppc/insn32.decode   |  37 ++
 target/ppc/translate.c | 145 -
 target/ppc/translate/fixedpoint-impl.c.inc | 114 
 3 files changed, 174 insertions(+), 122 deletions(-)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 2ed25c7e67..1c1b4620fc 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -26,6 +26,43 @@
 _D  rt ra si:int64_t r:bool
 @PLS_D  .. rt:5 ra:5 si:s16 _D r=0
 
+%ds_si  2:s14  !function=times_4
+@PLS_DS .. rt:5 ra:5 .. ..  _D si=%ds_si r=0
+
+  rt ra rb
+@X  .. rt:5 ra:5 rb:5 .. .  
+
+### Fixed-Point Load Instructions
+
+LBZ 100010 . .  @PLS_D
+LBZU100011 . .  @PLS_D
+LBZX01 . . . 0001010111 -   @X
+LBZUX   01 . . . 0001110111 -   @X
+
+LHZ 101000 . .  @PLS_D
+LHZU101001 . .  @PLS_D
+LHZX01 . . . 0100010111 -   @X
+LHZUX   01 . . . 0100110111 -   @X
+
+LHA 101010 . .  @PLS_D
+LHAU101011 . .  @PLS_D
+LHAX01 . . . 0101010111 -   @X
+LHAXU   01 . . . 0101110111 -   @X
+
+LWZ 10 . .  @PLS_D
+LWZU11 . .  @PLS_D
+LWZX01 . . . 010111 -   @X
+LWZUX   01 . . . 110111 -   @X
+
+LWA 111010 . . ..10 @PLS_DS
+LWAX01 . . . 0101010101 -   @X
+LWAUX   01 . . . 0101110101 -   @X
+
+LD  111010 . . ..00 @PLS_DS
+LDU 111010 . . ..01 @PLS_DS
+LDX 01 . . . 010101 -   @X
+LDUX01 . . . 110101 -   @X
+
 ### Fixed-Point Arithmetic Instructions
 
 ADDI001110 . .  @PLS_D
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 5a8a3c39c3..1fdb501ee9 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -2487,54 +2487,6 @@ GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_Q))
 GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q))
 #endif
 
-#define GEN_LD(name, ldop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx)   \
-{ \
-TCGv EA;  \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);   \
-tcg_temp_free(EA);\
-}
-
-#define GEN_LDU(name, ldop, opc, type)\
-static void glue(gen_, name##u)(DisasContext *ctx)\
-{ \
-TCGv EA;  \
-if (unlikely(rA(ctx->opcode) == 0 ||  \
- rA(ctx->opcode) == rD(ctx->opcode))) {   \
-gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);   \
-return;   \
-} \
-gen_set_access_type(ctx, ACCESS_INT); \
-EA = tcg_temp_new();  \
-if (type == PPC_64B)  \
-gen_addr_imm_index(ctx, EA, 0x03);\
-else  \
-gen_addr_imm_index(ctx, EA, 0);   \
-gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA);   \
-tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
-tcg_temp_free(EA);\
-}
-
-#define 

[PATCH v3 21/30] target/ppc: Use translator_loop_temp_check

2021-04-29 Thread Richard Henderson
The special logging is unnecessary.  It will have been done
immediately before in the log file.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index fe3982e289..112afd02d5 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -8046,11 +8046,7 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 handler->count++;
 #endif
 
-if (tcg_check_temp_count()) {
-qemu_log("Opcode %02x %02x %02x %02x (%08x) leaked "
- "temporaries\n", opc1(ctx->opcode), opc2(ctx->opcode),
- opc3(ctx->opcode), opc4(ctx->opcode), ctx->opcode);
-}
+translator_loop_temp_check(>base);
 }
 
 static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
-- 
2.25.1




[PATCH v3 24/30] target/ppc: Move page crossing check to ppc_tr_translate_insn

2021-04-29 Thread Richard Henderson
With prefixed instructions, the number of instructions
remaining until the page crossing is no longer constant.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 65848463ea..d782a13d27 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -8019,9 +8019,6 @@ static void ppc_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 
 if (ctx->singlestep_enabled & (CPU_SINGLE_STEP | GDBSTUB_SINGLE_STEP)) {
 ctx->base.max_insns = 1;
-} else {
-int bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
-ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
 }
 }
 
@@ -8098,6 +8095,11 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 handler->count++;
 #endif
 
+/* End the TB when crossing a page boundary. */
+if (ctx->base.is_jmp == DISAS_NEXT && !(pc & ~TARGET_PAGE_MASK)) {
+ctx->base.is_jmp = DISAS_TOO_MANY;
+}
+
 translator_loop_temp_check(>base);
 }
 
-- 
2.25.1




[PATCH v3 23/30] target/ppc: Add infrastructure for prefixed insns

2021-04-29 Thread Richard Henderson
Signed-off-by: Luis Pires 
Signed-off-by: Richard Henderson 
---
v3: Move page crossing check to its own patch,
fold in ISA310 check to is_prefix_insn
---
 target/ppc/cpu.h   |  1 +
 target/ppc/insn32.decode   | 18 
 target/ppc/insn64.decode   | 18 
 target/ppc/translate.c | 34 +++---
 target/ppc/translate/fixedpoint-impl.c.inc | 18 
 target/ppc/meson.build |  9 ++
 6 files changed, 94 insertions(+), 4 deletions(-)
 create mode 100644 target/ppc/insn32.decode
 create mode 100644 target/ppc/insn64.decode
 create mode 100644 target/ppc/translate/fixedpoint-impl.c.inc

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 5b22eb64dc..82a2bf1e58 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -144,6 +144,7 @@ enum {
 POWERPC_EXCP_ALIGN_PROT= 0x04,  /* Access cross protection boundary  */
 POWERPC_EXCP_ALIGN_BAT = 0x05,  /* Access cross a BAT/seg boundary   */
 POWERPC_EXCP_ALIGN_CACHE   = 0x06,  /* Impossible dcbz access*/
+POWERPC_EXCP_ALIGN_INSN= 0x07,  /* Pref. insn x-ing 64-byte boundary */
 /* Exception subtypes for POWERPC_EXCP_PROGRAM   */
 /* FP exceptions */
 POWERPC_EXCP_FP= 0x10,
diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
new file mode 100644
index 00..b175441209
--- /dev/null
+++ b/target/ppc/insn32.decode
@@ -0,0 +1,18 @@
+#
+# Power ISA decode for 32-bit insns (opcode space 0)
+#
+# Copyright (c) 2021 Luis Pires 
+#
+# 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 .
+#
diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
new file mode 100644
index 00..9fc45d0614
--- /dev/null
+++ b/target/ppc/insn64.decode
@@ -0,0 +1,18 @@
+#
+# Power ISA decode for 64-bit prefixed insns (opcode space 0 and 1)
+#
+# Copyright (c) 2021 Luis Pires 
+#
+# 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 .
+#
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index cde12e9d38..65848463ea 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6902,6 +6902,10 @@ static inline void set_avr64(int regno, TCGv_i64 src, 
bool high)
 # define REQUIRE_64BIT(CTX)  REQUIRE_INSNS_FLAGS(CTX, 64B)
 #endif
 
+#include "decode-insn32.c.inc"
+#include "decode-insn64.c.inc"
+#include "translate/fixedpoint-impl.c.inc"
+
 #include "translate/fp-impl.c.inc"
 
 #include "translate/vmx-impl.c.inc"
@@ -8047,11 +8051,18 @@ static bool ppc_tr_breakpoint_check(DisasContextBase 
*dcbase, CPUState *cs,
 return true;
 }
 
+static bool is_prefix_insn(DisasContext *ctx, uint32_t insn)
+{
+REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+return opc1(insn) == 1;
+}
+
 static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = cs->env_ptr;
+target_ulong pc;
 uint32_t insn;
 bool ok;
 
@@ -8059,11 +8070,26 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
   ctx->base.pc_next, ctx->mem_idx, (int)msr_ir);
 
-ctx->cia = ctx->base.pc_next;
-insn = translator_ldl_swap(env, ctx->base.pc_next, need_byteswap(ctx));
-ctx->base.pc_next += 4;
+ctx->cia = pc = ctx->base.pc_next;
+insn = translator_ldl_swap(env, pc, need_byteswap(ctx));
+ctx->base.pc_next = pc += 4;
 
-ok = decode_legacy(cpu, ctx, insn);
+if (!is_prefix_insn(ctx, insn)) {
+ok = (decode_insn32(ctx, insn) ||
+  

[PATCH v3 20/30] target/ppc: Mark helper_raise_exception* as noreturn

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/ppc/helper.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index 6a4dccf70c..af5b3586d1 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -1,5 +1,5 @@
-DEF_HELPER_FLAGS_3(raise_exception_err, TCG_CALL_NO_WG, void, env, i32, i32)
-DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, void, env, i32)
+DEF_HELPER_FLAGS_3(raise_exception_err, TCG_CALL_NO_WG, noreturn, env, i32, 
i32)
+DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, i32)
 DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32)
 #if defined(TARGET_PPC64)
 DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32)
-- 
2.25.1




[PATCH v3 30/30] target/ppc: Implement prefixed integer store instructions

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/ppc/insn64.decode | 12 
 1 file changed, 12 insertions(+)

diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index 4198e5c8f3..7a71a7a3bb 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -44,6 +44,18 @@ LWA 01 00 0--.-- .. \
 LD  01 00 0--.-- .. \
 111001 . .  @PLS_D
 
+### Fixed-Point Store Instructions
+
+STW 01 10 0--.-- .. \
+100100 . .  @PLS_D
+STB 01 10 0--.-- .. \
+100110 . .  @PLS_D
+STH 01 10 0--.-- .. \
+101100 . .  @PLS_D
+
+STD 01 00 0--.-- .. \
+01 . .  @PLS_D
+
 ### Fixed-Point Arithmetic Instructions
 
 ADDI01 10 0--.-- .. \
-- 
2.25.1




[PATCH v3 15/30] target/ppc: Replace POWERPC_EXCP_STOP with DISAS_EXIT_UPDATE

2021-04-29 Thread Richard Henderson
Remove the synthetic "exception" after no more uses.

Signed-off-by: Richard Henderson 
---
 target/ppc/cpu.h|  1 -
 linux-user/ppc/cpu_loop.c   |  3 ---
 target/ppc/translate.c  | 20 +---
 target/ppc/translate_init.c.inc |  4 ++--
 4 files changed, 7 insertions(+), 21 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index cf10117065..9bb370abba 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -132,7 +132,6 @@ enum {
 /* EOL   */
 POWERPC_EXCP_NB   = 103,
 /* QEMU exceptions: used internally during code translation  */
-POWERPC_EXCP_STOP = 0x200, /* stop translation   */
 POWERPC_EXCP_BRANCH   = 0x201, /* branch instruction */
 /* QEMU exceptions: special cases we want to stop translation*/
 POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only  */
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index df71e15a25..4c308835bd 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -423,9 +423,6 @@ void cpu_loop(CPUPPCState *env)
 cpu_abort(cs, "Maintenance exception while in user mode. "
   "Aborting\n");
 break;
-case POWERPC_EXCP_STOP: /* stop translation  */
-/* We did invalidate the instruction cache. Go on */
-break;
 case POWERPC_EXCP_BRANCH:   /* branch instruction:   */
 /* We just stopped because of a branch. Go on */
 break;
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 45cd3189c0..82fdf0bb77 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -367,13 +367,6 @@ static inline void gen_hvpriv_exception(DisasContext *ctx, 
uint32_t error)
 gen_exception_err(ctx, POWERPC_EXCP_HV_EMU, POWERPC_EXCP_PRIV | error);
 }
 
-/* Stop translation */
-static inline void gen_stop_exception(DisasContext *ctx)
-{
-gen_update_nip(ctx, ctx->base.pc_next);
-ctx->exception = POWERPC_EXCP_STOP;
-}
-
 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)  \
 GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
 
@@ -3157,7 +3150,7 @@ static void gen_isync(DisasContext *ctx)
 gen_check_tlb_flush(ctx, false);
 }
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
-gen_stop_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 }
 
 #define MEMOP_GET_SIZE(x)  (1 << ((x) & MO_SIZE))
@@ -4434,7 +4427,7 @@ static void gen_mtmsrd(DisasContext *ctx)
 gen_helper_store_msr(cpu_env, cpu_gpr[rS(ctx->opcode)]);
 }
 /* Must stop the translation as machine state (may have) changed */
-gen_stop_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 #endif /* !defined(CONFIG_USER_ONLY) */
 }
 #endif /* defined(TARGET_PPC64) */
@@ -4477,7 +4470,7 @@ static void gen_mtmsr(DisasContext *ctx)
 tcg_temp_free(msr);
 }
 /* Must stop the translation as machine state (may have) changed */
-gen_stop_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 #endif
 }
 
@@ -6614,7 +6607,7 @@ static void gen_wrtee(DisasContext *ctx)
  * Stop translation to have a chance to raise an exception if we
  * just set msr_ee to 1
  */
-gen_stop_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -6628,7 +6621,7 @@ static void gen_wrteei(DisasContext *ctx)
 if (ctx->opcode & 0x8000) {
 tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
 /* Stop translation to have a chance to raise an exception */
-gen_stop_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 } else {
 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
 }
@@ -8083,9 +8076,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 case POWERPC_EXCP_BRANCH:
 ctx->base.is_jmp = DISAS_NORETURN;
 break;
-case POWERPC_EXCP_STOP:
-ctx->base.is_jmp = DISAS_EXIT;
-break;
 default:
 /* Every other ctx->exception should have set NORETURN. */
 g_assert_not_reached();
diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index 9af3fb2066..f3e79b8685 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -463,7 +463,7 @@ static void spr_write_hid0_601(DisasContext *ctx, int sprn, 
int gprn)
 {
 gen_helper_store_hid0_601(cpu_env, cpu_gpr[gprn]);
 /* Must stop the translation as endianness may have changed */
-gen_stop_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT_UPDATE;
 }
 #endif
 
@@ -511,7 +511,7 @@ static void spr_write_40x_dbcr0(DisasContext *ctx, int 
sprn, int gprn)
 gen_store_spr(sprn, cpu_gpr[gprn]);
 

[PATCH v3 17/30] target/ppc: Remove DisasContext.exception

2021-04-29 Thread Richard Henderson
Now that we have removed all of the fake exceptions, and all real
exceptions exit via DISAS_NORETURN, we can remove this field.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 22 ++
 1 file changed, 2 insertions(+), 20 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 276a4a2a79..d78071a4a4 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -259,15 +259,12 @@ static void gen_exception_err(DisasContext *ctx, uint32_t 
excp, uint32_t error)
  * These are all synchronous exceptions, we set the PC back to the
  * faulting instruction
  */
-if (ctx->exception == POWERPC_EXCP_NONE) {
-gen_update_nip(ctx, ctx->cia);
-}
+gen_update_nip(ctx, ctx->cia);
 t0 = tcg_const_i32(excp);
 t1 = tcg_const_i32(error);
 gen_helper_raise_exception_err(cpu_env, t0, t1);
 tcg_temp_free_i32(t0);
 tcg_temp_free_i32(t1);
-ctx->exception = excp;
 ctx->base.is_jmp = DISAS_NORETURN;
 }
 
@@ -279,13 +276,10 @@ static void gen_exception(DisasContext *ctx, uint32_t 
excp)
  * These are all synchronous exceptions, we set the PC back to the
  * faulting instruction
  */
-if (ctx->exception == POWERPC_EXCP_NONE) {
-gen_update_nip(ctx, ctx->cia);
-}
+gen_update_nip(ctx, ctx->cia);
 t0 = tcg_const_i32(excp);
 gen_helper_raise_exception(cpu_env, t0);
 tcg_temp_free_i32(t0);
-ctx->exception = excp;
 ctx->base.is_jmp = DISAS_NORETURN;
 }
 
@@ -298,7 +292,6 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t 
excp,
 t0 = tcg_const_i32(excp);
 gen_helper_raise_exception(cpu_env, t0);
 tcg_temp_free_i32(t0);
-ctx->exception = excp;
 ctx->base.is_jmp = DISAS_NORETURN;
 }
 
@@ -7919,7 +7912,6 @@ static void ppc_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 CPUPPCState *env = cs->env_ptr;
 int bound;
 
-ctx->exception = POWERPC_EXCP_NONE;
 ctx->spr_cb = env->spr_cb;
 ctx->pr = msr_pr;
 ctx->mem_idx = env->dmmu_idx;
@@ -8067,16 +8059,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
  "temporaries\n", opc1(ctx->opcode), opc2(ctx->opcode),
  opc3(ctx->opcode), opc4(ctx->opcode), ctx->opcode);
 }
-
-if (ctx->base.is_jmp == DISAS_NEXT) {
-switch (ctx->exception) {
-case POWERPC_EXCP_NONE:
-break;
-default:
-/* Every other ctx->exception should have set NORETURN. */
-g_assert_not_reached();
-}
-}
 }
 
 static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
-- 
2.25.1




[PATCH v3 19/30] target/ppc: Tidy exception vs exit_tb

2021-04-29 Thread Richard Henderson
We do not need to emit an exit_tb after an exception,
as the latter will exit via longjmp.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index c018960ce9..fe3982e289 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3726,8 +3726,9 @@ static void gen_lookup_and_goto_ptr(DisasContext *ctx)
 } else if (sse & (CPU_SINGLE_STEP | CPU_BRANCH_STEP)) {
 uint32_t excp = gen_prep_dbgex(ctx);
 gen_exception(ctx, excp);
+} else {
+tcg_gen_exit_tb(NULL, 0);
 }
-tcg_gen_exit_tb(NULL, 0);
 } else {
 tcg_gen_lookup_and_goto_ptr();
 }
-- 
2.25.1




[PATCH v3 26/30] target/ppc: Implement PNOP

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/ppc/insn32.decode   |  2 ++
 target/ppc/insn64.decode   | 11 +++
 target/ppc/translate/fixedpoint-impl.c.inc |  5 +
 3 files changed, 18 insertions(+)

diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode
index 52d9b355d4..2ed25c7e67 100644
--- a/target/ppc/insn32.decode
+++ b/target/ppc/insn32.decode
@@ -17,6 +17,8 @@
 # License along with this library; if not, see .
 #
 
+
+
   rt ra si
 @D  .. rt:5 ra:5 si:s16 
 
diff --git a/target/ppc/insn64.decode b/target/ppc/insn64.decode
index f4272df724..5a82ce375e 100644
--- a/target/ppc/insn64.decode
+++ b/target/ppc/insn64.decode
@@ -20,6 +20,8 @@
 # Many all of these instruction names would be prefixed by "P",
 # but we share code with the non-prefixed instruction.
 
+  !extern
+
 # Format MLS:D and 8LS:D
 _D  rt ra si:int64_t r:bool  !extern
 %pls_si 32:s18 0:16
@@ -31,3 +33,12 @@
 
 ADDI01 10 0--.-- .. \
 001110 . .  @PLS_D
+
+### Prefixed No-operation Instruction
+
+# TODO: diagnose the set of patterns that are illegal:
+# branches, rfebb, sync other than isync, or a service processor attention.
+# The Engineering Note allows us to either diagnose these as illegal,
+# or treat them all as no-op.
+NOP 01 11 -- 00 \
+
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc 
b/target/ppc/translate/fixedpoint-impl.c.inc
index 7af1b3bcf5..96b8c38f60 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -55,3 +55,8 @@ static bool trans_ADDIS(DisasContext *ctx, arg_D *a)
 }
 return true;
 }
+
+static bool trans_NOP(DisasContext *ctx, arg_NOP *a)
+{
+return true;
+}
-- 
2.25.1




[PATCH v3 16/30] target/ppc: Replace POWERPC_EXCP_BRANCH with DISAS_NORETURN

2021-04-29 Thread Richard Henderson
The translation of branch instructions always results in exit from
the TB.  Remove the synthetic "exception" after no more uses.

Signed-off-by: Richard Henderson 
---
 target/ppc/cpu.h  | 2 --
 linux-user/ppc/cpu_loop.c | 3 ---
 target/ppc/translate.c| 8 ++--
 3 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 9bb370abba..5b22eb64dc 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -131,8 +131,6 @@ enum {
 POWERPC_EXCP_SYSCALL_VECTORED = 102, /* scv exception 
*/
 /* EOL   */
 POWERPC_EXCP_NB   = 103,
-/* QEMU exceptions: used internally during code translation  */
-POWERPC_EXCP_BRANCH   = 0x201, /* branch instruction */
 /* QEMU exceptions: special cases we want to stop translation*/
 POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only  */
 };
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 4c308835bd..adf5a8a4e6 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -423,9 +423,6 @@ void cpu_loop(CPUPPCState *env)
 cpu_abort(cs, "Maintenance exception while in user mode. "
   "Aborting\n");
 break;
-case POWERPC_EXCP_BRANCH:   /* branch instruction:   */
-/* We just stopped because of a branch. Go on */
-break;
 case POWERPC_EXCP_SYSCALL_USER:
 /* system call in user-mode emulation */
 /* WARNING:
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 82fdf0bb77..276a4a2a79 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3769,7 +3769,6 @@ static void gen_b(DisasContext *ctx)
 {
 target_ulong li, target;
 
-ctx->exception = POWERPC_EXCP_BRANCH;
 /* sign extend LI */
 li = LI(ctx->opcode);
 li = (li ^ 0x0200) - 0x0200;
@@ -3783,6 +3782,7 @@ static void gen_b(DisasContext *ctx)
 }
 gen_update_cfar(ctx, ctx->cia);
 gen_goto_tb(ctx, 0, target);
+ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 #define BCOND_IM  0
@@ -3795,7 +3795,6 @@ static void gen_bcond(DisasContext *ctx, int type)
 uint32_t bo = BO(ctx->opcode);
 TCGLabel *l1;
 TCGv target;
-ctx->exception = POWERPC_EXCP_BRANCH;
 
 if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
 target = tcg_temp_local_new();
@@ -3902,6 +3901,7 @@ static void gen_bcond(DisasContext *ctx, int type)
 gen_set_label(l1);
 gen_goto_tb(ctx, 1, ctx->base.pc_next);
 }
+ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 static void gen_bc(DisasContext *ctx)
@@ -8057,7 +8057,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 /* Check trace mode exceptions */
 if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP &&
  (ctx->base.pc_next <= 0x100 || ctx->base.pc_next > 0xF00) &&
- ctx->exception != POWERPC_EXCP_BRANCH &&
  ctx->base.is_jmp != DISAS_NORETURN)) {
 uint32_t excp = gen_prep_dbgex(ctx);
 gen_exception_nip(ctx, excp, ctx->base.pc_next);
@@ -8073,9 +8072,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 switch (ctx->exception) {
 case POWERPC_EXCP_NONE:
 break;
-case POWERPC_EXCP_BRANCH:
-ctx->base.is_jmp = DISAS_NORETURN;
-break;
 default:
 /* Every other ctx->exception should have set NORETURN. */
 g_assert_not_reached();
-- 
2.25.1




[PATCH v3 14/30] target/ppc: Introduce gen_icount_io_start

2021-04-29 Thread Richard Henderson
Create a function to handle the details for interacting with icount.

Force the exit from the tb via DISAS_TOO_MANY, which allows chaining
to the next tb, where the code emitted for gen_tb_start() will
determine if we must exit.  We can thus remove any matching
conditional call to gen_stop_exception.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c  |  41 +-
 target/ppc/translate_init.c.inc | 133 +---
 2 files changed, 39 insertions(+), 135 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index d22d6e5b85..45cd3189c0 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -302,6 +302,20 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t 
excp,
 ctx->base.is_jmp = DISAS_NORETURN;
 }
 
+static void gen_icount_io_start(DisasContext *ctx)
+{
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+/*
+ * An I/O instruction must be last in the TB.
+ * Chain to the next TB, and let the code from gen_tb_start
+ * decide if we need to return to the main loop.
+ * Doing this first also allows this value to be overridden.
+ */
+ctx->base.is_jmp = DISAS_TOO_MANY;
+}
+}
+
 /*
  * Tells the caller what is the appropriate exception to generate and prepares
  * SPR registers for this exception.
@@ -1842,18 +1856,13 @@ static void gen_darn(DisasContext *ctx)
 if (l > 2) {
 tcg_gen_movi_i64(cpu_gpr[rD(ctx->opcode)], -1);
 } else {
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 if (l == 0) {
 gen_helper_darn32(cpu_gpr[rD(ctx->opcode)]);
 } else {
 /* Return 64-bit random for both CRN and RRN */
 gen_helper_darn64(cpu_gpr[rD(ctx->opcode)]);
 }
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_stop_exception(ctx);
-}
 }
 }
 #endif
@@ -3995,9 +4004,7 @@ static void gen_rfi(DisasContext *ctx)
 }
 /* Restore CPU state */
 CHK_SV;
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfi(cpu_env);
 ctx->base.is_jmp = DISAS_EXIT;
@@ -4012,9 +4019,7 @@ static void gen_rfid(DisasContext *ctx)
 #else
 /* Restore CPU state */
 CHK_SV;
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfid(cpu_env);
 ctx->base.is_jmp = DISAS_EXIT;
@@ -4029,9 +4034,7 @@ static void gen_rfscv(DisasContext *ctx)
 #else
 /* Restore CPU state */
 CHK_SV;
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfscv(cpu_env);
 ctx->base.is_jmp = DISAS_EXIT;
@@ -4406,9 +4409,7 @@ static void gen_mtmsrd(DisasContext *ctx)
 CHK_SV;
 
 #if !defined(CONFIG_USER_ONLY)
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 if (ctx->opcode & 0x0001) {
 /* L=1 form only updates EE and RI */
 TCGv t0 = tcg_temp_new();
@@ -4443,9 +,7 @@ static void gen_mtmsr(DisasContext *ctx)
 CHK_SV;
 
 #if !defined(CONFIG_USER_ONLY)
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 if (ctx->opcode & 0x0001) {
 /* L=1 form only updates EE and RI */
 TCGv t0 = tcg_temp_new();
diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index 99e5f52925..9af3fb2066 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -183,24 +183,14 @@ static void spr_write_ureg(DisasContext *ctx, int sprn, 
int gprn)
 #if !defined(CONFIG_USER_ONLY)
 static void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
 {
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_stop_exception(ctx);
-}
 }
 
 static void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
 {
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_stop_exception(ctx);
-}
 }
 #endif
 
@@ -208,24 +198,14 @@ static void spr_write_decr(DisasContext *ctx, int sprn, 
int gprn)
 /* Time base */
 static void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
 {
-if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
+gen_icount_io_start(ctx);
 

[PATCH v3 18/30] target/ppc: Move single-step check to ppc_tr_tb_stop

2021-04-29 Thread Richard Henderson
When single-stepping, force max_insns to 1 in init_disas
so that we exit the translation loop immediately.

Combine the single-step checks in tb_stop, and give the
gdb exception priority over the cpu exception, just as
we already do in gen_lookup_and_goto_ptr.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 37 +++--
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index d78071a4a4..c018960ce9 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7910,7 +7910,6 @@ static void ppc_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 CPUPPCState *env = cs->env_ptr;
-int bound;
 
 ctx->spr_cb = env->spr_cb;
 ctx->pr = msr_pr;
@@ -7986,13 +7985,13 @@ static void ppc_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 if (unlikely(ctx->base.singlestep_enabled)) {
 ctx->singlestep_enabled |= GDBSTUB_SINGLE_STEP;
 }
-#if defined(DO_SINGLE_STEP) && 0
-/* Single step trace mode */
-msr_se = 1;
-#endif
 
-bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
-ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+if (ctx->singlestep_enabled & (CPU_SINGLE_STEP | GDBSTUB_SINGLE_STEP)) {
+ctx->base.max_insns = 1;
+} else {
+int bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
+ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+}
 }
 
 static void ppc_tr_tb_start(DisasContextBase *db, CPUState *cs)
@@ -8046,14 +8045,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 handler->count++;
 #endif
 
-/* Check trace mode exceptions */
-if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP &&
- (ctx->base.pc_next <= 0x100 || ctx->base.pc_next > 0xF00) &&
- ctx->base.is_jmp != DISAS_NORETURN)) {
-uint32_t excp = gen_prep_dbgex(ctx);
-gen_exception_nip(ctx, excp, ctx->base.pc_next);
-}
-
 if (tcg_check_temp_count()) {
 qemu_log("Opcode %02x %02x %02x %02x (%08x) leaked "
  "temporaries\n", opc1(ctx->opcode), opc2(ctx->opcode),
@@ -8066,6 +8057,7 @@ static void ppc_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cs)
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 DisasJumpType is_jmp = ctx->base.is_jmp;
 target_ulong nip = ctx->base.pc_next;
+int sse;
 
 if (is_jmp == DISAS_NORETURN) {
 /* We have already exited the TB. */
@@ -8073,7 +8065,8 @@ static void ppc_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cs)
 }
 
 /* Honor single stepping. */
-if (unlikely(ctx->base.singlestep_enabled)) {
+sse = ctx->singlestep_enabled & (CPU_SINGLE_STEP | GDBSTUB_SINGLE_STEP);
+if (unlikely(sse)) {
 switch (is_jmp) {
 case DISAS_TOO_MANY:
 case DISAS_EXIT_UPDATE:
@@ -8086,8 +8079,16 @@ static void ppc_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cs)
 default:
 g_assert_not_reached();
 }
-gen_debug_exception(ctx);
-return;
+
+if (sse & GDBSTUB_SINGLE_STEP) {
+gen_debug_exception(ctx);
+return;
+}
+/* else CPU_SINGLE_STEP... */
+if (nip <= 0x100 || nip > 0xf00) {
+gen_exception(ctx, gen_prep_dbgex(ctx));
+return;
+}
 }
 
 switch (is_jmp) {
-- 
2.25.1




[PATCH v3 22/30] target/ppc: Introduce macros to check isa extensions

2021-04-29 Thread Richard Henderson
These will be used by the decodetree trans_* functions
to early-exit when the instruction set is not enabled.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 112afd02d5..cde12e9d38 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6876,6 +6876,32 @@ static inline void set_avr64(int regno, TCGv_i64 src, 
bool high)
 tcg_gen_st_i64(src, cpu_env, avr64_offset(regno, high));
 }
 
+/*
+ * Helpers for trans_* functions to check for specific insns flags.
+ * Use token pasting to ensure that we use the proper flag with the
+ * proper variable.
+ */
+#define REQUIRE_INSNS_FLAGS(CTX, NAME) \
+do {\
+if (((CTX)->insns_flags & PPC_##NAME) == 0) {   \
+return false;   \
+}   \
+} while (0)
+
+#define REQUIRE_INSNS_FLAGS2(CTX, NAME) \
+do {\
+if (((CTX)->insns_flags2 & PPC2_##NAME) == 0) { \
+return false;   \
+}   \
+} while (0)
+
+/* Then special-case the check for 64-bit so that we elide code for ppc32. */
+#if TARGET_LONG_BITS == 32
+# define REQUIRE_64BIT(CTX)  return false
+#else
+# define REQUIRE_64BIT(CTX)  REQUIRE_INSNS_FLAGS(CTX, 64B)
+#endif
+
 #include "translate/fp-impl.c.inc"
 
 #include "translate/vmx-impl.c.inc"
-- 
2.25.1




[PATCH v3 07/30] target/ppc: Move DISAS_NORETURN setting into gen_exception*

2021-04-29 Thread Richard Henderson
There are other valid settings for is_jmp besides
DISAS_NEXT and DISAS_NORETURN, so eliminating that
dichotomy from ppc_tr_translate_insn is helpful.

Signed-off-by: Richard Henderson 
---
v3: Retain an exit from translator loop for ctx->exception.
Do not emit code for single-step or ppc_tr_tb_stop for NORETURN.
---
 target/ppc/translate.c | 26 ++
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index ebe5afe7ae..3607cc12f3 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -262,7 +262,8 @@ static void gen_exception_err(DisasContext *ctx, uint32_t 
excp, uint32_t error)
 gen_helper_raise_exception_err(cpu_env, t0, t1);
 tcg_temp_free_i32(t0);
 tcg_temp_free_i32(t1);
-ctx->exception = (excp);
+ctx->exception = excp;
+ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 static void gen_exception(DisasContext *ctx, uint32_t excp)
@@ -279,7 +280,8 @@ static void gen_exception(DisasContext *ctx, uint32_t excp)
 t0 = tcg_const_i32(excp);
 gen_helper_raise_exception(cpu_env, t0);
 tcg_temp_free_i32(t0);
-ctx->exception = (excp);
+ctx->exception = excp;
+ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
@@ -291,7 +293,8 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t 
excp,
 t0 = tcg_const_i32(excp);
 gen_helper_raise_exception(cpu_env, t0);
 tcg_temp_free_i32(t0);
-ctx->exception = (excp);
+ctx->exception = excp;
+ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 /*
@@ -337,6 +340,7 @@ static void gen_debug_exception(DisasContext *ctx)
 t0 = tcg_const_i32(EXCP_DEBUG);
 gen_helper_raise_exception(cpu_env, t0);
 tcg_temp_free_i32(t0);
+ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 static inline void gen_inval_exception(DisasContext *ctx, uint32_t error)
@@ -8037,7 +8041,6 @@ static bool ppc_tr_breakpoint_check(DisasContextBase 
*dcbase, CPUState *cs,
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 
 gen_debug_exception(ctx);
-dcbase->is_jmp = DISAS_NORETURN;
 /*
  * The address covered by the breakpoint must be included in
  * [tb->pc, tb->pc + tb->size) in order to for it to be properly
@@ -8067,18 +8070,19 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 ok = decode_legacy(cpu, ctx, insn);
 if (!ok) {
 gen_invalid(ctx);
-ctx->base.is_jmp = DISAS_NORETURN;
 }
 
 #if defined(DO_PPC_STATISTICS)
 handler->count++;
 #endif
+
 /* Check trace mode exceptions */
 if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP &&
  (ctx->base.pc_next <= 0x100 || ctx->base.pc_next > 0xF00) &&
  ctx->exception != POWERPC_SYSCALL &&
  ctx->exception != POWERPC_EXCP_TRAP &&
- ctx->exception != POWERPC_EXCP_BRANCH)) {
+ ctx->exception != POWERPC_EXCP_BRANCH &&
+ ctx->base.is_jmp != DISAS_NORETURN)) {
 uint32_t excp = gen_prep_dbgex(ctx);
 gen_exception_nip(ctx, excp, ctx->base.pc_next);
 }
@@ -8089,14 +8093,20 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
  opc3(ctx->opcode), opc4(ctx->opcode), ctx->opcode);
 }
 
-ctx->base.is_jmp = ctx->exception == POWERPC_EXCP_NONE ?
-DISAS_NEXT : DISAS_NORETURN;
+if (ctx->base.is_jmp == DISAS_NEXT
+&& ctx->exception != POWERPC_EXCP_NONE) {
+ctx->base.is_jmp = DISAS_TOO_MANY;
+}
 }
 
 static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 
+if (ctx->base.is_jmp == DISAS_NORETURN) {
+return;
+}
+
 if (ctx->exception == POWERPC_EXCP_NONE) {
 gen_goto_tb(ctx, 0, ctx->base.pc_next);
 } else if (ctx->exception != POWERPC_EXCP_BRANCH) {
-- 
2.25.1




[PATCH v3 09/30] target/ppc: Remove special case for POWERPC_EXCP_TRAP

2021-04-29 Thread Richard Henderson
Since POWERPC_EXCP_TRAP is raised by gen_exception_err,
we will have also set DISAS_NORETURN.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index b26b6964a7..5efa4d6566 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -8079,7 +8079,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 /* Check trace mode exceptions */
 if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP &&
  (ctx->base.pc_next <= 0x100 || ctx->base.pc_next > 0xF00) &&
- ctx->exception != POWERPC_EXCP_TRAP &&
  ctx->exception != POWERPC_EXCP_BRANCH &&
  ctx->base.is_jmp != DISAS_NORETURN)) {
 uint32_t excp = gen_prep_dbgex(ctx);
-- 
2.25.1




[PATCH v3 02/30] decodetree: More use of f-strings

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 scripts/decodetree.py | 50 ---
 1 file changed, 23 insertions(+), 27 deletions(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 0861e5d503..d5da101167 100644
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -59,9 +59,9 @@ def error_with_file(file, lineno, *args):
 
 prefix = ''
 if file:
-prefix += '{0}:'.format(file)
+prefix += f'{file}:'
 if lineno:
-prefix += '{0}:'.format(lineno)
+prefix += f'{lineno}:'
 if prefix:
 prefix += ' '
 print(prefix, end='error: ', file=sys.stderr)
@@ -203,7 +203,7 @@ def str_extract(self):
 extr = 'sextract32'
 else:
 extr = 'extract32'
-return '{0}(insn, {1}, {2})'.format(extr, self.pos, self.len)
+return f'{extr}(insn, {self.pos}, {self.len})'
 
 def __eq__(self, other):
 return self.sign == other.sign and self.mask == other.mask
@@ -227,11 +227,11 @@ def str_extract(self):
 ret = '0'
 pos = 0
 for f in reversed(self.subs):
+ext = f.str_extract()
 if pos == 0:
-ret = f.str_extract()
+ret = ext
 else:
-ret = 'deposit32({0}, {1}, {2}, {3})' \
-  .format(ret, pos, 32 - pos, f.str_extract())
+ret = f'deposit32({ret}, {pos}, {32 - pos}, {ext})'
 pos += f.len
 return ret
 
@@ -675,11 +675,11 @@ def parse_field(lineno, name, toks):
 subtoks = t.split(':')
 sign = False
 else:
-error(lineno, 'invalid field token "{0}"'.format(t))
+error(lineno, f'invalid field token "{t}"')
 po = int(subtoks[0])
 le = int(subtoks[1])
 if po + le > insnwidth:
-error(lineno, 'field {0} too large'.format(t))
+error(lineno, f'field {t} too large')
 f = Field(sign, po, le)
 subs.append(f)
 width += le
@@ -724,9 +724,9 @@ def parse_arguments(lineno, name, toks):
 anyextern = True
 continue
 if not re.fullmatch(re_C_ident, t):
-error(lineno, 'invalid argument set token "{0}"'.format(t))
+error(lineno, f'invalid argument set token "{t}"')
 if t in flds:
-error(lineno, 'duplicate argument "{0}"'.format(t))
+error(lineno, f'duplicate argument "{t}"')
 flds.append(t)
 
 if name in arguments:
@@ -895,14 +895,14 @@ def parse_generic(lineno, parent_pat, name, toks):
 flen = flen[1:]
 shift = int(flen, 10)
 if shift + width > insnwidth:
-error(lineno, 'field {0} exceeds insnwidth'.format(fname))
+error(lineno, f'field {fname} exceeds insnwidth')
 f = Field(sign, insnwidth - width - shift, shift)
 flds = add_field(lineno, flds, fname, f)
 fixedbits <<= shift
 fixedmask <<= shift
 undefmask <<= shift
 else:
-error(lineno, 'invalid token "{0}"'.format(t))
+error(lineno, f'invalid token "{t}"')
 width += shift
 
 if variablewidth and width < insnwidth and width % 8 == 0:
@@ -914,7 +914,7 @@ def parse_generic(lineno, parent_pat, name, toks):
 
 # We should have filled in all of the bits of the instruction.
 elif not (is_format and width == 0) and width != insnwidth:
-error(lineno, 'definition has {0} bits'.format(width))
+error(lineno, f'definition has {width} bits')
 
 # Do not check for fields overlapping fields; one valid usage
 # is to be able to duplicate fields via import.
@@ -932,8 +932,7 @@ def parse_generic(lineno, parent_pat, name, toks):
 if arg:
 for f in flds.keys():
 if f not in arg.fields:
-error(lineno, 'field {0} not in argument set {1}'
-  .format(f, arg.name))
+error(lineno, f'field {f} not in argument set {arg.name}')
 else:
 arg = infer_argument_set(flds)
 if name in formats:
@@ -960,13 +959,12 @@ def parse_generic(lineno, parent_pat, name, toks):
 arg = fmt.base
 for f in flds.keys():
 if f not in arg.fields:
-error(lineno, 'field {0} not in argument set {1}'
-  .format(f, arg.name))
+error(lineno, f'field {f} not in argument set {arg.name}')
 if f in fmt.fields.keys():
-error(lineno, 'field {0} set by format and pattern'.format(f))
+error(lineno, f'field {f} set by format and pattern')
 for f in arg.fields:
 if f not in flds.keys() and f not in fmt.fields.keys():
-error(lineno, 'field {0} not initialized'.format(f))
+error(lineno, f'field {f} not initialized')
  

[PATCH v3 13/30] target/ppc: Remove unnecessary gen_io_end calls

2021-04-29 Thread Richard Henderson
Since ba3e7926691ed33, we switched the implementation of icount
to always reset can_do_io at the start of the following TB.
Most of them were removed in 9e9b10c64911, but some were missed.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate_init.c.inc | 6 --
 1 file changed, 6 deletions(-)

diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index c03a7c4f52..99e5f52925 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -213,7 +213,6 @@ static void spr_read_tbl(DisasContext *ctx, int gprn, int 
sprn)
 }
 gen_helper_load_tbl(cpu_gpr[gprn], cpu_env);
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_end();
 gen_stop_exception(ctx);
 }
 }
@@ -225,7 +224,6 @@ static void spr_read_tbu(DisasContext *ctx, int gprn, int 
sprn)
 }
 gen_helper_load_tbu(cpu_gpr[gprn], cpu_env);
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_end();
 gen_stop_exception(ctx);
 }
 }
@@ -250,7 +248,6 @@ static void spr_write_tbl(DisasContext *ctx, int sprn, int 
gprn)
 }
 gen_helper_store_tbl(cpu_env, cpu_gpr[gprn]);
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_end();
 gen_stop_exception(ctx);
 }
 }
@@ -262,7 +259,6 @@ static void spr_write_tbu(DisasContext *ctx, int sprn, int 
gprn)
 }
 gen_helper_store_tbu(cpu_env, cpu_gpr[gprn]);
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_end();
 gen_stop_exception(ctx);
 }
 }
@@ -311,7 +307,6 @@ static void spr_read_hdecr(DisasContext *ctx, int gprn, int 
sprn)
 }
 gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_end();
 gen_stop_exception(ctx);
 }
 }
@@ -323,7 +318,6 @@ static void spr_write_hdecr(DisasContext *ctx, int sprn, 
int gprn)
 }
 gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
-gen_io_end();
 gen_stop_exception(ctx);
 }
 }
-- 
2.25.1




[PATCH v3 06/30] target/ppc: Split out decode_legacy

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 115 +++--
 1 file changed, 64 insertions(+), 51 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index ee25badba2..ebe5afe7ae 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7876,6 +7876,62 @@ void ppc_cpu_dump_statistics(CPUState *cs, int flags)
 #endif
 }
 
+static bool decode_legacy(PowerPCCPU *cpu, DisasContext *ctx, uint32_t insn)
+{
+opc_handler_t **table, *handler;
+uint32_t inval;
+
+ctx->opcode = insn;
+
+LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
+  insn, opc1(insn), opc2(insn), opc3(insn), opc4(insn),
+  ctx->le_mode ? "little" : "big");
+
+table = cpu->opcodes;
+handler = table[opc1(insn)];
+if (is_indirect_opcode(handler)) {
+table = ind_table(handler);
+handler = table[opc2(insn)];
+if (is_indirect_opcode(handler)) {
+table = ind_table(handler);
+handler = table[opc3(insn)];
+if (is_indirect_opcode(handler)) {
+table = ind_table(handler);
+handler = table[opc4(insn)];
+}
+}
+}
+
+/* Is opcode *REALLY* valid ? */
+if (unlikely(handler->handler == _invalid)) {
+qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
+  "%02x - %02x - %02x - %02x (%08x) "
+  TARGET_FMT_lx "\n",
+  opc1(insn), opc2(insn), opc3(insn), opc4(insn),
+  insn, ctx->cia);
+return false;
+}
+
+if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | PPC_SPE_DOUBLE)
+ && Rc(insn))) {
+inval = handler->inval2;
+} else {
+inval = handler->inval1;
+}
+
+if (unlikely((insn & inval) != 0)) {
+qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
+  "%02x - %02x - %02x - %02x (%08x) "
+  TARGET_FMT_lx "\n", insn & inval,
+  opc1(insn), opc2(insn), opc3(insn), opc4(insn),
+  insn, ctx->cia);
+return false;
+}
+
+handler->handler(ctx);
+return true;
+}
+
 static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
@@ -7997,66 +8053,23 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = cs->env_ptr;
-opc_handler_t **table, *handler;
+uint32_t insn;
+bool ok;
 
 LOG_DISAS("\n");
 LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
   ctx->base.pc_next, ctx->mem_idx, (int)msr_ir);
 
 ctx->cia = ctx->base.pc_next;
-ctx->opcode = translator_ldl_swap(env, ctx->base.pc_next,
-  need_byteswap(ctx));
-
-LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
-  ctx->opcode, opc1(ctx->opcode), opc2(ctx->opcode),
-  opc3(ctx->opcode), opc4(ctx->opcode),
-  ctx->le_mode ? "little" : "big");
+insn = translator_ldl_swap(env, ctx->base.pc_next, need_byteswap(ctx));
 ctx->base.pc_next += 4;
-table = cpu->opcodes;
-handler = table[opc1(ctx->opcode)];
-if (is_indirect_opcode(handler)) {
-table = ind_table(handler);
-handler = table[opc2(ctx->opcode)];
-if (is_indirect_opcode(handler)) {
-table = ind_table(handler);
-handler = table[opc3(ctx->opcode)];
-if (is_indirect_opcode(handler)) {
-table = ind_table(handler);
-handler = table[opc4(ctx->opcode)];
-}
-}
-}
-/* Is opcode *REALLY* valid ? */
-if (unlikely(handler->handler == _invalid)) {
-qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
-  "%02x - %02x - %02x - %02x (%08x) "
-  TARGET_FMT_lx " %d\n",
-  opc1(ctx->opcode), opc2(ctx->opcode),
-  opc3(ctx->opcode), opc4(ctx->opcode),
-  ctx->opcode, ctx->cia, (int)msr_ir);
-} else {
-uint32_t inval;
 
-if (unlikely(handler->type & (PPC_SPE | PPC_SPE_SINGLE | 
PPC_SPE_DOUBLE)
- && Rc(ctx->opcode))) {
-inval = handler->inval2;
-} else {
-inval = handler->inval1;
-}
-
-if (unlikely((ctx->opcode & inval) != 0)) {
-qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for opcode: "
-  "%02x - %02x - %02x - %02x (%08x) "
-  TARGET_FMT_lx "\n", ctx->opcode & inval,
-  opc1(ctx->opcode), opc2(ctx->opcode),
-  

[PATCH v3 08/30] target/ppc: Remove special case for POWERPC_SYSCALL

2021-04-29 Thread Richard Henderson
Since POWERPC_SYSCALL is raised by gen_exception_err,
we will have also set DISAS_NORETURN.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3607cc12f3..b26b6964a7 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -8079,7 +8079,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 /* Check trace mode exceptions */
 if (unlikely(ctx->singlestep_enabled & CPU_SINGLE_STEP &&
  (ctx->base.pc_next <= 0x100 || ctx->base.pc_next > 0xF00) &&
- ctx->exception != POWERPC_SYSCALL &&
  ctx->exception != POWERPC_EXCP_TRAP &&
  ctx->exception != POWERPC_EXCP_BRANCH &&
  ctx->base.is_jmp != DISAS_NORETURN)) {
-- 
2.25.1




[PATCH v3 11/30] target/ppc: Introduce DISAS_{EXIT,CHAIN}{,_UPDATE}

2021-04-29 Thread Richard Henderson
Rewrite ppc_tr_tb_stop to handle these new codes.

Convert ctx->exception into these new codes at the end of
ppc_tr_translate_insn, prior to pushing the change back
throughout translate.c.

Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 75 --
 1 file changed, 65 insertions(+), 10 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index b58e2ac8dc..7dbdf3d047 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -183,6 +183,11 @@ struct DisasContext {
 uint64_t insns_flags2;
 };
 
+#define DISAS_EXIT DISAS_TARGET_0  /* exit to main loop, pc updated */
+#define DISAS_EXIT_UPDATE  DISAS_TARGET_1  /* exit to main loop, pc stale */
+#define DISAS_CHAINDISAS_TARGET_2  /* lookup next tb, pc updated */
+#define DISAS_CHAIN_UPDATE DISAS_TARGET_3  /* lookup next tb, pc stale */
+
 /* Return true iff byteswap is needed in a scalar memop */
 static inline bool need_byteswap(const DisasContext *ctx)
 {
@@ -8080,28 +8085,78 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
  opc3(ctx->opcode), opc4(ctx->opcode), ctx->opcode);
 }
 
-if (ctx->base.is_jmp == DISAS_NEXT
-&& ctx->exception != POWERPC_EXCP_NONE) {
-ctx->base.is_jmp = DISAS_TOO_MANY;
+if (ctx->base.is_jmp == DISAS_NEXT) {
+switch (ctx->exception) {
+case POWERPC_EXCP_NONE:
+break;
+case POWERPC_EXCP_BRANCH:
+ctx->base.is_jmp = DISAS_NORETURN;
+break;
+case POWERPC_EXCP_SYNC:
+case POWERPC_EXCP_STOP:
+ctx->base.is_jmp = DISAS_EXIT;
+break;
+default:
+/* Every other ctx->exception should have set NORETURN. */
+g_assert_not_reached();
+}
 }
 }
 
 static void ppc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
+DisasJumpType is_jmp = ctx->base.is_jmp;
+target_ulong nip = ctx->base.pc_next;
 
-if (ctx->base.is_jmp == DISAS_NORETURN) {
+if (is_jmp == DISAS_NORETURN) {
+/* We have already exited the TB. */
 return;
 }
 
-if (ctx->exception == POWERPC_EXCP_NONE) {
-gen_goto_tb(ctx, 0, ctx->base.pc_next);
-} else if (ctx->exception != POWERPC_EXCP_BRANCH) {
-if (unlikely(ctx->base.singlestep_enabled)) {
-gen_debug_exception(ctx);
+/* Honor single stepping. */
+if (unlikely(ctx->base.singlestep_enabled)) {
+switch (is_jmp) {
+case DISAS_TOO_MANY:
+case DISAS_EXIT_UPDATE:
+case DISAS_CHAIN_UPDATE:
+gen_update_nip(ctx, nip);
+break;
+case DISAS_EXIT:
+case DISAS_CHAIN:
+break;
+default:
+g_assert_not_reached();
 }
-/* Generate the return instruction */
+gen_debug_exception(ctx);
+return;
+}
+
+switch (is_jmp) {
+case DISAS_TOO_MANY:
+if (use_goto_tb(ctx, nip)) {
+tcg_gen_goto_tb(0);
+gen_update_nip(ctx, nip);
+tcg_gen_exit_tb(ctx->base.tb, 0);
+break;
+}
+/* fall through */
+case DISAS_CHAIN_UPDATE:
+gen_update_nip(ctx, nip);
+/* fall through */
+case DISAS_CHAIN:
+tcg_gen_lookup_and_goto_ptr();
+break;
+
+case DISAS_EXIT_UPDATE:
+gen_update_nip(ctx, nip);
+/* fall through */
+case DISAS_EXIT:
 tcg_gen_exit_tb(NULL, 0);
+break;
+
+default:
+g_assert_not_reached();
 }
 }
 
-- 
2.25.1




[PATCH v3 10/30] target/ppc: Simplify gen_debug_exception

2021-04-29 Thread Richard Henderson
Two of the call sites that use gen_debug_exception have already
updated NIP.  Only ppc_tr_breakpoint_check requires the update.

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

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 5efa4d6566..b58e2ac8dc 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -327,19 +327,7 @@ static uint32_t gen_prep_dbgex(DisasContext *ctx)
 
 static void gen_debug_exception(DisasContext *ctx)
 {
-TCGv_i32 t0;
-
-/*
- * These are all synchronous exceptions, we set the PC back to the
- * faulting instruction
- */
-if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
-(ctx->exception != POWERPC_EXCP_SYNC)) {
-gen_update_nip(ctx, ctx->base.pc_next);
-}
-t0 = tcg_const_i32(EXCP_DEBUG);
-gen_helper_raise_exception(cpu_env, t0);
-tcg_temp_free_i32(t0);
+gen_helper_raise_exception(cpu_env, tcg_constant_i32(EXCP_DEBUG));
 ctx->base.is_jmp = DISAS_NORETURN;
 }
 
@@ -8040,6 +8028,7 @@ static bool ppc_tr_breakpoint_check(DisasContextBase 
*dcbase, CPUState *cs,
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
 
+gen_update_nip(ctx, ctx->base.pc_next);
 gen_debug_exception(ctx);
 /*
  * The address covered by the breakpoint must be included in
-- 
2.25.1




[PATCH v3 03/30] decodetree: Add support for 64-bit instructions

2021-04-29 Thread Richard Henderson
From: Luis Fernando Fujita Pires 

Allow '64' to be specified for the instruction width command line params
and use the appropriate extract and deposit functions in that case.

This will be used to implement the new 64-bit Power ISA 3.1 instructions.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Luis Pires 
Message-Id: 

[rth: Drop the change to the field type; use bitop_width instead of separate
variables for extract/deposit; use "ull" for 64-bit constants.]
Signed-off-by: Richard Henderson 
---
 scripts/decodetree.py | 21 ++---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index d5da101167..f85da45ee3 100644
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -27,6 +27,7 @@
 import getopt
 
 insnwidth = 32
+bitop_width = 32
 insnmask = 0x
 variablewidth = False
 fields = {}
@@ -112,7 +113,9 @@ def whexC(val):
 """Return a hex string for val padded for insnwidth,
and with the proper suffix for a C constant."""
 suffix = ''
-if val >= 0x8000:
+if val >= 0x1:
+suffix = 'ull'
+elif val >= 0x8000:
 suffix = 'u'
 return whex(val) + suffix
 
@@ -199,11 +202,9 @@ def __str__(self):
 return str(self.pos) + ':' + s + str(self.len)
 
 def str_extract(self):
-if self.sign:
-extr = 'sextract32'
-else:
-extr = 'extract32'
-return f'{extr}(insn, {self.pos}, {self.len})'
+global bitop_width
+s = 's' if self.sign else ''
+return f'{s}extract{bitop_width}(insn, {self.pos}, {self.len})'
 
 def __eq__(self, other):
 return self.sign == other.sign and self.mask == other.mask
@@ -224,6 +225,7 @@ def __str__(self):
 return str(self.subs)
 
 def str_extract(self):
+global bitop_width
 ret = '0'
 pos = 0
 for f in reversed(self.subs):
@@ -231,7 +233,7 @@ def str_extract(self):
 if pos == 0:
 ret = ext
 else:
-ret = f'deposit32({ret}, {pos}, {32 - pos}, {ext})'
+ret = f'deposit{bitop_width}({ret}, {pos}, {bitop_width - 
pos}, {ext})'
 pos += f.len
 return ret
 
@@ -1270,6 +1272,7 @@ def main():
 global insntype
 global insnmask
 global decode_function
+global bitop_width
 global variablewidth
 global anyextern
 
@@ -1299,6 +1302,10 @@ def main():
 if insnwidth == 16:
 insntype = 'uint16_t'
 insnmask = 0x
+elif insnwidth == 64:
+insntype = 'uint64_t'
+insnmask = 0x
+bitop_width = 64
 elif insnwidth != 32:
 error(0, 'cannot handle insns of width', insnwidth)
 else:
-- 
2.25.1




[PATCH v3 04/30] decodetree: Extend argument set syntax to allow types

2021-04-29 Thread Richard Henderson
Rather than force all structure members to be 'int',
allow the type of the member to be specified.

Signed-off-by: Richard Henderson 
---
 docs/devel/decodetree.rst | 11 ---
 tests/decode/succ_argset_type1.decode |  1 +
 scripts/decodetree.py | 45 +--
 3 files changed, 36 insertions(+), 21 deletions(-)
 create mode 100644 tests/decode/succ_argset_type1.decode

diff --git a/docs/devel/decodetree.rst b/docs/devel/decodetree.rst
index 74f66bf46e..49ea50c2a7 100644
--- a/docs/devel/decodetree.rst
+++ b/docs/devel/decodetree.rst
@@ -40,9 +40,6 @@ and returns an integral value extracted from there.
 
 A field with no ``unnamed_fields`` and no ``!function`` is in error.
 
-FIXME: the fields of the structure into which this result will be stored
-is restricted to ``int``.  Which means that we cannot expand 64-bit items.
-
 Field examples:
 
 +---+-+
@@ -66,9 +63,14 @@ Argument Sets
 Syntax::
 
   args_def:= '&' identifier ( args_elt )+ ( !extern )?
-  args_elt:= identifier
+  args_elt:= identifier (':' identifier)?
 
 Each *args_elt* defines an argument within the argument set.
+If the form of the *args_elt* contains a colon, the first
+identifier is the argument name and the second identifier is
+the argument type.  If the colon is missing, the argument
+type will be ``int``.
+
 Each argument set will be rendered as a C structure "arg_$name"
 with each of the fields being one of the member arguments.
 
@@ -86,6 +88,7 @@ Argument set examples::
 
  ra rb rc
 reg base offset
+ reg base offset:int64_t
 
 
 Formats
diff --git a/tests/decode/succ_argset_type1.decode 
b/tests/decode/succ_argset_type1.decode
new file mode 100644
index 00..ed946b420d
--- /dev/null
+++ b/tests/decode/succ_argset_type1.decode
@@ -0,0 +1 @@
+ b:bool c:uint64_t a
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index f85da45ee3..a03dc6b5e3 100644
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -165,11 +165,15 @@ def is_contiguous(bits):
 return -1
 
 
-def eq_fields_for_args(flds_a, flds_b):
-if len(flds_a) != len(flds_b):
+def eq_fields_for_args(flds_a, arg):
+if len(flds_a) != len(arg.fields):
 return False
+# Only allow inference on default types
+for t in arg.types:
+if t != 'int':
+return False
 for k, a in flds_a.items():
-if k not in flds_b:
+if k not in arg.fields:
 return False
 return True
 
@@ -313,10 +317,11 @@ def __ne__(self, other):
 
 class Arguments:
 """Class representing the extracted fields of a format"""
-def __init__(self, nm, flds, extern):
+def __init__(self, nm, flds, types, extern):
 self.name = nm
 self.extern = extern
-self.fields = sorted(flds)
+self.fields = flds
+self.types = types
 
 def __str__(self):
 return self.name + ' ' + str(self.fields)
@@ -327,8 +332,8 @@ def struct_name(self):
 def output_def(self):
 if not self.extern:
 output('typedef struct {\n')
-for n in self.fields:
-output('int ', n, ';\n')
+for (n, t) in zip(self.fields, self.types):
+output(f'{t} {n};\n')
 output('} ', self.struct_name(), ';\n\n')
 # end Arguments
 
@@ -719,21 +724,27 @@ def parse_arguments(lineno, name, toks):
 global anyextern
 
 flds = []
+types = []
 extern = False
-for t in toks:
-if re.fullmatch('!extern', t):
+for n in toks:
+if re.fullmatch('!extern', n):
 extern = True
 anyextern = True
 continue
-if not re.fullmatch(re_C_ident, t):
-error(lineno, f'invalid argument set token "{t}"')
-if t in flds:
-error(lineno, f'duplicate argument "{t}"')
-flds.append(t)
+if re.fullmatch(re_C_ident + ':' + re_C_ident, n):
+(n, t) = n.split(':')
+elif re.fullmatch(re_C_ident, n):
+t = 'int'
+else:
+error(lineno, f'invalid argument set token "{n}"')
+if n in flds:
+error(lineno, f'duplicate argument "{n}"')
+flds.append(n)
+types.append(t)
 
 if name in arguments:
 error(lineno, 'duplicate argument set', name)
-arguments[name] = Arguments(name, flds, extern)
+arguments[name] = Arguments(name, flds, types, extern)
 # end parse_arguments
 
 
@@ -760,11 +771,11 @@ def infer_argument_set(flds):
 global decode_function
 
 for arg in arguments.values():
-if eq_fields_for_args(flds, arg.fields):
+if eq_fields_for_args(flds, arg):
 return arg
 
 name = decode_function + str(len(arguments))
-arg = Arguments(name, flds.keys(), False)
+arg = Arguments(name, flds.keys(), ['int'] * len(flds), False)
 arguments[name] = arg
 

[PATCH v3 12/30] target/ppc: Replace POWERPC_EXCP_SYNC with DISAS_EXIT

2021-04-29 Thread Richard Henderson
Remove the synthetic "exception" after no more uses.

Signed-off-by: Richard Henderson 
---
 target/ppc/cpu.h   |  1 -
 target/ppc/translate.c | 27 +--
 2 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index e73416da68..cf10117065 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -135,7 +135,6 @@ enum {
 POWERPC_EXCP_STOP = 0x200, /* stop translation   */
 POWERPC_EXCP_BRANCH   = 0x201, /* branch instruction */
 /* QEMU exceptions: special cases we want to stop translation*/
-POWERPC_EXCP_SYNC = 0x202, /* context synchronizing instruction  */
 POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only  */
 };
 
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 7dbdf3d047..d22d6e5b85 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -360,14 +360,6 @@ static inline void gen_stop_exception(DisasContext *ctx)
 ctx->exception = POWERPC_EXCP_STOP;
 }
 
-#ifndef CONFIG_USER_ONLY
-/* No need to update nip here, as execution flow will change */
-static inline void gen_sync_exception(DisasContext *ctx)
-{
-ctx->exception = POWERPC_EXCP_SYNC;
-}
-#endif
-
 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type)  \
 GEN_OPCODE(name, opc1, opc2, opc3, inval, type, PPC_NONE)
 
@@ -4008,7 +4000,7 @@ static void gen_rfi(DisasContext *ctx)
 }
 gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfi(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif
 }
 
@@ -4025,7 +4017,7 @@ static void gen_rfid(DisasContext *ctx)
 }
 gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfid(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif
 }
 
@@ -4042,7 +4034,7 @@ static void gen_rfscv(DisasContext *ctx)
 }
 gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfscv(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif
 }
 #endif
@@ -4055,7 +4047,7 @@ static void gen_hrfid(DisasContext *ctx)
 /* Restore CPU state */
 CHK_HV;
 gen_helper_hrfid(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif
 }
 #endif
@@ -5941,7 +5933,7 @@ static void gen_rfsvc(DisasContext *ctx)
 CHK_SV;
 
 gen_helper_rfsvc(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -6321,7 +6313,7 @@ static void gen_rfci_40x(DisasContext *ctx)
 CHK_SV;
 /* Restore CPU state */
 gen_helper_40x_rfci(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -6333,7 +6325,7 @@ static void gen_rfci(DisasContext *ctx)
 CHK_SV;
 /* Restore CPU state */
 gen_helper_rfci(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -6348,7 +6340,7 @@ static void gen_rfdi(DisasContext *ctx)
 CHK_SV;
 /* Restore CPU state */
 gen_helper_rfdi(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -6361,7 +6353,7 @@ static void gen_rfmci(DisasContext *ctx)
 CHK_SV;
 /* Restore CPU state */
 gen_helper_rfmci(cpu_env);
-gen_sync_exception(ctx);
+ctx->base.is_jmp = DISAS_EXIT;
 #endif /* defined(CONFIG_USER_ONLY) */
 }
 
@@ -8092,7 +8084,6 @@ static void ppc_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 case POWERPC_EXCP_BRANCH:
 ctx->base.is_jmp = DISAS_NORETURN;
 break;
-case POWERPC_EXCP_SYNC:
 case POWERPC_EXCP_STOP:
 ctx->base.is_jmp = DISAS_EXIT;
 break;
-- 
2.25.1




[PATCH v3 05/30] target/ppc: Add cia field to DisasContext

2021-04-29 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 34 ++
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0984ce637b..ee25badba2 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -154,6 +154,7 @@ void ppc_translate_init(void)
 /* internal defines */
 struct DisasContext {
 DisasContextBase base;
+target_ulong cia;  /* current instruction address */
 uint32_t opcode;
 uint32_t exception;
 /* Routine used to access memory */
@@ -254,7 +255,7 @@ static void gen_exception_err(DisasContext *ctx, uint32_t 
excp, uint32_t error)
  * faulting instruction
  */
 if (ctx->exception == POWERPC_EXCP_NONE) {
-gen_update_nip(ctx, ctx->base.pc_next - 4);
+gen_update_nip(ctx, ctx->cia);
 }
 t0 = tcg_const_i32(excp);
 t1 = tcg_const_i32(error);
@@ -273,7 +274,7 @@ static void gen_exception(DisasContext *ctx, uint32_t excp)
  * faulting instruction
  */
 if (ctx->exception == POWERPC_EXCP_NONE) {
-gen_update_nip(ctx, ctx->base.pc_next - 4);
+gen_update_nip(ctx, ctx->cia);
 }
 t0 = tcg_const_i32(excp);
 gen_helper_raise_exception(cpu_env, t0);
@@ -3113,7 +3114,7 @@ static void gen_eieio(DisasContext *ctx)
  */
 if (!(ctx->insns_flags2 & PPC2_ISA300)) {
 qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
-  TARGET_FMT_lx "\n", ctx->base.pc_next - 4);
+  TARGET_FMT_lx "\n", ctx->cia);
 } else {
 bar = TCG_MO_ST_LD;
 }
@@ -3782,14 +3783,14 @@ static void gen_b(DisasContext *ctx)
 li = LI(ctx->opcode);
 li = (li ^ 0x0200) - 0x0200;
 if (likely(AA(ctx->opcode) == 0)) {
-target = ctx->base.pc_next + li - 4;
+target = ctx->cia + li;
 } else {
 target = li;
 }
 if (LK(ctx->opcode)) {
 gen_setlr(ctx, ctx->base.pc_next);
 }
-gen_update_cfar(ctx, ctx->base.pc_next - 4);
+gen_update_cfar(ctx, ctx->cia);
 gen_goto_tb(ctx, 0, target);
 }
 
@@ -3888,11 +3889,11 @@ static void gen_bcond(DisasContext *ctx, int type)
 }
 tcg_temp_free_i32(temp);
 }
-gen_update_cfar(ctx, ctx->base.pc_next - 4);
+gen_update_cfar(ctx, ctx->cia);
 if (type == BCOND_IM) {
 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
 if (likely(AA(ctx->opcode) == 0)) {
-gen_goto_tb(ctx, 0, ctx->base.pc_next + li - 4);
+gen_goto_tb(ctx, 0, ctx->cia + li);
 } else {
 gen_goto_tb(ctx, 0, li);
 }
@@ -4008,7 +4009,7 @@ static void gen_rfi(DisasContext *ctx)
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
 gen_io_start();
 }
-gen_update_cfar(ctx, ctx->base.pc_next - 4);
+gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfi(cpu_env);
 gen_sync_exception(ctx);
 #endif
@@ -4025,7 +4026,7 @@ static void gen_rfid(DisasContext *ctx)
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
 gen_io_start();
 }
-gen_update_cfar(ctx, ctx->base.pc_next - 4);
+gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfid(cpu_env);
 gen_sync_exception(ctx);
 #endif
@@ -4042,7 +4043,7 @@ static void gen_rfscv(DisasContext *ctx)
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
 gen_io_start();
 }
-gen_update_cfar(ctx, ctx->base.pc_next - 4);
+gen_update_cfar(ctx, ctx->cia);
 gen_helper_rfscv(cpu_env);
 gen_sync_exception(ctx);
 #endif
@@ -4338,7 +4339,7 @@ static inline void gen_op_mfspr(DisasContext *ctx)
 if (sprn != SPR_PVR) {
 qemu_log_mask(LOG_GUEST_ERROR, "Trying to read privileged spr "
   "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
-  ctx->base.pc_next - 4);
+  ctx->cia);
 }
 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
 }
@@ -4352,7 +4353,7 @@ static inline void gen_op_mfspr(DisasContext *ctx)
 /* Not defined */
 qemu_log_mask(LOG_GUEST_ERROR,
   "Trying to read invalid spr %d (0x%03x) at "
-  TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
+  TARGET_FMT_lx "\n", sprn, sprn, ctx->cia);
 
 /*
  * The behaviour depends on MSR:PR and SPR# bit 0x10, it can
@@ -4516,7 +4517,7 @@ static void gen_mtspr(DisasContext *ctx)
 /* Privilege exception */
 qemu_log_mask(LOG_GUEST_ERROR, "Trying to write privileged spr "
   "%d (0x%03x) at " TARGET_FMT_lx "\n", sprn, sprn,
-  ctx->base.pc_next - 4);
+  ctx->cia);
 gen_priv_exception(ctx, POWERPC_EXCP_PRIV_REG);
 }
 } else {
@@ -4530,7 +4531,7 @@ static void gen_mtspr(DisasContext *ctx)

[PATCH v3 01/30] decodetree: Introduce whex and whexC helpers

2021-04-29 Thread Richard Henderson
Form a hex constant of the appropriate insnwidth.
Begin using f-strings on changed lines.

Signed-off-by: Richard Henderson 
---
 scripts/decodetree.py | 66 +--
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 4637b633e7..0861e5d503 100644
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -102,6 +102,21 @@ def str_fields(fields):
 return r[1:]
 
 
+def whex(val):
+"""Return a hex string for val padded for insnwidth"""
+global insnwidth
+return f'0x{val:0{insnwidth // 4}x}'
+
+
+def whexC(val):
+"""Return a hex string for val padded for insnwidth,
+   and with the proper suffix for a C constant."""
+suffix = ''
+if val >= 0x8000:
+suffix = 'u'
+return whex(val) + suffix
+
+
 def str_match_bits(bits, mask):
 """Return a string pretty-printing BITS/MASK"""
 global insnwidth
@@ -477,11 +492,8 @@ def output_code(self, i, extracted, outerbits, outermask):
 if outermask != p.fixedmask:
 innermask = p.fixedmask & ~outermask
 innerbits = p.fixedbits & ~outermask
-output(ind, 'if ((insn & ',
-   '0x{0:08x}) == 0x{1:08x}'.format(innermask, innerbits),
-   ') {\n')
-output(ind, '/* ',
-   str_match_bits(p.fixedbits, p.fixedmask), ' */\n')
+output(ind, f'if ((insn & {whexC(innermask)}) == 
{whexC(innerbits)}) {{\n')
+output(ind, f'/* {str_match_bits(p.fixedbits, 
p.fixedmask)} */\n')
 p.output_code(i + 4, extracted, p.fixedbits, p.fixedmask)
 output(ind, '}\n')
 else:
@@ -500,12 +512,12 @@ def __init__(self, fm, tm):
 
 def str1(self, i):
 ind = str_indent(i)
-r = '{0}{1:08x}'.format(ind, self.fixedmask)
+r = ind + whex(self.fixedmask)
 if self.format:
 r += ' ' + self.format.name
 r += ' [\n'
 for (b, s) in self.subs:
-r += '{0}  {1:08x}:\n'.format(ind, b)
+r += ind + f'  {whex(b)}:\n'
 r += s.str1(i + 4) + '\n'
 r += ind + ']'
 return r
@@ -529,16 +541,16 @@ def output_code(self, i, extracted, outerbits, outermask):
 if sh > 0:
 # Propagate SH down into the local functions.
 def str_switch(b, sh=sh):
-return '(insn >> {0}) & 0x{1:x}'.format(sh, b >> sh)
+return f'(insn >> {sh}) & {b >> sh:#x}'
 
 def str_case(b, sh=sh):
-return '0x{0:x}'.format(b >> sh)
+return hex(b >> sh)
 else:
 def str_switch(b):
-return 'insn & 0x{0:08x}'.format(b)
+return f'insn & {whexC(b)}'
 
 def str_case(b):
-return '0x{0:08x}'.format(b)
+return whexC(b)
 
 output(ind, 'switch (', str_switch(self.thismask), ') {\n')
 for b, s in sorted(self.subs):
@@ -962,19 +974,19 @@ def parse_generic(lineno, parent_pat, name, toks):
 
 # Validate the masks that we have assembled.
 if fieldmask & fixedmask:
-error(lineno, 'fieldmask overlaps fixedmask (0x{0:08x} & 0x{1:08x})'
-  .format(fieldmask, fixedmask))
+error(lineno, 'fieldmask overlaps fixedmask ',
+  f'({whex(fieldmask)} & {whex(fixedmask)})')
 if fieldmask & undefmask:
-error(lineno, 'fieldmask overlaps undefmask (0x{0:08x} & 0x{1:08x})'
-  .format(fieldmask, undefmask))
+error(lineno, 'fieldmask overlaps undefmask ',
+  f'({whex(fieldmask)} & {whex(undefmask)})')
 if fixedmask & undefmask:
-error(lineno, 'fixedmask overlaps undefmask (0x{0:08x} & 0x{1:08x})'
-  .format(fixedmask, undefmask))
+error(lineno, 'fixedmask overlaps undefmask ',
+  f'({whex(fixedmask)} & {whex(undefmask)})')
 if not is_format:
 allbits = fieldmask | fixedmask | undefmask
 if allbits != insnmask:
-error(lineno, 'bits left unspecified (0x{0:08x})'
-  .format(allbits ^ insnmask))
+error(lineno, 'bits left unspecified ',
+  f'({whex(allbits ^ insnmask)})')
 # end parse_general
 
 
@@ -1104,10 +1116,9 @@ def __init__(self, m, w):
 
 def str1(self, i):
 ind = str_indent(i)
-r = '{0}{1:08x}'.format(ind, self.mask)
-r += ' [\n'
+r = ind + whex(self.mask) + ' [\n'
 for (b, s) in self.subs:
-r += '{0}  {1:08x}:\n'.format(ind, b)
+r += ind + f'  {whex(b)}:\n'
 r += s.str1(i + 4) + '\n'
 r += ind + ']'
 return r
@@ -1131,16 +1142,16 @@ def output_code(self, i, extracted, outerbits, 
outermask):
 if sh > 0:
 # Propagate SH down into the local functions.
 

[PATCH v3 00/30] Base for adding PowerPC 64-bit instructions

2021-04-29 Thread Richard Henderson
Changes for v3:
  * More changes for decodetree.
  * Cleanup exception/is_jmp logic to the point exception is removed.
  * Fold in Luis' isa check for prefixed insn support.
  * Share trans_* between prefixed and non-prefixed instructions.
  * Use macros to minimize the trans_* boilerplate.
  * Fix decode mistake for STHX/STHXU.


r~


Luis Fernando Fujita Pires (1):
  decodetree: Add support for 64-bit instructions

Richard Henderson (29):
  decodetree: Introduce whex and whexC helpers
  decodetree: More use of f-strings
  decodetree: Extend argument set syntax to allow types
  target/ppc: Add cia field to DisasContext
  target/ppc: Split out decode_legacy
  target/ppc: Move DISAS_NORETURN setting into gen_exception*
  target/ppc: Remove special case for POWERPC_SYSCALL
  target/ppc: Remove special case for POWERPC_EXCP_TRAP
  target/ppc: Simplify gen_debug_exception
  target/ppc: Introduce DISAS_{EXIT,CHAIN}{,_UPDATE}
  target/ppc: Replace POWERPC_EXCP_SYNC with DISAS_EXIT
  target/ppc: Remove unnecessary gen_io_end calls
  target/ppc: Introduce gen_icount_io_start
  target/ppc: Replace POWERPC_EXCP_STOP with DISAS_EXIT_UPDATE
  target/ppc: Replace POWERPC_EXCP_BRANCH with DISAS_NORETURN
  target/ppc: Remove DisasContext.exception
  target/ppc: Move single-step check to ppc_tr_tb_stop
  target/ppc: Tidy exception vs exit_tb
  target/ppc: Mark helper_raise_exception* as noreturn
  target/ppc: Use translator_loop_temp_check
  target/ppc: Introduce macros to check isa extensions
  target/ppc: Add infrastructure for prefixed insns
  target/ppc: Move page crossing check to ppc_tr_translate_insn
  target/ppc: Move ADDI, ADDIS to decodetree, implement PADDI
  target/ppc: Implement PNOP
  target/ppc: Move D/DS/X-form integer loads to decodetree
  target/ppc: Implement prefixed integer load instructions
  target/ppc: Move D/DS/X-form integer stores to decodetree
  target/ppc: Implement prefixed integer store instructions

 docs/devel/decodetree.rst  |  11 +-
 target/ppc/cpu.h   |   5 +-
 target/ppc/helper.h|   4 +-
 target/ppc/insn32.decode   |  91 +++
 target/ppc/insn64.decode   |  71 +++
 tests/decode/succ_argset_type1.decode  |   1 +
 linux-user/ppc/cpu_loop.c  |   6 -
 target/ppc/translate.c | 672 +
 target/ppc/translate/fixedpoint-impl.c.inc | 200 ++
 target/ppc/translate_init.c.inc| 143 +
 scripts/decodetree.py  | 172 +++---
 target/ppc/meson.build |   9 +
 12 files changed, 772 insertions(+), 613 deletions(-)
 create mode 100644 target/ppc/insn32.decode
 create mode 100644 target/ppc/insn64.decode
 create mode 100644 tests/decode/succ_argset_type1.decode
 create mode 100644 target/ppc/translate/fixedpoint-impl.c.inc

-- 
2.25.1




[PATCH 0/2] cocoa: keyboard quality of life

2021-04-29 Thread gustavo
From: Gustavo Noronha Silva 

This series adds two new options to the cocoa display:

 - full-grab causes it to use a global tap to steal system combos
   away from Mac OS X, so they can be handled by the VM

 - swap-option-command does what it says on the tin; while that is
   something you can do at the Mac OS X level or even supported by
   some keyboards, it is much more convenient to have qemu put
   Meta/Super and Alt where they belong if you are running a
   non-Mac VM

I propose to enable swap-option-command by default and leave full-grab
off because unfortunately it needs accessibility permissions for input
grabbing, so it requires more deliberate action by the user anyway.

Gustavo Noronha Silva (2):
  ui/cocoa: capture all keys and combos when mouse is grabbed
  ui/cocoa: add option to swap Option and Command, enable by default

 qapi/ui.json|  20 +++
 qemu-options.hx |   4 ++
 ui/cocoa.m  | 139 +++-
 3 files changed, 151 insertions(+), 12 deletions(-)

-- 
2.24.3 (Apple Git-128)




[PATCH 1/2] ui/cocoa: capture all keys and combos when mouse is grabbed

2021-04-29 Thread gustavo
From: Gustavo Noronha Silva 

Applications such as Gnome may use Alt-Tab and Super-Tab for different
purposes, some use Ctrl-arrows so we want to allow qemu to handle
everything when it captures the mouse/keyboard.

However, Mac OS handles some combos like Command-Tab and Ctrl-arrows
at an earlier part of the event handling chain, not letting qemu see it.

We add a global Event Tap that allows qemu to see all events when the
mouse is grabbed. Note that this requires additional permissions.

See:

https://developer.apple.com/documentation/coregraphics/1454426-cgeventtapcreate?language=objc#discussion
https://support.apple.com/en-in/guide/mac-help/mh32356/mac

Signed-off-by: Gustavo Noronha Silva 
---
 qapi/ui.json| 15 ++
 qemu-options.hx |  3 ++
 ui/cocoa.m  | 73 +++--
 3 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/qapi/ui.json b/qapi/ui.json
index 1052ca9c38..77bc00fd0d 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1088,6 +1088,20 @@
 { 'struct'  : 'DisplayCurses',
   'data': { '*charset'   : 'str' } }
 
+##
+# @DisplayCocoa:
+#
+# Cocoa display options.
+#
+# @full-grab:   Capture all key presses, including system combos. This
+#   requires accessibility permissions, since it performs
+#   a global grab on key events. (default: off)
+#   See 
https://support.apple.com/en-in/guide/mac-help/mh32356/mac
+#
+##
+{ 'struct'  : 'DisplayCocoa',
+  'data': { '*full-grab' : 'bool' } }
+
 ##
 # @DisplayType:
 #
@@ -1153,6 +1167,7 @@
 '*gl': 'DisplayGLMode' },
   'discriminator' : 'type',
   'data': { 'gtk': 'DisplayGTK',
+'cocoa'  : 'DisplayCocoa',
 'curses' : 'DisplayCurses',
 'egl-headless'   : 'DisplayEGLHeadless'} }
 
diff --git a/qemu-options.hx b/qemu-options.hx
index fd21002bd6..a77505241f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1783,6 +1783,9 @@ DEF("display", HAS_ARG, QEMU_OPTION_display,
 #if defined(CONFIG_CURSES)
 "-display curses[,charset=]\n"
 #endif
+#if defined(CONFIG_COCOA)
+"-display cocoa[,full_grab=on|off]\n"
+#endif
 #if defined(CONFIG_OPENGL)
 "-display egl-headless[,rendernode=]\n"
 #endif
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 37e1fb52eb..f1e4449082 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -72,6 +72,7 @@
 typedef struct {
 int width;
 int height;
+bool full_grab;
 } QEMUScreen;
 
 static void cocoa_update(DisplayChangeListener *dcl,
@@ -304,11 +305,13 @@ @interface QemuCocoaView : NSView
 BOOL isMouseGrabbed;
 BOOL isFullscreen;
 BOOL isAbsoluteEnabled;
+CFMachPortRef eventsTap;
 }
 - (void) switchSurface:(pixman_image_t *)image;
 - (void) grabMouse;
 - (void) ungrabMouse;
 - (void) toggleFullScreen:(id)sender;
+- (void) setFullGrab:(id)sender to:(BOOL)value;
 - (void) handleMonitorInput:(NSEvent *)event;
 - (bool) handleEvent:(NSEvent *)event;
 - (bool) handleEventLocked:(NSEvent *)event;
@@ -323,6 +326,7 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
  */
 - (BOOL) isMouseGrabbed;
 - (BOOL) isAbsoluteEnabled;
+- (BOOL) isFullGrabEnabled;
 - (float) cdx;
 - (float) cdy;
 - (QEMUScreen) gscreen;
@@ -331,6 +335,19 @@ - (void) raiseAllKeys;
 
 QemuCocoaView *cocoaView;
 
+static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, 
CGEventRef cgEvent, void *userInfo)
+{
+QemuCocoaView *cocoaView = (QemuCocoaView*) userInfo;
+NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
+if ([cocoaView isFullGrabEnabled] && [cocoaView isMouseGrabbed] && 
[cocoaView handleEvent:event]) {
+COCOA_DEBUG("Global events tap: qemu handled the event, capturing!\n");
+return NULL;
+}
+COCOA_DEBUG("Global events tap: qemu did not handle the event, letting it 
through...\n");
+
+return cgEvent;
+}
+
 @implementation QemuCocoaView
 - (id)initWithFrame:(NSRect)frameRect
 {
@@ -344,6 +361,32 @@ - (id)initWithFrame:(NSRect)frameRect
 kbd = qkbd_state_init(dcl.con);
 
 }
+
+CGEventMask mask = CGEventMaskBit(kCGEventKeyDown) | 
CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged);
+eventsTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 
kCGEventTapOptionDefault,
+ mask, handleTapEvent, self);
+if (!eventsTap) {
+warn_report("Could not create event tap, system key combos will not be 
captured.\n");
+return self;
+} else {
+COCOA_DEBUG("Global events tap created! Will capture system key 
combos.\n");
+}
+
+CFRunLoopRef runLoop = CFRunLoopGetCurrent();
+if (!runLoop) {
+warn_report("Could not obtain current CF RunLoop, system key combos 
will not be captured.\n");
+return self;
+}
+
+CFRunLoopSourceRef tapEventsSrc = 
CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventsTap, 0);
+if 

[PATCH 2/2] ui/cocoa: add option to swap Option and Command, enable by default

2021-04-29 Thread gustavo
From: Gustavo Noronha Silva 

On Mac OS X the Option key maps to Alt and Command to Super/Meta. This change
swaps them around so that Alt is the key closer to the space bar and Meta/Super
is between Control and Alt, like on non-Mac keyboards.

It is a cocoa display option, enabled by default.

Signed-off-by: Gustavo Noronha Silva 
---
 qapi/ui.json|  7 +-
 qemu-options.hx |  1 +
 ui/cocoa.m  | 66 +
 3 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/qapi/ui.json b/qapi/ui.json
index 77bc00fd0d..02db684251 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1098,9 +1098,14 @@
 #   a global grab on key events. (default: off)
 #   See 
https://support.apple.com/en-in/guide/mac-help/mh32356/mac
 #
+# @swap-option-command: Swaps the Option and Command keys so that their key 
codes
+#   match their position on non-Mac keyboards and you can 
use
+#   Meta/Super and Alt where you expect them. (default: on)
+#
 ##
 { 'struct'  : 'DisplayCocoa',
-  'data': { '*full-grab' : 'bool' } }
+  'data': { '*full-grab'   : 'bool',
+'*swap-option-command' : 'bool' } }
 
 ##
 # @DisplayType:
diff --git a/qemu-options.hx b/qemu-options.hx
index a77505241f..d6137eedac 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1785,6 +1785,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display,
 #endif
 #if defined(CONFIG_COCOA)
 "-display cocoa[,full_grab=on|off]\n"
+"  [,swap_option_command=on|off]\n"
 #endif
 #if defined(CONFIG_OPENGL)
 "-display egl-headless[,rendernode=]\n"
diff --git a/ui/cocoa.m b/ui/cocoa.m
index f1e4449082..879e568a9d 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -73,6 +73,7 @@
 int width;
 int height;
 bool full_grab;
+bool swap_option_command;
 } QEMUScreen;
 
 static void cocoa_update(DisplayChangeListener *dcl,
@@ -327,6 +328,7 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
 - (BOOL) isMouseGrabbed;
 - (BOOL) isAbsoluteEnabled;
 - (BOOL) isFullGrabEnabled;
+- (BOOL) isSwapOptionCommandEnabled;
 - (float) cdx;
 - (float) cdy;
 - (QEMUScreen) gscreen;
@@ -648,6 +650,13 @@ - (void) setFullGrab:(id)sender to:(BOOL)value
 screen.full_grab = value;
 }
 
+- (void) setSwapOptionCommand:(id)sender
+{
+COCOA_DEBUG("QemuCocoaView: setSwapOptionCommand\n");
+
+screen.swap_option_command = true;
+}
+
 - (void) toggleKey: (int)keycode {
 qkbd_state_key_event(kbd, keycode, !qkbd_state_key_get(kbd, keycode));
 }
@@ -797,12 +806,22 @@ - (bool) handleEventLocked:(NSEvent *)event
 qkbd_state_key_event(kbd, Q_KEY_CODE_CTRL_R, false);
 }
 if (!(modifiers & NSEventModifierFlagOption)) {
-qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false);
-qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false);
+if ([self isSwapOptionCommandEnabled]) {
+qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false);
+qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false);
+} else {
+qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false);
+qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false);
+}
 }
 if (!(modifiers & NSEventModifierFlagCommand)) {
-qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false);
-qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false);
+if ([self isSwapOptionCommandEnabled]) {
+qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false);
+qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false);
+} else {
+qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false);
+qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false);
+}
 }
 
 switch ([event type]) {
@@ -834,13 +853,21 @@ - (bool) handleEventLocked:(NSEvent *)event
 
 case kVK_Option:
 if (!!(modifiers & NSEventModifierFlagOption)) {
-[self toggleKey:Q_KEY_CODE_ALT];
+if ([self isSwapOptionCommandEnabled]) {
+[self toggleKey:Q_KEY_CODE_META_L];
+} else {
+[self toggleKey:Q_KEY_CODE_ALT];
+}
 }
 break;
 
 case kVK_RightOption:
 if (!!(modifiers & NSEventModifierFlagOption)) {
-[self toggleKey:Q_KEY_CODE_ALT_R];
+if ([self isSwapOptionCommandEnabled]) {
+[self toggleKey:Q_KEY_CODE_META_R];
+} else {
+[self toggleKey:Q_KEY_CODE_ALT_R];
+}
 }
 break;
 
@@ -848,15 +875,21 @@ - (bool) handleEventLocked:(NSEvent *)event
 case kVK_Command:
 if (isMouseGrabbed &&
 !!(modifiers & 

[PATCH v3 7/8] hw/arm/sbsa-ref: add ITS support in SBSA GIC

2021-04-29 Thread Shashi Mallela
Included creation of ITS as part of SBSA platform GIC
initialization.

Signed-off-by: Shashi Mallela 
---
 hw/arm/sbsa-ref.c | 26 +++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 88dfb2284c..d05cbcae48 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -35,7 +35,7 @@
 #include "hw/boards.h"
 #include "hw/ide/internal.h"
 #include "hw/ide/ahci_internal.h"
-#include "hw/intc/arm_gicv3_common.h"
+#include "hw/intc/arm_gicv3_its_common.h"
 #include "hw/loader.h"
 #include "hw/pci-host/gpex.h"
 #include "hw/qdev-properties.h"
@@ -65,6 +65,7 @@ enum {
 SBSA_CPUPERIPHS,
 SBSA_GIC_DIST,
 SBSA_GIC_REDIST,
+SBSA_GIC_ITS,
 SBSA_SECURE_EC,
 SBSA_GWDT,
 SBSA_GWDT_REFRESH,
@@ -108,6 +109,7 @@ static const MemMapEntry sbsa_ref_memmap[] = {
 [SBSA_CPUPERIPHS] = { 0x4000, 0x0004 },
 [SBSA_GIC_DIST] =   { 0x4006, 0x0001 },
 [SBSA_GIC_REDIST] = { 0x4008, 0x0400 },
+[SBSA_GIC_ITS] ={ 0x4409, 0x0002 },
 [SBSA_SECURE_EC] =  { 0x5000, 0x1000 },
 [SBSA_GWDT_REFRESH] =   { 0x5001, 0x1000 },
 [SBSA_GWDT_CONTROL] =   { 0x50011000, 0x1000 },
@@ -378,7 +380,20 @@ static void create_secure_ram(SBSAMachineState *sms,
 memory_region_add_subregion(secure_sysmem, base, secram);
 }
 
-static void create_gic(SBSAMachineState *sms)
+static void create_its(SBSAMachineState *sms)
+{
+DeviceState *dev;
+
+dev = qdev_new(TYPE_ARM_GICV3_ITS);
+SysBusDevice *s = SYS_BUS_DEVICE(dev);
+
+object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(sms->gic),
+ _abort);
+sysbus_realize_and_unref(s, _fatal);
+sysbus_mmio_map(s, 0, sbsa_ref_memmap[SBSA_GIC_ITS].base);
+}
+
+static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
 {
 unsigned int smp_cpus = MACHINE(sms)->smp.cpus;
 SysBusDevice *gicbusdev;
@@ -405,6 +420,10 @@ static void create_gic(SBSAMachineState *sms)
 qdev_prop_set_uint32(sms->gic, "len-redist-region-count", 1);
 qdev_prop_set_uint32(sms->gic, "redist-region-count[0]", redist0_count);
 
+object_property_set_link(OBJECT(sms->gic), "sysmem", OBJECT(mem),
+ _fatal);
+qdev_prop_set_bit(sms->gic, "has-lpi", true);
+
 gicbusdev = SYS_BUS_DEVICE(sms->gic);
 sysbus_realize_and_unref(gicbusdev, _fatal);
 sysbus_mmio_map(gicbusdev, 0, sbsa_ref_memmap[SBSA_GIC_DIST].base);
@@ -451,6 +470,7 @@ static void create_gic(SBSAMachineState *sms)
 sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
 }
+create_its(sms);
 }
 
 static void create_uart(const SBSAMachineState *sms, int uart,
@@ -763,7 +783,7 @@ static void sbsa_ref_init(MachineState *machine)
 
 create_secure_ram(sms, secure_sysmem);
 
-create_gic(sms);
+create_gic(sms, sysmem);
 
 create_uart(sms, SBSA_UART, sysmem, serial_hd(0));
 create_uart(sms, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));
-- 
2.27.0




[PATCH v3 0/8] GICv3 LPI and ITS feature implementation

2021-04-29 Thread Shashi Mallela
This patchset implements qemu device model for enabling physical
LPI support and ITS functionality in GIC as per GICv3 specification.
Both flat table and 2 level tables are implemented.The ITS commands
for adding/deleting ITS table entries,trigerring LPI interrupts are
implemented.Translated LPI interrupt ids are processed by redistributor
to determine priority and set pending state appropriately before
forwarding the same to cpu interface.
The ITS feature support has been added to sbsa-ref platform as well as
virt platform,wherein the emulated functionality co-exists with kvm
kernel functionality.

Changes in v3:
 - review comments addressed

Shashi Mallela (8):
  hw/intc: GICv3 ITS initial framework
  hw/intc: GICv3 ITS register definitions added
  hw/intc: GICv3 ITS command queue framework
  hw/intc: GICv3 ITS Command processing
  hw/intc: GICv3 ITS Feature enablement
  hw/intc: GICv3 redistributor ITS processing
  hw/arm/sbsa-ref: add ITS support in SBSA GIC
  hw/arm/virt: add ITS support in virt GIC

 hw/arm/sbsa-ref.c  |   26 +-
 hw/arm/virt.c  |   27 +-
 hw/intc/arm_gicv3.c|6 +
 hw/intc/arm_gicv3_common.c |   13 +
 hw/intc/arm_gicv3_cpuif.c  |   20 +-
 hw/intc/arm_gicv3_dist.c   |   21 +-
 hw/intc/arm_gicv3_its.c| 1247 
 hw/intc/arm_gicv3_its_common.c |   11 +-
 hw/intc/arm_gicv3_its_kvm.c|2 +-
 hw/intc/arm_gicv3_redist.c |  163 +++-
 hw/intc/gicv3_internal.h   |  186 +++-
 hw/intc/meson.build|1 +
 include/hw/arm/virt.h  |2 +
 include/hw/intc/arm_gicv3_common.h |6 +
 include/hw/intc/arm_gicv3_its_common.h |   40 +-
 target/arm/kvm_arm.h   |4 +-
 16 files changed, 1738 insertions(+), 37 deletions(-)
 create mode 100644 hw/intc/arm_gicv3_its.c

--
2.27.0



[PATCH v3 2/8] hw/intc: GICv3 ITS register definitions added

2021-04-29 Thread Shashi Mallela
Defined descriptors for ITS device table,collection table and ITS
command queue entities.Implemented register read/write functions,
extract ITS table parameters and command queue parameters,extended
gicv3 common to capture qemu address space(which host the ITS table
platform memories required for subsequent ITS processing) and
initialize the same in ITS device.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c| 333 +
 hw/intc/gicv3_internal.h   |  23 ++
 include/hw/intc/arm_gicv3_common.h |   3 +
 include/hw/intc/arm_gicv3_its_common.h |  30 +++
 4 files changed, 389 insertions(+)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 7b11330e01..a7ccb38a89 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -28,6 +28,162 @@ struct GICv3ITSClass {
 void (*parent_reset)(DeviceState *dev);
 };
 
+static bool extract_table_params(GICv3ITSState *s)
+{
+bool result = true;
+uint16_t num_pages = 0;
+uint8_t  page_sz_type;
+uint8_t type;
+uint32_t page_sz = 0;
+uint64_t value;
+
+for (int i = 0; i < 8; i++) {
+value = s->baser[i];
+
+if (!value) {
+continue;
+}
+
+page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
+
+switch (page_sz_type) {
+case 0:
+page_sz = GITS_ITT_PAGE_SIZE_0;
+break;
+
+case 1:
+page_sz = GITS_ITT_PAGE_SIZE_1;
+break;
+
+case 2:
+case 3:
+page_sz = GITS_ITT_PAGE_SIZE_2;
+break;
+
+default:
+result = false;
+break;
+}
+
+if (result) {
+num_pages = FIELD_EX64(value, GITS_BASER, SIZE);
+
+type = FIELD_EX64(value, GITS_BASER, TYPE);
+
+switch (type) {
+
+case GITS_ITT_TYPE_DEVICE:
+memset(>dt, 0 , sizeof(s->dt));
+s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
+
+if (s->dt.valid) {
+s->dt.page_sz = page_sz;
+s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+
+if (!s->dt.indirect) {
+s->dt.max_entries = ((num_pages + 1) * page_sz) /
+   s->dt.entry_sz;
+} else {
+s->dt.max_entries = num_pages + 1) * page_sz) /
+L1TABLE_ENTRY_SIZE) *
+(page_sz / s->dt.entry_sz));
+}
+
+s->dt.max_devids = (1UL << (FIELD_EX64(s->typer, 
GITS_TYPER,
+DEVBITS) + 1));
+
+if ((page_sz == GITS_ITT_PAGE_SIZE_0) ||
+(page_sz == GITS_ITT_PAGE_SIZE_1)) {
+s->dt.base_addr = FIELD_EX64(value, GITS_BASER,
+  PHYADDR);
+s->dt.base_addr <<= R_GITS_BASER_PHYADDR_SHIFT;
+} else if (page_sz == GITS_ITT_PAGE_SIZE_2) {
+s->dt.base_addr = FIELD_EX64(value, GITS_BASER,
+   PHYADDRL_64K) <<
+   R_GITS_BASER_PHYADDRL_64K_SHIFT;
+s->dt.base_addr |= ((value >>
+ R_GITS_BASER_PHYADDR_SHIFT) &
+ R_GITS_BASER_PHYADDRH_64K_MASK) <<
+ R_GITS_BASER_PHYADDRH_64K_SHIFT;
+}
+}
+break;
+
+case GITS_ITT_TYPE_COLLECTION:
+memset(>ct, 0 , sizeof(s->ct));
+s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
+
+/*
+ * GITS_TYPER.HCC is 0 for this implementation
+ * hence writes are discarded if ct.valid is 0
+ */
+if (s->ct.valid) {
+s->ct.page_sz = page_sz;
+s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
+s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
+
+if (!s->ct.indirect) {
+s->ct.max_entries = ((num_pages + 1) * page_sz) /
+  s->ct.entry_sz;
+} else {
+s->ct.max_entries = num_pages + 1) * page_sz) /
+  L1TABLE_ENTRY_SIZE) *
+  (page_sz / s->ct.entry_sz));
+}
+
+if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
+s->ct.max_collids = (1UL 

[PATCH v3 4/8] hw/intc: GICv3 ITS Command processing

2021-04-29 Thread Shashi Mallela
Added ITS command queue handling for MAPTI,MAPI commands,handled ITS
translation which triggers an LPI via INT command as well as write
to GITS_TRANSLATER register,defined enum to differentiate between ITS
command interrupt trigger and GITS_TRANSLATER based interrupt trigger.
Each of these commands make use of other functionalities implemented to
get device table entry,collection table entry or interrupt translation
table entry required for their processing.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c| 346 -
 hw/intc/gicv3_internal.h   |  12 +
 include/hw/intc/arm_gicv3_common.h |   2 +
 3 files changed, 359 insertions(+), 1 deletion(-)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 7cb465813a..98c984dd22 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -28,6 +28,156 @@ struct GICv3ITSClass {
 void (*parent_reset)(DeviceState *dev);
 };
 
+typedef enum ItsCmdType {
+NONE = 0, /* internal indication for GITS_TRANSLATER write */
+CLEAR = 1,
+DISCARD = 2,
+INT = 3,
+} ItsCmdType;
+
+static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
+MemTxResult *res)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t l2t_addr;
+uint64_t value;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+bool status = false;
+
+if (s->ct.indirect) {
+l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->ct.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+valid_l2t = (value >> VALID_SHIFT) & VALID_MASK;
+
+if (valid_l2t) {
+max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+
+l2t_addr = value & ((1ULL << 51) - 1);
+
+*cte =  address_space_ldq_le(as, l2t_addr +
+((icid % max_l2_entries) * GITS_CTE_SIZE),
+MEMTXATTRS_UNSPECIFIED, res);
+   }
+   }
+} else {
+/* Flat level table */
+*cte =  address_space_ldq_le(as, s->ct.base_addr +
+ (icid * GITS_CTE_SIZE),
+  MEMTXATTRS_UNSPECIFIED, res);
+}
+
+if (*cte & VALID_MASK) {
+status = true;
+}
+
+return status;
+}
+
+static MemTxResult update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
+uint64_t itel, uint32_t iteh)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t itt_addr;
+MemTxResult res = MEMTX_OK;
+
+itt_addr = (dte >> 6ULL) & ITTADDR_MASK;
+itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
+
+address_space_stq_le(as, itt_addr + (eventid * sizeof(uint64_t)),
+ itel, MEMTXATTRS_UNSPECIFIED, );
+
+if (res == MEMTX_OK) {
+address_space_stl_le(as, itt_addr + ((eventid + sizeof(uint64_t)) *
+ sizeof(uint32_t)), iteh, MEMTXATTRS_UNSPECIFIED,
+ );
+}
+   return res;
+}
+
+static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
+  uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t itt_addr;
+bool status = false;
+uint64_t itel = 0;
+uint32_t iteh = 0;
+
+itt_addr = (dte >> 6ULL) & ITTADDR_MASK;
+itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
+
+itel = address_space_ldq_le(as, itt_addr + (eventid * sizeof(uint64_t)),
+MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+iteh = address_space_ldl_le(as, itt_addr + ((eventid +
+sizeof(uint64_t)) * sizeof(uint32_t)),
+MEMTXATTRS_UNSPECIFIED, res);
+
+if (*res == MEMTX_OK) {
+if (itel & VALID_MASK) {
+if ((itel >> ITE_ENTRY_INTTYPE_SHIFT) & GITS_TYPE_PHYSICAL) {
+*pIntid = (itel >> ITE_ENTRY_INTID_SHIFT) &
+  ITE_ENTRY_INTID_MASK;
+*icid = iteh & ITE_ENTRY_ICID_MASK;
+status = true;
+}
+}
+}
+}
+return status;
+}
+
+static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t l2t_addr;
+uint64_t value;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+
+if (s->dt.indirect) {
+l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->dt.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+   

Re: [PATCH v2 8/8] hw/arm/virt: add ITS support in virt GIC

2021-04-29 Thread shashi . mallela
On Mon, 2021-04-19 at 13:46 +0100, Peter Maydell wrote:
> On Thu, 1 Apr 2021 at 03:42, Shashi Mallela <
> shashi.mall...@linaro.org> wrote:
> > Included creation of ITS as part of virt platform GIC
> > initialization.This Emulated ITS model now co-exists with kvm
> > ITS and is enabled in absence of kvm irq kernel support in a
> > platform.
> > 
> > Signed-off-by: Shashi Mallela 
> > ---
> >  hw/arm/virt.c| 10 --
> >  target/arm/kvm_arm.h |  4 ++--
> >  2 files changed, 10 insertions(+), 4 deletions(-)
> > 
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index aa2bbd14e0..77cf2db90f 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -622,7 +622,7 @@ static void create_v2m(VirtMachineState *vms)
> >  vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
> >  }
> > 
> > -static void create_gic(VirtMachineState *vms)
> > +static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
> >  {
> >  MachineState *ms = MACHINE(vms);
> >  /* We create a standalone GIC */
> > @@ -656,6 +656,12 @@ static void create_gic(VirtMachineState *vms)
> >   nb_redist_regions);
> >  qdev_prop_set_uint32(vms->gic, "redist-region-count[0]",
> > redist0_count);
> > 
> > +if (!kvm_irqchip_in_kernel()) {
> > +object_property_set_link(OBJECT(vms->gic), "sysmem",
> > OBJECT(mem),
> > + _fatal);
> > +qdev_prop_set_bit(vms->gic, "has-lpi", true);
> > +}
> > +
> >  if (nb_redist_regions == 2) {
> >  uint32_t redist1_capacity =
> >  vms->memmap[VIRT_HIGH_GIC_REDIST2].size /
> > GICV3_REDIST_SIZE;
> > @@ -2039,7 +2045,7 @@ static void machvirt_init(MachineState
> > *machine)
> > 
> >  virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
> > 
> > -create_gic(vms);
> > +create_gic(vms, sysmem);
> > 
> >  virt_cpu_post_init(vms, sysmem);
> > 
> > diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
> > index 34f8daa377..0613454975 100644
> > --- a/target/arm/kvm_arm.h
> > +++ b/target/arm/kvm_arm.h
> > @@ -525,8 +525,8 @@ static inline const char *its_class_name(void)
> >  /* KVM implementation requires this capability */
> >  return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
> >  } else {
> > -/* Software emulation is not implemented yet */
> > -return NULL;
> > +/* Software emulation based model */
> > +return "arm-gicv3-its";
> >  }
> >  }
> 
> This is OK as far as it goes, but I think we need to add the
> versioned-machine support so that only "virt-6.1" and later get the
> new ITS, and "virt-6.0" behave the same way (ie no ITS) as they did
> in older QEMU versions.
> 
> Have added versioned machine support to enable new ITS only for
> versions 6.1 and above
> thanks
> -- PMM




[PATCH v3 6/8] hw/intc: GICv3 redistributor ITS processing

2021-04-29 Thread Shashi Mallela
Implemented lpi processing at redistributor to get lpi config info
from lpi configuration table,determine priority,set pending state in
lpi pending table and forward the lpi to cpuif.Added logic to invoke
redistributor lpi processing with translated LPI which set/clear LPI
from ITS device as part of ITS INT,CLEAR,DISCARD command and
GITS_TRANSLATER processing.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3.c|   6 ++
 hw/intc/arm_gicv3_cpuif.c  |  20 --
 hw/intc/arm_gicv3_its.c|  12 ++--
 hw/intc/arm_gicv3_redist.c | 133 +
 hw/intc/gicv3_internal.h   |   9 +++
 5 files changed, 171 insertions(+), 9 deletions(-)

diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index 66eaa97198..618fa1af95 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -166,6 +166,12 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
 cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
 }
 
+if (cs->gic->lpi_enable) {
+if (gicv3_redist_update_lpi(cs)) {
+seenbetter = true;
+}
+}
+
 /* If the best interrupt we just found would preempt whatever
  * was the previous best interrupt before this update, then
  * we know it's definitely the best one now.
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 43ef1d7a84..11b1df5b6b 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -899,9 +899,14 @@ static void icc_activate_irq(GICv3CPUState *cs, int irq)
 cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
 gicv3_redist_update(cs);
 } else {
-gicv3_gicd_active_set(cs->gic, irq);
-gicv3_gicd_pending_clear(cs->gic, irq);
-gicv3_update(cs->gic, irq, 1);
+if (irq >= GICV3_LPI_INTID_START) {
+gicv3_redist_lpi_pending(cs, irq, 0);
+gicv3_redist_update(cs);
+} else {
+gicv3_gicd_active_set(cs->gic, irq);
+gicv3_gicd_pending_clear(cs->gic, irq);
+gicv3_update(cs->gic, irq, 1);
+}
 }
 }
 
@@ -1328,7 +1333,8 @@ static void icc_eoir_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 }
 }
 
-if (irq >= cs->gic->num_irq) {
+if ((irq >= cs->gic->num_irq) && (!(cs->gic->lpi_enable &&
+(irq >= GICV3_LPI_INTID_START {
 /* This handles two cases:
  * 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
  * to the GICC_EOIR, the GIC ignores that write.
@@ -1348,7 +1354,11 @@ static void icc_eoir_write(CPUARMState *env, const 
ARMCPRegInfo *ri,
 
 if (!icc_eoi_split(env, cs)) {
 /* Priority drop and deactivate not split: deactivate irq now */
-icc_deactivate_irq(cs, irq);
+if (irq >= GICV3_LPI_INTID_START) {
+gicv3_update(cs->gic, irq, 1);
+} else {
+icc_deactivate_irq(cs, irq);
+}
 }
 }
 
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 98c984dd22..28da2d1d77 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -219,6 +219,7 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t 
value,
 bool ite_valid = false;
 uint64_t cte = 0;
 bool cte_valid = false;
+uint64_t rdbase;
 uint64_t itel = 0;
 uint32_t iteh = 0;
 
@@ -275,10 +276,13 @@ static MemTxResult process_int(GICv3ITSState *s, uint64_t 
value,
  * command in the queue
  */
 } else {
-/*
- * Current implementation only supports rdbase == procnum
- * Hence rdbase physical address is ignored
- */
+rdbase = (cte >> 1U) & RDBASE_PROCNUM_MASK;
+if ((cmd == CLEAR) || (cmd == DISCARD)) {
+gicv3_redist_process_lpi(>gicv3->cpu[rdbase], pIntid, 0);
+} else {
+gicv3_redist_process_lpi(>gicv3->cpu[rdbase], pIntid, 1);
+}
+
 if (cmd == DISCARD) {
 /* remove mapping from interrupt translation table */
 res = update_ite(s, eventid, dte, itel, iteh);
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 7604ccdc83..82ca9d71e5 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -256,6 +256,8 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr 
offset,
 if (cs->gicr_typer & GICR_TYPER_PLPIS) {
 if (value & GICR_CTLR_ENABLE_LPIS) {
 cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
+/* Check for any pending interr in pending table */
+gicv3_redist_update(cs);
 } else {
 cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
 }
@@ -546,6 +548,137 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr 
offset, uint64_t data,
 return r;
 }
 
+bool gicv3_redist_update_lpi(GICv3CPUState *cs)
+{
+/*
+ * This function scans the LPI pending table and for each pending
+ * LPI, reads the corresponding entry from 

[PATCH v3 3/8] hw/intc: GICv3 ITS command queue framework

2021-04-29 Thread Shashi Mallela
Added functionality to trigger ITS command queue processing on
write to CWRITE register and process each command queue entry to
identify the command type and handle commands like MAPD,MAPC,SYNC.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c  | 327 +++
 hw/intc/gicv3_internal.h |  41 +
 2 files changed, 368 insertions(+)

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index a7ccb38a89..7cb465813a 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -28,6 +28,327 @@ struct GICv3ITSClass {
 void (*parent_reset)(DeviceState *dev);
 };
 
+static MemTxResult process_sync(GICv3ITSState *s, uint32_t offset)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t rdbase;
+uint64_t value;
+MemTxResult res = MEMTX_OK;
+
+offset += NUM_BYTES_IN_DW;
+offset += NUM_BYTES_IN_DW;
+
+value = address_space_ldq_le(as, s->cq.base_addr + offset,
+ MEMTXATTRS_UNSPECIFIED, );
+
+rdbase = (value >> RDBASE_SHIFT) & RDBASE_PROCNUM_MASK;
+
+if (rdbase < (s->gicv3->num_cpu)) {
+/*
+ * Current implementation makes a blocking synchronous call
+ * for every command issued earlier,hence the internal state
+ * is already consistent by the time SYNC command is executed.
+ */
+}
+
+offset += NUM_BYTES_IN_DW;
+return res;
+}
+
+static MemTxResult update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
+uint64_t rdbase)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t value;
+uint64_t l2t_addr;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+uint64_t cte = 0;
+MemTxResult res = MEMTX_OK;
+
+if (s->ct.valid) {
+if (valid) {
+/* add mapping entry to collection table */
+cte = (valid & VALID_MASK) |
+  ((rdbase & RDBASE_PROCNUM_MASK) << 1ULL);
+}
+} else {
+return res;
+}
+
+/*
+ * The specification defines the format of level 1 entries of a
+ * 2-level table, but the format of level 2 entries and the format
+ * of flat-mapped tables is IMPDEF.
+ */
+if (s->ct.indirect) {
+l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
+
+value = address_space_ldq_le(as,
+ s->ct.base_addr +
+ (l2t_id * L1TABLE_ENTRY_SIZE),
+ MEMTXATTRS_UNSPECIFIED, );
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+valid_l2t = (value >> VALID_SHIFT) & VALID_MASK;
+
+if (valid_l2t) {
+max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
+
+l2t_addr = value & ((1ULL << 51) - 1);
+
+address_space_stq_le(as, l2t_addr +
+ ((icid % max_l2_entries) * GITS_CTE_SIZE),
+ cte, MEMTXATTRS_UNSPECIFIED, );
+}
+} else {
+/* Flat level table */
+address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
+ cte, MEMTXATTRS_UNSPECIFIED, );
+}
+return res;
+}
+
+static MemTxResult process_mapc(GICv3ITSState *s, uint32_t offset)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint16_t icid;
+uint64_t rdbase;
+bool valid;
+MemTxResult res = MEMTX_OK;
+uint64_t value;
+
+offset += NUM_BYTES_IN_DW;
+offset += NUM_BYTES_IN_DW;
+
+value = address_space_ldq_le(as, s->cq.base_addr + offset,
+ MEMTXATTRS_UNSPECIFIED, );
+
+if (res != MEMTX_OK) {
+return res;
+}
+
+icid = value & ICID_MASK;
+
+rdbase = (value >> RDBASE_SHIFT) & RDBASE_PROCNUM_MASK;
+
+valid = (value >> VALID_SHIFT) & VALID_MASK;
+
+if ((icid > s->ct.max_collids) || (rdbase > s->gicv3->num_cpu)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+"ITS MAPC: invalid collection table attributes "
+"icid %d rdbase %lu\n",  icid, rdbase);
+/*
+ * in this implementation,in case of error
+ * we ignore this command and move onto the next
+ * command in the queue
+ */
+} else {
+res = update_cte(s, icid, valid, rdbase);
+}
+
+offset += NUM_BYTES_IN_DW;
+offset += NUM_BYTES_IN_DW;
+
+return res;
+}
+
+static MemTxResult update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
+uint8_t size, uint64_t itt_addr)
+{
+AddressSpace *as = >gicv3->dma_as;
+uint64_t value;
+uint64_t l2t_addr;
+bool valid_l2t;
+uint32_t l2t_id;
+uint32_t max_l2_entries;
+uint64_t dte = 0;
+MemTxResult res = MEMTX_OK;
+
+if (s->dt.valid) {
+if (valid) {
+/* add mapping entry to device table */
+dte = (valid & VALID_MASK) |
+  ((size & SIZE_MASK) << 1U) |
+  ((itt_addr & ITTADDR_MASK) << 6ULL);
+}
+} else {

Re: [PATCH v2 3/8] hw/intc: GICv3 ITS command queue framework

2021-04-29 Thread shashi . mallela
On Mon, 2021-04-19 at 11:30 +0100, Peter Maydell wrote:
> On Thu, 1 Apr 2021 at 03:41, Shashi Mallela <
> shashi.mall...@linaro.org> wrote:
> > Added functionality to trigger ITS command queue processing on
> > write to CWRITE register and process each command queue entry to
> > identify the command type and handle commands like MAPD,MAPC,SYNC.
> > 
> > Signed-off-by: Shashi Mallela 
> > ---
> >  hw/intc/arm_gicv3_its.c  | 347
> > +++
> >  hw/intc/gicv3_internal.h |  41 +
> >  2 files changed, 388 insertions(+)
> > 
> > diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> > index 81373f049d..fcac33c836 100644
> > --- a/hw/intc/arm_gicv3_its.c
> > +++ b/hw/intc/arm_gicv3_its.c
> > @@ -28,6 +28,347 @@ struct GICv3ITSClass {
> >  void (*parent_reset)(DeviceState *dev);
> >  };
> > 
> > +static MemTxResult process_sync(GICv3ITSState *s, uint32_t offset)
> > +{
> > +AddressSpace *as = >gicv3->sysmem_as;
> > +uint64_t rdbase;
> > +uint64_t value;
> > +bool pta = false;
> > +MemTxResult res = MEMTX_OK;
> > +
> > +offset += NUM_BYTES_IN_DW;
> > +offset += NUM_BYTES_IN_DW;
> > +
> > +value = address_space_ldq_le(as, s->cq.base_addr + offset,
> > + MEMTXATTRS_UNSPECIFIED,
> > );
> 
> If the ITS fails to read or write DMA, it does not report that
> by provoking a bus error for the CPU's write to GITS_CWRITER,
> which is what will happen if you just propagate up the MemTxResult
> from this DMA operation back through the register write function
> to its caller. The spec doesn't seem to define a particular behaviour
> for "I couldn't read the command out of the command queue", but
> it would seem sensible to pick one of the options from the "Command
> errors"
> section: ignore the command, or stall the command queue ("treat as
> valid" is the other option there but doesn't seem relevant here).
> 
> "Stall" is probably best as otherwise we might loop forever through
> a region of unreadable addresses.
>
> have implemented "stall" indication for all failing dma read/write
calls(based on the return value of each call) 
> 
> > +if (FIELD_EX64(s->typer, GITS_TYPER, PTA)) {
> > +/*
> > + * only bits[47:16] are considered instead of bits [51:16]
> > + * since with a physical address the target address must
> > be
> > + * 64KB aligned
> > + */
> > +rdbase = (value >> RDBASE_OFFSET) & RDBASE_MASK;
> > +pta = true;
> > +} else {
> > +rdbase = (value >> RDBASE_OFFSET) & RDBASE_PROCNUM_MASK;
> > +}
> > +
> > +if (!pta && (rdbase < (s->gicv3->num_cpu))) {
> > +/*
> > + * Current implementation makes a blocking synchronous
> > call
> > + * for every command issued earlier,hence the internal
> > state
> > + * is already consistent by the time SYNC command is
> > executed.
> > + */
> > +}
> > +
> > +offset += NUM_BYTES_IN_DW;
> > +return res;
> > +}
> 
> TODO: review process_mapd and process_mapc
> 
> > +
> > +static void update_cte(GICv3ITSState *s, uint16_t icid, uint64_t
> > cte)
> > +{
> > +AddressSpace *as = >gicv3->sysmem_as;
> > +uint64_t value;
> > +uint8_t  page_sz_type;
> > +uint64_t l2t_addr;
> > +bool valid_l2t;
> > +uint32_t l2t_id;
> > +uint32_t page_sz = 0;
> > +uint32_t max_l2_entries;
> 
> I think it's worth having a comment here:
> 
> /*
>  * The specification defines the format of level 1 entries of a
>  * 2-level table, but the format of level 2 entries and the format
>  * of flat-mapped tables is IMPDEF.
>  */
> 
> Q: why have you chosen to make the level-2 and flatmap entries
> 64 bits here ? They only need to contain the valid bit plus a
> 16 bit processor number. (We know the processor number fits in 16
> bits because the GICR_TYPER.Processor_Number field in the
> redistributor
> is that large.) Is there something I'm missing in the spec that makes
> 64-bit entries a good choice anyway ?
> 
> I chose 64 bits to be able to have the data structure ready for both
the processor number and RD_base address possibilities, in case we add
RD_Base address support in the future
> > +
> > +if (s->ct.indirect) {
> > +/* 2 level table */
> > +page_sz_type = FIELD_EX64(s->baser[1], GITS_BASER,
> > PAGESIZE);
> > +
> > +if (page_sz_type == 0) {
> > +page_sz = GITS_ITT_PAGE_SIZE_0;
> > +} else if (page_sz_type == 1) {
> > +page_sz = GITS_ITT_PAGE_SIZE_1;
> > +} else if (page_sz_type == 2) {
> > +page_sz = GITS_ITT_PAGE_SIZE_2;
> > +}
> 
> page_sz_type == 3 has a defined meaning: must be treated like 2.
> 
> If we're caching stuff in s->ct, maybe we should cache page_sz too ?
> 
> > +
> > +l2t_id = icid / (page_sz / L1TABLE_ENTRY_SIZE);
> > +
> > +value = address_space_ldq_le(as,
> > + s->ct.base_addr +
> > + 

[PATCH v3 5/8] hw/intc: GICv3 ITS Feature enablement

2021-04-29 Thread Shashi Mallela
Added properties to enable ITS feature and define qemu system
address space memory in gicv3 common,setup distributor and
redistributor registers to indicate LPI support.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_common.c | 13 +
 hw/intc/arm_gicv3_dist.c   | 21 +++--
 hw/intc/arm_gicv3_redist.c | 30 +-
 hw/intc/gicv3_internal.h   | 17 +
 include/hw/intc/arm_gicv3_common.h |  1 +
 5 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 58ef65f589..a55e91071a 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -381,6 +381,16 @@ static void arm_gicv3_common_realize(DeviceState *dev, 
Error **errp)
 (1 << 24) |
 (i << 8) |
 (last << 4);
+
+if (s->lpi_enable) {
+s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
+
+if (!s->dma) {
+error_setg(errp,
+"Redist-ITS: Guest 'sysmem' reference link not set");
+return;
+}
+}
 }
 }
 
@@ -494,9 +504,12 @@ static Property arm_gicv3_common_properties[] = {
 DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
 DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
 DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
+DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
 DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
 DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
   redist_region_count, qdev_prop_uint32, uint32_t),
+DEFINE_PROP_LINK("sysmem", GICv3State, dma, TYPE_MEMORY_REGION,
+ MemoryRegion *),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index b65f56f903..43e0ea4367 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -366,12 +366,15 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr 
offset,
 return MEMTX_OK;
 case GICD_TYPER:
 {
+bool lpi_supported = false;
 /* For this implementation:
  * No1N == 1 (1-of-N SPI interrupts not supported)
  * A3V == 1 (non-zero values of Affinity level 3 supported)
  * IDbits == 0xf (we support 16-bit interrupt identifiers)
  * DVIS == 0 (Direct virtual LPI injection not supported)
- * LPIS == 0 (LPIs not supported)
+ * LPIS == 1 (LPIs are supported if affinity routing is enabled)
+ * num_LPIs == 0b0 (bits [15:11],Number of LPIs as indicated
+ *  by GICD_TYPER.IDbits)
  * MBIS == 0 (message-based SPIs not supported)
  * SecurityExtn == 1 if security extns supported
  * CPUNumber == 0 since for us ARE is always 1
@@ -385,8 +388,22 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
  */
 bool sec_extn = !(s->gicd_ctlr & GICD_CTLR_DS);
 
+/*
+ * With securityextn on, LPIs are supported when affinity routing
+ * is enabled for non-secure state and if off LPIs are supported
+ * when affinity routing is enabled.
+ */
+if (s->lpi_enable) {
+if (sec_extn) {
+lpi_supported = (s->gicd_ctlr & GICD_CTLR_ARE_NS);
+} else {
+lpi_supported = (s->gicd_ctlr & GICD_CTLR_ARE);
+}
+}
+
 *data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
-(0xf << 19) | itlinesnumber;
+(lpi_supported << GICD_TYPER_LPIS_OFFSET) | (GICD_TYPER_IDBITS <<
+GICD_TYPER_IDBITS_OFFSET) | itlinesnumber;
 return MEMTX_OK;
 }
 case GICD_IIDR:
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 8645220d61..7604ccdc83 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -244,14 +244,22 @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr 
offset,
 static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
uint64_t value, MemTxAttrs attrs)
 {
+uint64_t data;
+
 switch (offset) {
 case GICR_CTLR:
 /* For our implementation, GICR_TYPER.DPGS is 0 and so all
  * the DPG bits are RAZ/WI. We don't do anything asynchronously,
- * so UWP and RWP are RAZ/WI. And GICR_TYPER.LPIS is 0 (we don't
- * implement LPIs) so Enable_LPIs is RES0. So there are no writable
- * bits for us.
+ * so UWP and RWP are RAZ/WI. GICR_TYPER.LPIS is 1 (we
+ * implement LPIs) so Enable_LPIs is programmable.
  */
+if (cs->gicr_typer & GICR_TYPER_PLPIS) {
+if (value & GICR_CTLR_ENABLE_LPIS) {
+cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
+} else {
+cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
+}
+   

Re: [PATCH v2 6/8] hw/intc: GICv3 redistributor ITS processing

2021-04-29 Thread shashi . mallela
On Thu, 2021-04-29 at 18:16 -0400, shashi.mall...@linaro.org wrote:
On Mon, 2021-04-19 at 13:44 +0100, Peter Maydell wrote:
> On Thu, 1 Apr 2021 at 03:41, Shashi Mallela <
> shashi.mall...@linaro.org> wrote:
> > Implemented lpi processing at redistributor to get lpi config info
> > from lpi configuration table,determine priority,set pending state
> > in
> > lpi pending table and forward the lpi to cpuif.Added logic to
> > invoke
> > redistributor lpi processing with translated LPI which set/clear
> > LPI
> > from ITS device as part of ITS INT,CLEAR,DISCARD command and
> > GITS_TRANSLATER processing.
> 
> Nit: commas should all have a space following.
> 
> > Signed-off-by: Shashi Mallela 
> > ---
> >  hw/intc/arm_gicv3.c|   6 ++
> >  hw/intc/arm_gicv3_cpuif.c  |  15 +++--
> >  hw/intc/arm_gicv3_its.c|   9 ++-
> >  hw/intc/arm_gicv3_redist.c | 124
> > +
> >  hw/intc/gicv3_internal.h   |   9 +++
> >  5 files changed, 158 insertions(+), 5 deletions(-)
> > 
> > diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
> > index 66eaa97198..618fa1af95 100644
> > --- a/hw/intc/arm_gicv3.c
> > +++ b/hw/intc/arm_gicv3.c
> > @@ -166,6 +166,12 @@ static void
> > gicv3_redist_update_noirqset(GICv3CPUState *cs)
> >  cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq);
> >  }
> > 
> > +if (cs->gic->lpi_enable) {
> > +if (gicv3_redist_update_lpi(cs)) {
> > +seenbetter = true;
> > +}
> > +}
> > +
> >  /* If the best interrupt we just found would preempt whatever
> >   * was the previous best interrupt before this update, then
> >   * we know it's definitely the best one now.
> > diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
> > index 43ef1d7a84..c225b80f66 100644
> > --- a/hw/intc/arm_gicv3_cpuif.c
> > +++ b/hw/intc/arm_gicv3_cpuif.c
> > @@ -899,9 +899,14 @@ static void icc_activate_irq(GICv3CPUState
> > *cs, int irq)
> >  cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 0);
> >  gicv3_redist_update(cs);
> >  } else {
> > -gicv3_gicd_active_set(cs->gic, irq);
> > -gicv3_gicd_pending_clear(cs->gic, irq);
> > -gicv3_update(cs->gic, irq, 1);
> > +if (irq >= GICV3_LPI_INTID_START) {
> > +gicv3_redist_lpi_pending(cs, irq, 0);
> > +gicv3_redist_update(cs);
> > +} else {
> > +gicv3_gicd_active_set(cs->gic, irq);
> > +gicv3_gicd_pending_clear(cs->gic, irq);
> > +gicv3_update(cs->gic, irq, 1);
> > +}
> >  }
> >  }
> > 
> > @@ -1337,7 +1342,9 @@ static void icc_eoir_write(CPUARMState *env,
> > const ARMCPRegInfo *ri,
> >   * valid interrupt value read from the Interrupt
> > Acknowledge
> >   * register" and so this is UNPREDICTABLE. We choose to
> > ignore it.
> >   */
> > -return;
> > +if (!(cs->gic->lpi_enable && (irq >=
> > GICV3_LPI_INTID_START))) {
> > +return;
> > +}
> 
> This condition is in the wrong place. I think what you are trying to
> do is modify "what is the set of numbers we consider to be valid IRQ
> numbers", in which case you want to be changing the outer
> "if (irq >= cs->gic->num_irq)" condition, not adding an extra one
> inside it.
> 
> More importantly, the thing this condition is guarding is that
> the code below it assumes that IRQ numbers are in range for the
> GIC's own internal non-LPI interrupts. If you allow numbers
> > = cs->gic->num_irq through, then you will get array overruns
> when icc_deactivate_irq() tries to clear its Active bit.
> 
> >  }
> > 
> >  if (icc_highest_active_group(cs) != grp) {
> > diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> > index 0e3f176809..41e1e8b2a8 100644
> > --- a/hw/intc/arm_gicv3_its.c
> > +++ b/hw/intc/arm_gicv3_its.c
> > @@ -226,6 +226,7 @@ static MemTxResult process_int(GICv3ITSState
> > *s, uint64_t value,
> >  bool ite_valid = false;
> >  uint64_t cte = 0;
> >  bool cte_valid = false;
> > +uint64_t rdbase;
> >  uint8_t buff[ITS_ITT_ENTRY_SIZE];
> >  uint64_t itt_addr;
> > 
> > @@ -278,12 +279,18 @@ static MemTxResult process_int(GICv3ITSState
> > *s, uint64_t value,
> >   * since with a physical address the target address
> > must be
> >   * 64KB aligned
> >   */
> > -
> > +rdbase = (cte >> 1U) & RDBASE_MASK;
> 
> What's going on here? Shouldn't this be in a previous patch ?
> > 
> No,this part relates to the ITS processing wherein the rdbase is
extracted and used for subsequent redistributor trigger
> > >  /*
> >   * Current implementation only supports rdbase ==
> > procnum
> >   * Hence rdbase physical address is ignored
> >   */
> >  } else {
> > +rdbase = (cte >> 1U) & RDBASE_PROCNUM_MASK;
> > +if ((cmd == CLEAR) || (cmd == DISCARD)) {
> > +

[PATCH v3 8/8] hw/arm/virt: add ITS support in virt GIC

2021-04-29 Thread Shashi Mallela
Included creation of ITS as part of virt platform GIC
initialization.This Emulated ITS model now co-exists with kvm
ITS and is enabled in absence of kvm irq kernel support in a
platform.

Signed-off-by: Shashi Mallela 
---
 hw/arm/virt.c | 27 +--
 include/hw/arm/virt.h |  2 ++
 target/arm/kvm_arm.h  |  4 ++--
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 9f01d9041b..8f581747bc 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -585,6 +585,12 @@ static void create_its(VirtMachineState *vms)
 const char *itsclass = its_class_name();
 DeviceState *dev;
 
+if (!strcmp(itsclass, "arm-gicv3-its")) {
+if (!vms->tcg_its) {
+itsclass = NULL;
+}
+}
+
 if (!itsclass) {
 /* Do nothing if not supported */
 return;
@@ -622,7 +628,7 @@ static void create_v2m(VirtMachineState *vms)
 vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
 }
 
-static void create_gic(VirtMachineState *vms)
+static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
 {
 MachineState *ms = MACHINE(vms);
 /* We create a standalone GIC */
@@ -656,6 +662,14 @@ static void create_gic(VirtMachineState *vms)
  nb_redist_regions);
 qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", 
redist0_count);
 
+if (!kvm_irqchip_in_kernel()) {
+if (vms->tcg_its) {
+object_property_set_link(OBJECT(vms->gic), "sysmem",
+ OBJECT(mem), _fatal);
+qdev_prop_set_bit(vms->gic, "has-lpi", true);
+}
+}
+
 if (nb_redist_regions == 2) {
 uint32_t redist1_capacity =
 vms->memmap[VIRT_HIGH_GIC_REDIST2].size / 
GICV3_REDIST_SIZE;
@@ -2039,7 +2053,7 @@ static void machvirt_init(MachineState *machine)
 
 virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem);
 
-create_gic(vms);
+create_gic(vms, sysmem);
 
 virt_cpu_post_init(vms, sysmem);
 
@@ -2718,6 +2732,12 @@ static void virt_instance_init(Object *obj)
 } else {
 /* Default allows ITS instantiation */
 vms->its = true;
+
+if (vmc->no_tcg_its) {
+vms->tcg_its = false;
+} else {
+vms->tcg_its = true;
+}
 }
 
 /* Default disallows iommu instantiation */
@@ -2759,6 +2779,9 @@ type_init(machvirt_machine_init);
 
 static void virt_machine_6_0_options(MachineClass *mc)
 {
+VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+/* qemu ITS was introduced with 6.1 */
+vmc->no_tcg_its = true;
 }
 DEFINE_VIRT_MACHINE_AS_LATEST(6, 0)
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 921416f918..f873ab9068 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -120,6 +120,7 @@ struct VirtMachineClass {
 MachineClass parent;
 bool disallow_affinity_adjustment;
 bool no_its;
+bool no_tcg_its;
 bool no_pmu;
 bool claim_edge_triggered_timers;
 bool smbios_old_sys_ver;
@@ -141,6 +142,7 @@ struct VirtMachineState {
 bool highmem;
 bool highmem_ecam;
 bool its;
+bool tcg_its;
 bool virt;
 bool ras;
 bool mte;
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 34f8daa377..0613454975 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -525,8 +525,8 @@ static inline const char *its_class_name(void)
 /* KVM implementation requires this capability */
 return kvm_direct_msi_enabled() ? "arm-its-kvm" : NULL;
 } else {
-/* Software emulation is not implemented yet */
-return NULL;
+/* Software emulation based model */
+return "arm-gicv3-its";
 }
 }
 
-- 
2.27.0




[PATCH v3 1/8] hw/intc: GICv3 ITS initial framework

2021-04-29 Thread Shashi Mallela
Added register definitions relevant to ITS,implemented overall
ITS device framework with stubs for ITS control and translater
regions read/write,extended ITS common to handle mmio init between
existing kvm device and newer qemu device.

Signed-off-by: Shashi Mallela 
---
 hw/intc/arm_gicv3_its.c| 239 +
 hw/intc/arm_gicv3_its_common.c |  11 +-
 hw/intc/arm_gicv3_its_kvm.c|   2 +-
 hw/intc/gicv3_internal.h   |  88 +++--
 hw/intc/meson.build|   1 +
 include/hw/intc/arm_gicv3_its_common.h |  10 +-
 6 files changed, 331 insertions(+), 20 deletions(-)
 create mode 100644 hw/intc/arm_gicv3_its.c

diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
new file mode 100644
index 00..7b11330e01
--- /dev/null
+++ b/hw/intc/arm_gicv3_its.c
@@ -0,0 +1,239 @@
+/*
+ * ITS emulation for a GICv3-based system
+ *
+ * Copyright Linaro.org 2021
+ *
+ * Authors:
+ *  Shashi Mallela 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version.  See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/qdev-properties.h"
+#include "hw/intc/arm_gicv3_its_common.h"
+#include "gicv3_internal.h"
+#include "qom/object.h"
+
+typedef struct GICv3ITSClass GICv3ITSClass;
+/* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
+DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
+ ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
+
+struct GICv3ITSClass {
+GICv3ITSCommonClass parent_class;
+void (*parent_reset)(DeviceState *dev);
+};
+
+static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
+   uint64_t data, unsigned size, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_writel(GICv3ITSState *s, hwaddr offset,
+   uint64_t value, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_readl(GICv3ITSState *s, hwaddr offset,
+   uint64_t *data, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_writell(GICv3ITSState *s, hwaddr offset,
+   uint64_t value, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult its_readll(GICv3ITSState *s, hwaddr offset,
+   uint64_t *data, MemTxAttrs attrs)
+{
+MemTxResult result = MEMTX_OK;
+
+return result;
+}
+
+static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
+  unsigned size, MemTxAttrs attrs)
+{
+GICv3ITSState *s = (GICv3ITSState *)opaque;
+MemTxResult result;
+
+switch (size) {
+case 4:
+result = its_readl(s, offset, data, attrs);
+break;
+case 8:
+result = its_readll(s, offset, data, attrs);
+break;
+default:
+result = MEMTX_ERROR;
+break;
+}
+
+if (result == MEMTX_ERROR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid guest read at offset " TARGET_FMT_plx
+  "size %u\n", __func__, offset, size);
+/*
+ * The spec requires that reserved registers are RAZ/WI;
+ * so use MEMTX_ERROR returns from leaf functions as a way to
+ * trigger the guest-error logging but don't return it to
+ * the caller, or we'll cause a spurious guest data abort.
+ */
+result = MEMTX_OK;
+*data = 0;
+}
+return result;
+}
+
+static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
+   unsigned size, MemTxAttrs attrs)
+{
+GICv3ITSState *s = (GICv3ITSState *)opaque;
+MemTxResult result;
+
+switch (size) {
+case 4:
+result = its_writel(s, offset, data, attrs);
+break;
+case 8:
+result = its_writell(s, offset, data, attrs);
+break;
+default:
+result = MEMTX_ERROR;
+break;
+}
+
+if (result == MEMTX_ERROR) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: invalid guest write at offset " TARGET_FMT_plx
+  "size %u\n", __func__, offset, size);
+/*
+ * The spec requires that reserved registers are RAZ/WI;
+ * so use MEMTX_ERROR returns from leaf functions as a way to
+ * trigger the guest-error logging but don't return it to
+ * the caller, or we'll cause a spurious guest data abort.
+ */
+result = MEMTX_OK;
+}
+return result;
+}
+
+static const MemoryRegionOps gicv3_its_control_ops = {
+.read_with_attrs = gicv3_its_read,
+.write_with_attrs = gicv3_its_write,
+.valid.min_access_size = 4,
+

Re: [PATCH v2 2/8] hw/intc: GICv3 ITS register definitions added

2021-04-29 Thread shashi . mallela
On Thu, 2021-04-29 at 17:46 -0400, shashi.mall...@linaro.org wrote:
On Fri, 2021-04-16 at 19:54 +0100, Peter Maydell wrote:
> On Thu, 1 Apr 2021 at 03:41, Shashi Mallela <
> shashi.mall...@linaro.org> wrote:
> > Defined descriptors for ITS device table,collection table and ITS
> > command queue entities.Implemented register read/write functions,
> > extract ITS table parameters and command queue parameters,extended
> > gicv3 common to capture qemu address space(which host the ITS table
> > platform memories required for subsequent ITS processing) and
> > initialize the same in its device.
> > 
> > Signed-off-by: Shashi Mallela 
> > ---
> >  hw/intc/arm_gicv3_its.c| 313
> > +
> >  hw/intc/arm_gicv3_its_common.c |  42 
> >  hw/intc/gicv3_internal.h   |  33 ++-
> >  include/hw/intc/arm_gicv3_common.h |   4 +
> >  include/hw/intc/arm_gicv3_its_common.h |  28 +++
> >  5 files changed, 414 insertions(+), 6 deletions(-)
> > 
> > diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
> > index 209120d102..81373f049d 100644
> > --- a/hw/intc/arm_gicv3_its.c
> > +++ b/hw/intc/arm_gicv3_its.c
> > @@ -28,6 +28,131 @@ struct GICv3ITSClass {
> >  void (*parent_reset)(DeviceState *dev);
> >  };
> > 
> > +static bool extract_table_params(GICv3ITSState *s, int index)
> > +{
> > +uint16_t num_pages = 0;
> > +uint8_t  page_sz_type;
> > +uint8_t type;
> > +uint32_t page_sz = 0;
> > +uint64_t value = s->baser[index];
> > +
> > +num_pages = FIELD_EX64(value, GITS_BASER, SIZE);
> > +page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
> > +
> > +if (page_sz_type == 0) {
> > +page_sz = GITS_ITT_PAGE_SIZE_0;
> > +} else if (page_sz_type == 0) {
> > +page_sz = GITS_ITT_PAGE_SIZE_1;
> > +} else if (page_sz_type == 2) {
> > +page_sz = GITS_ITT_PAGE_SIZE_2;
> > +} else {
> > +return false;
> 
> The spec says that page_sz+type = 0b11 should be treated as 0b10.
> So we could log this as a guest error if you like but otherwise
> should handle it the same way we do 0b10.
> 
> > +}
> 
> if (x == CONST1) {
> } else if (x == CONST2) {
> } else {
> }
> 
> is usually clearer written with switch(). (There are other instances
> of this pattern below.)
> 
> > +
> > +type = FIELD_EX64(value, GITS_BASER, TYPE);
> > +
> > +if (type == GITS_ITT_TYPE_DEVICE) {
> > +s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
> > +
> > +if (s->dt.valid) {
> > +s->dt.indirect = FIELD_EX64(value, GITS_BASER,
> > INDIRECT);
> > +s->dt.entry_sz = FIELD_EX64(value, GITS_BASER,
> > ENTRYSIZE);
> > +
> > +if (!s->dt.indirect) {
> > +s->dt.max_entries = ((num_pages + 1) * page_sz) /
> > +   s-
> > >dt.entry_sz;
> > +} else {
> > +s->dt.max_entries = num_pages + 1) * page_sz)
> > /
> > +L1TABLE_ENTRY_SIZE) *
> > +(page_sz / s->dt.entry_sz));
> > +}
> > +
> > +s->dt.max_devids = (1UL << (FIELD_EX64(s->typer,
> > GITS_TYPER,
> > +DEVBITS) +
> > 1));
> > +
> > +if ((page_sz == GITS_ITT_PAGE_SIZE_0) ||
> > +(page_sz == GITS_ITT_PAGE_SIZE_1)) {
> > +s->dt.base_addr = FIELD_EX64(value, GITS_BASER,
> > PHYADDR);
> > +s->dt.base_addr <<= R_GITS_BASER_PHYADDR_SHIFT;
> > +} else if (page_sz == GITS_ITT_PAGE_SIZE_2) {
> > +s->dt.base_addr = FIELD_EX64(value, GITS_BASER,
> > PHYADDRL_64K) <<
> > +  R_GITS_BASER_PHYADDRL_64K_SHIFT;
> > +  s->dt.base_addr |= ((value >>
> > R_GITS_BASER_PHYADDR_SHIFT) &
> > +   R_GITS_BASER_PHYADDRH_64K_M
> > ASK) <<
> > +   R_GITS_BASER_PHYADDRH_64K_S
> > HIFT;
> > +}
> > +}
> > +} else if (type == GITS_ITT_TYPE_COLLECTION) {
> > +s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
> > +
> > +/*
> > + * GITS_TYPER.HCC is 0 for this implementation
> > + * hence writes are discarded if ct.valid is 0
> > + */
> > +if (s->ct.valid) {
> > +s->ct.indirect = FIELD_EX64(value, GITS_BASER,
> > INDIRECT);
> > +s->ct.entry_sz = FIELD_EX64(value, GITS_BASER,
> > ENTRYSIZE);
> > +
> > +if (!s->ct.indirect) {
> > +s->ct.max_entries = ((num_pages + 1) * page_sz) /
> > +  s->ct.entry_sz;
> > +} else {
> > +s->ct.max_entries = num_pages + 1) * page_sz)
> > /
> > +  L1TABLE_ENTRY_SIZE) *
> > +  (page_sz / s->ct.entry_sz));
> > +   

Re: [PATCH v2 5/8] hw/intc: GICv3 ITS Feature enablement

2021-04-29 Thread shashi . mallela
On Mon, 2021-04-19 at 11:51 +0100, Peter Maydell wrote:
> On Thu, 1 Apr 2021 at 03:41, Shashi Mallela <
> shashi.mall...@linaro.org> wrote:
> > Added properties to enable ITS feature and define qemu system
> > address space memory in gicv3 common,setup distributor and
> > redistributor registers to indicate LPI support.
> > 
> > Signed-off-by: Shashi Mallela 
> > ---
> >  hw/intc/arm_gicv3_common.c | 16 
> >  hw/intc/arm_gicv3_dist.c   | 22 --
> >  hw/intc/arm_gicv3_redist.c | 28 +-
> > --
> >  hw/intc/gicv3_internal.h   | 17 +
> >  include/hw/intc/arm_gicv3_common.h |  8 
> >  5 files changed, 86 insertions(+), 5 deletions(-)
> > 
> > diff --git a/hw/intc/arm_gicv3_common.c
> > b/hw/intc/arm_gicv3_common.c
> > index 58ef65f589..3bfc52f7fa 100644
> > --- a/hw/intc/arm_gicv3_common.c
> > +++ b/hw/intc/arm_gicv3_common.c
> > @@ -156,6 +156,7 @@ static const VMStateDescription
> > vmstate_gicv3_cpu = {
> >  VMSTATE_UINT32(gicr_waker, GICv3CPUState),
> >  VMSTATE_UINT64(gicr_propbaser, GICv3CPUState),
> >  VMSTATE_UINT64(gicr_pendbaser, GICv3CPUState),
> > +VMSTATE_BOOL(lpi_outofrange, GICv3CPUState),
> >  VMSTATE_UINT32(gicr_igroupr0, GICv3CPUState),
> >  VMSTATE_UINT32(gicr_ienabler0, GICv3CPUState),
> >  VMSTATE_UINT32(gicr_ipendr0, GICv3CPUState),
> > @@ -227,6 +228,7 @@ static const VMStateDescription vmstate_gicv3 =
> > {
> >  .priority = MIG_PRI_GICV3,
> >  .fields = (VMStateField[]) {
> >  VMSTATE_UINT32(gicd_ctlr, GICv3State),
> > +VMSTATE_UINT32(gicd_typer, GICv3State),
> >  VMSTATE_UINT32_ARRAY(gicd_statusr, GICv3State, 2),
> >  VMSTATE_UINT32_ARRAY(group, GICv3State, GICV3_BMP_SIZE),
> >  VMSTATE_UINT32_ARRAY(grpmod, GICv3State, GICV3_BMP_SIZE),
> 
> You can't add fields to an existing VMStateDescription like this
> without extra effort to handle migration compatibility.
> What are we trying to achieve with the extra fields?
> GICD_TYPER is read-only, I think.
> I don't think we need an lpi_outofrange flag: we should just
> naturally
> handle this as part of working with the GITR_PROPBASER.IDbits field.
> 
> Removed all fields to VMStateDescription,handled as part of working 
> with GITR_PROPBASER.IDbits field
>
> > @@ -381,6 +383,16 @@ static void
> > arm_gicv3_common_realize(DeviceState *dev, Error **errp)
> >  (1 << 24) |
> >  (i << 8) |
> >  (last << 4);
> > +
> > +if (s->lpi_enable) {
> > +s->cpu[i].gicr_typer |= GICR_TYPER_PLPIS;
> > +
> > +if (!s->sysmem) {
> > +error_setg(errp,
> > +"Redist-ITS: Guest 'sysmem' reference link not
> > set");
> > +return;
> > +}
> > +}
> >  }
> >  }
> > 
> > @@ -406,6 +418,7 @@ static void arm_gicv3_common_reset(DeviceState
> > *dev)
> >  cs->gicr_waker = GICR_WAKER_ProcessorSleep |
> > GICR_WAKER_ChildrenAsleep;
> >  cs->gicr_propbaser = 0;
> >  cs->gicr_pendbaser = 0;
> > +cs->lpi_outofrange = false;
> >  /* If we're resetting a TZ-aware GIC as if secure firmware
> >   * had set it up ready to start a kernel in non-secure, we
> >   * need to set interrupts to group 1 so the kernel can use
> > them.
> > @@ -494,9 +507,12 @@ static Property arm_gicv3_common_properties[]
> > = {
> >  DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
> >  DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
> >  DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
> > +DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
> >  DEFINE_PROP_BOOL("has-security-extensions", GICv3State,
> > security_extn, 0),
> >  DEFINE_PROP_ARRAY("redist-region-count", GICv3State,
> > nb_redist_regions,
> >redist_region_count, qdev_prop_uint32,
> > uint32_t),
> > +DEFINE_PROP_LINK("sysmem", GICv3State, sysmem,
> > TYPE_MEMORY_REGION,
> > + MemoryRegion *),
> >  DEFINE_PROP_END_OF_LIST(),
> >  };
> > 
> > diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
> > index b65f56f903..96a317a8ef 100644
> > --- a/hw/intc/arm_gicv3_dist.c
> > +++ b/hw/intc/arm_gicv3_dist.c
> > @@ -366,12 +366,15 @@ static MemTxResult gicd_readl(GICv3State *s,
> > hwaddr offset,
> >  return MEMTX_OK;
> >  case GICD_TYPER:
> >  {
> > +bool lpi_supported = false;
> >  /* For this implementation:
> >   * No1N == 1 (1-of-N SPI interrupts not supported)
> >   * A3V == 1 (non-zero values of Affinity level 3
> > supported)
> >   * IDbits == 0xf (we support 16-bit interrupt identifiers)
> >   * DVIS == 0 (Direct virtual LPI injection not supported)
> > - * LPIS == 0 (LPIs not supported)
> > + * LPIS == 1 (LPIs are supported if affinity 

Re: [PATCH v2 1/8] hw/intc: GICv3 ITS initial framework

2021-04-29 Thread shashi . mallela
On Fri, 2021-04-16 at 18:21 +0100, Peter Maydell wrote:
> On Thu, 1 Apr 2021 at 03:41, Shashi Mallela <
> shashi.mall...@linaro.org> wrote:
> > Added register definitions relevant to ITS,implemented overall
> > ITS device framework with stubs for ITS control and translater
> > regions read/write,extended ITS common to handle mmio init between
> > existing kvm device and newer qemu device.
> > 
> > Signed-off-by: Shashi Mallela 
> > ---
> >  hw/intc/arm_gicv3_its.c| 334
> > +
> >  hw/intc/arm_gicv3_its_common.c |  12 +-
> >  hw/intc/arm_gicv3_its_kvm.c|   2 +-
> >  hw/intc/gicv3_internal.h   |  86 ++-
> >  hw/intc/meson.build|   1 +
> >  include/hw/intc/arm_gicv3_its_common.h |  12 +-
> >  6 files changed, 430 insertions(+), 17 deletions(-)
> >  create mode 100644 hw/intc/arm_gicv3_its.c
> 
> Overall I think the structure of the patchset and of the device
> is good, so I'm just going to dive into more detailed review
> comments.
> 
> Have accepted and addressed all the comments and will share the
> updated patch sets soon,responding to comments which need 
>  clarification in all the relevant patch sets 
> 
> > +static MemTxResult its_trans_writew(GICv3ITSState *s, hwaddr
> > offset,
> > +   uint64_t value, MemTxAttrs attrs)
> > +{
> > +MemTxResult result = MEMTX_OK;
> > +
> > +return result;
> > +}
> > +
> > +static MemTxResult its_trans_writel(GICv3ITSState *s, hwaddr
> > offset,
> > +   uint64_t value, MemTxAttrs attrs)
> > +{
> > +MemTxResult result = MEMTX_OK;
> > +
> > +return result;
> > +}
> > +
> > +static MemTxResult gicv3_its_translation_write(void *opaque,
> > hwaddr offset,
> > +   uint64_t data, unsigned size,
> > MemTxAttrs attrs)
> > +{
> > +GICv3ITSState *s = (GICv3ITSState *)opaque;
> > +MemTxResult result;
> > +
> > +switch (size) {
> > +case 2:
> > +result = its_trans_writew(s, offset, data, attrs);
> > +break;
> > +case 4:
> > +result = its_trans_writel(s, offset, data, attrs);
> > +break;
> > +default:
> > +result = MEMTX_ERROR;
> > +break;
> > +}
> > +
> > +if (result == MEMTX_ERROR) {
> > +qemu_log_mask(LOG_GUEST_ERROR,
> > +  "%s: invalid guest write at offset "
> > TARGET_FMT_plx
> > +  "size %u\n", __func__, offset, size);
> > +/*
> > + * The spec requires that reserved registers are RAZ/WI;
> > + * so use MEMTX_ERROR returns from leaf functions as a way
> > to
> > + * trigger the guest-error logging but don't return it to
> > + * the caller, or we'll cause a spurious guest data abort.
> > + */
> > +result = MEMTX_OK;
> > +}
> > +return result;
> > +}
> 
> There is exactly one register in the translation register frame, so
> having this generic top level write function that calls out to
> separate writew and writel functions is overkill and ends up
> with duplication of code. I would suggest you just fold the
> implementation into gicv3_its_translation_write(), which would
> end up looking something like
> 
> switch (offset) {
> case GITS_TRANSLATER:
> if (s->ctlr & ITS_CTLR_ENABLED) {
> /* 16 bit accesses behave as writes with bits [31:16]
> zero */
> s->translater = value;
> devid = attrs.requester_id;
> process_int(s, s->translater, devid, NONE);
> }
> break;
> default:
> break;
> }
> return MEMTX_OK;
> 
> which handles both the 16 and 32 bit case. You can tell the
> core memory system code not to hand you 8 or 64 bit accesses
> using fields in the MemoryRegionOps; see below.
> 
> > +static MemTxResult gicv3_its_translation_read(void *opaque, hwaddr
> > offset,
> > +  uint64_t *data, unsigned size,
> > MemTxAttrs attrs)
> > +{
> > +qemu_log_mask(LOG_GUEST_ERROR,
> > +"%s: Invalid read from translation register area at offset
> > "
> > +TARGET_FMT_plx "\n", __func__, offset);
> > +return MEMTX_ERROR;
> > +}
> > +
> > +static MemTxResult its_writeb(GICv3ITSState *s, hwaddr offset,
> > +   uint64_t value, MemTxAttrs attrs)
> > +{
> > +qemu_log_mask(LOG_UNIMP,
> > +"%s: unsupported byte write to register at offset
> > "
> > +TARGET_FMT_plx "\n", __func__, offset);
> > +return MEMTX_ERROR;
> > +}
> > +
> > +static MemTxResult its_readb(GICv3ITSState *s, hwaddr offset,
> > +   uint64_t *data, MemTxAttrs attrs)
> > +{
> > +qemu_log_mask(LOG_UNIMP,
> > +"%s: unsupported byte read from register at offset
> > "
> > +TARGET_FMT_plx "\n", __func__, offset);
> > +return MEMTX_ERROR;
> > +}
> > +
> > +static MemTxResult 

Re: [PATCH v4 00/30] target/mips: Re-org to allow KVM-only builds

2021-04-29 Thread Philippe Mathieu-Daudé
On 4/28/21 7:03 PM, Philippe Mathieu-Daudé wrote:
> TL;DR:
> 
> This series restrict TCG-specific objects by moving them to
> the tcg/ subdir. Code is moved around to satisfy 3 cases:
> { generic sysemu / tcg sysemu / tcg user}.

> Philippe Mathieu-Daudé (30):
>   target/mips: Simplify meson TCG rules
>   target/mips: Move IEEE rounding mode array to new source file
>   target/mips: Move msa_reset() to new source file
>   target/mips: Make CPU/FPU regnames[] arrays global
>   target/mips: Optimize CPU/FPU regnames[] arrays
>   target/mips: Restrict mips_cpu_dump_state() to cpu.c
>   target/mips: Turn printfpr() macro into a proper function
>   target/mips: Declare mips_env_set_pc() inlined in "internal.h"
>   target/mips: Merge do_translate_address into
> cpu_mips_translate_address
>   target/mips: Extract load/store helpers to ldst_helper.c
>   meson: Introduce meson_user_arch source set for arch-specific
> user-mode
>   target/mips: Introduce tcg-internal.h for TCG specific declarations
>   target/mips: Add simple user-mode mips_cpu_do_interrupt()
>   target/mips: Add simple user-mode mips_cpu_tlb_fill()
>   target/mips: Move cpu_signal_handler definition around
>   target/mips: Move sysemu specific files under sysemu/ subfolder
>   target/mips: Move physical addressing code to sysemu/physaddr.c
>   target/mips: Restrict cpu_mips_get_random() / update_pagemask() to TCG
>   target/mips: Move sysemu TCG-specific code to tcg/sysemu/ subfolder
>   target/mips: Restrict mmu_init() to TCG
>   target/mips: Move tlb_helper.c to tcg/sysemu/
>   target/mips: Restrict CPUMIPSTLBContext::map_address() handlers scope
>   target/mips: Move Special opcodes to tcg/sysemu/special_helper.c
>   target/mips: Move helper_cache() to tcg/sysemu/special_helper.c
>   target/mips: Move TLB management helpers to tcg/sysemu/tlb_helper.c
>   target/mips: Move exception management code to exception.c
>   target/mips: Move CP0 helpers to sysemu/cp0.c
>   target/mips: Move TCG source files under tcg/ sub directory
>   hw/mips: Restrict non-virtualized machines to TCG
>   gitlab-ci: Add KVM mips64el cross-build jobs

Thanks, series applied to mips-next tree.



Re: [PATCH v2 7/7] target/ppc: isolated cpu init from translation logic

2021-04-29 Thread Fabiano Rosas
"Bruno Larsen (billionai)"  writes:

> finished isolation of CPU initialization logic from
> translation logic. CPU initialization now only has common code
> which may or may not call accelerator-specific code, as the
> build options require, and is compiled separately.
>
> Signed-off-by: Bruno Larsen (billionai) 
> ---
>  target/ppc/{translate_init.c.inc => cpu_init.c} | 12 +++-
>  target/ppc/meson.build  |  1 +
>  target/ppc/translate.c  |  4 +++-
>  3 files changed, 15 insertions(+), 2 deletions(-)
>  rename target/ppc/{translate_init.c.inc => cpu_init.c} (99%)
>
> diff --git a/target/ppc/translate_init.c.inc b/target/ppc/cpu_init.c
> similarity index 99%
> rename from target/ppc/translate_init.c.inc
> rename to target/ppc/cpu_init.c
> index b329e953cb..f0f8fc481e 100644
> --- a/target/ppc/translate_init.c.inc
> +++ b/target/ppc/cpu_init.c
> @@ -18,6 +18,7 @@
>   * License along with this library; if not, see 
> .
>   */
>  
> +#include "qemu/osdep.h"
>  #include "disas/dis-asm.h"
>  #include "exec/gdbstub.h"
>  #include "kvm_ppc.h"
> @@ -42,6 +43,10 @@
>  #include "fpu/softfloat.h"
>  #include "qapi/qapi-commands-machine-target.h"
>  
> +#include "helper_regs.h"
> +#include "internal.h"
> +#include "spr_tcg.h"

These two includes look like they belong in patch 3 and 4 respectively.

And we probably want an #ifdef CONFIG_TCG around them.

> +
>  /* #define PPC_DEBUG_SPR */
>  /* #define USE_APPLE_GDB */
>  
> @@ -49,7 +54,12 @@ static inline void vscr_init(CPUPPCState *env, uint32_t 
> val)
>  {
>  /* Altivec always uses round-to-nearest */
>  set_float_rounding_mode(float_round_nearest_even, >vec_status);
> -helper_mtvscr(env, val);
> +/*
> + * This comment is here just so the project will build.
> + * The current solution is in another patch and will be
> + * added when we figure out an internal fork of qemu
> + */
> +/* helper_mtvscr(env, val); */
>  }
>  
>  #ifdef CONFIG_TCG
> diff --git a/target/ppc/meson.build b/target/ppc/meson.build
> index bbfef90e08..ad53629298 100644
> --- a/target/ppc/meson.build
> +++ b/target/ppc/meson.build
> @@ -2,6 +2,7 @@ ppc_ss = ss.source_set()
>  ppc_ss.add(files(
>'cpu-models.c',
>'cpu.c',
> +  'cpu_init.c',
>'dfp_helper.c',
>'excp_helper.c',
>'fpu_helper.c',
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index a6e677fa6d..afb8a2aa27 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -38,6 +38,9 @@
>  #include "qemu/atomic128.h"
>  #include "internal.h"
>  
> +#include "qemu/qemu-print.h"
> +#include "qapi/error.h"
> +#include "internal.h"

This one is already included.

>  
>  #define CPU_SINGLE_STEP 0x1
>  #define CPU_BRANCH_STEP 0x2
> @@ -7595,7 +7598,6 @@ GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 
> 0x03FFF800, \
>  
>  #include "helper_regs.h"
>  #include "spr_tcg.c.inc"
> -#include "translate_init.c.inc"
>  
>  
> /*/
>  /* Misc PowerPC helpers */



Re: [PATCH v6 00/10] KVM: Dirty ring support (QEMU part)

2021-04-29 Thread Peter Xu
On Wed, Mar 24, 2021 at 02:39:44PM -0400, Peter Xu wrote:
> This is v6 of the qemu dirty ring interface support.
> 
> v6:
> - Fix slots_lock init [Keqian, Paolo]
> - Comment above KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 on todo (to enable
>   KVM_CLEAR_DIRTY_LOG for dirty ring too) [Keqian, Paolo]
> - Fix comment for CPUState [Keqian]

Ping after v6.0 released (seems still ok to apply).

-- 
Peter Xu




[ANNOUNCE] QEMU 6.0.0 is now available

2021-04-29 Thread Michael Roth
Hello,

On behalf of the QEMU Team, I'd like to announce the availability of
the QEMU 6.0.0 release. This release contains 3300+ commits from 268
authors.

You can grab the tarball from our download page here:

  https://www.qemu.org/download/#source

The full list of changes are available at:

  https://wiki.qemu.org/ChangeLog/6.0

Highlights include:

 * 68k: new 'virt' machine type based on virtio devices
 * ARM: support for ARMv8.1-M 'Helium' architecture and Cortex-M55 CPU
 * ARM: support for ARMv8.4 TTST, SEL2, and DIT extensions
 * ARM: ARMv8.5 MemTag extension now available for both system and usermode
   emulation
 * ARM: support for new mps3-an524, mps3-an547 board models
 * ARM: additional device emulation support for xlnx-zynqmp, xlnx-versal,
   sbsa-ref, npcm7xx, and sabrelite board models
 * Hexagon: new emulation support for Qualcomm hexagon DSP units
 * MIPS: new Loongson-3 'virt' machine type
 * PowerPC: external BMC support for powernv machine type
 * PowerPC: pseries machines now report memory unplug failures to management
   tools, as well as retrying unsuccessful CPU unplug requests
 * RISC-V: Microchip PolarFire board now supports QSPI NOR flash
 * Tricore: support for new TriBoard board model emulating Infineon TC27x SoC
 * x86: AMD SEV-ES support for running guests with secured CPU register state
 * x86: TCG emulation support for protection keys (PKS)
 
 * ACPI: support for assigning NICs to known names in guest OS independently of
   PCI slot placement
 * NVMe: new emulation support for v1.4 spec with many new features,
   experimental support for Zoned Namespaces, multipath I/O, and End-to-End
   Data Protection.
 * virtiofs: performance improvements with new USE_KILLPRIV_V2 guest feature
 * VNC: virtio-vga support for scaling resolution based on client window size
 * QMP: backup jobs now support multiple asynchronous requests in parallel

 * and lots more...

Thank you to everyone involved!



Re: [PATCH v2 4/7] target/ppc: turned SPR R/W callbacks not static

2021-04-29 Thread Fabiano Rosas
"Bruno Larsen (billionai)"  writes:

> To be able to compile translate_init.c.inc as a standalone file,
> we have to make the callbacks accessible outside of translate.c;
> This patch does that, making the callbacks not static and creating
> a new .h file
>
> Signed-off-by: Bruno Larsen (billionai) 
> ---



> diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h
> new file mode 100644
> index 00..b573a23e7b
> --- /dev/null
> +++ b/target/ppc/spr_tcg.h
> @@ -0,0 +1,121 @@
> +#ifndef SPR_TCG_H
> +#define SPR_TCG_H
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "exec/translator.h"
> +#include "tcg/tcg.h"

Why the last two?

> +
> +/* prototypes for readers and writers for SPRs */
> +
> +void spr_read_generic(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_xer(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_xer(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_lr(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_lr(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_ctr(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_ctr(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_ureg(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_tbl(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_tbu(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_atbl(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_atbu(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_601_rtcl(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_601_rtcu(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_spefscr(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_spefscr(DisasContext *ctx, int sprn, int gprn);
> +
> +#ifndef CONFIG_USER_ONLY
> +void spr_write_generic32(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_clear(DisasContext *ctx, int sprn, int gprn);
> +void spr_access_nop(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_decr(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_decr(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_tbl(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_tbu(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_atbl(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_atbu(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_ibat(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_ibat_h(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_ibatu(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_ibatu_h(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_ibatl(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_ibatl_h(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_dbat(DisasContext *ctx, int gprn, int sprn);
> +void spr_read_dbat_h(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_dbatu(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_dbatu_h(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_dbatl(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_dbatl_h(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_sdr1(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_601_rtcu(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_601_rtcl(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_601_ubatl(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_403_pbr(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_pir(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_excp_prefix(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_excp_vector(DisasContext *ctx, int sprn, int gprn);
> +void spr_read_thrm(DisasContext *ctx, int gprn, int sprn);
> +void spr_write_e500_l1csr0(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_e500_l1csr1(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_e500_l2csr0(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_booke206_mmucsr0(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_booke_pid(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_eplc(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_epsc(DisasContext *ctx, int sprn, int gprn);
> +void spr_write_mas73(DisasContext *ctx, int sprn, int gprn);
> +void 

Re: [PATCH v2 3/7] target/ppc: Isolated SPR read/write callbacks

2021-04-29 Thread Fabiano Rosas
"Bruno Larsen (billionai)"  writes:

> Moved all SPR read/write callback, and some related functions, to a
> new file specific for it. These callbacks are TCG only, so separating
> them is required to support the flag disable-tcg.
>
> Making the spr_noaccess function not static, and moving the define to
> internal.h is required, as spr_tcg.c.inc has to be included after
> SPR_NOACCESS has been used.
>
> Signed-off-by: Bruno Larsen (billionai) 
> ---
>  target/ppc/internal.h   |3 +
>  target/ppc/spr_tcg.c.inc| 1033 +++
>  target/ppc/translate.c  |   49 +-
>  target/ppc/translate_init.c.inc |  981 -
>  4 files changed, 1039 insertions(+), 1027 deletions(-)
>  create mode 100644 target/ppc/spr_tcg.c.inc
>
> diff --git a/target/ppc/internal.h b/target/ppc/internal.h
> index 184ba6d6b3..1de15acfbd 100644
> --- a/target/ppc/internal.h
> +++ b/target/ppc/internal.h
> @@ -228,4 +228,7 @@ void destroy_ppc_opcodes(PowerPCCPU *cpu);
>  void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
>  gchar *ppc_gdb_arch_name(CPUState *cs);
>  
> +void spr_noaccess(DisasContext *ctx, int gprn, int sprn);
> +#define SPR_NOACCESS (_noaccess)
> +
>  #endif /* PPC_INTERNAL_H */
> diff --git a/target/ppc/spr_tcg.c.inc b/target/ppc/spr_tcg.c.inc
> new file mode 100644
> index 00..48274dd52b
> --- /dev/null
> +++ b/target/ppc/spr_tcg.c.inc
> @@ -0,0 +1,1033 @@
> +#include "exec/translator.h"

This is already in translate.c.

> +
> +/*/
> +/* Reader and writer functions for SPRs */
> +
> +/* I really see no reason to keep these gen_*_xer */
> +/* instead of just leaving the code in the spr_*_xer */

Ok, let's do this for the next version then.

> +static void gen_read_xer(DisasContext *ctx, TCGv dst)
> +{
> +TCGv t0 = tcg_temp_new();
> +TCGv t1 = tcg_temp_new();
> +TCGv t2 = tcg_temp_new();
> +tcg_gen_mov_tl(dst, cpu_xer);
> +tcg_gen_shli_tl(t0, cpu_so, XER_SO);
> +tcg_gen_shli_tl(t1, cpu_ov, XER_OV);
> +tcg_gen_shli_tl(t2, cpu_ca, XER_CA);
> +tcg_gen_or_tl(t0, t0, t1);
> +tcg_gen_or_tl(dst, dst, t2);
> +tcg_gen_or_tl(dst, dst, t0);
> +if (is_isa300(ctx)) {
> +tcg_gen_shli_tl(t0, cpu_ov32, XER_OV32);
> +tcg_gen_or_tl(dst, dst, t0);
> +tcg_gen_shli_tl(t0, cpu_ca32, XER_CA32);
> +tcg_gen_or_tl(dst, dst, t0);
> +}
> +tcg_temp_free(t0);
> +tcg_temp_free(t1);
> +tcg_temp_free(t2);
> +}
> +
> +static void gen_write_xer(TCGv src)
> +{
> +/* Write all flags, while reading back check for isa300 */
> +tcg_gen_andi_tl(cpu_xer, src,
> +~((1u << XER_SO) |
> +  (1u << XER_OV) | (1u << XER_OV32) |
> +  (1u << XER_CA) | (1u << XER_CA32)));
> +tcg_gen_extract_tl(cpu_ov32, src, XER_OV32, 1);
> +tcg_gen_extract_tl(cpu_ca32, src, XER_CA32, 1);
> +tcg_gen_extract_tl(cpu_so, src, XER_SO, 1);
> +tcg_gen_extract_tl(cpu_ov, src, XER_OV, 1);
> +tcg_gen_extract_tl(cpu_ca, src, XER_CA, 1);
> +}



> +/* User read access to SPR */
> +/* USPRx */
> +/* UMMCRx */
> +/* UPMCx */
> +/* USIA */
> +/* UDECR */
> +static void spr_read_ureg(DisasContext *ctx, int gprn, int sprn)
> +{
> +gen_load_spr(cpu_gpr[gprn], sprn + 0x10);
> +}
> +
> +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
> +static void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
> +{
> +gen_store_spr(sprn + 0x10, cpu_gpr[gprn]);
> +}
> +#endif
> +

You missed this:

/* SPR common to all non-embedded PowerPC */

> +#if !defined(CONFIG_USER_ONLY)
> +static void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
> +{
> +if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +gen_io_start();
> +}
> +gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
> +if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +gen_stop_exception(ctx);
> +}
> +}
> +
> +static void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
> +{
> +if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +gen_io_start();
> +}
> +gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
> +if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +gen_stop_exception(ctx);
> +}
> +}
> +#endif
> +
> +/* SPR common to all non-embedded PowerPC, except 601 */
> +/* Time base */
> +static void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
> +{
> +if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +gen_io_start();
> +}
> +gen_helper_load_tbl(cpu_gpr[gprn], cpu_env);
> +if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +gen_io_end();
> +gen_stop_exception(ctx);
> +}
> +}
> +
> +static void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
> +{
> +if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
> +gen_io_start();
> +}
> +gen_helper_load_tbu(cpu_gpr[gprn], cpu_env);
> +if 

Re: [Bug 1926202] Re: qemu-user can't run some ppc binaries

2021-04-29 Thread Laurent Vivier
Le 29/04/2021 à 19:20, Aaron Simmons a écrit :
> Thanks for looking into this.  What reference did you use to check which
> ISA "cmpb" is in?
> 

It's in the QEMU source, but you can check the specs:

POWER ISA 2.04 -> no cmpb

https://wiki.raptorcs.com/w/images/6/65/PowerISA_V2.04-FINAL.Public.pdf

POWER ISA 2.05 -> cmpb

https://wiki.raptorcs.com/w/images/5/50/PowerISA_V2.05.pdf

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

Title:
  qemu-user can't run some ppc binaries

Status in QEMU:
  New

Bug description:
  qemu-user v6.0.0-rc5, built in static mode, will crash for certain ppc
  binaries.  It seems to have something to do with glibc for some Centos
  versions.  The problem is easiest to see with statically-linked
  binaries.

  The attached Dockerfile shows how to produce a ppc binary that will
  crash qemu-user.  Here is how to reproduce the problem:

  $ uname -m
  x86_64

  $ docker run --rm --privileged multiarch/qemu-user-static --reset -p
  yes

  $ docker build -t qemu-bug:centos -f Dockerfile.centos .

  $ docker run --rm -it -v$PWD:$PWD -w$PWD qemu-bug:centos cp
  /helloworld-centos.static.ppc .

  $ qemu-ppc-static --version
  qemu-ppc version 5.2.95 (v6.0.0-rc5)
  Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

  $ qemu-ppc-static ./helloworld-centos.static.ppc
  emu: uncaught target signal 4 (Illegal instruction) - core dumped
  [1]16678 illegal hardware instruction (core dumped)  qemu-ppc-static 
./helloworld-centos.static.ppc

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



Re: [PATCH v2 2/7] target/ppc: Created !TCG SPR registration macro

2021-04-29 Thread Fabiano Rosas
"Bruno Larsen (billionai)"  writes:

> Added macros for spr_register and spr_register_kvm that can
> ignore SPR RW callbacks, in preparation to support building
> without TCG.
>
> Signed-off-by: Bruno Larsen (billionai) 
> ---
>  target/ppc/translate_init.c.inc | 22 ++
>  1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
> index 6235eb7536..3ddcfefb62 100644
> --- a/target/ppc/translate_init.c.inc
> +++ b/target/ppc/translate_init.c.inc
> @@ -720,6 +720,7 @@ static inline void vscr_init(CPUPPCState *env, uint32_t 
> val)
>  helper_mtvscr(env, val);
>  }
>  
> +#ifdef CONFIG_TCG
>  #ifdef CONFIG_USER_ONLY
>  #define spr_register_kvm(env, num, name, uea_read, uea_write,
>   \
>   oea_read, oea_write, one_reg_id, initial_value) 
>   \
> @@ -728,7 +729,7 @@ static inline void vscr_init(CPUPPCState *env, uint32_t 
> val)
>  oea_read, oea_write, hea_read, hea_write,
>   \
>  one_reg_id, initial_value)   
>   \
>  _spr_register(env, num, name, uea_read, uea_write, initial_value)
> -#else
> +#else /*CONFIG_USER_ONLY */

Missing a space after the first *

>  #if !defined(CONFIG_KVM)
>  #define spr_register_kvm(env, num, name, uea_read, uea_write,
>   \
>   oea_read, oea_write, one_reg_id, initial_value) 
>   \
> @@ -739,7 +740,7 @@ static inline void vscr_init(CPUPPCState *env, uint32_t 
> val)
>  one_reg_id, initial_value)   
>   \
>  _spr_register(env, num, name, uea_read, uea_write,   
>   \
>oea_read, oea_write, hea_read, hea_write, initial_value)
> -#else
> +#else /* CONFIG_KVM */
>  #define spr_register_kvm(env, num, name, uea_read, uea_write,
>   \
>   oea_read, oea_write, one_reg_id, initial_value) 
>   \
>  _spr_register(env, num, name, uea_read, uea_write,   
>   \

This won't work if you don't include the change to _spr_register as well.

> @@ -751,8 +752,21 @@ static inline void vscr_init(CPUPPCState *env, uint32_t 
> val)
>  _spr_register(env, num, name, uea_read, uea_write,   
>   \
>oea_read, oea_write, hea_read, hea_write,  
>   \
>one_reg_id, initial_value)
> -#endif
> -#endif
> +#endif /* CONFIG_KVM */
> +#endif /* CONFIG_USER_ONLY */
> +#else /* CONFIG_TCG */
> +#ifdef CONFIG_KVM /* sanity check. should always enter this */
> +#define spr_register_kvm(env, num, name, uea_read, uea_write,
>   \
> + oea_read, oea_write, one_reg_id, initial_value) 
>   \
> +_spr_register(env, num, name, one_reg_id, initial_value)
> +#define spr_register_kvm_hv(env, num, name, uea_read, uea_write, 
>   \
> +oea_read, oea_write, hea_read, hea_write,
>   \
> +one_reg_id, initial_value)   
>   \
> +_spr_register(env, num, name, one_reg_id, initial_value)
> +#else /* CONFIG_KVM */
> +#error "Either TCG or KVM should be condigured"

configured

> +#endif /* CONFIG_KVM */
> +#endif /* CONFIG_TCG */
>  
>  #define spr_register(env, num, name, uea_read, uea_write,
>   \
>   oea_read, oea_write, initial_value) 
>   \



Re: Incorrect NVMe DLFEAT?

2021-04-29 Thread Harris, James R


On 4/29/21, 10:22 AM, "Klaus Jensen"  wrote:

On Apr 29 16:51, Harris, James R wrote:
>Hi,
>

Hi Jim,

>I’m seeing SPDK test failures with QEMU NVMe controllers that I’ve 
>bisected to QEMU commit 2605257a26 (“hw/block/nvme: add the dataset 
>management command”).
>
>The failing tests are related to write zeroes handling.  If an NVMe 
>controller supports DSM, and DLFEAT indicates that deallocated blocks 
>will read back as zeroes, then SPDK uses DEALLOCATE to implement the 
>write zeroes operation.  (Note: SPDK prefers this method to using NVMe 
>WRITE_ZEROES, since the latter is limited to a 16-bit block count.)
>

The Dataset Management command is advisory, the controller gives no 
guarantee that it will actually deallocate anything. You cannot use DSM 
as a realiable alternative to Write Zeroes. The QEMU emulated nvme 
device exploits this and in many cases wont deallocate anything if it 
does not fit nicely with the underlying block device setup.

[JH] Hmmm, looks like we may need some SPDK changes for this case.

>QEMU sets DLFEAT = 0x9 – and actually set it to 0x9 even before this 
>commit.  Since the lower 3 bits are 0b001, it is reporting that 
>deallocated blocks will read back later as 0.  This does not actually 
>seem to be the case however – reading previously deallocated blocks do 
>not actually return 0s.
>

Can you share the configuration you use for QEMU? DSM works best with 
4096 byte LBAs (logical_block_size=4096) and the raw format driver.

Also, please test with the Error Recovery feature (and set DULBE) to 
test if the device reports that the block is actually deallocated.

[JH] I've tested both 512 and 4096 LBAs and hacked something up to enable
DULBE.  I am not seeing any errors reading blocks that were part of a
previous DSM command.  So at least for the cases in the SPDK test, these
blocks are not actually being deallocated.

>It seems DLFEAT is being set incorrectly here – should probably be 0x8 
>instead?
>
>Thanks,
>
>Jim
>
>
>

-- 
k



Re: Let's remove some deprecated stuff

2021-04-29 Thread Eduardo Habkost
+Jiri, +Daniel, +Igor

On Thu, Apr 29, 2021 at 11:59:41AM +0200, Markus Armbruster wrote:
[...]
> I'm not sure there's anything to remove here, but anyway, Peter Maydell:
> 

This one is mine.

There's no code to remove, but the intention is to eventually
change default_cpu_version to CPU_VERSION_LATEST on newer machine
types.

> 
> Runnability guarantee of CPU models (since 4.1.0)
> '
> 
> Previous versions of QEMU never changed existing CPU models in
> ways that introduced additional host software or hardware
> requirements to the VM.  This allowed management software to
> safely change the machine type of an existing VM without
> introducing new requirements ("runnability guarantee").  This
> prevented CPU models from being updated to include CPU
> vulnerability mitigations, leaving guests vulnerable in the
> default configuration.
> 
> The CPU model runnability guarantee won't apply anymore to
> existing CPU models.  Management software that needs runnability
> guarantees must resolve the CPU model aliases using the
> ``alias-of`` field returned by the ``query-cpu-definitions`` QMP
> command.
> 
> While those guarantees are kept, the return value of
> ``query-cpu-definitions`` will have existing CPU model aliases
> point to a version that doesn't break runnability guarantees
> (specifically, version 1 of those CPU models).  In future QEMU
> versions, aliases will point to newer CPU model versions
> depending on the machine type, so management software must
> resolve CPU model aliases before starting a virtual machine.

libvirt had no time to adapt to this yet.  As far as I
understand, they need the following series to be merged first so
they can more easily resolve the unversioned CPU model name
aliases:

https://lore.kernel.org/qemu-devel/20201013230457.150630-1-ehabk...@redhat.com

I need to rebase that series and resubmit.

-- 
Eduardo




Re: [PATCH] virtio-blk: drop deprecated scsi=on|off property

2021-04-29 Thread Eduardo Habkost
On Thu, Apr 29, 2021 at 04:52:21PM +0100, Stefan Hajnoczi wrote:
> The scsi=on|off property was deprecated in QEMU 5.0 and can be removed
> completely at this point.
> 
> Drop the scsi=on|off option. It was only available on Legacy virtio-blk
> devices. Linux v5.6 already dropped support for it.
> 
> Remove the hw_compat_2_4[] property assignment since scsi=on|off no
> longer exists. Old guests with Legacy virtio-blk devices no longer see
> the SCSI host features bit.
> 

This means pc-2.4 will now break guest ABI if using virtio-blk
devices, correct?

This looks like a sign we should have deprecated pc-2.4 a long
time ago.

> Live migrating old guests from an old QEMU with the SCSI feature bit
> enabled will fail with "Features 0x... unsupported. Allowed features:
> 0x...". We've followed the QEMU deprecation policy so users have been
> warned...
> 

Were they really warned, though?  People running
"-machine pc-i440fx-2.4" might be completely unaware that it was
silently enabling a deprecated feature.

Can we have this documented in a more explicit way?  Maybe just a
comment at hw_compat_2_4 would be enough, to warn people doing
backports and rebases downstream.

Can we make QEMU refuse to start if using pc-2.4 + virtio-blk
together, just to be sure?

An alternative would be keeping the property (and the
hw_compat_2_4 entry) just to keep pc-2.4 working (until pc-2.4 is
deprecated and removed), but refusing to realize the device if
the feature is enabled.


> I have tested that libvirt still works when the property is absent. It
> no longer adds scsi=on|off to the command-line.
> 
> Cc: Markus Armbruster 
> Cc: Christoph Hellwig 
> Cc: Peter Krempa 
> Cc: Dr. David Alan Gilbert 
> Signed-off-by: Stefan Hajnoczi 
> ---
[...]
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 40def78183..286f18ec6d 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -194,8 +194,6 @@ GlobalProperty hw_compat_2_5[] = {
>  const size_t hw_compat_2_5_len = G_N_ELEMENTS(hw_compat_2_5);
>  
>  GlobalProperty hw_compat_2_4[] = {
> -/* Optional because the 'scsi' property is Linux-only */
> -{ "virtio-blk-device", "scsi", "true", .optional = true },
>  { "e1000", "extra_mac_registers", "off" },
>  { "virtio-pci", "x-disable-pcie", "on" },
>  { "virtio-pci", "migrate-extra", "off" },


-- 
Eduardo




Re: [PATCH] make vfio and DAX cache work together

2021-04-29 Thread Dr. David Alan Gilbert
* Alex Williamson (alex.william...@redhat.com) wrote:
> On Thu, 29 Apr 2021 09:44:51 +0100
> "Dr. David Alan Gilbert"  wrote:
> 
> > * Alex Williamson (alex.william...@redhat.com) wrote:
> > > On Wed, 28 Apr 2021 20:17:23 +0100
> > > "Dr. David Alan Gilbert"  wrote:
> > >   
> > > > * Dev Audsin (dev.devaq...@gmail.com) wrote:  
> > > > > Thanks Dave for your explanation.
> > > > > Any suggestions on how to make VFIO not attempt to map into the
> > > > > unaccessible and unallocated RAM.
> > > > 
> > > > I'm not sure;:
> > > > 
> > > > static bool vfio_listener_skipped_section(MemoryRegionSection *section)
> > > > {
> > > > return (!memory_region_is_ram(section->mr) &&
> > > > !memory_region_is_iommu(section->mr)) ||
> > > >section->offset_within_address_space & (1ULL << 63);
> > > > }
> > > > 
> > > > I'm declaring that region with memory_region_init_ram_ptr;  should I be?
> > > > it's not quite like RAM.
> > > > But then I *do* want a kvm slot for it, and I do want it to be accessed
> > > > by mapping rather htan calling IO functions; that makes me think mr->ram
> > > > has to be true.
> > > > But then do we need to add another flag to memory-regions; if we do,
> > > > what is it;
> > > >a) We don't want an 'is_virtio_fs' - it needs to be more generic
> > > >b) 'no_vfio' also feels wrong
> > > > 
> > > > Is perhaps 'not_lockable' the right thing to call it?  
> > > 
> > > This reasoning just seems to lead back to "it doesn't work, therefore
> > > don't do it" rather than identifying the property of the region that
> > > makes it safe not to map it for device DMA (assuming that's actually
> > > the case).   
> > 
> > Yes, I'm struggling to get to what that generic form of that property
> > is, possibly because I've not got an example of another case to compare
> > it with.
> > 
> > > It's clearly "RAM" as far as QEMU is concerned given how
> > > it's created, but does it actually appear in the VM as generic physical
> > > RAM that the guest OS could program to the device as a DMA target?  If
> > > not, what property makes that so, create a flag for that.  Thanks,  
> > 
> > The guest sees it as a PCI-bar; so it knows it's not 'generic physical
> > RAM' - but can a guest set other BARs (like frame buffers or pmem) as
> > DMA targets?  If so, how do I distinguish our bar?
> 
> They can, this is how peer-to-peer DMA between devices works.  However,
> we can perhaps take advantage that drivers are generally a bit more
> cautious in probing that this type of DMA works before relying on it,
> and declare it with memory_region_init_ram_device_ptr() which vfio
> would not consider fatal if it fails to map it.  The other semantic
> difference is that ram_device_mem_ops are used for read/write access to
> avoid some of the opcodes that are not meant to be used for physical
> device memory with the default memcpy ops.  If you expect this region
> to be mapped as a kvm memory slot, presumably these would never get
> used anyway.  Thanks,

Oh, nice, I hadn't spotted memory_region_init_ram_device_ptr();

diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 7afd9495c9..11fb9b5979 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -604,7 +604,7 @@ static void vuf_device_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-memory_region_init_ram_ptr(>cache, OBJECT(vdev),
+memory_region_init_ram_device_ptr(>cache, OBJECT(vdev),
"virtio-fs-cache",
fs->conf.cache_size, cache_ptr);
 }

apparently still works for us; Dev does that fix it for you?

Dave

> Alex
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




[Bug 1926202] Re: qemu-user can't run some ppc binaries

2021-04-29 Thread Aaron Simmons
Thanks for looking into this.  What reference did you use to check which
ISA "cmpb" is in?

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

Title:
  qemu-user can't run some ppc binaries

Status in QEMU:
  New

Bug description:
  qemu-user v6.0.0-rc5, built in static mode, will crash for certain ppc
  binaries.  It seems to have something to do with glibc for some Centos
  versions.  The problem is easiest to see with statically-linked
  binaries.

  The attached Dockerfile shows how to produce a ppc binary that will
  crash qemu-user.  Here is how to reproduce the problem:

  $ uname -m
  x86_64

  $ docker run --rm --privileged multiarch/qemu-user-static --reset -p
  yes

  $ docker build -t qemu-bug:centos -f Dockerfile.centos .

  $ docker run --rm -it -v$PWD:$PWD -w$PWD qemu-bug:centos cp
  /helloworld-centos.static.ppc .

  $ qemu-ppc-static --version
  qemu-ppc version 5.2.95 (v6.0.0-rc5)
  Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

  $ qemu-ppc-static ./helloworld-centos.static.ppc
  emu: uncaught target signal 4 (Illegal instruction) - core dumped
  [1]16678 illegal hardware instruction (core dumped)  qemu-ppc-static 
./helloworld-centos.static.ppc

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



[PATCH v3] target/i386/sev: add support to query the attestation report

2021-04-29 Thread Brijesh Singh
The SEV FW >= 0.23 added a new command that can be used to query the
attestation report containing the SHA-256 digest of the guest memory
and VMSA encrypted with the LAUNCH_UPDATE and sign it with the PEK.

Note, we already have a command (LAUNCH_MEASURE) that can be used to
query the SHA-256 digest of the guest memory encrypted through the
LAUNCH_UPDATE. The main difference between previous and this command
is that the report is signed with the PEK and unlike the LAUNCH_MEASURE
command the ATTESATION_REPORT command can be called while the guest
is running.

Add a QMP interface "query-sev-attestation-report" that can be used
to get the report encoded in base64.

Cc: James Bottomley 
Cc: Tom Lendacky 
Cc: Eric Blake 
Cc: Paolo Bonzini 
Cc: k...@vger.kernel.org
Reviewed-by: James Bottomley 
Tested-by: James Bottomley 
Signed-off-by: Brijesh Singh 
---
v3:
  * free the buffer in error path.

v2:
  * add trace event.
  * fix the goto to return NULL on failure.
  * make the mnonce as a base64 encoded string

 linux-headers/linux/kvm.h |  8 +
 qapi/misc-target.json | 38 ++
 target/i386/monitor.c |  6 
 target/i386/sev-stub.c|  7 
 target/i386/sev.c | 67 +++
 target/i386/sev_i386.h|  2 ++
 target/i386/trace-events  |  1 +
 7 files changed, 129 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 020b62a619..897f831374 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1591,6 +1591,8 @@ enum sev_cmd_id {
KVM_SEV_DBG_ENCRYPT,
/* Guest certificates commands */
KVM_SEV_CERT_EXPORT,
+   /* Attestation report */
+   KVM_SEV_GET_ATTESTATION_REPORT,
 
KVM_SEV_NR_MAX,
 };
@@ -1643,6 +1645,12 @@ struct kvm_sev_dbg {
__u32 len;
 };
 
+struct kvm_sev_attestation_report {
+   __u8 mnonce[16];
+   __u64 uaddr;
+   __u32 len;
+};
+
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU(1 << 0)
 #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
 #define KVM_DEV_ASSIGN_MASK_INTX   (1 << 2)
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 0c7491cd82..4b62f0ac05 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -285,3 +285,41 @@
 ##
 { 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
   'if': 'defined(TARGET_ARM)' }
+
+
+##
+# @SevAttestationReport:
+#
+# The struct describes attestation report for a Secure Encrypted Virtualization
+# feature.
+#
+# @data:  guest attestation report (base64 encoded)
+#
+#
+# Since: 6.1
+##
+{ 'struct': 'SevAttestationReport',
+  'data': { 'data': 'str'},
+  'if': 'defined(TARGET_I386)' }
+
+##
+# @query-sev-attestation-report:
+#
+# This command is used to get the SEV attestation report, and is supported on 
AMD
+# X86 platforms only.
+#
+# @mnonce: a random 16 bytes value encoded in base64 (it will be included in 
report)
+#
+# Returns: SevAttestationReport objects.
+#
+# Since: 6.1
+#
+# Example:
+#
+# -> { "execute" : "query-sev-attestation-report", "arguments": { "mnonce": 
"aaa" } }
+# <- { "return" : { "data": "bbbd"} }
+#
+##
+{ 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' },
+  'returns': 'SevAttestationReport',
+  'if': 'defined(TARGET_I386)' }
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 5994408bee..119211f0b0 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -757,3 +757,9 @@ void qmp_sev_inject_launch_secret(const char *packet_hdr,
 
 sev_inject_launch_secret(packet_hdr, secret, gpa, errp);
 }
+
+SevAttestationReport *
+qmp_query_sev_attestation_report(const char *mnonce, Error **errp)
+{
+return sev_get_attestation_report(mnonce, errp);
+}
diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
index 0207f1c5aa..0227cb5177 100644
--- a/target/i386/sev-stub.c
+++ b/target/i386/sev-stub.c
@@ -74,3 +74,10 @@ int sev_es_save_reset_vector(void *flash_ptr, uint64_t 
flash_size)
 {
 abort();
 }
+
+SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp)
+{
+error_setg(errp, "SEV is not available in this QEMU");
+return NULL;
+}
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 72b9e2ab40..4b9d7d3bb9 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -491,6 +491,73 @@ out:
 return cap;
 }
 
+SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp)
+{
+struct kvm_sev_attestation_report input = {};
+SevAttestationReport *report = NULL;
+SevGuestState *sev = sev_guest;
+guchar *data;
+guchar *buf;
+gsize len;
+int err = 0, ret;
+
+if (!sev_enabled()) {
+error_setg(errp, "SEV is not enabled");
+return NULL;
+}
+
+/* lets decode the mnonce string */
+buf = g_base64_decode(mnonce, );
+if (!buf) {
+error_setg(errp, "SEV: failed to decode mnonce input");
+return NULL;
+}
+
+/* verify the input mnonce 

[PATCH v2 4/6] vhost-user-blk: Get more feature flags from vhost device

2021-04-29 Thread Kevin Wolf
VIRTIO_F_RING_PACKED and VIRTIO_F_IOMMU_PLATFORM need to be supported by
the vhost device, otherwise advertising it to the guest doesn't result
in a working configuration. They are currently not supported by the
vhost-user-blk export in QEMU.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1935020
Signed-off-by: Kevin Wolf 
Acked-by: Raphael Norwitz 
---
 hw/block/vhost-user-blk.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index f3a45af97c..c7e502f4c7 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -47,6 +47,8 @@ static const int user_feature_bits[] = {
 VIRTIO_RING_F_INDIRECT_DESC,
 VIRTIO_RING_F_EVENT_IDX,
 VIRTIO_F_NOTIFY_ON_EMPTY,
+VIRTIO_F_RING_PACKED,
+VIRTIO_F_IOMMU_PLATFORM,
 VHOST_INVALID_FEATURE_BIT
 };
 
-- 
2.30.2




Re: [PATCH v2 04/15] target/ppc: Move DISAS_NORETURN setting into gen_exception*

2021-04-29 Thread Richard Henderson

On 4/29/21 10:07 AM, Luis Fernando Fujita Pires wrote:

-static inline void gen_stop_exception(DisasContext *ctx)
+static inline void gen_end_tb_exception(DisasContext *ctx, uint32_t
+excp)
   {
-gen_update_nip(ctx, ctx->base.pc_next);
-ctx->exception = POWERPC_EXCP_STOP;
+/* No need to update nip for SYNC/BRANCH, as execution flow will change

*/

+if ((excp != POWERPC_EXCP_SYNC) &&
+(excp != POWERPC_EXCP_BRANCH))
+{
+gen_update_nip(ctx, ctx->base.pc_next);
+}
+ctx->exception = excp;
+ctx->base.is_jmp = DISAS_NORETURN;
   }


Hmm.  You didn't actually raise the exception, so you can't set
DISAS_NORETURN that way.  It looks like you should be using
gen_exception_nip().


This is reproducing the behavior that was implemented before the DISAS_NORETURN 
changes, that caused check-tcg to fail with an assertion otherwise.

IIUC, POWERPC_EXCP_{STOP,SYNC,BRANCH} are not really exceptions and, in these cases, 
ctx->exception is being used just to cause  ppc_tr_translate_insn() to end the 
translation block. If so, we should not be using ctx->exception for that, but I 
believe fixing that to not use ctx->exception belongs in a separate stand-alone patch.


Hum.  Well, you can set is_jmp = DISAS_TOO_MANY to force exit from the 
translation loop.


I believe a proper fix would be to turn all of these "fake" exceptions into 
DISAS_FOO constants, to be assigned to is_jmp. There are a bunch of 
DISAS_TARGET_N enumerators which should be renamed like in target/arm/translate.h:


#define DISAS_WFI   DISAS_TARGET_2
#define DISAS_SWI   DISAS_TARGET_3

etc.  Then most of the code that is special casing these constants should get 
moved to ppc_tr_tb_stop.



r~



Re: libnbd thread-local errors and dlclose (was: Re: [ANNOUNCE] libblkio v0.1.0 preview release)

2021-04-29 Thread Daniel P . Berrangé
On Thu, Apr 29, 2021 at 06:17:32PM +0100, Richard W.M. Jones wrote:
> On Thu, Apr 29, 2021 at 04:08:22PM +0100, Daniel P. Berrangé wrote:
> > On Thu, Apr 29, 2021 at 04:00:38PM +0100, Richard W.M. Jones wrote:
> > > On Thu, Apr 29, 2021 at 03:41:29PM +0100, Stefan Hajnoczi wrote:
> > > > On Thu, Apr 29, 2021 at 03:22:59PM +0100, Richard W.M. Jones wrote:
> > > > > libvirt originally, and now libnbd, keep a per-thread error message
> > > > > (stored in thread-local storage).  It's a lot nicer than having to
> > > > > pass  to every function.  You can just write:
> > > > > 
> > > > >  if (nbd_connect_tcp (nbd, "remote", "nbd") == -1) {
> > > > >fprintf (stderr,
> > > > > "failed to connect to remote server: %s (errno = %d)\n",
> > > > > nbd_get_error (), nbd_get_errno ());
> > > > >exit (EXIT_FAILURE);
> > > > >  }
> > > > > 
> > > > > (https://libguestfs.org/libnbd.3.html#ERROR-HANDLING)
> > > > > 
> > > > > It means you can extend the range of error information available in
> > > > > future.  Also you can return a 'const char *' and the application
> > > > > doesn't have to worry about lifetimes, at least in the common case.
> > > > 
> > > > Thanks for sharing the idea, I think it would work well for libblkio
> > > > too.
> > > > 
> > > > Do you ignore the dlclose(3) memory leak?
> > > 
> > > I believe this mechanism in libnbd ensures there is no leak in the
> > > ordinary shared library (not dlopen/dlclose) case:
> > > 
> > > https://gitlab.com/nbdkit/libnbd/-/blob/f9257a9fdc68706a4079deb4ced61e1d468f28d6/lib/errors.c#L35
> > > 
> > > However I'm not sure what happens in the dlopen case, so I'm going to
> > > test that out now ...
> > 
> > pthread_key destructors are a disaster waiting to happen with
> > dlclose, if the dlclose happens while non-main threads are
> > still running. When those threads exit, they'll run the
> > destructor which points to a function that is no longer
> > resident in memory.
> 
> While libnbd had a memory leak there, now fixed by:
> 
> https://gitlab.com/nbdkit/libnbd/-/commit/026d281c57dd95485cc9bf829918b5efd9e32ddb

So on dlclose(), the errors_free() method will be run by the linker.

The pthread_key_delete method doesn't run the cleanup callbacks, so
your fix here frees the thread local error string in the thread that
called dlclose explicitly.

If any other thread had an error string associated with the thread
local, that will still be leaked.  I don't see any attractive way
to avoid that leak.

IOW, I think the fix is incomplete, but its better than nothing,
and I don't have suggestion to improve it.

> I don't actually think we have the bug you're describing.  We have a
> destructor (errors_free()) which runs on dlclose, which deletes the
> thread-local storage key, so the destructor will not run after the
> library has been unloaded.
> 
> I added a test for this which works fine for me:
> 
> https://gitlab.com/nbdkit/libnbd/-/commit/831d142787aba4f5b638418e02cf7e0f2a051565

Yes, I think your using of ELF destructor function is enough in this
scenario.

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




Incorrect NVMe DLFEAT?

2021-04-29 Thread Harris, James R
Hi,

I’m seeing SPDK test failures with QEMU NVMe controllers that I’ve bisected to 
QEMU commit 2605257a26 (“hw/block/nvme: add the dataset management command”).

The failing tests are related to write zeroes handling.  If an NVMe controller 
supports DSM, and DLFEAT indicates that deallocated blocks will read back as 
zeroes, then SPDK uses DEALLOCATE to implement the write zeroes operation.  
(Note: SPDK prefers this method to using NVMe WRITE_ZEROES, since the latter is 
limited to a 16-bit block count.)

QEMU sets DLFEAT = 0x9 – and actually set it to 0x9 even before this commit.  
Since the lower 3 bits are 0b001, it is reporting that deallocated blocks will 
read back later as 0.  This does not actually seem to be the case however – 
reading previously deallocated blocks do not actually return 0s.

It seems DLFEAT is being set incorrectly here – should probably be 0x8 instead?

Thanks,

Jim





[PATCH v2 5/6] virtio: Fail if iommu_platform is requested, but unsupported

2021-04-29 Thread Kevin Wolf
Commit 2943b53f6 (' virtio: force VIRTIO_F_IOMMU_PLATFORM') made sure
that vhost can't just reject VIRTIO_F_IOMMU_PLATFORM when it was
requested. However, just adding it back to the negotiated flags isn't
right either because it promises support to the guest that the device
actually doesn't support. One example of a vhost-user device that
doesn't have support for the flag is the vhost-user-blk export of QEMU.

Instead of successfully creating a device that doesn't work, just fail
to plug the device when it doesn't support the feature, but it was
requested. This results in much clearer error messages.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1935019
Signed-off-by: Kevin Wolf 
Reviewed-by: Raphael Norwitz 
---
 hw/virtio/virtio-bus.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index d6332d45c3..859978d248 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -69,6 +69,11 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error 
**errp)
 return;
 }
 
+if (has_iommu && !virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
+error_setg(errp, "iommu_platform=true is not supported by the device");
+return;
+}
+
 if (klass->device_plugged != NULL) {
 klass->device_plugged(qbus->parent, _err);
 }
-- 
2.30.2




libnbd thread-local errors and dlclose (was: Re: [ANNOUNCE] libblkio v0.1.0 preview release)

2021-04-29 Thread Richard W.M. Jones
On Thu, Apr 29, 2021 at 04:08:22PM +0100, Daniel P. Berrangé wrote:
> On Thu, Apr 29, 2021 at 04:00:38PM +0100, Richard W.M. Jones wrote:
> > On Thu, Apr 29, 2021 at 03:41:29PM +0100, Stefan Hajnoczi wrote:
> > > On Thu, Apr 29, 2021 at 03:22:59PM +0100, Richard W.M. Jones wrote:
> > > > libvirt originally, and now libnbd, keep a per-thread error message
> > > > (stored in thread-local storage).  It's a lot nicer than having to
> > > > pass  to every function.  You can just write:
> > > > 
> > > >  if (nbd_connect_tcp (nbd, "remote", "nbd") == -1) {
> > > >fprintf (stderr,
> > > > "failed to connect to remote server: %s (errno = %d)\n",
> > > > nbd_get_error (), nbd_get_errno ());
> > > >exit (EXIT_FAILURE);
> > > >  }
> > > > 
> > > > (https://libguestfs.org/libnbd.3.html#ERROR-HANDLING)
> > > > 
> > > > It means you can extend the range of error information available in
> > > > future.  Also you can return a 'const char *' and the application
> > > > doesn't have to worry about lifetimes, at least in the common case.
> > > 
> > > Thanks for sharing the idea, I think it would work well for libblkio
> > > too.
> > > 
> > > Do you ignore the dlclose(3) memory leak?
> > 
> > I believe this mechanism in libnbd ensures there is no leak in the
> > ordinary shared library (not dlopen/dlclose) case:
> > 
> > https://gitlab.com/nbdkit/libnbd/-/blob/f9257a9fdc68706a4079deb4ced61e1d468f28d6/lib/errors.c#L35
> > 
> > However I'm not sure what happens in the dlopen case, so I'm going to
> > test that out now ...
> 
> pthread_key destructors are a disaster waiting to happen with
> dlclose, if the dlclose happens while non-main threads are
> still running. When those threads exit, they'll run the
> destructor which points to a function that is no longer
> resident in memory.

While libnbd had a memory leak there, now fixed by:

https://gitlab.com/nbdkit/libnbd/-/commit/026d281c57dd95485cc9bf829918b5efd9e32ddb

I don't actually think we have the bug you're describing.  We have a
destructor (errors_free()) which runs on dlclose, which deletes the
thread-local storage key, so the destructor will not run after the
library has been unloaded.

I added a test for this which works fine for me:

https://gitlab.com/nbdkit/libnbd/-/commit/831d142787aba4f5b638418e02cf7e0f2a051565

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://libguestfs.org




Re: Incorrect NVMe DLFEAT?

2021-04-29 Thread Klaus Jensen

On Apr 29 16:51, Harris, James R wrote:

Hi,



Hi Jim,

I’m seeing SPDK test failures with QEMU NVMe controllers that I’ve 
bisected to QEMU commit 2605257a26 (“hw/block/nvme: add the dataset 
management command”).


The failing tests are related to write zeroes handling.  If an NVMe 
controller supports DSM, and DLFEAT indicates that deallocated blocks 
will read back as zeroes, then SPDK uses DEALLOCATE to implement the 
write zeroes operation.  (Note: SPDK prefers this method to using NVMe 
WRITE_ZEROES, since the latter is limited to a 16-bit block count.)




The Dataset Management command is advisory, the controller gives no 
guarantee that it will actually deallocate anything. You cannot use DSM 
as a realiable alternative to Write Zeroes. The QEMU emulated nvme 
device exploits this and in many cases wont deallocate anything if it 
does not fit nicely with the underlying block device setup.


QEMU sets DLFEAT = 0x9 – and actually set it to 0x9 even before this 
commit.  Since the lower 3 bits are 0b001, it is reporting that 
deallocated blocks will read back later as 0.  This does not actually 
seem to be the case however – reading previously deallocated blocks do 
not actually return 0s.




Can you share the configuration you use for QEMU? DSM works best with 
4096 byte LBAs (logical_block_size=4096) and the raw format driver.


Also, please test with the Error Recovery feature (and set DULBE) to 
test if the device reports that the block is actually deallocated.


It seems DLFEAT is being set incorrectly here – should probably be 0x8 
instead?


Thanks,

Jim





--
k



[PATCH v2 1/6] vhost-user-blk: Make sure to set Error on realize failure

2021-04-29 Thread Kevin Wolf
We have to set errp before jumping to virtio_err, otherwise the caller
(virtio_device_realize()) will take this as success and crash when it
later tries to access things that we've already freed in the error path.

Fixes: 77542d431491788d1e8e79d93ce10172ef207775
Signed-off-by: Kevin Wolf 
---
 hw/block/vhost-user-blk.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index f5e9682703..7c85248a7b 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -447,7 +447,6 @@ static void vhost_user_blk_device_realize(DeviceState *dev, 
Error **errp)
 {
 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 VHostUserBlk *s = VHOST_USER_BLK(vdev);
-Error *err = NULL;
 int i, ret;
 
 if (!s->chardev.chr) {
@@ -495,8 +494,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, 
Error **errp)
  NULL, true);
 
 reconnect:
-if (qemu_chr_fe_wait_connected(>chardev, ) < 0) {
-error_report_err(err);
+if (qemu_chr_fe_wait_connected(>chardev, errp) < 0) {
 goto virtio_err;
 }
 
-- 
2.30.2




Re: [PATCH 1/5] vhost-user-blk: Don't reconnect during initialisation

2021-04-29 Thread Raphael Norwitz
On Thu, Apr 29, 2021 at 02:48:52PM +0200, Kevin Wolf wrote:
> So maybe patch 2 should come first and also fix the preexisting bug, and
> of course this patch needs a v2 that doesn't introduce the new instances
> of the bug.

Sounds good to me.

> 
> Kevin
> 


[PATCH v2 2/6] vhost-user-blk: Don't reconnect during initialisation

2021-04-29 Thread Kevin Wolf
This is a partial revert of commits 77542d43149 and bc79c87bcde.

Usually, an error during initialisation means that the configuration was
wrong. Reconnecting won't make the error go away, but just turn the
error condition into an endless loop. Avoid this and return errors
again.

Additionally, calling vhost_user_blk_disconnect() from the chardev event
handler could result in use-after-free because none of the
initialisation code expects that the device could just go away in the
middle. So removing the call fixes crashes in several places.

For example, using a num-queues setting that is incompatible with the
backend would result in a crash like this (dereferencing dev->opaque,
which is already NULL):

 #0  0x55d0a4bd in vhost_user_read_cb (source=0x568f4690, 
condition=(G_IO_IN | G_IO_HUP), opaque=0x7fffcbf0) at 
../hw/virtio/vhost-user.c:313
 #1  0x55d950d3 in qio_channel_fd_source_dispatch 
(source=0x57c3f750, callback=0x55d0a478 , 
user_data=0x7fffcbf0) at ../io/channel-watch.c:84
 #2  0x77b32a9f in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
 #3  0x77b84a98 in g_main_context_iterate.constprop () at 
/lib64/libglib-2.0.so.0
 #4  0x77b32163 in g_main_loop_run () at /lib64/libglib-2.0.so.0
 #5  0x55d0a724 in vhost_user_read (dev=0x57bc62f8, 
msg=0x7fffcc50) at ../hw/virtio/vhost-user.c:402
 #6  0x55d0ee6b in vhost_user_get_config (dev=0x57bc62f8, 
config=0x57bc62ac "", config_len=60) at ../hw/virtio/vhost-user.c:2133
 #7  0x55d56d46 in vhost_dev_get_config (hdev=0x57bc62f8, 
config=0x57bc62ac "", config_len=60) at ../hw/virtio/vhost.c:1566
 #8  0x55cdd150 in vhost_user_blk_device_realize (dev=0x57bc60b0, 
errp=0x7fffcf90) at ../hw/block/vhost-user-blk.c:510
 #9  0x55d08f6d in virtio_device_realize (dev=0x57bc60b0, 
errp=0x7fffcff0) at ../hw/virtio/virtio.c:3660

Signed-off-by: Kevin Wolf 
---
 hw/block/vhost-user-blk.c | 59 +++
 1 file changed, 17 insertions(+), 42 deletions(-)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 7c85248a7b..c0b9958da1 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -50,6 +50,8 @@ static const int user_feature_bits[] = {
 VHOST_INVALID_FEATURE_BIT
 };
 
+static void vhost_user_blk_event(void *opaque, QEMUChrEvent event);
+
 static void vhost_user_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 {
 VHostUserBlk *s = VHOST_USER_BLK(vdev);
@@ -362,19 +364,6 @@ static void vhost_user_blk_disconnect(DeviceState *dev)
 vhost_dev_cleanup(>dev);
 }
 
-static void vhost_user_blk_event(void *opaque, QEMUChrEvent event,
- bool realized);
-
-static void vhost_user_blk_event_realize(void *opaque, QEMUChrEvent event)
-{
-vhost_user_blk_event(opaque, event, false);
-}
-
-static void vhost_user_blk_event_oper(void *opaque, QEMUChrEvent event)
-{
-vhost_user_blk_event(opaque, event, true);
-}
-
 static void vhost_user_blk_chr_closed_bh(void *opaque)
 {
 DeviceState *dev = opaque;
@@ -382,12 +371,11 @@ static void vhost_user_blk_chr_closed_bh(void *opaque)
 VHostUserBlk *s = VHOST_USER_BLK(vdev);
 
 vhost_user_blk_disconnect(dev);
-qemu_chr_fe_set_handlers(>chardev, NULL, NULL,
-vhost_user_blk_event_oper, NULL, opaque, NULL, true);
+qemu_chr_fe_set_handlers(>chardev, NULL, NULL, vhost_user_blk_event,
+ NULL, opaque, NULL, true);
 }
 
-static void vhost_user_blk_event(void *opaque, QEMUChrEvent event,
- bool realized)
+static void vhost_user_blk_event(void *opaque, QEMUChrEvent event)
 {
 DeviceState *dev = opaque;
 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -401,17 +389,7 @@ static void vhost_user_blk_event(void *opaque, 
QEMUChrEvent event,
 }
 break;
 case CHR_EVENT_CLOSED:
-/*
- * Closing the connection should happen differently on device
- * initialization and operation stages.
- * On initalization, we want to re-start vhost_dev initialization
- * from the very beginning right away when the connection is closed,
- * so we clean up vhost_dev on each connection closing.
- * On operation, we want to postpone vhost_dev cleanup to let the
- * other code perform its own cleanup sequence using vhost_dev data
- * (e.g. vhost_dev_set_log).
- */
-if (realized && !runstate_check(RUN_STATE_SHUTDOWN)) {
+if (!runstate_check(RUN_STATE_SHUTDOWN)) {
 /*
  * A close event may happen during a read/write, but vhost
  * code assumes the vhost_dev remains setup, so delay the
@@ -431,8 +409,6 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent 
event,
  * knowing its type (in this case vhost-user).
  */
 s->dev.started = 

[PATCH v2 3/6] vhost-user-blk: Improve error reporting in realize

2021-04-29 Thread Kevin Wolf
Now that vhost_user_blk_connect() is not called from an event handler
any more, but directly from vhost_user_blk_device_realize(), we can
actually make use of Error again instead of calling error_report() in
the inner function and setting a more generic and therefore less useful
error message in realize() itself.

With Error, the callers are responsible for adding context if necessary
(such as the "-device" option the error refers to). Additional prefixes
are redundant and better omitted.

Signed-off-by: Kevin Wolf 
Acked-by: Raphael Norwitz 
---
 hw/block/vhost-user-blk.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index c0b9958da1..f3a45af97c 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -311,7 +311,7 @@ static void vhost_user_blk_reset(VirtIODevice *vdev)
 vhost_dev_free_inflight(s->inflight);
 }
 
-static int vhost_user_blk_connect(DeviceState *dev)
+static int vhost_user_blk_connect(DeviceState *dev, Error **errp)
 {
 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 VHostUserBlk *s = VHOST_USER_BLK(vdev);
@@ -331,8 +331,7 @@ static int vhost_user_blk_connect(DeviceState *dev)
 
 ret = vhost_dev_init(>dev, >vhost_user, VHOST_BACKEND_TYPE_USER, 0);
 if (ret < 0) {
-error_report("vhost-user-blk: vhost initialization failed: %s",
- strerror(-ret));
+error_setg_errno(errp, -ret, "vhost initialization failed");
 return ret;
 }
 
@@ -340,8 +339,7 @@ static int vhost_user_blk_connect(DeviceState *dev)
 if (virtio_device_started(vdev, vdev->status)) {
 ret = vhost_user_blk_start(vdev);
 if (ret < 0) {
-error_report("vhost-user-blk: vhost start failed: %s",
- strerror(-ret));
+error_setg_errno(errp, -ret, "vhost start failed");
 return ret;
 }
 }
@@ -380,10 +378,12 @@ static void vhost_user_blk_event(void *opaque, 
QEMUChrEvent event)
 DeviceState *dev = opaque;
 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
 VHostUserBlk *s = VHOST_USER_BLK(vdev);
+Error *local_err = NULL;
 
 switch (event) {
 case CHR_EVENT_OPENED:
-if (vhost_user_blk_connect(dev) < 0) {
+if (vhost_user_blk_connect(dev, _err) < 0) {
+error_report_err(local_err);
 qemu_chr_fe_disconnect(>chardev);
 return;
 }
@@ -426,7 +426,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, 
Error **errp)
 int i, ret;
 
 if (!s->chardev.chr) {
-error_setg(errp, "vhost-user-blk: chardev is mandatory");
+error_setg(errp, "chardev is mandatory");
 return;
 }
 
@@ -434,16 +434,16 @@ static void vhost_user_blk_device_realize(DeviceState 
*dev, Error **errp)
 s->num_queues = 1;
 }
 if (!s->num_queues || s->num_queues > VIRTIO_QUEUE_MAX) {
-error_setg(errp, "vhost-user-blk: invalid number of IO queues");
+error_setg(errp, "invalid number of IO queues");
 return;
 }
 
 if (!s->queue_size) {
-error_setg(errp, "vhost-user-blk: queue size must be non-zero");
+error_setg(errp, "queue size must be non-zero");
 return;
 }
 if (s->queue_size > VIRTQUEUE_MAX_SIZE) {
-error_setg(errp, "vhost-user-blk: queue size must not exceed %d",
+error_setg(errp, "queue size must not exceed %d",
VIRTQUEUE_MAX_SIZE);
 return;
 }
@@ -469,8 +469,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, 
Error **errp)
 goto virtio_err;
 }
 
-if (vhost_user_blk_connect(dev) < 0) {
-error_setg(errp, "vhost-user-blk: could not connect");
+if (vhost_user_blk_connect(dev, errp) < 0) {
 qemu_chr_fe_disconnect(>chardev);
 goto virtio_err;
 }
-- 
2.30.2




[PATCH v2 0/6] vhost-user-blk: Error handling fixes during initialistion

2021-04-29 Thread Kevin Wolf
vhost-user-blk neglects for several properties to check whether the
configured value is even compatible with the backend. This results
sometimes in crashes because of buggy error handling code, and sometimes
in devices that are presented differently to the guest than the backend
would expect and that don't work properly therefore.

This series fixes some of these bugs.

v2:
- Fix error paths in realize() that didn't set errp
- Added vhost_dev_cleanup() back in the error path (more faithful revert
  of 77542d43149)

Kevin Wolf (6):
  vhost-user-blk: Make sure to set Error on realize failure
  vhost-user-blk: Don't reconnect during initialisation
  vhost-user-blk: Improve error reporting in realize
  vhost-user-blk: Get more feature flags from vhost device
  virtio: Fail if iommu_platform is requested, but unsupported
  vhost-user-blk: Check that num-queues is supported by backend

 include/hw/virtio/vhost.h |  2 +
 hw/block/vhost-user-blk.c | 85 ++-
 hw/virtio/vhost-user.c|  5 +++
 hw/virtio/virtio-bus.c|  5 +++
 4 files changed, 42 insertions(+), 55 deletions(-)

-- 
2.30.2




[PATCH v2 6/6] vhost-user-blk: Check that num-queues is supported by backend

2021-04-29 Thread Kevin Wolf
Creating a device with a number of queues that isn't supported by the
backend is pointless, the device won't work properly and the error
messages are rather confusing.

Just fail to create the device if num-queues is higher than what the
backend supports.

Since the relationship between num-queues and the number of virtqueues
depends on the specific device, this is an additional value that needs
to be initialised by the device. For convenience, allow leaving it 0 if
the check should be skipped. This makes sense for vhost-user-net where
separate vhost devices are used for the queues and custom initialisation
code is needed to perform the check.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1935031
Signed-off-by: Kevin Wolf 
Reviewed-by: Raphael Norwitz 
---
 include/hw/virtio/vhost.h | 2 ++
 hw/block/vhost-user-blk.c | 1 +
 hw/virtio/vhost-user.c| 5 +
 3 files changed, 8 insertions(+)

diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 4a8bc75415..21a9a52088 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -74,6 +74,8 @@ struct vhost_dev {
 int nvqs;
 /* the first virtqueue which would be used by this vhost dev */
 int vq_index;
+/* if non-zero, minimum required value for max_queues */
+int num_queues;
 uint64_t features;
 uint64_t acked_features;
 uint64_t backend_features;
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index c7e502f4c7..c6210fad0c 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -324,6 +324,7 @@ static int vhost_user_blk_connect(DeviceState *dev, Error 
**errp)
 }
 s->connected = true;
 
+s->dev.num_queues = s->num_queues;
 s->dev.nvqs = s->num_queues;
 s->dev.vqs = s->vhost_vqs;
 s->dev.vq_index = 0;
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index ded0c10453..ee57abe045 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1909,6 +1909,11 @@ static int vhost_user_backend_init(struct vhost_dev 
*dev, void *opaque)
 return err;
 }
 }
+if (dev->num_queues && dev->max_queues < dev->num_queues) {
+error_report("The maximum number of queues supported by the "
+ "backend is %" PRIu64, dev->max_queues);
+return -EINVAL;
+}
 
 if (virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM) &&
 !(virtio_has_feature(dev->protocol_features,
-- 
2.30.2




Re: [PATCH v4 0/3] nvdimm: Enable sync-dax property for nvdimm

2021-04-29 Thread Aneesh Kumar K.V

On 4/29/21 9:25 PM, Stefan Hajnoczi wrote:

On Wed, Apr 28, 2021 at 11:48:21PM -0400, Shivaprasad G Bhat wrote:

The nvdimm devices are expected to ensure write persistence during power
failure kind of scenarios.

The libpmem has architecture specific instructions like dcbf on POWER
to flush the cache data to backend nvdimm device during normal writes
followed by explicit flushes if the backend devices are not synchronous
DAX capable.

Qemu - virtual nvdimm devices are memory mapped. The dcbf in the guest
and the subsequent flush doesn't traslate to actual flush to the backend
file on the host in case of file backed v-nvdimms. This is addressed by
virtio-pmem in case of x86_64 by making explicit flushes translating to
fsync at qemu.

On SPAPR, the issue is addressed by adding a new hcall to
request for an explicit flush from the guest ndctl driver when the backend
nvdimm cannot ensure write persistence with dcbf alone. So, the approach
here is to convey when the hcall flush is required in a device tree
property. The guest makes the hcall when the property is found, instead
of relying on dcbf.


Sorry, I'm not very familiar with SPAPR. Why add a hypercall when the
virtio-nvdimm device already exists?



On virtualized ppc64 platforms, guests use papr_scm.ko kernel drive for 
persistent memory support. This was done such that we can use one kernel 
driver to support persistent memory with multiple hypervisors. To avoid 
supporting multiple drivers in the guest, -device nvdimm Qemu 
command-line results in Qemu using PAPR SCM backend. What this patch 
series does is to make sure we expose the correct synchronous fault 
support, when we back such nvdimm device with a file.


The existing PAPR SCM backend enables persistent memory support with the 
help of multiple hypercall.


#define H_SCM_READ_METADATA 0x3E4
#define H_SCM_WRITE_METADATA0x3E8
#define H_SCM_BIND_MEM  0x3EC
#define H_SCM_UNBIND_MEM0x3F0
#define H_SCM_UNBIND_ALL0x3FC

Most of them are already implemented in Qemu. This patch series 
implements H_SCM_FLUSH hypercall.





-aneesh




RE: [PATCH v2 04/15] target/ppc: Move DISAS_NORETURN setting into gen_exception*

2021-04-29 Thread Luis Fernando Fujita Pires
> > -static inline void gen_stop_exception(DisasContext *ctx)
> > +static inline void gen_end_tb_exception(DisasContext *ctx, uint32_t
> > +excp)
> >   {
> > -gen_update_nip(ctx, ctx->base.pc_next);
> > -ctx->exception = POWERPC_EXCP_STOP;
> > +/* No need to update nip for SYNC/BRANCH, as execution flow will change
> */
> > +if ((excp != POWERPC_EXCP_SYNC) &&
> > +(excp != POWERPC_EXCP_BRANCH))
> > +{
> > +gen_update_nip(ctx, ctx->base.pc_next);
> > +}
> > +ctx->exception = excp;
> > +ctx->base.is_jmp = DISAS_NORETURN;
> >   }
> 
> Hmm.  You didn't actually raise the exception, so you can't set
> DISAS_NORETURN that way.  It looks like you should be using
> gen_exception_nip().

This is reproducing the behavior that was implemented before the DISAS_NORETURN 
changes, that caused check-tcg to fail with an assertion otherwise.

IIUC, POWERPC_EXCP_{STOP,SYNC,BRANCH} are not really exceptions and, in these 
cases, ctx->exception is being used just to cause  ppc_tr_translate_insn() to 
end the translation block. If so, we should not be using ctx->exception for 
that, but I believe fixing that to not use ctx->exception belongs in a separate 
stand-alone patch.

> 
> And as side notes: (1) no need for extra parentheses, (2) brace is misplaced.
> 
> 
> r~


[PATCH v2 6/7] target/ttc: renamed SPR registration functions

2021-04-29 Thread Bruno Larsen (billionai)
Renamed all gen_spr_* and gen_* functions specifically related to
registering SPRs to register_*_sprs and register_*, to avoid future
confusion with other TCG related code.

Signed-off-by: Bruno Larsen (billionai) 
---
 target/ppc/translate_init.c.inc | 860 
 1 file changed, 430 insertions(+), 430 deletions(-)

diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index f470a8533e..b329e953cb 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -165,7 +165,7 @@ static inline void _spr_register(CPUPPCState *env, int num,
 }
 
 /* Generic PowerPC SPRs */
-static void gen_spr_generic(CPUPPCState *env)
+static void register_generic_sprs(CPUPPCState *env)
 {
 /* Integer processing */
 spr_register(env, SPR_XER, "XER",
@@ -210,7 +210,7 @@ static void gen_spr_generic(CPUPPCState *env)
 }
 
 /* SPR common to all non-embedded PowerPC, including 601 */
-static void gen_spr_ne_601(CPUPPCState *env)
+static void register_ne_601_sprs(CPUPPCState *env)
 {
 /* Exception processing */
 spr_register_kvm(env, SPR_DSISR, "DSISR",
@@ -229,7 +229,7 @@ static void gen_spr_ne_601(CPUPPCState *env)
 }
 
 /* Storage Description Register 1 */
-static void gen_spr_sdr1(CPUPPCState *env)
+static void register_sdr1_sprs(CPUPPCState *env)
 {
 #ifndef CONFIG_USER_ONLY
 if (env->has_hv_mode) {
@@ -252,7 +252,7 @@ static void gen_spr_sdr1(CPUPPCState *env)
 }
 
 /* BATs 0-3 */
-static void gen_low_BATs(CPUPPCState *env)
+static void register_low_BATs(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
 spr_register(env, SPR_IBAT0U, "IBAT0U",
@@ -324,7 +324,7 @@ static void gen_low_BATs(CPUPPCState *env)
 }
 
 /* BATs 4-7 */
-static void gen_high_BATs(CPUPPCState *env)
+static void register_high_BATs(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
 spr_register(env, SPR_IBAT4U, "IBAT4U",
@@ -396,7 +396,7 @@ static void gen_high_BATs(CPUPPCState *env)
 }
 
 /* Generic PowerPC time base */
-static void gen_tbl(CPUPPCState *env)
+static void register_tbl(CPUPPCState *env)
 {
 spr_register(env, SPR_VTBL,  "TBL",
  _read_tbl, SPR_NOACCESS,
@@ -417,7 +417,7 @@ static void gen_tbl(CPUPPCState *env)
 }
 
 /* Softare table search registers */
-static void gen_6xx_7xx_soft_tlb(CPUPPCState *env, int nb_tlbs, int nb_ways)
+static void register_6xx_7xx_soft_tlb(CPUPPCState *env, int nb_tlbs, int 
nb_ways)
 {
 #if !defined(CONFIG_USER_ONLY)
 env->nb_tlb = nb_tlbs;
@@ -456,7 +456,7 @@ static void gen_6xx_7xx_soft_tlb(CPUPPCState *env, int 
nb_tlbs, int nb_ways)
 }
 
 /* SPR common to MPC755 and G2 */
-static void gen_spr_G2_755(CPUPPCState *env)
+static void register_G2_755_sprs(CPUPPCState *env)
 {
 /* SGPRs */
 spr_register(env, SPR_SPRG4, "SPRG4",
@@ -478,7 +478,7 @@ static void gen_spr_G2_755(CPUPPCState *env)
 }
 
 /* SPR common to all 7xx PowerPC implementations */
-static void gen_spr_7xx(CPUPPCState *env)
+static void register_7xx_sprs(CPUPPCState *env)
 {
 /* Breakpoints */
 /* XXX : not implemented */
@@ -578,7 +578,7 @@ static void gen_spr_7xx(CPUPPCState *env)
 
 #ifdef TARGET_PPC64
 
-static void gen_spr_amr(CPUPPCState *env)
+static void register_amr_sprs(CPUPPCState *env)
 {
 #ifndef CONFIG_USER_ONLY
 /*
@@ -610,7 +610,7 @@ static void gen_spr_amr(CPUPPCState *env)
 #endif /* !CONFIG_USER_ONLY */
 }
 
-static void gen_spr_iamr(CPUPPCState *env)
+static void register_iamr_sprs(CPUPPCState *env)
 {
 #ifndef CONFIG_USER_ONLY
 spr_register_kvm_hv(env, SPR_IAMR, "IAMR",
@@ -622,7 +622,7 @@ static void gen_spr_iamr(CPUPPCState *env)
 }
 #endif /* TARGET_PPC64 */
 
-static void gen_spr_thrm(CPUPPCState *env)
+static void register_thrm_sprs(CPUPPCState *env)
 {
 /* Thermal management */
 /* XXX : not implemented */
@@ -643,7 +643,7 @@ static void gen_spr_thrm(CPUPPCState *env)
 }
 
 /* SPR specific to PowerPC 604 implementation */
-static void gen_spr_604(CPUPPCState *env)
+static void register_604_sprs(CPUPPCState *env)
 {
 /* Processor identification */
 spr_register(env, SPR_PIR, "PIR",
@@ -696,7 +696,7 @@ static void gen_spr_604(CPUPPCState *env)
 }
 
 /* SPR specific to PowerPC 603 implementation */
-static void gen_spr_603(CPUPPCState *env)
+static void register_603_sprs(CPUPPCState *env)
 {
 /* External access control */
 /* XXX : not implemented */
@@ -714,7 +714,7 @@ static void gen_spr_603(CPUPPCState *env)
 }
 
 /* SPR specific to PowerPC G2 implementation */
-static void gen_spr_G2(CPUPPCState *env)
+static void register_G2_sprs(CPUPPCState *env)
 {
 /* Memory base address */
 /* MBAR */
@@ -766,7 +766,7 @@ static void gen_spr_G2(CPUPPCState *env)
 }
 
 /* SPR specific to PowerPC 602 implementation */
-static void gen_spr_602(CPUPPCState *env)
+static void register_602_sprs(CPUPPCState *env)
 {
 /* ESA registers */
 /* XXX : not implemented */
@@ -814,7 +814,7 @@ static void gen_spr_602(CPUPPCState *env)
 }
 
 /* SPR specific 

[PATCH v2 5/7] target/ppc: removed VSCR from SPR registration

2021-04-29 Thread Bruno Larsen (billionai)
Since vscr is not an spr, its initialization was removed from the
spr registration functions, and moved to the relevant init_procs.

We may look into adding vscr to the reset path instead of the init
path (as suggested by David Gibson), but this looked like a good
enough solution for now.

Signed-off-by: Bruno Larsen (billionai) 
---
 target/ppc/translate_init.c.inc | 20 +---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index f809941c5e..f470a8533e 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -938,8 +938,6 @@ static void gen_spr_74xx(CPUPPCState *env)
  SPR_NOACCESS, SPR_NOACCESS,
  _read_generic, spr_access_nop,
  0x);
-/* Not strictly an SPR */
-vscr_init(env, 0x0001);
 }
 
 static void gen_l3_ctrl(CPUPPCState *env)
@@ -5787,6 +5785,7 @@ static void init_proc_7400(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* XXX : not implemented */
 spr_register(env, SPR_UBAMR, "UBAMR",
  _read_ureg, SPR_NOACCESS,
@@ -5866,6 +5865,7 @@ static void init_proc_7410(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* XXX : not implemented */
 spr_register(env, SPR_UBAMR, "UBAMR",
  _read_ureg, SPR_NOACCESS,
@@ -5951,6 +5951,7 @@ static void init_proc_7440(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* XXX : not implemented */
 spr_register(env, SPR_UBAMR, "UBAMR",
  _read_ureg, SPR_NOACCESS,
@@ -6059,6 +6060,7 @@ static void init_proc_7450(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* Level 3 cache control */
 gen_l3_ctrl(env);
 /* L3ITCR1 */
@@ -6193,6 +6195,7 @@ static void init_proc_7445(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* LDSTCR */
 /* XXX : not implemented */
 spr_register(env, SPR_LDSTCR, "LDSTCR",
@@ -6330,6 +6333,7 @@ static void init_proc_7455(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* Level 3 cache control */
 gen_l3_ctrl(env);
 /* LDSTCR */
@@ -6469,6 +6473,7 @@ static void init_proc_7457(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* Level 3 cache control */
 gen_l3_ctrl(env);
 /* L3ITCR1 */
@@ -6632,6 +6637,7 @@ static void init_proc_e600(CPUPPCState *env)
 gen_tbl(env);
 /* 74xx specific SPR */
 gen_spr_74xx(env);
+vscr_init(env, 0x0001);
 /* XXX : not implemented */
 spr_register(env, SPR_UBAMR, "UBAMR",
  _read_ureg, SPR_NOACCESS,
@@ -6830,11 +6836,6 @@ static void gen_spr_book3s_altivec(CPUPPCState *env)
  _read_generic, _write_generic,
  KVM_REG_PPC_VRSAVE, 0x);
 
-/*
- * Can't find information on what this should be on reset.  This
- * value is the one used by 74xx processors.
- */
-vscr_init(env, 0x0001);
 }
 
 static void gen_spr_book3s_dbg(CPUPPCState *env)
@@ -7454,6 +7455,11 @@ static void init_proc_book3s_common(CPUPPCState *env)
 gen_spr_book3s_pmu_sup(env);
 gen_spr_book3s_pmu_user(env);
 gen_spr_book3s_ctrl(env);
+/*
+ * Can't find information on what this should be on reset.  This
+ * value is the one used by 74xx processors.
+ */
+vscr_init(env, 0x0001);
 }
 
 static void init_proc_970(CPUPPCState *env)
-- 
2.17.1




[PATCH v2 2/7] target/ppc: Created !TCG SPR registration macro

2021-04-29 Thread Bruno Larsen (billionai)
Added macros for spr_register and spr_register_kvm that can
ignore SPR RW callbacks, in preparation to support building
without TCG.

Signed-off-by: Bruno Larsen (billionai) 
---
 target/ppc/translate_init.c.inc | 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index 6235eb7536..3ddcfefb62 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -720,6 +720,7 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val)
 helper_mtvscr(env, val);
 }
 
+#ifdef CONFIG_TCG
 #ifdef CONFIG_USER_ONLY
 #define spr_register_kvm(env, num, name, uea_read, uea_write,  
\
  oea_read, oea_write, one_reg_id, initial_value)   
\
@@ -728,7 +729,7 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val)
 oea_read, oea_write, hea_read, hea_write,  
\
 one_reg_id, initial_value) 
\
 _spr_register(env, num, name, uea_read, uea_write, initial_value)
-#else
+#else /*CONFIG_USER_ONLY */
 #if !defined(CONFIG_KVM)
 #define spr_register_kvm(env, num, name, uea_read, uea_write,  
\
  oea_read, oea_write, one_reg_id, initial_value)   
\
@@ -739,7 +740,7 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val)
 one_reg_id, initial_value) 
\
 _spr_register(env, num, name, uea_read, uea_write, 
\
   oea_read, oea_write, hea_read, hea_write, initial_value)
-#else
+#else /* CONFIG_KVM */
 #define spr_register_kvm(env, num, name, uea_read, uea_write,  
\
  oea_read, oea_write, one_reg_id, initial_value)   
\
 _spr_register(env, num, name, uea_read, uea_write, 
\
@@ -751,8 +752,21 @@ static inline void vscr_init(CPUPPCState *env, uint32_t 
val)
 _spr_register(env, num, name, uea_read, uea_write, 
\
   oea_read, oea_write, hea_read, hea_write,
\
   one_reg_id, initial_value)
-#endif
-#endif
+#endif /* CONFIG_KVM */
+#endif /* CONFIG_USER_ONLY */
+#else /* CONFIG_TCG */
+#ifdef CONFIG_KVM /* sanity check. should always enter this */
+#define spr_register_kvm(env, num, name, uea_read, uea_write,  
\
+ oea_read, oea_write, one_reg_id, initial_value)   
\
+_spr_register(env, num, name, one_reg_id, initial_value)
+#define spr_register_kvm_hv(env, num, name, uea_read, uea_write,   
\
+oea_read, oea_write, hea_read, hea_write,  
\
+one_reg_id, initial_value) 
\
+_spr_register(env, num, name, one_reg_id, initial_value)
+#else /* CONFIG_KVM */
+#error "Either TCG or KVM should be condigured"
+#endif /* CONFIG_KVM */
+#endif /* CONFIG_TCG */
 
 #define spr_register(env, num, name, uea_read, uea_write,  
\
  oea_read, oea_write, initial_value)   
\
-- 
2.17.1




[PATCH v2 7/7] target/ppc: isolated cpu init from translation logic

2021-04-29 Thread Bruno Larsen (billionai)
finished isolation of CPU initialization logic from
translation logic. CPU initialization now only has common code
which may or may not call accelerator-specific code, as the
build options require, and is compiled separately.

Signed-off-by: Bruno Larsen (billionai) 
---
 target/ppc/{translate_init.c.inc => cpu_init.c} | 12 +++-
 target/ppc/meson.build  |  1 +
 target/ppc/translate.c  |  4 +++-
 3 files changed, 15 insertions(+), 2 deletions(-)
 rename target/ppc/{translate_init.c.inc => cpu_init.c} (99%)

diff --git a/target/ppc/translate_init.c.inc b/target/ppc/cpu_init.c
similarity index 99%
rename from target/ppc/translate_init.c.inc
rename to target/ppc/cpu_init.c
index b329e953cb..f0f8fc481e 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/cpu_init.c
@@ -18,6 +18,7 @@
  * License along with this library; if not, see .
  */
 
+#include "qemu/osdep.h"
 #include "disas/dis-asm.h"
 #include "exec/gdbstub.h"
 #include "kvm_ppc.h"
@@ -42,6 +43,10 @@
 #include "fpu/softfloat.h"
 #include "qapi/qapi-commands-machine-target.h"
 
+#include "helper_regs.h"
+#include "internal.h"
+#include "spr_tcg.h"
+
 /* #define PPC_DEBUG_SPR */
 /* #define USE_APPLE_GDB */
 
@@ -49,7 +54,12 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val)
 {
 /* Altivec always uses round-to-nearest */
 set_float_rounding_mode(float_round_nearest_even, >vec_status);
-helper_mtvscr(env, val);
+/*
+ * This comment is here just so the project will build.
+ * The current solution is in another patch and will be
+ * added when we figure out an internal fork of qemu
+ */
+/* helper_mtvscr(env, val); */
 }
 
 #ifdef CONFIG_TCG
diff --git a/target/ppc/meson.build b/target/ppc/meson.build
index bbfef90e08..ad53629298 100644
--- a/target/ppc/meson.build
+++ b/target/ppc/meson.build
@@ -2,6 +2,7 @@ ppc_ss = ss.source_set()
 ppc_ss.add(files(
   'cpu-models.c',
   'cpu.c',
+  'cpu_init.c',
   'dfp_helper.c',
   'excp_helper.c',
   'fpu_helper.c',
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index a6e677fa6d..afb8a2aa27 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -38,6 +38,9 @@
 #include "qemu/atomic128.h"
 #include "internal.h"
 
+#include "qemu/qemu-print.h"
+#include "qapi/error.h"
+#include "internal.h"
 
 #define CPU_SINGLE_STEP 0x1
 #define CPU_BRANCH_STEP 0x2
@@ -7595,7 +7598,6 @@ GEN_HANDLER2_E(trechkpt, "trechkpt", 0x1F, 0x0E, 0x1F, 
0x03FFF800, \
 
 #include "helper_regs.h"
 #include "spr_tcg.c.inc"
-#include "translate_init.c.inc"
 
 /*/
 /* Misc PowerPC helpers */
-- 
2.17.1




[PATCH v2 1/7] target/ppc: move opcode table logic to translate.c

2021-04-29 Thread Bruno Larsen (billionai)
code motion to remove opcode callback table from
translate_init.c.inc to translate.c in preparation to remove
the #include  from translate.c. Also created
destroy_ppc_opcodes and removed that logic from ppc_cpu_unrealize

Signed-off-by: Bruno Larsen (billionai) 
---
 target/ppc/internal.h   |   8 +
 target/ppc/translate.c  | 394 
 target/ppc/translate_init.c.inc | 391 +--
 3 files changed, 403 insertions(+), 390 deletions(-)

diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index c401658e8d..184ba6d6b3 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -216,6 +216,14 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
  MMUAccessType access_type,
  int mmu_idx, uintptr_t retaddr);
 
+/* translate.c */
+
+/* #define PPC_DUMP_CPU */
+
+int ppc_fixup_cpu(PowerPCCPU *cpu);
+void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp);
+void destroy_ppc_opcodes(PowerPCCPU *cpu);
+
 /* gdbstub.c */
 void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
 gchar *ppc_gdb_arch_name(CPUState *cs);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0984ce637b..b319d409c6 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7825,6 +7825,400 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 #undef RFPL
 }
 
+/*/
+/* Opcode types */
+enum {
+PPC_DIRECT   = 0, /* Opcode routine*/
+PPC_INDIRECT = 1, /* Indirect opcode table */
+};
+
+#define PPC_OPCODE_MASK 0x3
+
+static inline int is_indirect_opcode(void *handler)
+{
+return ((uintptr_t)handler & PPC_OPCODE_MASK) == PPC_INDIRECT;
+}
+
+static inline opc_handler_t **ind_table(void *handler)
+{
+return (opc_handler_t **)((uintptr_t)handler & ~PPC_OPCODE_MASK);
+}
+
+/* Instruction table creation */
+/* Opcodes tables creation */
+static void fill_new_table(opc_handler_t **table, int len)
+{
+int i;
+
+for (i = 0; i < len; i++) {
+table[i] = _handler;
+}
+}
+
+static int create_new_table(opc_handler_t **table, unsigned char idx)
+{
+opc_handler_t **tmp;
+
+tmp = g_new(opc_handler_t *, PPC_CPU_INDIRECT_OPCODES_LEN);
+fill_new_table(tmp, PPC_CPU_INDIRECT_OPCODES_LEN);
+table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
+
+return 0;
+}
+
+static int insert_in_table(opc_handler_t **table, unsigned char idx,
+opc_handler_t *handler)
+{
+if (table[idx] != _handler) {
+return -1;
+}
+table[idx] = handler;
+
+return 0;
+}
+
+static int register_direct_insn(opc_handler_t **ppc_opcodes,
+unsigned char idx, opc_handler_t *handler)
+{
+if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
+printf("*** ERROR: opcode %02x already assigned in main "
+   "opcode table\n", idx);
+#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
+printf("   Registered handler '%s' - new handler '%s'\n",
+   ppc_opcodes[idx]->oname, handler->oname);
+#endif
+return -1;
+}
+
+return 0;
+}
+
+static int register_ind_in_table(opc_handler_t **table,
+ unsigned char idx1, unsigned char idx2,
+ opc_handler_t *handler)
+{
+if (table[idx1] == _handler) {
+if (create_new_table(table, idx1) < 0) {
+printf("*** ERROR: unable to create indirect table "
+   "idx=%02x\n", idx1);
+return -1;
+}
+} else {
+if (!is_indirect_opcode(table[idx1])) {
+printf("*** ERROR: idx %02x already assigned to a direct "
+   "opcode\n", idx1);
+#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
+printf("   Registered handler '%s' - new handler '%s'\n",
+   ind_table(table[idx1])[idx2]->oname, handler->oname);
+#endif
+return -1;
+}
+}
+if (handler != NULL &&
+insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
+printf("*** ERROR: opcode %02x already assigned in "
+   "opcode table %02x\n", idx2, idx1);
+#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
+printf("   Registered handler '%s' - new handler '%s'\n",
+   ind_table(table[idx1])[idx2]->oname, handler->oname);
+#endif
+return -1;
+}
+
+return 0;
+}
+
+static int register_ind_insn(opc_handler_t **ppc_opcodes,
+ unsigned char idx1, unsigned char idx2,
+ opc_handler_t *handler)
+{
+return register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
+}
+
+static int register_dblind_insn(opc_handler_t **ppc_opcodes,
+unsigned char idx1, unsigned char idx2,
+

[PATCH v2 4/7] target/ppc: turned SPR R/W callbacks not static

2021-04-29 Thread Bruno Larsen (billionai)
To be able to compile translate_init.c.inc as a standalone file,
we have to make the callbacks accessible outside of translate.c;
This patch does that, making the callbacks not static and creating
a new .h file

Signed-off-by: Bruno Larsen (billionai) 
---
 target/ppc/spr_tcg.c.inc | 203 ---
 target/ppc/spr_tcg.h | 121 +++
 2 files changed, 223 insertions(+), 101 deletions(-)
 create mode 100644 target/ppc/spr_tcg.h

diff --git a/target/ppc/spr_tcg.c.inc b/target/ppc/spr_tcg.c.inc
index 48274dd52b..2728c7246c 100644
--- a/target/ppc/spr_tcg.c.inc
+++ b/target/ppc/spr_tcg.c.inc
@@ -1,4 +1,5 @@
 #include "exec/translator.h"
+#include "spr_tcg.h"
 
 /*/
 /* Reader and writer functions for SPRs */
@@ -65,7 +66,7 @@ static void spr_load_dump_spr(int sprn)
 #endif
 }
 
-static void spr_read_generic(DisasContext *ctx, int gprn, int sprn)
+void spr_read_generic(DisasContext *ctx, int gprn, int sprn)
 {
 gen_load_spr(cpu_gpr[gprn], sprn);
 spr_load_dump_spr(sprn);
@@ -80,14 +81,14 @@ static void spr_store_dump_spr(int sprn)
 #endif
 }
 
-static void spr_write_generic(DisasContext *ctx, int sprn, int gprn)
+void spr_write_generic(DisasContext *ctx, int sprn, int gprn)
 {
 gen_store_spr(sprn, cpu_gpr[gprn]);
 spr_store_dump_spr(sprn);
 }
 
 #if !defined(CONFIG_USER_ONLY)
-static void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
+void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
 {
 #ifdef TARGET_PPC64
 TCGv t0 = tcg_temp_new();
@@ -100,7 +101,7 @@ static void spr_write_generic32(DisasContext *ctx, int 
sprn, int gprn)
 #endif
 }
 
-static void spr_write_clear(DisasContext *ctx, int sprn, int gprn)
+void spr_write_clear(DisasContext *ctx, int sprn, int gprn)
 {
 TCGv t0 = tcg_temp_new();
 TCGv t1 = tcg_temp_new();
@@ -112,7 +113,7 @@ static void spr_write_clear(DisasContext *ctx, int sprn, 
int gprn)
 tcg_temp_free(t1);
 }
 
-static void spr_access_nop(DisasContext *ctx, int sprn, int gprn)
+void spr_access_nop(DisasContext *ctx, int sprn, int gprn)
 {
 }
 
@@ -120,47 +121,47 @@ static void spr_access_nop(DisasContext *ctx, int sprn, 
int gprn)
 
 /* SPR common to all PowerPC */
 /* XER */
-static void spr_read_xer(DisasContext *ctx, int gprn, int sprn)
+void spr_read_xer(DisasContext *ctx, int gprn, int sprn)
 {
 gen_read_xer(ctx, cpu_gpr[gprn]);
 }
 
-static void spr_write_xer(DisasContext *ctx, int sprn, int gprn)
+void spr_write_xer(DisasContext *ctx, int sprn, int gprn)
 {
 gen_write_xer(cpu_gpr[gprn]);
 }
 
 /* LR */
-static void spr_read_lr(DisasContext *ctx, int gprn, int sprn)
+void spr_read_lr(DisasContext *ctx, int gprn, int sprn)
 {
 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_lr);
 }
 
-static void spr_write_lr(DisasContext *ctx, int sprn, int gprn)
+void spr_write_lr(DisasContext *ctx, int sprn, int gprn)
 {
 tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
 }
 
 /* CFAR */
 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
-static void spr_read_cfar(DisasContext *ctx, int gprn, int sprn)
+void spr_read_cfar(DisasContext *ctx, int gprn, int sprn)
 {
 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_cfar);
 }
 
-static void spr_write_cfar(DisasContext *ctx, int sprn, int gprn)
+void spr_write_cfar(DisasContext *ctx, int sprn, int gprn)
 {
 tcg_gen_mov_tl(cpu_cfar, cpu_gpr[gprn]);
 }
 #endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
 
 /* CTR */
-static void spr_read_ctr(DisasContext *ctx, int gprn, int sprn)
+void spr_read_ctr(DisasContext *ctx, int gprn, int sprn)
 {
 tcg_gen_mov_tl(cpu_gpr[gprn], cpu_ctr);
 }
 
-static void spr_write_ctr(DisasContext *ctx, int sprn, int gprn)
+void spr_write_ctr(DisasContext *ctx, int sprn, int gprn)
 {
 tcg_gen_mov_tl(cpu_ctr, cpu_gpr[gprn]);
 }
@@ -171,20 +172,20 @@ static void spr_write_ctr(DisasContext *ctx, int sprn, 
int gprn)
 /* UPMCx */
 /* USIA */
 /* UDECR */
-static void spr_read_ureg(DisasContext *ctx, int gprn, int sprn)
+void spr_read_ureg(DisasContext *ctx, int gprn, int sprn)
 {
 gen_load_spr(cpu_gpr[gprn], sprn + 0x10);
 }
 
 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
-static void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
+void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
 {
 gen_store_spr(sprn + 0x10, cpu_gpr[gprn]);
 }
 #endif
 
 #if !defined(CONFIG_USER_ONLY)
-static void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
+void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
 {
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
 gen_io_start();
@@ -195,7 +196,7 @@ static void spr_read_decr(DisasContext *ctx, int gprn, int 
sprn)
 }
 }
 
-static void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
+void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
 {
 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
 gen_io_start();
@@ -209,7 +210,7 @@ static void 

  1   2   3   >