Re: [PATCH 2/2] tests/acceptance/integratorcp: Verify Tux is displayed on framebuffer

2020-01-31 Thread Thomas Huth
On 31/01/2020 22.11, Philippe Mathieu-Daudé wrote:
> Add a test that verifies the Tux logo is displayed on the framebuffer.
> 
> We simply follow the OpenCV "Template Matching with Multiple Objects"
> tutorial, replacing Lionel Messi by Tux:
> https://docs.opencv.org/4.2.0/d4/dc6/tutorial_py_template_matching.html

What a cool idea :-)

If you like, there are some more images with Tux in the QEMU advent
calendar 2018 which you could use for testing the framebuffer:

 https://www.qemu-advent-calendar.org/2018/download/day13.tar.xz
 https://www.qemu-advent-calendar.org/2018/download/day15.tar.xz
 https://www.qemu-advent-calendar.org/2018/download/day16.tar.xz
 https://www.qemu-advent-calendar.org/2018/download/day19.tar.xz

These two use a slightly different tux:

 https://www.qemu-advent-calendar.org/2018/download/day09.tar.xz
 https://www.qemu-advent-calendar.org/2018/download/day11.tar.xz

And day 22 (MIPS64) and 23 (SPARC64) use a framebuffer, too, but they
seem to be broken with the current version from the git master branch.

 Thomas




Re: [PATCH 1/2] tests/acceptance: Extract boot_integratorcp() from test_integratorcp()

2020-01-31 Thread Thomas Huth
On 31/01/2020 22.11, Philippe Mathieu-Daudé wrote:
> As we want to re-use this code, extract it as a new function.
> Since we are using the PL011 serial console, add a Avocado tag
> to ease filtering of tests.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  tests/acceptance/machine_arm_integratorcp.py | 16 ++--
>  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/tests/acceptance/machine_arm_integratorcp.py 
> b/tests/acceptance/machine_arm_integratorcp.py
> index 4f9ab40f2f..748819916d 100644
> --- a/tests/acceptance/machine_arm_integratorcp.py
> +++ b/tests/acceptance/machine_arm_integratorcp.py
> @@ -19,12 +19,7 @@ class IntegratorMachine(Test):
>  
>  timeout = 90
>  
> -@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
> -def test_integratorcp(self):
> -"""
> -:avocado: tags=arch:arm
> -:avocado: tags=machine:integratorcp
> -"""
> +def boot_integratorcp(self):
>  kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
>'arm-test/kernel/zImage.integrator')
>  kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
> @@ -40,4 +35,13 @@ class IntegratorMachine(Test):
>   '-initrd', initrd_path,
>   '-append', 'printk.time=0 console=ttyAMA0')

I wonder whether you might want to move the "console=ttyAMA0" to the
test_integratorcp(), too, to get the text in the framebuffer in the
second test instead?

>  self.vm.launch()
> +
> +@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
> +def test_integratorcp(self):
> +"""
> +:avocado: tags=arch:arm
> +:avocado: tags=machine:integratorcp
> +:avocado: tags=device:pl011
> +"""
> +self.boot_integratorcp()
>  wait_for_console_pattern(self, 'Log in as root')
> 

Anyway, patch looks fine,

Reviewed-by: Thomas Huth 




[PATCH v3] target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none

2020-01-31 Thread Liang Yan
Commit e19afd56 mentioned that target-arm only supports queryable
cpu models 'max', 'host', and the current type when KVM is in use.
The logic works well until using machine type none.

For machine type none, cpu_type will be null if cpu option is not
set by command line, strlen(cpu_type) will terminate process.
So We add a check above it.

This won't affect i386 and s390x since they do not use current_cpu.

Signed-off-by: Liang Yan 
---
 v3: change git commit message
 v2: fix code style issue
---
 target/arm/monitor.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 9725dfff16..3350cd65d0 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -137,17 +137,19 @@ CpuModelExpansionInfo 
*qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 }
 
 if (kvm_enabled()) {
-const char *cpu_type = current_machine->cpu_type;
-int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
 bool supported = false;
 
 if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
 /* These are kvmarm's recommended cpu types */
 supported = true;
-} else if (strlen(model->name) == len &&
-   !strncmp(model->name, cpu_type, len)) {
-/* KVM is enabled and we're using this type, so it works. */
-supported = true;
+} else if (current_machine->cpu_type) {
+const char *cpu_type = current_machine->cpu_type;
+int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
+if (strlen(model->name) == len &&
+!strncmp(model->name, cpu_type, len)) {
+/* KVM is enabled and we're using this type, so it works. */
+supported = true;
+}
 }
 if (!supported) {
 error_setg(errp, "We cannot guarantee the CPU type '%s' works "
-- 
2.25.0




[Bug 1859291] Re: RISC-V incorrect exception generated

2020-01-31 Thread Alistair Francis
Do you have steps to reproduce this?

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

Title:
  RISC-V incorrect exception generated

Status in QEMU:
  New

Bug description:
  When using 'ecall' from supervisor mode, user exception is raised
  instead of supervisor exception. The problem is located under
  'target/riscv/insn_trans/trans_priviledged.inc.c' in function 'static
  bool trans_ecall(DisasContext *ctx, arg_ecall *a)'. Best regards,
  Serge Teodori

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



Re: [Bug 1859291] [NEW] RISC-V incorrect exception generated

2020-01-31 Thread Alistair Francis
Do you have steps to reproduce this?

Alistair

On Sat, Jan 11, 2020 at 8:25 AM Teodori Serge  wrote:
>
> Public bug reported:
>
> When using 'ecall' from supervisor mode, user exception is raised
> instead of supervisor exception. The problem is located under
> 'target/riscv/insn_trans/trans_priviledged.inc.c' in function 'static
> bool trans_ecall(DisasContext *ctx, arg_ecall *a)'. Best regards, Serge
> Teodori
>
> ** Affects: qemu
>  Importance: Undecided
>  Status: New
>
>
> ** Tags: risc-v
>
> --
> You received this bug notification because you are a member of qemu-
> devel-ml, which is subscribed to QEMU.
> https://bugs.launchpad.net/bugs/1859291
>
> Title:
>   RISC-V incorrect exception generated
>
> Status in QEMU:
>   New
>
> Bug description:
>   When using 'ecall' from supervisor mode, user exception is raised
>   instead of supervisor exception. The problem is located under
>   'target/riscv/insn_trans/trans_priviledged.inc.c' in function 'static
>   bool trans_ecall(DisasContext *ctx, arg_ecall *a)'. Best regards,
>   Serge Teodori
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/qemu/+bug/1859291/+subscriptions
>



[PATCH v2 30/35] target/riscv: Implement second stage MMU

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.h|   1 +
 target/riscv/cpu_helper.c | 193 ++
 2 files changed, 175 insertions(+), 19 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index aa04e5cca7..a8534fdf2b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -104,6 +104,7 @@ struct CPURISCVState {
 target_ulong frm;
 
 target_ulong badaddr;
+target_ulong guest_phys_fault_addr;
 
 target_ulong priv_ver;
 target_ulong misa;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index cd2d9341b9..5f96631637 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -285,11 +285,12 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
newpriv)
  * @mmu_idx: Indicates current privilege level
  * @first_stage: Are we in first stage translation?
  *   Second stage is used for hypervisor guest translation
+ * @two_stage: Are we going to perform two stage translation
  */
 static int get_physical_address(CPURISCVState *env, hwaddr *physical,
 int *prot, target_ulong addr,
 int access_type, int mmu_idx,
-bool first_stage)
+bool first_stage, bool two_stage)
 {
 /* NOTE: the env->pc value visible here will not be
  * correct, but the value visible to the exception handler
@@ -297,13 +298,40 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 MemTxResult res;
 MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
 int mode = mmu_idx;
+bool use_background = false;
 
+/*
+ * Check if we should use the background registers for the two
+ * stage translation. We don't need to check if we actually need
+ * two stage translation as that happened before this function
+ * was called. Background registers will be used if the guest has
+ * forced a two stage translation to be on (in HS or M mode).
+ */
 if (mode == PRV_M && access_type != MMU_INST_FETCH) {
 if (get_field(env->mstatus, MSTATUS_MPRV)) {
 mode = get_field(env->mstatus, MSTATUS_MPP);
+
+if (riscv_has_ext(env, RVH) &&
+get_field(env->mstatus, MSTATUS_MPV)) {
+use_background = true;
+}
+}
+}
+
+if (mode == PRV_S && access_type != MMU_INST_FETCH &&
+riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) {
+if (get_field(env->hstatus, HSTATUS_SPRV)) {
+mode = get_field(env->mstatus, SSTATUS_SPP);
+use_background = true;
 }
 }
 
+if (first_stage == false) {
+/* We are in stage 2 translation, this is similar to stage 1. */
+/* Stage 2 is always taken as U-mode */
+mode = PRV_U;
+}
+
 if (mode == PRV_M || !riscv_feature(env, RISCV_FEATURE_MMU)) {
 *physical = addr;
 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
@@ -313,13 +341,30 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 *prot = 0;
 
 hwaddr base;
-int levels, ptidxbits, ptesize, vm, sum;
-int mxr = get_field(env->mstatus, MSTATUS_MXR);
+int levels, ptidxbits, ptesize, vm, sum, mxr, widened;
+
+if (first_stage == true) {
+mxr = get_field(env->mstatus, MSTATUS_MXR);
+} else {
+mxr = get_field(env->vsstatus, MSTATUS_MXR);
+}
 
 if (env->priv_ver >= PRIV_VERSION_1_10_0) {
-base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
+if (first_stage == true) {
+if (use_background) {
+base = (hwaddr)get_field(env->vsatp, SATP_PPN) << PGSHIFT;
+vm = get_field(env->vsatp, SATP_MODE);
+} else {
+base = (hwaddr)get_field(env->satp, SATP_PPN) << PGSHIFT;
+vm = get_field(env->satp, SATP_MODE);
+}
+widened = 0;
+} else {
+base = (hwaddr)get_field(env->hgatp, HGATP_PPN) << PGSHIFT;
+vm = get_field(env->hgatp, HGATP_MODE);
+widened = 2;
+}
 sum = get_field(env->mstatus, MSTATUS_SUM);
-vm = get_field(env->satp, SATP_MODE);
 switch (vm) {
 case VM_1_10_SV32:
   levels = 2; ptidxbits = 10; ptesize = 4; break;
@@ -337,6 +382,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr 
*physical,
   g_assert_not_reached();
 }
 } else {
+widened = 0;
 base = (hwaddr)(env->sptbr) << PGSHIFT;
 sum = !get_field(env->mstatus, MSTATUS_PUM);
 vm = get_field(env->mstatus, MSTATUS_VM);
@@ -357,9 +403,16 @@ static int get_physical_address(CPURISCVState *env, hwaddr 
*physical,
 }
 
 CPUState *cs = env_cpu(env);
-int va_bits = PGSHIFT + levels * ptidxbits;
-target_ulong mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
-   

[PATCH v2 28/35] target/riscv: Respect MPRV and SPRV for floating point ops

2020-01-31 Thread Alistair Francis
mark_fs_dirty() is the only place in translate.c that uses the
virt_enabled bool. Let's respect the contents of MSTATUS.MPRV and
HSTATUS.SPRV when setting the bool as this is used for performing
floating point operations when V=0.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/translate.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 61fe9f03be..240fd7c971 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -748,7 +748,21 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
 ctx->priv_ver = env->priv_ver;
 #if !defined(CONFIG_USER_ONLY)
-ctx->virt_enabled = riscv_cpu_virt_enabled(env);
+if (riscv_has_ext(env, RVH)) {
+ctx->virt_enabled = riscv_cpu_virt_enabled(env);
+if (env->priv_ver == PRV_M &&
+get_field(env->mstatus, MSTATUS_MPRV) &&
+get_field(env->mstatus, MSTATUS_MPV)) {
+ctx->virt_enabled = true;
+} else if (env->priv == PRV_S &&
+   !riscv_cpu_virt_enabled(env) &&
+   get_field(env->hstatus, HSTATUS_SPRV) &&
+   get_field(env->hstatus, HSTATUS_SPV)) {
+ctx->virt_enabled = true;
+}
+} else {
+ctx->virt_enabled = false;
+}
 #else
 ctx->virt_enabled = false;
 #endif
-- 
2.25.0




[PATCH v2 35/35] target/riscv: Allow enabling the Hypervisor extension

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.c | 5 +
 target/riscv/cpu.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b27066f6a7..c47d10b739 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -453,6 +453,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 if (cpu->cfg.ext_u) {
 target_misa |= RVU;
 }
+if (cpu->cfg.ext_h) {
+target_misa |= RVH;
+}
 
 set_misa(env, RVXLEN | target_misa);
 }
@@ -488,6 +491,8 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true),
 DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
 DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
+/* This is experimental so mark with 'x-' */
+DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
 DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6f9c29322a..d52f209361 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -258,6 +258,7 @@ typedef struct RISCVCPU {
 bool ext_c;
 bool ext_s;
 bool ext_u;
+bool ext_h;
 bool ext_counters;
 bool ext_ifencei;
 bool ext_icsr;
-- 
2.25.0




[PATCH v2 27/35] target/riscv: Mark both sstatus and msstatus_hs as dirty

2020-01-31 Thread Alistair Francis
Mark both sstatus and vsstatus as dirty (3).

Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index afa2d6eea2..61fe9f03be 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -44,6 +44,7 @@ typedef struct DisasContext {
 /* pc_succ_insn points to the instruction following base.pc_next */
 target_ulong pc_succ_insn;
 target_ulong priv_ver;
+bool virt_enabled;
 uint32_t opcode;
 uint32_t mstatus_fs;
 uint32_t misa;
@@ -396,6 +397,12 @@ static void mark_fs_dirty(DisasContext *ctx)
 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
 tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | MSTATUS_SD);
 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
+
+if (ctx->virt_enabled) {
+tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | MSTATUS_SD);
+tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
+}
 tcg_temp_free(tmp);
 }
 #else
@@ -740,6 +747,11 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->mem_idx = ctx->base.tb->flags & TB_FLAGS_MMU_MASK;
 ctx->mstatus_fs = ctx->base.tb->flags & TB_FLAGS_MSTATUS_FS;
 ctx->priv_ver = env->priv_ver;
+#if !defined(CONFIG_USER_ONLY)
+ctx->virt_enabled = riscv_cpu_virt_enabled(env);
+#else
+ctx->virt_enabled = false;
+#endif
 ctx->misa = env->misa;
 ctx->frm = -1;  /* unknown rounding mode */
 ctx->ext_ifencei = cpu->cfg.ext_ifencei;
-- 
2.25.0




[PATCH v2 33/35] target/riscv: Add support for the 32-bit MSTATUSH CSR

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c|  3 +++
 target/riscv/cpu.h| 10 ++
 target/riscv/cpu_bits.h   |  3 +++
 target/riscv/cpu_helper.c | 17 +
 target/riscv/csr.c| 25 +
 target/riscv/op_helper.c  |  4 
 6 files changed, 62 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 44ad768a84..b27066f6a7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -237,6 +237,9 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 #ifndef CONFIG_USER_ONLY
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
+#ifdef TARGET_RISCV32
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", env->mstatush);
+#endif
 if (riscv_has_ext(env, RVH)) {
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a8534fdf2b..6f9c29322a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -127,6 +127,10 @@ struct CPURISCVState {
 
 target_ulong mip;
 
+#ifdef TARGET_RISCV32
+target_ulong mstatush;
+#endif
+
 uint32_t miclaim;
 
 target_ulong mie;
@@ -164,6 +168,9 @@ struct CPURISCVState {
 target_ulong vscause;
 target_ulong vstval;
 target_ulong vsatp;
+#ifdef TARGET_RISCV32
+target_ulong vsstatush;
+#endif
 
 target_ulong mtval2;
 target_ulong mtinst;
@@ -176,6 +183,9 @@ struct CPURISCVState {
 target_ulong stval_hs;
 target_ulong satp_hs;
 target_ulong mstatus_hs;
+#ifdef TARGET_RISCV32
+target_ulong mstatush_hs;
+#endif
 
 target_ulong scounteren;
 target_ulong mcounteren;
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index a24654d137..049032f2ae 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -135,6 +135,9 @@
 #define CSR_MTVEC   0x305
 #define CSR_MCOUNTEREN  0x306
 
+/* 32-bit only */
+#define CSR_MSTATUSH0x310
+
 /* Legacy Counter Setup (priv v1.9.1) */
 /* Update to #define CSR_MCOUNTINHIBIT 0x320 for 1.11.0 */
 #define CSR_MUCOUNTEREN 0x320
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 10786a077b..e04545adf7 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -126,6 +126,11 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
 env->mstatus &= ~mstatus_mask;
 env->mstatus |= env->mstatus_hs;
 
+#if defined(TARGET_RISCV32)
+env->vsstatush = env->mstatush;
+env->mstatush |= env->mstatush_hs;
+#endif
+
 env->vstvec = env->stvec;
 env->stvec = env->stvec_hs;
 
@@ -149,6 +154,11 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
 env->mstatus &= ~mstatus_mask;
 env->mstatus |= env->vsstatus;
 
+#if defined(TARGET_RISCV32)
+env->mstatush_hs = env->mstatush;
+env->mstatush |= env->vsstatush;
+#endif
+
 env->stvec_hs = env->stvec;
 env->stvec = env->vstvec;
 
@@ -937,10 +947,17 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 if (riscv_cpu_virt_enabled(env)) {
 riscv_cpu_swap_hypervisor_regs(env);
 }
+#ifdef TARGET_RISCV32
+env->mstatush = set_field(env->mstatush, MSTATUS_MPV,
+   riscv_cpu_virt_enabled(env));
+env->mstatush = set_field(env->mstatush, MSTATUS_MTL,
+   riscv_cpu_force_hs_excep_enabled(env));
+#else
 env->mstatus = set_field(env->mstatus, MSTATUS_MPV,
   riscv_cpu_virt_enabled(env));
 env->mstatus = set_field(env->mstatus, MSTATUS_MTL,
   riscv_cpu_force_hs_excep_enabled(env));
+#endif
 
 mtval2 = env->guest_phys_fault_addr;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 2e6700bbeb..572a478e8c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -371,6 +371,27 @@ static int write_mstatus(CPURISCVState *env, int csrno, 
target_ulong val)
 return 0;
 }
 
+#ifdef TARGET_RISCV32
+static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->mstatush;
+return 0;
+}
+
+static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val)
+{
+if ((val ^ env->mstatush) & (MSTATUS_MPV)) {
+tlb_flush(env_cpu(env));
+}
+
+val &= MSTATUS_MPV | MSTATUS_MTL;
+
+env->mstatush = val;
+
+return 0;
+}
+#endif
+
 static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
 {
 *val = env->misa;
@@ -1214,6 +1235,10 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MTVEC] =   { any,  read_mtvec,   write_mtvec   },
 [CSR_MCOUNTEREN] =  { any,  read_mcounteren,  

[PATCH v2 26/35] target/riscv: Disable guest FP support based on virtual status

2020-01-31 Thread Alistair Francis
When the Hypervisor extension is in use we only enable floating point
support when both status and vsstatus have enabled floating point
support.

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

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index e7728cb0ca..827a38324c 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -99,6 +99,9 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int 
interrupt_request)
 bool riscv_cpu_fp_enabled(CPURISCVState *env)
 {
 if (env->mstatus & MSTATUS_FS) {
+if (riscv_cpu_virt_enabled(env) && !(env->mstatus_hs & MSTATUS_FS)) {
+return false;
+}
 return true;
 }
 
-- 
2.25.0




[PATCH v2 31/35] target/riscv: Raise the new execptions when 2nd stage translation fails

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu_helper.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 5f96631637..da994aba57 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -585,16 +585,28 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 }
 switch (access_type) {
 case MMU_INST_FETCH:
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+if (riscv_cpu_virt_enabled(env) && !first_stage) {
+cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
+} else {
+cs->exception_index = page_fault_exceptions ?
+RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+}
 break;
 case MMU_DATA_LOAD:
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+if (riscv_cpu_virt_enabled(env) && !first_stage) {
+cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
+} else {
+cs->exception_index = page_fault_exceptions ?
+RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+}
 break;
 case MMU_DATA_STORE:
-cs->exception_index = page_fault_exceptions ?
-RISCV_EXCP_STORE_PAGE_FAULT : RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+if (riscv_cpu_virt_enabled(env) && !first_stage) {
+cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
+} else {
+cs->exception_index = page_fault_exceptions ?
+RISCV_EXCP_STORE_PAGE_FAULT : 
RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+}
 break;
 default:
 g_assert_not_reached();
-- 
2.25.0




[PATCH v2 29/35] target/riscv: Allow specifying MMU stage

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu_helper.c | 37 -
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 827a38324c..cd2d9341b9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -277,10 +277,19 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
newpriv)
  *
  * Adapted from Spike's mmu_t::translate and mmu_t::walk
  *
+ * @env: CPURISCVState
+ * @physical: This will be set to the calculated physical address
+ * @prot: The returned protection attributes
+ * @addr: The virtual address to be translated
+ * @access_type: The type of MMU access
+ * @mmu_idx: Indicates current privilege level
+ * @first_stage: Are we in first stage translation?
+ *   Second stage is used for hypervisor guest translation
  */
 static int get_physical_address(CPURISCVState *env, hwaddr *physical,
 int *prot, target_ulong addr,
-int access_type, int mmu_idx)
+int access_type, int mmu_idx,
+bool first_stage)
 {
 /* NOTE: the env->pc value visible here will not be
  * correct, but the value visible to the exception handler
@@ -483,13 +492,21 @@ restart:
 }
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
-MMUAccessType access_type, bool pmp_violation)
+MMUAccessType access_type, bool pmp_violation,
+bool first_stage)
 {
 CPUState *cs = env_cpu(env);
-int page_fault_exceptions =
-(env->priv_ver >= PRIV_VERSION_1_10_0) &&
-get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
-!pmp_violation;
+int page_fault_exceptions;
+if (first_stage) {
+page_fault_exceptions =
+(env->priv_ver >= PRIV_VERSION_1_10_0) &&
+get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
+!pmp_violation;
+} else {
+page_fault_exceptions =
+get_field(env->hgatp, HGATP_MODE) != VM_1_10_MBARE &&
+!pmp_violation;
+}
 switch (access_type) {
 case MMU_INST_FETCH:
 cs->exception_index = page_fault_exceptions ?
@@ -516,7 +533,8 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr 
addr)
 int prot;
 int mmu_idx = cpu_mmu_index(>env, false);
 
-if (get_physical_address(>env, _addr, , addr, 0, mmu_idx)) {
+if (get_physical_address(>env, _addr, , addr, 0, mmu_idx,
+ true)) {
 return -1;
 }
 return phys_addr;
@@ -581,7 +599,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
   __func__, address, access_type, mmu_idx);
 
-ret = get_physical_address(env, , , address, access_type, mmu_idx);
+ret = get_physical_address(env, , , address, access_type, mmu_idx,
+   true);
 
 if (mode == PRV_M && access_type != MMU_INST_FETCH) {
 if (get_field(env->mstatus, MSTATUS_MPRV)) {
@@ -608,7 +627,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 } else if (probe) {
 return false;
 } else {
-raise_mmu_exception(env, address, access_type, pmp_violation);
+raise_mmu_exception(env, address, access_type, pmp_violation, true);
 riscv_raise_exception(env, cs->exception_index, retaddr);
 }
 #else
-- 
2.25.0




[PATCH v2 24/35] target/riscv: Remove the hret instruction

2020-01-31 Thread Alistair Francis
The hret instruction does not exist in the new spec versions, so remove
it from QEMU.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/insn32.decode | 1 -
 target/riscv/insn_trans/trans_privileged.inc.c | 5 -
 2 files changed, 6 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index cfd9ca6d2b..b883672e63 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -75,7 +75,6 @@ ecall    0 000 0 1110011
 ebreak  0001 0 000 0 1110011
 uret00000010 0 000 0 1110011
 sret000100000010 0 000 0 1110011
-hret00100010 0 000 0 1110011
 mret001100000010 0 000 0 1110011
 wfi 000100000101 0 000 0 1110011
 hfence_gvma 0110001. . 000 0 1110011 @hfence_gvma
diff --git a/target/riscv/insn_trans/trans_privileged.inc.c 
b/target/riscv/insn_trans/trans_privileged.inc.c
index b9b5a89b52..76c2fad71c 100644
--- a/target/riscv/insn_trans/trans_privileged.inc.c
+++ b/target/riscv/insn_trans/trans_privileged.inc.c
@@ -58,11 +58,6 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
 #endif
 }
 
-static bool trans_hret(DisasContext *ctx, arg_hret *a)
-{
-return false;
-}
-
 static bool trans_mret(DisasContext *ctx, arg_mret *a)
 {
 #ifndef CONFIG_USER_ONLY
-- 
2.25.0




[PATCH v2 23/35] target/riscv: Add hfence instructions

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/insn32.decode| 23 ++-
 .../riscv/insn_trans/trans_privileged.inc.c   | 40 +++
 2 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 77f794ed70..cfd9ca6d2b 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -63,20 +63,25 @@
 @r2_rm   ...   . . ... . ... %rs1 %rm %rd
 @r2  ...   . . ... . ... %rs1 %rd
 
+@hfence_gvma ... . .   ... . ... %rs2 %rs1
+@hfence_bvma ... . .   ... . ... %rs2 %rs1
+
 @sfence_vma ... . .   ... . ... %rs2 %rs1
 @sfence_vm  ... . .   ... . ... %rs1
 
 
 # *** Privileged Instructions ***
-ecall   0 000 0 1110011
-ebreak 0001 0 000 0 1110011
-uret   00000010 0 000 0 1110011
-sret   000100000010 0 000 0 1110011
-hret   00100010 0 000 0 1110011
-mret   001100000010 0 000 0 1110011
-wfi000100000101 0 000 0 1110011
-sfence_vma 0001001. . 000 0 1110011 @sfence_vma
-sfence_vm  000100000100 . 000 0 1110011 @sfence_vm
+ecall    0 000 0 1110011
+ebreak  0001 0 000 0 1110011
+uret00000010 0 000 0 1110011
+sret000100000010 0 000 0 1110011
+hret00100010 0 000 0 1110011
+mret001100000010 0 000 0 1110011
+wfi 000100000101 0 000 0 1110011
+hfence_gvma 0110001. . 000 0 1110011 @hfence_gvma
+hfence_bvma 0010001. . 000 0 1110011 @hfence_bvma
+sfence_vma  0001001. . 000 0 1110011 @sfence_vma
+sfence_vm   000100000100 . 000 0 1110011 @sfence_vm
 
 # *** RV32I Base Instruction Set ***
 lui     . 0110111 @u
diff --git a/target/riscv/insn_trans/trans_privileged.inc.c 
b/target/riscv/insn_trans/trans_privileged.inc.c
index c5e4b3e49a..b9b5a89b52 100644
--- a/target/riscv/insn_trans/trans_privileged.inc.c
+++ b/target/riscv/insn_trans/trans_privileged.inc.c
@@ -108,3 +108,43 @@ static bool trans_sfence_vm(DisasContext *ctx, 
arg_sfence_vm *a)
 #endif
 return false;
 }
+
+static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
+{
+#ifndef CONFIG_USER_ONLY
+if (ctx->priv_ver >= PRIV_VERSION_1_10_0 &&
+has_ext(ctx, RVH)) {
+/* Hpervisor extensions exist */
+/*
+ * if (env->priv == PRV_M ||
+ *   (env->priv == PRV_S &&
+ *!riscv_cpu_virt_enabled(env) &&
+ *get_field(ctx->mstatus_fs, MSTATUS_TVM))) {
+ */
+gen_helper_tlb_flush(cpu_env);
+return true;
+/* } */
+}
+#endif
+return false;
+}
+
+static bool trans_hfence_bvma(DisasContext *ctx, arg_sfence_vma *a)
+{
+#ifndef CONFIG_USER_ONLY
+if (ctx->priv_ver >= PRIV_VERSION_1_10_0 &&
+has_ext(ctx, RVH)) {
+/* Hpervisor extensions exist */
+/*
+ * if (env->priv == PRV_M ||
+ *   (env->priv == PRV_S &&
+ *!riscv_cpu_virt_enabled(env) &&
+ *get_field(ctx->mstatus_fs, MSTATUS_TVM))) {
+ */
+gen_helper_tlb_flush(cpu_env);
+return true;
+/* } */
+}
+#endif
+return false;
+}
-- 
2.25.0




[PATCH v2 20/35] target/riscv: Generate illegal instruction on WFI when V=1

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/op_helper.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index e87c9115bc..455eb28907 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -130,9 +130,10 @@ void helper_wfi(CPURISCVState *env)
 {
 CPUState *cs = env_cpu(env);
 
-if (env->priv == PRV_S &&
+if ((env->priv == PRV_S &&
 env->priv_ver >= PRIV_VERSION_1_10_0 &&
-get_field(env->mstatus, MSTATUS_TW)) {
+get_field(env->mstatus, MSTATUS_TW)) ||
+riscv_cpu_virt_enabled(env)) {
 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
 } else {
 cs->halted = 1;
-- 
2.25.0




[PATCH v2 16/35] target/riscv: Extend the MIE CSR to support virtulisation

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/csr.c | 24 
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index c0e942684d..918678789a 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -244,8 +244,10 @@ static int read_timeh(CPURISCVState *env, int csrno, 
target_ulong *val)
 #define S_MODE_INTERRUPTS  (MIP_SSIP | MIP_STIP | MIP_SEIP)
 #define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
 
-static const target_ulong delegable_ints = S_MODE_INTERRUPTS;
-static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS;
+static const target_ulong delegable_ints = S_MODE_INTERRUPTS |
+   VS_MODE_INTERRUPTS;
+static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS |
+ VS_MODE_INTERRUPTS;
 static const target_ulong delegable_excps =
 (1ULL << (RISCV_EXCP_INST_ADDR_MIS)) |
 (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) |
@@ -630,13 +632,27 @@ static int write_sstatus(CPURISCVState *env, int csrno, 
target_ulong val)
 
 static int read_sie(CPURISCVState *env, int csrno, target_ulong *val)
 {
-*val = env->mie & env->mideleg;
+if (riscv_cpu_virt_enabled(env)) {
+/* Tell the guest the VS bits, shifted to the S bit locations */
+*val = (env->mie & env->mideleg & VS_MODE_INTERRUPTS) >> 1;
+} else {
+*val = env->mie & env->mideleg;
+}
 return 0;
 }
 
 static int write_sie(CPURISCVState *env, int csrno, target_ulong val)
 {
-target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg);
+target_ulong newval;
+
+if (riscv_cpu_virt_enabled(env)) {
+/* Shift the guests S bits to VS */
+newval = (env->mie & ~VS_MODE_INTERRUPTS) |
+ ((val << 1) & VS_MODE_INTERRUPTS);
+} else {
+newval = (env->mie & ~S_MODE_INTERRUPTS) | (val & S_MODE_INTERRUPTS);
+}
+
 return write_mie(env, CSR_MIE, newval);
 }
 
-- 
2.25.0




[PATCH v2 25/35] target/riscv: Only set TB flags with FP status if enabled

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5b889a0065..aa04e5cca7 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -332,7 +332,10 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState 
*env, target_ulong *pc,
 #ifdef CONFIG_USER_ONLY
 *flags = TB_FLAGS_MSTATUS_FS;
 #else
-*flags = cpu_mmu_index(env, 0) | (env->mstatus & MSTATUS_FS);
+*flags = cpu_mmu_index(env, 0);
+if (riscv_cpu_fp_enabled(env)) {
+*flags |= env->mstatus & MSTATUS_FS;
+}
 #endif
 }
 
-- 
2.25.0




[PATCH v2 17/35] target/riscv: Extend the SIP CSR to support virtulisation

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/csr.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 918678789a..2e6700bbeb 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -743,8 +743,19 @@ static int write_sbadaddr(CPURISCVState *env, int csrno, 
target_ulong val)
 static int rmw_sip(CPURISCVState *env, int csrno, target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
 {
-int ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
+int ret;
+
+if (riscv_cpu_virt_enabled(env)) {
+/* Shift the new values to line up with the VS bits */
+ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value << 1,
+  (write_mask & sip_writable_mask) << 1 & env->mideleg);
+ret &= vsip_writable_mask;
+ret >>= 1;
+} else {
+ret = rmw_mip(env, CSR_MSTATUS, ret_value, new_value,
   write_mask & env->mideleg & sip_writable_mask);
+}
+
 *ret_value &= env->mideleg;
 return ret;
 }
-- 
2.25.0




[PATCH v2 34/35] target/riscv: Add the MSTATUS_MPV_ISSET helper macro

2020-01-31 Thread Alistair Francis
Add a helper macro MSTATUS_MPV_ISSET() which will determine if the
MSTATUS_MPV bit is set for both 32-bit and 64-bit RISC-V.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu_bits.h   | 11 +++
 target/riscv/cpu_helper.c |  4 ++--
 target/riscv/op_helper.c  |  2 +-
 target/riscv/translate.c  |  2 +-
 4 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 049032f2ae..7f64ee1174 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -363,8 +363,19 @@
 #define MSTATUS_TVM 0x0010 /* since: priv-1.10 */
 #define MSTATUS_TW  0x2000 /* since: priv-1.10 */
 #define MSTATUS_TSR 0x4000 /* since: priv-1.10 */
+#if defined(TARGET_RISCV64)
 #define MSTATUS_MTL 0x40ULL
 #define MSTATUS_MPV 0x80ULL
+#elif defined(TARGET_RISCV32)
+#define MSTATUS_MTL 0x0040
+#define MSTATUS_MPV 0x0080
+#endif
+
+#ifdef TARGET_RISCV32
+# define MSTATUS_MPV_ISSET(env)  get_field(env->mstatush, MSTATUS_MPV)
+#else
+# define MSTATUS_MPV_ISSET(env)  get_field(env->mstatus, MSTATUS_MPV)
+#endif
 
 #define MSTATUS64_UXL   0x0003ULL
 #define MSTATUS64_SXL   0x000CULL
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index e04545adf7..b9e90dfd9a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -322,7 +322,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr 
*physical,
 mode = get_field(env->mstatus, MSTATUS_MPP);
 
 if (riscv_has_ext(env, RVH) &&
-get_field(env->mstatus, MSTATUS_MPV)) {
+MSTATUS_MPV_ISSET(env)) {
 use_background = true;
 }
 }
@@ -720,7 +720,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 m_mode_two_stage = env->priv == PRV_M &&
access_type != MMU_INST_FETCH &&
get_field(env->mstatus, MSTATUS_MPRV) &&
-   get_field(env->mstatus, MSTATUS_MPV);
+   MSTATUS_MPV_ISSET(env);
 
 hs_mode_two_stage = env->priv == PRV_S &&
 !riscv_cpu_virt_enabled(env) &&
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index dca68fa96e..8736f689c2 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -146,7 +146,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong 
cpu_pc_deb)
 
 target_ulong mstatus = env->mstatus;
 target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
-target_ulong prev_virt = get_field(mstatus, MSTATUS_MPV);
+target_ulong prev_virt = MSTATUS_MPV_ISSET(env);
 mstatus = set_field(mstatus,
 env->priv_ver >= PRIV_VERSION_1_10_0 ?
 MSTATUS_MIE : MSTATUS_UIE << prev_priv,
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 240fd7c971..ae8818efb3 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -752,7 +752,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->virt_enabled = riscv_cpu_virt_enabled(env);
 if (env->priv_ver == PRV_M &&
 get_field(env->mstatus, MSTATUS_MPRV) &&
-get_field(env->mstatus, MSTATUS_MPV)) {
+MSTATUS_MPV_ISSET(env)) {
 ctx->virt_enabled = true;
 } else if (env->priv == PRV_S &&
!riscv_cpu_virt_enabled(env) &&
-- 
2.25.0




[PATCH v2 14/35] target/riscv: Add virtual register swapping function

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.h| 11 +++
 target/riscv/cpu_bits.h   |  7 +
 target/riscv/cpu_helper.c | 61 +++
 3 files changed, 79 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 42720d65f9..5b889a0065 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -125,6 +125,7 @@ struct CPURISCVState {
 target_ulong mstatus;
 
 target_ulong mip;
+
 uint32_t miclaim;
 
 target_ulong mie;
@@ -166,6 +167,15 @@ struct CPURISCVState {
 target_ulong mtval2;
 target_ulong mtinst;
 
+/* HS Backup CSRs */
+target_ulong stvec_hs;
+target_ulong sscratch_hs;
+target_ulong sepc_hs;
+target_ulong scause_hs;
+target_ulong stval_hs;
+target_ulong satp_hs;
+target_ulong mstatus_hs;
+
 target_ulong scounteren;
 target_ulong mcounteren;
 
@@ -296,6 +306,7 @@ void riscv_cpu_list(void);
 #define cpu_mmu_index riscv_cpu_mmu_index
 
 #ifndef CONFIG_USER_ONLY
+void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
 uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
 #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index ad6479796c..a24654d137 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -553,4 +553,11 @@
 #define SIP_STIP   MIP_STIP
 #define SIP_SEIP   MIP_SEIP
 
+/* MIE masks */
+#define MIE_SEIE   (1 << IRQ_S_EXT)
+#define MIE_UEIE   (1 << IRQ_U_EXT)
+#define MIE_STIE   (1 << IRQ_S_TIMER)
+#define MIE_UTIE   (1 << IRQ_U_TIMER)
+#define MIE_SSIE   (1 << IRQ_S_SOFT)
+#define MIE_USIE   (1 << IRQ_U_SOFT)
 #endif
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 1e28103500..e9d75b45d6 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -82,6 +82,67 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
 return false;
 }
 
+void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
+{
+target_ulong mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
+MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE;
+bool current_virt = riscv_cpu_virt_enabled(env);
+
+g_assert(riscv_has_ext(env, RVH));
+
+#if defined(TARGET_RISCV64)
+mstatus_mask |= MSTATUS64_UXL;
+#endif
+
+if (current_virt) {
+/* Current V=1 and we are about to change to V=0 */
+env->vsstatus = env->mstatus & mstatus_mask;
+env->mstatus &= ~mstatus_mask;
+env->mstatus |= env->mstatus_hs;
+
+env->vstvec = env->stvec;
+env->stvec = env->stvec_hs;
+
+env->vsscratch = env->sscratch;
+env->sscratch = env->sscratch_hs;
+
+env->vsepc = env->sepc;
+env->sepc = env->sepc_hs;
+
+env->vscause = env->scause;
+env->scause = env->scause_hs;
+
+env->vstval = env->sbadaddr;
+env->sbadaddr = env->stval_hs;
+
+env->vsatp = env->satp;
+env->satp = env->satp_hs;
+} else {
+/* Current V=0 and we are about to change to V=1 */
+env->mstatus_hs = env->mstatus & mstatus_mask;
+env->mstatus &= ~mstatus_mask;
+env->mstatus |= env->vsstatus;
+
+env->stvec_hs = env->stvec;
+env->stvec = env->vstvec;
+
+env->sscratch_hs = env->sscratch;
+env->sscratch = env->vsscratch;
+
+env->sepc_hs = env->sepc;
+env->sepc = env->vsepc;
+
+env->scause_hs = env->scause;
+env->scause = env->vscause;
+
+env->stval_hs = env->sbadaddr;
+env->sbadaddr = env->vstval;
+
+env->satp_hs = env->satp;
+env->satp = env->vsatp;
+}
+}
+
 bool riscv_cpu_virt_enabled(CPURISCVState *env)
 {
 if (!riscv_has_ext(env, RVH)) {
-- 
2.25.0




[PATCH v2 11/35] target/riscv: Add Hypervisor CSR access functions

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/csr.c | 136 -
 1 file changed, 134 insertions(+), 2 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index c63b2f980c..bee639e92e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -98,6 +98,20 @@ static int smode(CPURISCVState *env, int csrno)
 return -!riscv_has_ext(env, RVS);
 }
 
+static int hmode(CPURISCVState *env, int csrno)
+{
+if (riscv_has_ext(env, RVS) &&
+riscv_has_ext(env, RVH)) {
+/* Hypervisor extension is supported */
+if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
+env->priv == PRV_M) {
+return 0;
+}
+}
+
+return -1;
+}
+
 static int pmp(CPURISCVState *env, int csrno)
 {
 return -!riscv_feature(env, RISCV_FEATURE_PMP);
@@ -226,8 +240,9 @@ static int read_timeh(CPURISCVState *env, int csrno, 
target_ulong *val)
 
 /* Machine constants */
 
-#define M_MODE_INTERRUPTS (MIP_MSIP | MIP_MTIP | MIP_MEIP)
-#define S_MODE_INTERRUPTS (MIP_SSIP | MIP_STIP | MIP_SEIP)
+#define M_MODE_INTERRUPTS  (MIP_MSIP | MIP_MTIP | MIP_MEIP)
+#define S_MODE_INTERRUPTS  (MIP_SSIP | MIP_STIP | MIP_SEIP)
+#define VS_MODE_INTERRUPTS (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
 
 static const target_ulong delegable_ints = S_MODE_INTERRUPTS;
 static const target_ulong all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS;
@@ -257,6 +272,7 @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE 
| SSTATUS_SPIE |
 SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
 SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
+static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
 
 #if defined(TARGET_RISCV32)
 static const char valid_vm_1_09[16] = {
@@ -756,6 +772,112 @@ static int write_satp(CPURISCVState *env, int csrno, 
target_ulong val)
 return 0;
 }
 
+/* Hypervisor Extensions */
+static int read_hstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->hstatus;
+return 0;
+}
+
+static int write_hstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->hstatus = val;
+return 0;
+}
+
+static int read_hedeleg(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->hedeleg;
+return 0;
+}
+
+static int write_hedeleg(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->hedeleg = val;
+return 0;
+}
+
+static int read_hideleg(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->hideleg;
+return 0;
+}
+
+static int write_hideleg(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->hideleg = val;
+return 0;
+}
+
+static int rmw_hip(CPURISCVState *env, int csrno, target_ulong *ret_value,
+   target_ulong new_value, target_ulong write_mask)
+{
+int ret = rmw_mip(env, 0, ret_value, new_value,
+  write_mask & hip_writable_mask);
+
+return ret;
+}
+
+static int read_hie(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->mie & VS_MODE_INTERRUPTS;
+return 0;
+}
+
+static int write_hie(CPURISCVState *env, int csrno, target_ulong val)
+{
+target_ulong newval = (env->mie & ~VS_MODE_INTERRUPTS) | (val & 
VS_MODE_INTERRUPTS);
+return write_mie(env, CSR_MIE, newval);
+}
+
+static int read_hcounteren(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->hcounteren;
+return 0;
+}
+
+static int write_hcounteren(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->hcounteren = val;
+return 0;
+}
+
+static int read_htval(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->htval;
+return 0;
+}
+
+static int write_htval(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->htval = val;
+return 0;
+}
+
+static int read_htinst(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->htinst;
+return 0;
+}
+
+static int write_htinst(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->htinst = val;
+return 0;
+}
+
+static int read_hgatp(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->hgatp;
+return 0;
+}
+
+static int write_hgatp(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->hgatp = val;
+return 0;
+}
+
 /* Physical Memory Protection */
 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
 {
@@ -959,6 +1081,16 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 /* Supervisor Protection and Translation */
 [CSR_SATP] ={ smode, read_satp,write_satp},
 
+[CSR_HSTATUS] = { hmode,   read_hstatus, write_hstatus
},
+[CSR_HEDELEG] = { hmode,   read_hedeleg, write_hedeleg
},
+[CSR_HIDELEG] = { hmode,   read_hideleg, write_hideleg
},
+[CSR_HIP] =

[PATCH v2 13/35] target/riscv: Add Hypervisor machine CSRs accesses

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/csr.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 3fa8d2cfda..f7333286bd 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -984,6 +984,30 @@ static int write_vsatp(CPURISCVState *env, int csrno, 
target_ulong val)
 return 0;
 }
 
+static int read_mtval2(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->mtval2;
+return 0;
+}
+
+static int write_mtval2(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->mtval2 = val;
+return 0;
+}
+
+static int read_mtinst(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->mtinst;
+return 0;
+}
+
+static int write_mtinst(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->mtinst = val;
+return 0;
+}
+
 /* Physical Memory Protection */
 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
 {
@@ -1207,6 +1231,9 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_VSTVAL] =  { hmode,   read_vstval,  write_vstval 
},
 [CSR_VSATP] =   { hmode,   read_vsatp,   write_vsatp  
},
 
+[CSR_MTVAL2] =  { hmode,   read_mtval2,  write_mtval2 
},
+[CSR_MTINST] =  { hmode,   read_mtinst,  write_mtinst 
},
+
 /* Physical Memory Protection */
 [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
 [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },
-- 
2.25.0




[PATCH v2 19/35] target/ricsv: Flush the TLB on virtulisation mode changes

2020-01-31 Thread Alistair Francis
To ensure our TLB isn't out-of-date we flush it on all virt mode
changes. Unlike priv mode this isn't saved in the mmu_idx as all
guests share V=1. The easiest option is just to flush on all changes.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu_helper.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 3984a1f1ac..98017df33b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -181,6 +181,11 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool 
enable)
 return;
 }
 
+/* Flush the TLB on all virt mode changes. */
+if (get_field(env->virt, VIRT_ONOFF) != enable) {
+tlb_flush(env_cpu(env));
+}
+
 env->virt = set_field(env->virt, VIRT_ONOFF, enable);
 }
 
-- 
2.25.0




[PATCH v2 32/35] target/riscv: Set htval and mtval2 on execptions

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu_helper.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index da994aba57..10786a077b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -838,6 +838,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK;
 target_ulong deleg = async ? env->mideleg : env->medeleg;
 target_ulong tval = 0;
+target_ulong htval = 0;
+target_ulong mtval2 = 0;
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
@@ -899,6 +901,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
  riscv_cpu_virt_enabled(env));
 
+htval = env->guest_phys_fault_addr;
+
 riscv_cpu_set_virt_enabled(env, 0);
 riscv_cpu_set_force_hs_excep(env, 0);
 } else {
@@ -909,6 +913,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
  get_field(env->mstatus, SSTATUS_SPP));
 env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
  riscv_cpu_virt_enabled(env));
+
+htval = env->guest_phys_fault_addr;
 }
 }
 
@@ -921,6 +927,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
 env->sepc = env->pc;
 env->sbadaddr = tval;
+env->htval = htval;
 env->pc = (env->stvec >> 2 << 2) +
 ((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
 riscv_cpu_set_mode(env, PRV_S);
@@ -935,6 +942,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 env->mstatus = set_field(env->mstatus, MSTATUS_MTL,
   riscv_cpu_force_hs_excep_enabled(env));
 
+mtval2 = env->guest_phys_fault_addr;
+
 /* Trapping to M mode, virt is disabled */
 riscv_cpu_set_virt_enabled(env, 0);
 riscv_cpu_set_force_hs_excep(env, 0);
@@ -949,6 +958,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 env->mcause = cause | ~(((target_ulong)-1) >> async);
 env->mepc = env->pc;
 env->mbadaddr = tval;
+env->mtval2 = mtval2;
 env->pc = (env->mtvec >> 2 << 2) +
 ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
 riscv_cpu_set_mode(env, PRV_M);
-- 
2.25.0




[PATCH v2 22/35] target/riscv: Add Hypervisor trap return support

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/op_helper.c | 62 +---
 1 file changed, 52 insertions(+), 10 deletions(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 455eb28907..804936e9d5 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -73,6 +73,8 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong 
src,
 
 target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
 {
+target_ulong prev_priv, prev_virt, mstatus;
+
 if (!(env->priv >= PRV_S)) {
 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
 }
@@ -87,16 +89,46 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong 
cpu_pc_deb)
 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
 }
 
-target_ulong mstatus = env->mstatus;
-target_ulong prev_priv = get_field(mstatus, MSTATUS_SPP);
-mstatus = set_field(mstatus,
-env->priv_ver >= PRIV_VERSION_1_10_0 ?
-MSTATUS_SIE : MSTATUS_UIE << prev_priv,
-get_field(mstatus, MSTATUS_SPIE));
-mstatus = set_field(mstatus, MSTATUS_SPIE, 1);
-mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
+mstatus = env->mstatus;
+
+if (riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) {
+/* We support Hypervisor extensions and virtulisation is disabled */
+target_ulong hstatus = env->hstatus;
+
+prev_priv = get_field(mstatus, MSTATUS_SPP);
+prev_virt = get_field(hstatus, HSTATUS_SPV);
+
+hstatus = set_field(hstatus, HSTATUS_SPV,
+ get_field(hstatus, HSTATUS_SP2V));
+mstatus = set_field(mstatus, MSTATUS_SPP,
+get_field(hstatus, HSTATUS_SP2P));
+hstatus = set_field(hstatus, HSTATUS_SP2V, 0);
+hstatus = set_field(hstatus, HSTATUS_SP2P, 0);
+mstatus = set_field(mstatus, SSTATUS_SIE,
+get_field(mstatus, SSTATUS_SPIE));
+mstatus = set_field(mstatus, SSTATUS_SPIE, 1);
+
+env->mstatus = mstatus;
+env->hstatus = hstatus;
+
+if (prev_virt) {
+riscv_cpu_swap_hypervisor_regs(env);
+}
+
+riscv_cpu_set_virt_enabled(env, prev_virt);
+} else {
+prev_priv = get_field(mstatus, MSTATUS_SPP);
+
+mstatus = set_field(mstatus,
+env->priv_ver >= PRIV_VERSION_1_10_0 ?
+MSTATUS_SIE : MSTATUS_UIE << prev_priv,
+get_field(mstatus, MSTATUS_SPIE));
+mstatus = set_field(mstatus, MSTATUS_SPIE, 1);
+mstatus = set_field(mstatus, MSTATUS_SPP, PRV_U);
+env->mstatus = mstatus;
+}
+
 riscv_cpu_set_mode(env, prev_priv);
-env->mstatus = mstatus;
 
 return retpc;
 }
@@ -114,14 +146,24 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong 
cpu_pc_deb)
 
 target_ulong mstatus = env->mstatus;
 target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
+target_ulong prev_virt = get_field(mstatus, MSTATUS_MPV);
 mstatus = set_field(mstatus,
 env->priv_ver >= PRIV_VERSION_1_10_0 ?
 MSTATUS_MIE : MSTATUS_UIE << prev_priv,
 get_field(mstatus, MSTATUS_MPIE));
 mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
 mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
-riscv_cpu_set_mode(env, prev_priv);
+mstatus = set_field(mstatus, MSTATUS_MPV, 0);
 env->mstatus = mstatus;
+riscv_cpu_set_mode(env, prev_priv);
+
+if (riscv_has_ext(env, RVH)) {
+if (prev_virt) {
+riscv_cpu_swap_hypervisor_regs(env);
+}
+
+riscv_cpu_set_virt_enabled(env, prev_virt);
+}
 
 return retpc;
 }
-- 
2.25.0




[PATCH v2 21/35] target/riscv: Add hypvervisor trap support

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 69 +--
 1 file changed, 59 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 98017df33b..e7728cb0ca 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -639,6 +639,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
+bool force_hs_execp = riscv_cpu_force_hs_excep_enabled(env);
+target_ulong s;
 
 /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
  * so we mask off the MSB and separate into trap type and cause.
@@ -648,19 +650,14 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong deleg = async ? env->mideleg : env->medeleg;
 target_ulong tval = 0;
 
-static const int ecall_cause_map[] = {
-[PRV_U] = RISCV_EXCP_U_ECALL,
-[PRV_S] = RISCV_EXCP_S_ECALL,
-[PRV_H] = RISCV_EXCP_VS_ECALL,
-[PRV_M] = RISCV_EXCP_M_ECALL
-};
-
 if (!async) {
 /* set tval to badaddr for traps with address information */
 switch (cause) {
 case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
 case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
 case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
+force_hs_execp = true;
+/* fallthrough */
 case RISCV_EXCP_INST_ADDR_MIS:
 case RISCV_EXCP_INST_ACCESS_FAULT:
 case RISCV_EXCP_LOAD_ADDR_MIS:
@@ -678,7 +675,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 /* ecall is dispatched as one cause so translate based on mode */
 if (cause == RISCV_EXCP_U_ECALL) {
 assert(env->priv <= 3);
-cause = ecall_cause_map[env->priv];
+
+if (env->priv == PRV_M) {
+cause = RISCV_EXCP_M_ECALL;
+} else if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) {
+cause = RISCV_EXCP_VS_ECALL;
+} else if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) {
+cause = RISCV_EXCP_S_ECALL;
+} else if (env->priv == PRV_U) {
+cause = RISCV_EXCP_U_ECALL;
+}
 }
 }
 
@@ -688,7 +694,36 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 if (env->priv <= PRV_S &&
 cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
 /* handle the trap in S-mode */
-target_ulong s = env->mstatus;
+if (riscv_has_ext(env, RVH)) {
+target_ulong hdeleg = async ? env->hideleg : env->hedeleg;
+
+if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1) &&
+!force_hs_execp) {
+/* Trap to VS mode */
+} else if (riscv_cpu_virt_enabled(env)) {
+/* Trap into HS mode, from virt */
+riscv_cpu_swap_hypervisor_regs(env);
+env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
+ get_field(env->hstatus, HSTATUS_SPV));
+env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
+ get_field(env->mstatus, SSTATUS_SPP));
+env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
+ riscv_cpu_virt_enabled(env));
+
+riscv_cpu_set_virt_enabled(env, 0);
+riscv_cpu_set_force_hs_excep(env, 0);
+} else {
+/* Trap into HS mode */
+env->hstatus = set_field(env->hstatus, HSTATUS_SP2V,
+ get_field(env->hstatus, HSTATUS_SPV));
+env->hstatus = set_field(env->hstatus, HSTATUS_SP2P,
+ get_field(env->mstatus, SSTATUS_SPP));
+env->hstatus = set_field(env->hstatus, HSTATUS_SPV,
+ riscv_cpu_virt_enabled(env));
+}
+}
+
+s = env->mstatus;
 s = set_field(s, MSTATUS_SPIE, env->priv_ver >= PRIV_VERSION_1_10_0 ?
 get_field(s, MSTATUS_SIE) : get_field(s, MSTATUS_UIE << 
env->priv));
 s = set_field(s, MSTATUS_SPP, env->priv);
@@ -702,7 +737,21 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 riscv_cpu_set_mode(env, PRV_S);
 } else {
 /* handle the trap in M-mode */
-target_ulong s = env->mstatus;
+if (riscv_has_ext(env, RVH)) {
+if (riscv_cpu_virt_enabled(env)) {
+riscv_cpu_swap_hypervisor_regs(env);
+}
+env->mstatus = set_field(env->mstatus, MSTATUS_MPV,
+  riscv_cpu_virt_enabled(env));
+env->mstatus = set_field(env->mstatus, MSTATUS_MTL,
+  riscv_cpu_force_hs_excep_enabled(env));
+
+/* Trapping to M mode, virt is disabled */
+riscv_cpu_set_virt_enabled(env, 0);
+

[PATCH v2 09/35] target/riscv: Print priv and virt in disas log

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/translate.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 14dc71156b..afa2d6eea2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -808,7 +808,15 @@ static void riscv_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cpu)
 
 static void riscv_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
 {
+#ifndef CONFIG_USER_ONLY
+RISCVCPU *rvcpu = RISCV_CPU(cpu);
+CPURISCVState *env = >env;
+#endif
+
 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
+#ifndef CONFIG_USER_ONLY
+qemu_log("Priv: "TARGET_FMT_ld"; Virt: "TARGET_FMT_ld"\n", env->priv, 
env->virt);
+#endif
 log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
 }
 
-- 
2.25.0




[PATCH v2 12/35] target/riscv: Add Hypervisor virtual CSRs accesses

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/csr.c | 116 +
 1 file changed, 116 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index bee639e92e..3fa8d2cfda 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -273,6 +273,7 @@ static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE 
| SSTATUS_SPIE |
 SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
 static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP;
 static const target_ulong hip_writable_mask = MIP_VSSIP | MIP_VSTIP | 
MIP_VSEIP;
+static const target_ulong vsip_writable_mask = MIP_VSSIP;
 
 #if defined(TARGET_RISCV32)
 static const char valid_vm_1_09[16] = {
@@ -878,6 +879,111 @@ static int write_hgatp(CPURISCVState *env, int csrno, 
target_ulong val)
 return 0;
 }
 
+/* Virtual CSR Registers */
+static int read_vsstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->vsstatus;
+return 0;
+}
+
+static int write_vsstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->vsstatus = val;
+return 0;
+}
+
+static int rmw_vsip(CPURISCVState *env, int csrno, target_ulong *ret_value,
+target_ulong new_value, target_ulong write_mask)
+{
+int ret = rmw_mip(env, 0, ret_value, new_value,
+  write_mask & env->mideleg & vsip_writable_mask);
+return ret;
+}
+
+static int read_vsie(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->mie & env->mideleg & VS_MODE_INTERRUPTS;
+return 0;
+}
+
+static int write_vsie(CPURISCVState *env, int csrno, target_ulong val)
+{
+target_ulong newval = (env->mie & ~env->mideleg) | (val & env->mideleg & 
MIP_VSSIP);
+return write_mie(env, CSR_MIE, newval);
+}
+
+static int read_vstvec(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->vstvec;
+return 0;
+}
+
+static int write_vstvec(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->vstvec = val;
+return 0;
+}
+
+static int read_vsscratch(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->vsscratch;
+return 0;
+}
+
+static int write_vsscratch(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->vsscratch = val;
+return 0;
+}
+
+static int read_vsepc(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->vsepc;
+return 0;
+}
+
+static int write_vsepc(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->vsepc = val;
+return 0;
+}
+
+static int read_vscause(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->vscause;
+return 0;
+}
+
+static int write_vscause(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->vscause = val;
+return 0;
+}
+
+static int read_vstval(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->vstval;
+return 0;
+}
+
+static int write_vstval(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->vstval = val;
+return 0;
+}
+
+static int read_vsatp(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = env->vsatp;
+return 0;
+}
+
+static int write_vsatp(CPURISCVState *env, int csrno, target_ulong val)
+{
+env->vsatp = val;
+return 0;
+}
+
 /* Physical Memory Protection */
 static int read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val)
 {
@@ -1091,6 +1197,16 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_HTINST] =  { hmode,   read_htinst,  write_htinst 
},
 [CSR_HGATP] =   { hmode,   read_hgatp,   write_hgatp  
},
 
+[CSR_VSSTATUS] ={ hmode,   read_vsstatus,write_vsstatus   
},
+[CSR_VSIP] ={ hmode,   NULL, NULL, rmw_vsip   
},
+[CSR_VSIE] ={ hmode,   read_vsie,write_vsie   
},
+[CSR_VSTVEC] =  { hmode,   read_vstvec,  write_vstvec 
},
+[CSR_VSSCRATCH] =   { hmode,   read_vsscratch,   write_vsscratch  
},
+[CSR_VSEPC] =   { hmode,   read_vsepc,   write_vsepc  
},
+[CSR_VSCAUSE] = { hmode,   read_vscause, write_vscause
},
+[CSR_VSTVAL] =  { hmode,   read_vstval,  write_vstval 
},
+[CSR_VSATP] =   { hmode,   read_vsatp,   write_vsatp  
},
+
 /* Physical Memory Protection */
 [CSR_PMPCFG0  ... CSR_PMPADDR9] =  { pmp,   read_pmpcfg,  write_pmpcfg   },
 [CSR_PMPADDR0 ... CSR_PMPADDR15] = { pmp,   read_pmpaddr, write_pmpaddr  },
-- 
2.25.0




[PATCH v2 07/35] target/riscv: Add the force HS exception mode

2020-01-31 Thread Alistair Francis
Add a FORCE_HS_EXCEP mode to the RISC-V virtulisation status. This bit
specifies if an exeption should be taken to HS mode no matter the
current delegation status. This is used when an exeption must be taken
to HS mode, such as when handling interrupts.

Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h|  2 ++
 target/riscv/cpu_bits.h   |  6 ++
 target/riscv/cpu_helper.c | 18 ++
 3 files changed, 26 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index a9cbd8584e..42720d65f9 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -273,6 +273,8 @@ bool riscv_cpu_exec_interrupt(CPUState *cs, int 
interrupt_request);
 bool riscv_cpu_fp_enabled(CPURISCVState *env);
 bool riscv_cpu_virt_enabled(CPURISCVState *env);
 void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
+bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env);
+void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 2cdb0de4fe..ad6479796c 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -432,6 +432,12 @@
 
 /* Virtulisation Register Fields */
 #define VIRT_ONOFF  1
+/* This is used to save state for when we take an exception. If this is set
+ * that means that we want to force a HS level exception (no matter what the
+ * delegation is set to). This will occur for things such as a second level
+ * page table fault.
+ */
+#define FORCE_HS_EXCEP  2
 
 /* RV32 satp CSR field masks */
 #define SATP32_MODE 0x8000
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 5844e543f3..1e28103500 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -100,6 +100,24 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool 
enable)
 env->virt = set_field(env->virt, VIRT_ONOFF, enable);
 }
 
+bool riscv_cpu_force_hs_excep_enabled(CPURISCVState *env)
+{
+if (!riscv_has_ext(env, RVH)) {
+return false;
+}
+
+return get_field(env->virt, FORCE_HS_EXCEP);
+}
+
+void riscv_cpu_set_force_hs_excep(CPURISCVState *env, bool enable)
+{
+if (!riscv_has_ext(env, RVH)) {
+return;
+}
+
+env->virt = set_field(env->virt, FORCE_HS_EXCEP, enable);
+}
+
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
 {
 CPURISCVState *env = >env;
-- 
2.25.0




[PATCH v2 18/35] target/riscv: Add support for virtual interrupt setting

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu_helper.c | 33 -
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index e9d75b45d6..3984a1f1ac 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -37,13 +37,36 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 #ifndef CONFIG_USER_ONLY
 static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
+target_ulong irqs;
+
 target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
 target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
-target_ulong pending = env->mip & env->mie;
-target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && 
mstatus_mie);
-target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && 
mstatus_sie);
-target_ulong irqs = (pending & ~env->mideleg & -mie) |
-(pending &  env->mideleg & -sie);
+target_ulong hs_mstatus_sie = get_field(env->mstatus_hs, MSTATUS_SIE);
+
+target_ulong pending = env->mip & env->mie &
+   ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
+target_ulong vspending = (env->mip & env->mie &
+  (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) >> 1;
+
+target_ulong mie= env->priv < PRV_M ||
+  (env->priv == PRV_M && mstatus_mie);
+target_ulong sie= env->priv < PRV_S ||
+  (env->priv == PRV_S && mstatus_sie);
+target_ulong hs_sie = env->priv < PRV_S ||
+  (env->priv == PRV_S && hs_mstatus_sie);
+
+if (riscv_cpu_virt_enabled(env)) {
+target_ulong pending_hs_irq = pending & -hs_sie;
+
+if (pending_hs_irq) {
+riscv_cpu_set_force_hs_excep(env, FORCE_HS_EXCEP);
+return ctz64(pending_hs_irq);
+}
+
+pending = vspending;
+}
+
+irqs = (pending & ~env->mideleg & -mie) | (pending &  env->mideleg & -sie);
 
 if (irqs) {
 return ctz64(irqs); /* since non-zero */
-- 
2.25.0




[PATCH v2 05/35] target/riscv: Rename the H irqs to VS irqs

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.c  |  6 +++---
 target/riscv/cpu_bits.h | 12 ++--
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 2f62f5ea19..f7a35c74c2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -80,14 +80,14 @@ const char * const riscv_excp_names[] = {
 const char * const riscv_intr_names[] = {
 "u_software",
 "s_software",
-"h_software",
+"vs_software",
 "m_software",
 "u_timer",
 "s_timer",
-"h_timer",
+"vs_timer",
 "m_timer",
 "u_external",
-"s_external",
+"vs_external",
 "h_external",
 "m_external",
 "reserved",
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 9ce73c36de..eeaa03c0f8 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -514,29 +514,29 @@
 /* Interrupt causes */
 #define IRQ_U_SOFT 0
 #define IRQ_S_SOFT 1
-#define IRQ_H_SOFT 2  /* reserved */
+#define IRQ_VS_SOFT2
 #define IRQ_M_SOFT 3
 #define IRQ_U_TIMER4
 #define IRQ_S_TIMER5
-#define IRQ_H_TIMER6  /* reserved */
+#define IRQ_VS_TIMER   6
 #define IRQ_M_TIMER7
 #define IRQ_U_EXT  8
 #define IRQ_S_EXT  9
-#define IRQ_H_EXT  10 /* reserved */
+#define IRQ_VS_EXT 10
 #define IRQ_M_EXT  11
 
 /* mip masks */
 #define MIP_USIP   (1 << IRQ_U_SOFT)
 #define MIP_SSIP   (1 << IRQ_S_SOFT)
-#define MIP_HSIP   (1 << IRQ_H_SOFT)
+#define MIP_VSSIP  (1 << IRQ_VS_SOFT)
 #define MIP_MSIP   (1 << IRQ_M_SOFT)
 #define MIP_UTIP   (1 << IRQ_U_TIMER)
 #define MIP_STIP   (1 << IRQ_S_TIMER)
-#define MIP_HTIP   (1 << IRQ_H_TIMER)
+#define MIP_VSTIP  (1 << IRQ_VS_TIMER)
 #define MIP_MTIP   (1 << IRQ_M_TIMER)
 #define MIP_UEIP   (1 << IRQ_U_EXT)
 #define MIP_SEIP   (1 << IRQ_S_EXT)
-#define MIP_HEIP   (1 << IRQ_H_EXT)
+#define MIP_VSEIP  (1 << IRQ_VS_EXT)
 #define MIP_MEIP   (1 << IRQ_M_EXT)
 
 /* sip masks */
-- 
2.25.0




[PATCH v2 08/35] target/riscv: Fix CSR perm checking for HS mode

2020-01-31 Thread Alistair Francis
Update the CSR permission checking to work correctly when we are in
HS-mode.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/csr.c | 18 ++
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index ca27359c7e..c63b2f980c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -801,12 +801,22 @@ int riscv_csrrw(CPURISCVState *env, int csrno, 
target_ulong *ret_value,
 
 /* check privileges and return -1 if check fails */
 #if !defined(CONFIG_USER_ONLY)
-int csr_priv = get_field(csrno, 0x300);
+int effective_priv = env->priv;
 int read_only = get_field(csrno, 0xC00) == 3;
-if ((!env->debugger) && (env->priv < csr_priv)) {
-return -1;
+
+if (riscv_has_ext(env, RVH) &&
+env->priv == PRV_S &&
+!riscv_cpu_virt_enabled(env)) {
+/*
+ * We are in S mode without virtualisation, therefore we are in HS 
Mode.
+ * Add 1 to the effective privledge level to allow us to access the
+ * Hypervisor CSRs.
+ */
+effective_priv++;
 }
-if (write_mask && read_only) {
+
+if ((write_mask && read_only) ||
+(!env->debugger && (effective_priv < get_field(csrno, 0x300 {
 return -1;
 }
 #endif
-- 
2.25.0




[PATCH v2 15/35] target/riscv: Set VS bits in mideleg for Hyp extension

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/csr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index f7333286bd..c0e942684d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -448,6 +448,9 @@ static int read_mideleg(CPURISCVState *env, int csrno, 
target_ulong *val)
 static int write_mideleg(CPURISCVState *env, int csrno, target_ulong val)
 {
 env->mideleg = (env->mideleg & ~delegable_ints) | (val & delegable_ints);
+if (riscv_has_ext(env, RVH)) {
+env->mideleg |= VS_MODE_INTERRUPTS;
+}
 return 0;
 }
 
-- 
2.25.0




[PATCH v2 06/35] target/riscv: Add the virtulisation mode

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.h|  4 
 target/riscv/cpu_bits.h   |  3 +++
 target/riscv/cpu_helper.c | 18 ++
 3 files changed, 25 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c7f7ae5c38..a9cbd8584e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -117,6 +117,8 @@ struct CPURISCVState {
 
 #ifndef CONFIG_USER_ONLY
 target_ulong priv;
+/* This contains QEMU specific information about the virt state. */
+target_ulong virt;
 target_ulong resetvec;
 
 target_ulong mhartid;
@@ -269,6 +271,8 @@ int riscv_cpu_gdb_read_register(CPUState *cpu, uint8_t 
*buf, int reg);
 int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
 bool riscv_cpu_fp_enabled(CPURISCVState *env);
+bool riscv_cpu_virt_enabled(CPURISCVState *env);
+void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index eeaa03c0f8..2cdb0de4fe 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -430,6 +430,9 @@
 #define PRV_H 2 /* Reserved */
 #define PRV_M 3
 
+/* Virtulisation Register Fields */
+#define VIRT_ONOFF  1
+
 /* RV32 satp CSR field masks */
 #define SATP32_MODE 0x8000
 #define SATP32_ASID 0x7fc0
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8f746fb06f..5844e543f3 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -82,6 +82,24 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
 return false;
 }
 
+bool riscv_cpu_virt_enabled(CPURISCVState *env)
+{
+if (!riscv_has_ext(env, RVH)) {
+return false;
+}
+
+return get_field(env->virt, VIRT_ONOFF);
+}
+
+void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
+{
+if (!riscv_has_ext(env, RVH)) {
+return;
+}
+
+env->virt = set_field(env->virt, VIRT_ONOFF, enable);
+}
+
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts)
 {
 CPURISCVState *env = >env;
-- 
2.25.0




[PATCH v2 02/35] target/riscv: Add the Hypervisor extension

2020-01-31 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Chih-Min Chao 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 95de9e58a2..010125efd6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -67,6 +67,7 @@
 #define RVC RV('C')
 #define RVS RV('S')
 #define RVU RV('U')
+#define RVH RV('H')
 
 /* S extension denotes that Supervisor mode exists, however it is possible
to have a core that support S mode but does not have an MMU and there
-- 
2.25.0




[PATCH v2 04/35] target/riscv: Add support for the new execption numbers

2020-01-31 Thread Alistair Francis
The v0.5 Hypervisor spec add new execption numbers, let's add support
for those.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.c|  8 
 target/riscv/cpu_bits.h   | 35 +++
 target/riscv/cpu_helper.c |  7 +--
 target/riscv/csr.c|  7 +--
 4 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index efbd676edb..2f62f5ea19 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -67,6 +67,14 @@ const char * const riscv_excp_names[] = {
 "load_page_fault",
 "reserved",
 "store_page_fault"
+"reserved",
+"reserved",
+"reserved",
+"reserved",
+"guest_exec_page_fault",
+"guest_load_page_fault",
+"reserved",
+"guest_store_page_fault"
 };
 
 const char * const riscv_intr_names[] = {
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 25c0fb258d..9ce73c36de 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -488,22 +488,25 @@
 #define DEFAULT_RSTVEC  0x1000
 
 /* Exception causes */
-#define EXCP_NONE  -1 /* sentinel value */
-#define RISCV_EXCP_INST_ADDR_MIS   0x0
-#define RISCV_EXCP_INST_ACCESS_FAULT   0x1
-#define RISCV_EXCP_ILLEGAL_INST0x2
-#define RISCV_EXCP_BREAKPOINT  0x3
-#define RISCV_EXCP_LOAD_ADDR_MIS   0x4
-#define RISCV_EXCP_LOAD_ACCESS_FAULT   0x5
-#define RISCV_EXCP_STORE_AMO_ADDR_MIS  0x6
-#define RISCV_EXCP_STORE_AMO_ACCESS_FAULT  0x7
-#define RISCV_EXCP_U_ECALL 0x8
-#define RISCV_EXCP_S_ECALL 0x9
-#define RISCV_EXCP_H_ECALL 0xa
-#define RISCV_EXCP_M_ECALL 0xb
-#define RISCV_EXCP_INST_PAGE_FAULT 0xc /* since: priv-1.10.0 */
-#define RISCV_EXCP_LOAD_PAGE_FAULT 0xd /* since: priv-1.10.0 */
-#define RISCV_EXCP_STORE_PAGE_FAULT0xf /* since: priv-1.10.0 */
+#define EXCP_NONE-1 /* sentinel value */
+#define RISCV_EXCP_INST_ADDR_MIS 0x0
+#define RISCV_EXCP_INST_ACCESS_FAULT 0x1
+#define RISCV_EXCP_ILLEGAL_INST  0x2
+#define RISCV_EXCP_BREAKPOINT0x3
+#define RISCV_EXCP_LOAD_ADDR_MIS 0x4
+#define RISCV_EXCP_LOAD_ACCESS_FAULT 0x5
+#define RISCV_EXCP_STORE_AMO_ADDR_MIS0x6
+#define RISCV_EXCP_STORE_AMO_ACCESS_FAULT0x7
+#define RISCV_EXCP_U_ECALL   0x8
+#define RISCV_EXCP_S_ECALL  0x9
+#define RISCV_EXCP_VS_ECALL  0xa
+#define RISCV_EXCP_M_ECALL   0xb
+#define RISCV_EXCP_INST_PAGE_FAULT   0xc /* since: priv-1.10.0 */
+#define RISCV_EXCP_LOAD_PAGE_FAULT   0xd /* since: priv-1.10.0 */
+#define RISCV_EXCP_STORE_PAGE_FAULT  0xf /* since: priv-1.10.0 */
+#define RISCV_EXCP_INST_GUEST_PAGE_FAULT 0x14
+#define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT   0x15
+#define RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT  0x17
 
 #define RISCV_EXCP_INT_FLAG0x8000
 #define RISCV_EXCP_INT_MASK0x7fff
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b8e85d5b20..8f746fb06f 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -526,13 +526,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 static const int ecall_cause_map[] = {
 [PRV_U] = RISCV_EXCP_U_ECALL,
 [PRV_S] = RISCV_EXCP_S_ECALL,
-[PRV_H] = RISCV_EXCP_H_ECALL,
+[PRV_H] = RISCV_EXCP_VS_ECALL,
 [PRV_M] = RISCV_EXCP_M_ECALL
 };
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
 switch (cause) {
+case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
+case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
+case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
 case RISCV_EXCP_INST_ADDR_MIS:
 case RISCV_EXCP_INST_ACCESS_FAULT:
 case RISCV_EXCP_LOAD_ADDR_MIS:
@@ -554,7 +557,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 }
 }
 
-trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 16 ?
+trace_riscv_trap(env->mhartid, async, cause, env->pc, tval, cause < 23 ?
 (async ? riscv_intr_names : riscv_excp_names)[cause] : "(unknown)");
 
 if (env->priv <= PRV_S &&
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0e34c292c5..ca27359c7e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -242,11 +242,14 @@ static const target_ulong delegable_excps =
 (1ULL << (RISCV_EXCP_STORE_AMO_ACCESS_FAULT)) |
 (1ULL << (RISCV_EXCP_U_ECALL)) |
 (1ULL << (RISCV_EXCP_S_ECALL)) |
-(1ULL << (RISCV_EXCP_H_ECALL)) |
+(1ULL << (RISCV_EXCP_VS_ECALL)) |
 (1ULL << (RISCV_EXCP_M_ECALL)) |
 (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) |
 (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) |
-(1ULL << 

[PATCH v2 01/35] target/riscv: Convert MIP CSR to target_ulong

2020-01-31 Thread Alistair Francis
The MIP CSR is a xlen CSR, it was only 32-bits to allow atomic access.
Now that we don't use atomics for MIP we can change this back to a xlen
CSR.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.c | 2 +-
 target/riscv/cpu.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8c86ebc109..efbd676edb 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -224,7 +224,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 #ifndef CONFIG_USER_ONLY
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
-qemu_fprintf(f, " %s 0x%x\n", "mip ", env->mip);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index de0a8d893a..95de9e58a2 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -121,7 +121,7 @@ struct CPURISCVState {
 target_ulong mhartid;
 target_ulong mstatus;
 
-uint32_t mip;
+target_ulong mip;
 uint32_t miclaim;
 
 target_ulong mie;
-- 
2.25.0




[PATCH v2 10/35] target/riscv: Dump Hypervisor registers if enabled

2020-01-31 Thread Alistair Francis
Dump the Hypervisor registers and the current Hypervisor state.

While we are editing this code let's also dump stvec and scause.

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

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f7a35c74c2..44ad768a84 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -228,17 +228,50 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 CPURISCVState *env = >env;
 int i;
 
+#if !defined(CONFIG_USER_ONLY)
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s %d\n", "V  =  ", riscv_cpu_virt_enabled(env));
+}
+#endif
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc  ", env->pc);
 #ifndef CONFIG_USER_ONLY
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", env->vsstatus);
+}
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg);
+}
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg);
+}
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec   ", env->mtvec);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec   ", env->stvec);
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec  ", env->vstvec);
+}
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc", env->mepc);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc", env->sepc);
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc   ", env->vsepc);
+}
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause  ", env->mcause);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause  ", env->scause);
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause);
+}
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->sbadaddr);
+if (riscv_has_ext(env, RVH)) {
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval);
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2);
+}
 #endif
 
 for (i = 0; i < 32; i++) {
-- 
2.25.0




[PATCH v2 03/35] target/riscv: Add the Hypervisor CSRs to CPUState

2020-01-31 Thread Alistair Francis
Add the Hypervisor CSRs to CPUState and at the same time (to avoid
bisect issues) update the CSR macros for the v0.5 Hyp spec.

Signed-off-by: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
---
 target/riscv/cpu.h  | 21 +
 target/riscv/cpu_bits.h | 34 +-
 target/riscv/gdbstub.c  | 11 ++-
 3 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 010125efd6..c7f7ae5c38 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -143,6 +143,27 @@ struct CPURISCVState {
 target_ulong mcause;
 target_ulong mtval;  /* since: priv-1.10.0 */
 
+/* Hypervisor CSRs */
+target_ulong hstatus;
+target_ulong hedeleg;
+target_ulong hideleg;
+target_ulong hcounteren;
+target_ulong htval;
+target_ulong htinst;
+target_ulong hgatp;
+
+/* Virtual CSRs */
+target_ulong vsstatus;
+target_ulong vstvec;
+target_ulong vsscratch;
+target_ulong vsepc;
+target_ulong vscause;
+target_ulong vstval;
+target_ulong vsatp;
+
+target_ulong mtval2;
+target_ulong mtinst;
+
 target_ulong scounteren;
 target_ulong mcounteren;
 
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index e99834856c..25c0fb258d 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -177,8 +177,14 @@
 #define CSR_HSTATUS 0x600
 #define CSR_HEDELEG 0x602
 #define CSR_HIDELEG 0x603
-#define CSR_HCOUNTERNEN 0x606
+#define CSR_HIE 0x604
+#define CSR_HCOUNTEREN  0x606
+#define CSR_HTVAL   0x643
+#define CSR_HIP 0x644
+#define CSR_HTINST  0x64A
 #define CSR_HGATP   0x680
+#define CSR_HTIMEDELTA  0x605
+#define CSR_HTIMEDELTAH 0x615
 
 #if defined(TARGET_RISCV32)
 #define HGATP_MODE   SATP32_MODE
@@ -191,6 +197,20 @@
 #define HGATP_PPNSATP64_PPN
 #endif
 
+/* Virtual CSRs */
+#define CSR_VSSTATUS0x200
+#define CSR_VSIE0x204
+#define CSR_VSTVEC  0x205
+#define CSR_VSSCRATCH   0x240
+#define CSR_VSEPC   0x241
+#define CSR_VSCAUSE 0x242
+#define CSR_VSTVAL  0x243
+#define CSR_VSIP0x244
+#define CSR_VSATP   0x280
+
+#define CSR_MTINST  0x34a
+#define CSR_MTVAL2  0x34b
+
 /* Physical Memory Protection */
 #define CSR_PMPCFG0 0x3a0
 #define CSR_PMPCFG1 0x3a1
@@ -313,17 +333,6 @@
 #define CSR_MHPMCOUNTER30H  0xb9e
 #define CSR_MHPMCOUNTER31H  0xb9f
 
-/* Legacy Hypervisor Trap Setup (priv v1.9.1) */
-#define CSR_HIE 0x204
-#define CSR_HTVEC   0x205
-
-/* Legacy Hypervisor Trap Handling (priv v1.9.1) */
-#define CSR_HSCRATCH0x240
-#define CSR_HEPC0x241
-#define CSR_HCAUSE  0x242
-#define CSR_HBADADDR0x243
-#define CSR_HIP 0x244
-
 /* Legacy Machine Protection and Translation (priv v1.9.1) */
 #define CSR_MBASE   0x380
 #define CSR_MBOUND  0x381
@@ -400,7 +409,6 @@
 
 /* hstatus CSR bits */
 #define HSTATUS_SPRV 0x0001
-#define HSTATUS_STL  0x0040
 #define HSTATUS_SPV  0x0080
 #define HSTATUS_SP2P 0x0100
 #define HSTATUS_SP2V 0x0200
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 1a7947e019..6d606f0d90 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -130,6 +130,8 @@ static int csr_register_map[] = {
 CSR_MCAUSE,
 CSR_MTVAL,
 CSR_MIP,
+CSR_MTINST,
+CSR_MTVAL2,
 CSR_PMPCFG0,
 CSR_PMPCFG1,
 CSR_PMPCFG2,
@@ -252,12 +254,11 @@ static int csr_register_map[] = {
 CSR_HEDELEG,
 CSR_HIDELEG,
 CSR_HIE,
-CSR_HTVEC,
-CSR_HSCRATCH,
-CSR_HEPC,
-CSR_HCAUSE,
-CSR_HBADADDR,
+CSR_HCOUNTEREN,
+CSR_HTVAL,
 CSR_HIP,
+CSR_HTINST,
+CSR_HGATP,
 CSR_MBASE,
 CSR_MBOUND,
 CSR_MIBASE,
-- 
2.25.0




[PATCH v2 00/35] Add RISC-V Hypervisor Extension v0.5

2020-01-31 Thread Alistair Francis
This patch series adds the RISC-V Hypervisor extension v0.5. This is the
latest draft spec of the Hypervisor extension.

The Hypervisor extension is disabled by default, so this series should
result in no changes to anyone using QEMU unless they enable the
extension. The extention can be enabled with the -cpu property (see
below).

Testing of this implementation has been done by using the baremetal
Xvisor Hypervisor. We are able to run two Linux guests (that's all I
have tried) as guests in 64-bit. In 32-bit so far I can only run
baremetal guests, but I think this is a baremetal boot loader issue and
not an issue in QEMU.

The RISC-V KVM implementation was also written using these patches. The
KVM implementation is currently under review.

At the moment this spec is in a draft state and is subject to change. As
QEMU is extreamly useful in early bring up I think it makes sense for
QEMU to support non-frozen extensions.

Thanks to Anup for doing the initial port of Xvisor. The port is avaliable here:
https://github.com/avpatel/xvisor-next and will run on QEMU.

Also thanks to Atish for implementing the SBI call support in Xvisor and
for lots of help debugging.

To run this yourself:
 1. Apply this patch series to QEMU. The latest branch can be found here:
  
https://github.com/alistair23/qemu/tree/mainline/alistair/riscv-hyp-ext-v0.5.next
 2. Get the version of OpenSBI that supports the H extension. This can
be found here:
  https://github.com/avpatel/opensbi/tree/riscv_hyp_ext_0_5_v1
 3. Build the next release of Xvisor. It is available here:
  https://github.com/avpatel/xvisor-next
 4. Make sure you build the Xvisor tests, see here for details:
  
https://github.com/avpatel/xvisor-next/tree/master/tests/riscv/virt64/linux
 5. Run QEMU:
 ./riscv64-softmmu/qemu-system-riscv64 -nographic \
   -machine virt -cpu rv64,x-h=true \
   -serial mon:stdio -serial null -m 4G \
   -device loader,file=vmm.bin,addr=0x8020 \
   -kernel fw_jump.elf \
   -initrd vmm-disk-linux.img \
   -append "vmm.console=uart@1000 vmm.bootcmd=\"vfs mount initrd /;vfs 
run /boot.xscript;vfs cat /system/banner.txt\""

   Once you get to the prompt you can start the geust by running:
 guest kick guest0
   You can then bind to the serial port using:
 vserial bind guest0/uart0
   Then you can start Linux using:
 autoexec

 This was all tested with the mainline 5.2/5.3 kernels.

There is very early work on a Xen port as well which is avaliable here:
https://github.com/alistair23/xen/tree/alistair/riscv-port

ToDo/Issues
 - Get 32-bit fully working

v2:
 - Don't use riscv_cpu_set_force_hs_excep() for 2nd stage MMU fauls as
   the v0.5 spec has a specific fault
 - Address review comments
 - Rebase on master
 - Remove pointers for mstatus

Alistair Francis (35):
  target/riscv: Convert MIP CSR to target_ulong
  target/riscv: Add the Hypervisor extension
  target/riscv: Add the Hypervisor CSRs to CPUState
  target/riscv: Add support for the new execption numbers
  target/riscv: Rename the H irqs to VS irqs
  target/riscv: Add the virtulisation mode
  target/riscv: Add the force HS exception mode
  target/riscv: Fix CSR perm checking for HS mode
  target/riscv: Print priv and virt in disas log
  target/riscv: Dump Hypervisor registers if enabled
  target/riscv: Add Hypervisor CSR access functions
  target/riscv: Add Hypervisor virtual CSRs accesses
  target/riscv: Add Hypervisor machine CSRs accesses
  target/riscv: Add virtual register swapping function
  target/riscv: Set VS bits in mideleg for Hyp extension
  target/riscv: Extend the MIE CSR to support virtulisation
  target/riscv: Extend the SIP CSR to support virtulisation
  target/riscv: Add support for virtual interrupt setting
  target/ricsv: Flush the TLB on virtulisation mode changes
  target/riscv: Generate illegal instruction on WFI when V=1
  target/riscv: Add hypvervisor trap support
  target/riscv: Add Hypervisor trap return support
  target/riscv: Add hfence instructions
  target/riscv: Remove the hret instruction
  target/riscv: Only set TB flags with FP status if enabled
  target/riscv: Disable guest FP support based on virtual status
  target/riscv: Mark both sstatus and msstatus_hs as dirty
  target/riscv: Respect MPRV and SPRV for floating point ops
  target/riscv: Allow specifying MMU stage
  target/riscv: Implement second stage MMU
  target/riscv: Raise the new execptions when 2nd stage translation
fails
  target/riscv: Set htval and mtval2 on execptions
  target/riscv: Add support for the 32-bit MSTATUSH CSR
  target/riscv: Add the MSTATUS_MPV_ISSET helper macro
  target/riscv: Allow enabling the Hypervisor extension

 target/riscv/cpu.c|  57 ++-
 target/riscv/cpu.h|  58 ++-
 target/riscv/cpu_bits.h   | 111 ++--
 target/riscv/cpu_helper.c | 481 --
 target/riscv/csr.c

Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers

2020-01-31 Thread Alistair Francis
On Fri, Jan 31, 2020 at 9:31 AM Alistair Francis  wrote:
>
> On Thu, Jan 30, 2020 at 6:48 AM Palmer Dabbelt  
> wrote:
> >
> > On Tue, 21 Jan 2020 11:02:01 GMT (+), alistai...@gmail.com wrote:
> > > On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt  
> > > wrote:
> > >>
> > >> On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> > >> > To handle the new Hypervisor CSR register aliasing let's use pointers.
> > >>
> > >> For some reason I thought we were making this explicit?  In other words,
> > >> requiring that all callers provide which privilege mode they're using 
> > >> when
> > >> accessing these CSRs, as opposed to swapping around pointers.  I don't 
> > >> actually
> > >> care that much, but IIRC when we were talking with the ARM guys at 
> > >> Plumbers
> > >> they were pretty adament that would end up being a much cleaner 
> > >> implementation
> > >> as they'd tried this way and later changed over.
> > >
> > > I think their implementation is different so it doesn't apply the same 
> > > here.
> > >
> > > My main concern is that due to the modularity of RISC-V I don't expect
> > > all future developers to keep track of the Hypervisor extensions. This
> > > way we always have the correct state in the registers.
> > >
> > > There is only one pointer variable left, so we could drop the pointer
> > > swapping part, but for now it's still here.
> >
> > OK, so in the interest of moving things forwards let's just
> >
> > Reviewed-by: Palmer Dabbelt 
>
> Thanks
>
> >
> > so we can merge this -- it's too big of a patch set to wait around on 
> > something
> > so small for.  I think that was the last one missing a review, right?
>
> I have made one small change and dismissed your review from a patch,
> it also looks like one patch hasn't been reviewed either.
>
> I'll send a v2 later today that has been rebased on master.

After rebasing everything stopped working. While attempting to fix the
problem I remeoved this patch and managed to get it working again. So
now in v2 there are no CSR pointers, just value swapping for
everything.

I fixed a few bugs that I noticed related to FP, I have cleared your
review Palmer from a few patches. I'll send the v2 for review soon.
It's pretty similar to the v1 so should be easy to review.

Alistair

>
> Alistair
>
> >
> > >
> > > Alistair
> > >
> > >>
> > >> > Signed-off-by: Alistair Francis 
> > >> > ---
> > >> >  target/riscv/cpu.c| 11 +--
> > >> >  target/riscv/cpu.h|  9 -
> > >> >  target/riscv/cpu_helper.c | 30 +++---
> > >> >  target/riscv/csr.c| 20 ++--
> > >> >  target/riscv/op_helper.c  | 14 +++---
> > >> >  5 files changed, 49 insertions(+), 35 deletions(-)
> > >> >
> > >> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > >> > index a07c5689b3..e61cf46a73 100644
> > >> > --- a/target/riscv/cpu.c
> > >> > +++ b/target/riscv/cpu.c
> > >> > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, 
> > >> > FILE *f, int flags)
> > >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc  ", env->pc);
> > >> >  #ifndef CONFIG_USER_ONLY
> > >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", 
> > >> > env->mhartid);
> > >> > -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
> > >> > env->mstatus);
> > >> > +qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
> > >> > *env->mstatus);
> > >> >  if (riscv_has_ext(env, RVH)) {
> > >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", 
> > >> > env->hstatus);
> > >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", 
> > >> > env->vsstatus);
> > >> > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
> > >> >  mcc->parent_reset(cs);
> > >> >  #ifndef CONFIG_USER_ONLY
> > >> >  env->priv = PRV_M;
> > >> > -env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> > >> > +*env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> > >> >  env->mcause = 0;
> > >> >  env->pc = env->resetvec;
> > >> >  #endif
> > >> > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, 
> > >> > Error **errp)
> > >> >  static void riscv_cpu_init(Object *obj)
> > >> >  {
> > >> >  RISCVCPU *cpu = RISCV_CPU(obj);
> > >> > +#ifndef CONFIG_USER_ONLY
> > >> > +CPURISCVState *env = >env;
> > >> > +#endif
> > >> >
> > >> >  cpu_set_cpustate_pointers(cpu);
> > >> > +
> > >> > +#ifndef CONFIG_USER_ONLY
> > >> > +env->mstatus = >mstatus_novirt;
> > >> > +#endif
> > >> >  }
> > >> >
> > >> >  static const VMStateDescription vmstate_riscv_cpu = {
> > >> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > >> > index 21ae5a8b19..9dc8303c62 100644
> > >> > --- a/target/riscv/cpu.h
> > >> > +++ b/target/riscv/cpu.h
> > >> > @@ -122,7 +122,7 @@ struct CPURISCVState {
> > >> >  target_ulong resetvec;
> > >> >
> > >> >  target_ulong mhartid;
> > >> > -target_ulong mstatus;
> > >> > +target_ulong 

[PATCH 0/1] tests/acceptance: Count Raspberry Pi logos displayed on framebuffer

2020-01-31 Thread Philippe Mathieu-Daudé
This is a simple Avocado test that use OpenCV to find the
4 Raspberry Pi logo on the framebuffer screen dump.

The resulting match can be visualised at:
https://pasteboard.co/ISzNHtx.png

It is very fast, around 11 seconds on my laptop.

The test probably won't stay in boot_linux_console.py but will
go into tests/acceptance/machine_arm_raspi.py, but I wanted to
show this test could work to test SMP CPUs.

Similar test: "integratorcp: Verify Tux is displayed on framebuffer"
https://lists.gnu.org/archive/html/qemu-devel/2020-01/msg08103.html

Philippe Mathieu-Daudé (1):
  tests/acceptance: Count Raspberry Pi logos displayed on framebuffer

 tests/acceptance/boot_linux_console.py | 62 ++
 1 file changed, 62 insertions(+)

-- 
2.21.1




[PATCH 1/1] tests/acceptance: Count Raspberry Pi logos displayed on framebuffer

2020-01-31 Thread Philippe Mathieu-Daudé
Add a test that verifies that each core properly displays the
Raspberry Pi logo on the framebuffer device.

We simply follow the OpenCV "Template Matching with Multiple Objects"
tutorial, replacing Lionel Messi by a raspberrry:
https://docs.opencv.org/4.2.0/d4/dc6/tutorial_py_template_matching.html

When OpenCV and NumPy are installed, this test can be run using:

  $ avocado --show=app,framebuffer run -t device:bcm2835-fb tests/acceptance/
  JOB ID : 9bbbc54c0a6fa180348d0b5305507f76852b4da2
  JOB LOG: avocado/job-results/job-2020-01-31T23.48-9bbbc54/job.log
   (1/1) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_raspi2_framebuffer_logo:
  framebuffer: found raspberry at position (x, y) = (0, 0)
  framebuffer: found raspberry at position (x, y) = (71, 0)
  framebuffer: found raspberry at position (x, y) = (142, 0)
  framebuffer: found raspberry at position (x, y) = (213, 0)
  PASS (11.06 s)
  RESULTS: PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | 
CANCEL 0
  JOB TIME   : 11.39 s

Signed-off-by: Philippe Mathieu-Daudé 
---
The resulting match can be visualised at https://pasteboard.co/ISzNHtx.png
---
 tests/acceptance/boot_linux_console.py | 62 ++
 1 file changed, 62 insertions(+)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index e40b84651b..4e69a83a12 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -12,6 +12,7 @@ import os
 import lzma
 import gzip
 import shutil
+import logging
 
 from avocado import skipUnless
 from avocado_qemu import Test
@@ -21,6 +22,19 @@ from avocado.utils import process
 from avocado.utils import archive
 
 
+NUMPY_AVAILABLE = True
+try:
+import numpy as np
+except ImportError:
+NUMPY_AVAILABLE = False
+
+CV2_AVAILABLE = True
+try:
+import cv2
+except ImportError:
+CV2_AVAILABLE = False
+
+
 class BootLinuxConsole(Test):
 """
 Boots a Linux kernel and checks that the console is operational and the
@@ -360,6 +374,54 @@ class BootLinuxConsole(Test):
 """
 self.do_test_arm_raspi2(0)
 
+@skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed')
+@skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed')
+def test_arm_raspi2_framebuffer_logo(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:raspi2
+:avocado: tags=device:bcm2835-fb
+"""
+screendump_path = os.path.join(self.workdir, 'screendump.pbm')
+rpilogo_url = ('https://github.com/raspberrypi/linux/raw/'
+   'raspberrypi-kernel_1.20190517-1/'
+   'drivers/video/logo/logo_linux_clut224.ppm')
+rpilogo_hash = 'fff3cc20c6030acce0953147f9baac43f44ed6b0'
+rpilogo_path = self.fetch_asset(rpilogo_url, asset_hash=rpilogo_hash)
+deb_url = ('http://archive.raspberrypi.org/debian/'
+   'pool/main/r/raspberrypi-firmware/'
+   'raspberrypi-kernel_1.20190215-1_armhf.deb')
+deb_hash = 'cd284220b32128c5084037553db3c482426f3972'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path, '/boot/kernel7.img')
+dtb_path = self.extract_from_deb(deb_path, '/boot/bcm2709-rpi-2-b.dtb')
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'earlycon=pl011,0x3f201000 console=ttyAMA0')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+self.vm.launch()
+framebuffer_ready = 'Console: switching to colour frame buffer device'
+wait_for_console_pattern(self, framebuffer_ready)
+self.vm.command('human-monitor-command', command_line='stop')
+self.vm.command('human-monitor-command',
+command_line='screendump %s' % screendump_path)
+logger = logging.getLogger('framebuffer')
+
+cpu_cores_count = 4
+match_threshold = 0.95
+screendump_bgr = cv2.imread(screendump_path, cv2.IMREAD_COLOR)
+rpilogo_bgr = cv2.imread(rpilogo_path, cv2.IMREAD_COLOR)
+result = cv2.matchTemplate(screendump_bgr, rpilogo_bgr,
+   cv2.TM_CCOEFF_NORMED)
+loc = np.where(result >= match_threshold)
+rpilogo_count = 0
+for rpilogo_count, pt in enumerate(zip(*loc[::-1]), start=1):
+logger.debug('found raspberry at position (x, y) = %s', pt)
+self.assertGreaterEqual(rpilogo_count, cpu_cores_count)
+
 def test_arm_exynos4210_initrd(self):
 """
 :avocado: tags=arch:arm
-- 
2.21.1




Re: [PATCH v11 2/2] docs: qcow2: introduce compression type feature

2020-01-31 Thread Alberto Garcia
On Fri 31 Jan 2020 07:15:33 PM CET, Vladimir Sementsov-Ogievskiy wrote:

> I'm OK with it too, as well as I'm OK with the stricter variant, when
> we don't allow incompatible images with zlib set. I don't see any
> serious difference.

I also think both options are fine.

Berto



[PATCH v2] target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none

2020-01-31 Thread Liang Yan
>From commit e19afd56, we know target-arm restricts the list of
queryable cpu models to 'max', 'host', and the current type when
KVM is in use. The logic works well until using machine type none.

For machine type none, cpu_type will be null, and strlen(cpu_type)
will terminate process. So I add a check above it.

This won't affect i386 and s390x, because they are not invovled
current_cpu.

Signed-off-by: Liang Yan 
---
 v2: fix code style issue
---
 target/arm/monitor.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 9725dfff16..3350cd65d0 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -137,17 +137,19 @@ CpuModelExpansionInfo 
*qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 }
 
 if (kvm_enabled()) {
-const char *cpu_type = current_machine->cpu_type;
-int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
 bool supported = false;
 
 if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
 /* These are kvmarm's recommended cpu types */
 supported = true;
-} else if (strlen(model->name) == len &&
-   !strncmp(model->name, cpu_type, len)) {
-/* KVM is enabled and we're using this type, so it works. */
-supported = true;
+} else if (current_machine->cpu_type) {
+const char *cpu_type = current_machine->cpu_type;
+int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
+if (strlen(model->name) == len &&
+!strncmp(model->name, cpu_type, len)) {
+/* KVM is enabled and we're using this type, so it works. */
+supported = true;
+}
 }
 if (!supported) {
 error_setg(errp, "We cannot guarantee the CPU type '%s' works "
-- 
2.25.0




Re: [PATCH 10/11] target/arm: Implement ATS1E1 system registers

2020-01-31 Thread Richard Henderson
On 12/9/19 5:41 AM, Peter Maydell wrote:
>>  case 1:
>> -mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_Stage1_E1;
>> +if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
>> +mmu_idx = secure ? ARMMMUIdx_SE1_PAN : 
>> ARMMMUIdx_Stage1_E1_PAN;
>> +} else {
>> +mmu_idx = secure ? ARMMMUIdx_SE1 : ARMMMUIdx_Stage1_E1;
>> +}
> 
> This way of writing it is fine, but just to check my understanding:
> if the CPSR_PAN bit isn't set, then will a lookup via Idx_SE1_PAN
> and a lookup via Idx_SE1 return the same results?

No.

> Or do we guarantee that we only use the _PAN versions of the indexes
> if the PAN bit is actually active?

Yes.  We enforce the PAN behaviour based on *_PAN deep within a
get_phys_addr_lpae subroutine.  See patch 8.


r~



Re: [PATCH] target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none

2020-01-31 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20200131212742.18579-1-l...@suse.com/



Hi,

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

Subject: [PATCH] target/arm/monitor: query-cpu-model-expansion crashed qemu 
when using machine type none
Message-id: 20200131212742.18579-1-l...@suse.com
Type: series

=== 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 ===

From https://github.com/patchew-project/qemu
   aeab8e5..28db64f  master -> master
From https://github.com/patchew-project/qemu
 * [new tag] patchew/20200131212742.18579-1-l...@suse.com -> 
patchew/20200131212742.18579-1-l...@suse.com
Switched to a new branch 'test'
54bd33b target/arm/monitor: query-cpu-model-expansion crashed qemu when using 
machine type none

=== OUTPUT BEGIN ===
ERROR: code indent should never use tabs
#43: FILE: target/arm/monitor.c:149:
+^I^I^I!strncmp(model->name, cpu_type, len)) {$

ERROR: code indent should never use tabs
#44: FILE: target/arm/monitor.c:150:
+^I^I/* KVM is enabled and we're using this type, so it works. */$

ERROR: code indent should never use tabs
#45: FILE: target/arm/monitor.c:151:
+^I^Isupported = true;$

total: 3 errors, 0 warnings, 25 lines checked

Commit 54bd33b5bf01 (target/arm/monitor: query-cpu-model-expansion crashed qemu 
when using machine type none) has style problems, please review.  If any of 
these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20200131212742.18579-1-l...@suse.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [PATCH v1 23/36] target/riscv: Add hypvervisor trap support

2020-01-31 Thread Alistair Francis
On Mon, Jan 20, 2020 at 12:34 AM Jiangyifei  wrote:
>
> Hi Alistair,
>
> When I boot a riscv OS (the host) on the QEMU emulator and then boot a
> guest riscv OS in the host. The guest riscv OS fails to boot.
>
> The riscv OS is a linux kernel in the riscv_kvm_v10 branch, the qemu emulator
> is the riscv-hyp-ext-v0.5.next branch.
>
> The QEMU command line:
> ./qemu-system-riscv64 -M virt -m 4096M -cpu rv64,x-h=true -nographic \
> -smp 8 \
> -name guest=riscv-test,debug-threads=on \
> -kernel ./fw_jump.elf \
> -device loader,file=./Image,addr=0x8020 \
> -drive file=./hyp.img,format=raw,id=hd0 \
> -device virtio-blk-device,drive=hd0 \
> -append "root=/dev/vda rw console=ttyS0 earlycon=sbi"
>
> The kvmtool command line:
> ./lkvm-static run -m 2048 -c2 --console serial -p "console=ttyS0 \
> earlycon=uart8250,mmio,0x3f8" -k ./Image -d guest.img
>
> The error message is:
> [   46.136740] kvm [128]: VCPU exit error -14
> [   46.137967] kvm [128]: SEPC=0x3febbf234e SSTATUS=0x4020 HSTATUS=0x380
> [   46.140075] kvm [128]: SCAUSE=0x8 STVAL=0x0
> KVM_RUN failed: Bad address
>
> According to the error message printed by kvm, the exception of Environment
> call from VU-mode should to be delivered to VS-mode, instead of delivered
> to kvm in HS-mode.
>
> The problem is that the FORCE_HS_EXCEP flag is set when there is a pending
> irq that should trap to V==0, but this bit is not cleared in  
> riscv_cpu_do_interrupt
> when trapping to M-mode. So clearing FORCE_HS_EXCEP flag when trap to
> M-mode. The patch is as follows:
>
> Signed-off-by: Jiang Yifei 
> ---
> target/riscv/cpu_helper.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 7166e61..cb6a1d6 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -954,6 +954,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>
> /* Trapping to M mode, virt is disabled */
> riscv_cpu_set_virt_enabled(env, 0);
> +riscv_cpu_set_force_hs_excep(env, 0);
> }
>
> s = *env->mstatus;

Thanks, I think you are correct and I have included this change in my patch.

Alistair

> --
>
> Regards,
> Yifei
>
> > -Original Message-
> > From: Qemu-riscv [mailto:qemu-riscv-
> > bounces+jiangyifei=huawei@nongnu.org] On Behalf Of Alistair Francis
> > Sent: Tuesday, December 10, 2019 2:12 AM
> > To: qemu-devel@nongnu.org; qemu-ri...@nongnu.org
> > Cc: alistair.fran...@wdc.com; pal...@dabbelt.com; alistai...@gmail.com
> > Subject: [PATCH v1 23/36] target/riscv: Add hypvervisor trap support
> >
> > Signed-off-by: Alistair Francis 
> > Reviewed-by: Palmer Dabbelt 
> > ---
> >  target/riscv/cpu_helper.c | 65 +---
> > ---
> >  1 file changed, 55 insertions(+), 10 deletions(-)
> >
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index
> > 1b747abf93..2c6d2bc3a3 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -641,6 +641,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >
> >  RISCVCPU *cpu = RISCV_CPU(cs);
> >  CPURISCVState *env = >env;
> > +target_ulong s;
> >
> >  /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
> >   * so we mask off the MSB and separate into trap type and cause.
> > @@ -650,13 +651,6 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >  target_ulong deleg = async ? env->mideleg : env->medeleg;
> >  target_ulong tval = 0;
> >
> > -static const int ecall_cause_map[] = {
> > -[PRV_U] = RISCV_EXCP_U_ECALL,
> > -[PRV_S] = RISCV_EXCP_S_ECALL,
> > -[PRV_H] = RISCV_EXCP_VS_ECALL,
> > -[PRV_M] = RISCV_EXCP_M_ECALL
> > -};
> > -
> >  if (!async) {
> >  /* set tval to badaddr for traps with address information */
> >  switch (cause) {
> > @@ -680,7 +674,16 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >  /* ecall is dispatched as one cause so translate based on mode */
> >  if (cause == RISCV_EXCP_U_ECALL) {
> >  assert(env->priv <= 3);
> > -cause = ecall_cause_map[env->priv];
> > +
> > +if (env->priv == PRV_M) {
> > +cause = RISCV_EXCP_M_ECALL;
> > +} else if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) {
> > +cause = RISCV_EXCP_VS_ECALL;
> > +} else if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) 
> > {
> > +cause = RISCV_EXCP_S_ECALL;
> > +} else if (env->priv == PRV_U) {
> > +cause = RISCV_EXCP_U_ECALL;
> > +}
> >  }
> >  }
> >
> > @@ -690,7 +693,36 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >  if (env->priv <= PRV_S &&
> >  cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) {
> >  /* handle the trap in S-mode */
> > -target_ulong s = 

[PATCH] target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none

2020-01-31 Thread Liang Yan
>From commit e19afd56, we know target-arm restricts the list of
queryable cpu models to 'max', 'host', and the current type when
KVM is in use. The logic works well until using machine type none.

For machine type none, cpu_type will be null, and strlen(cpu_type)
will terminate process. So I add a check above it.

This won't affect i386 and s390x, because they are not invovled
current_cpu.

Signed-off-by: Liang Yan 
---
 target/arm/monitor.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/target/arm/monitor.c b/target/arm/monitor.c
index 9725dfff16..0c0130c1af 100644
--- a/target/arm/monitor.c
+++ b/target/arm/monitor.c
@@ -137,17 +137,19 @@ CpuModelExpansionInfo 
*qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 }
 
 if (kvm_enabled()) {
-const char *cpu_type = current_machine->cpu_type;
-int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
 bool supported = false;
 
 if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
 /* These are kvmarm's recommended cpu types */
 supported = true;
-} else if (strlen(model->name) == len &&
-   !strncmp(model->name, cpu_type, len)) {
-/* KVM is enabled and we're using this type, so it works. */
-supported = true;
+} else if (current_machine->cpu_type) {
+const char *cpu_type = current_machine->cpu_type;
+int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
+if (strlen(model->name) == len &&
+   !strncmp(model->name, cpu_type, len)) {
+   /* KVM is enabled and we're using this type, so it works. */
+   supported = true;
+}
 }
 if (!supported) {
 error_setg(errp, "We cannot guarantee the CPU type '%s' works "
-- 
2.25.0




[Bug 1861404] Re: AVX instruction VMOVDQU implementation error for YMM registers

2020-01-31 Thread Richard Henderson
Because the sse code is sloppy, and it was interpreted
as the sse instruction movdqu.

AVX support was coded for GSoC last year,

https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg05369.html

but it has not been completely reviewed and committed.

There is no support for AVX in master.

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

Title:
  AVX instruction VMOVDQU implementation error for YMM registers

Status in QEMU:
  New

Bug description:
  Hi,

  Tested with Qemu 4.2.0, and with git version
  bddff6f6787c916b0e9d63ef9e4d442114257739.

  The x86 AVX instruction VMOVDQU doesn't work properly with YMM registers (32 
bytes).
  It works with XMM registers (16 bytes) though.

  See the attached test case `ymm.c`: when copying from memory-to-ymm0
  and then back from ymm0-to-memory using VMOVDQU, Qemu only copies the
  first 16 of the total 32 bytes.

  ```
  user@ubuntu ~/Qemu % gcc -o ymm ymm.c -Wall -Wextra -Werror

  user@ubuntu ~/Qemu % ./ymm
  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 
1A 1B 1C 1D 1E 1F

  user@ubuntu ~/Qemu % ./x86_64-linux-user/qemu-x86_64 -cpu max ymm
  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00
  ```

  This seems to be because in `translate.c > gen_sse()`, the case
  handling the VMOVDQU instruction calls `gen_ldo_env_A0` which always
  performs a 16 bytes copy using two 8 bytes load and store operations
  (with `tcg_gen_qemu_ld_i64` and `tcg_gen_st_i64`).

  Instead, the `gen_ldo_env_A0` function should generate a copy with a
  size corresponding to the used register.

  
  ```
  static void gen_sse(CPUX86State *env, DisasContext *s, int b,
  target_ulong pc_start, int rex_r)
  {
  [...]
  case 0x26f: /* movdqu xmm, ea */
  if (mod != 3) {
  gen_lea_modrm(env, s, modrm);
  gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
  } else { 
  [...]
  ```

  ```
  static inline void gen_ldo_env_A0(DisasContext *s, int offset)
  {
  int mem_index = s->mem_index;
  tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
  tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
  tcg_gen_addi_tl(s->tmp0, s->A0, 8);
  tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
  tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
  }
  ```

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



[PATCH 1/2] tests/acceptance: Extract boot_integratorcp() from test_integratorcp()

2020-01-31 Thread Philippe Mathieu-Daudé
As we want to re-use this code, extract it as a new function.
Since we are using the PL011 serial console, add a Avocado tag
to ease filtering of tests.

Signed-off-by: Philippe Mathieu-Daudé 
---
 tests/acceptance/machine_arm_integratorcp.py | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/tests/acceptance/machine_arm_integratorcp.py 
b/tests/acceptance/machine_arm_integratorcp.py
index 4f9ab40f2f..748819916d 100644
--- a/tests/acceptance/machine_arm_integratorcp.py
+++ b/tests/acceptance/machine_arm_integratorcp.py
@@ -19,12 +19,7 @@ class IntegratorMachine(Test):
 
 timeout = 90
 
-@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
-def test_integratorcp(self):
-"""
-:avocado: tags=arch:arm
-:avocado: tags=machine:integratorcp
-"""
+def boot_integratorcp(self):
 kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
   'arm-test/kernel/zImage.integrator')
 kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
@@ -40,4 +35,13 @@ class IntegratorMachine(Test):
  '-initrd', initrd_path,
  '-append', 'printk.time=0 console=ttyAMA0')
 self.vm.launch()
+
+@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
+def test_integratorcp(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:integratorcp
+:avocado: tags=device:pl011
+"""
+self.boot_integratorcp()
 wait_for_console_pattern(self, 'Log in as root')
-- 
2.21.1




[PATCH 0/2] tests/acceptance/integratorcp: Verify Tux is displayed on framebuffer

2020-01-31 Thread Philippe Mathieu-Daudé
Hi,

This is a simple Avocado test that use OpenCV to find the
Tux logo on the framebuffer screen dump.

It is very fast, around 4 seconds on my laptop.

Tux found by OpenCV: https://pasteboard.co/ISz7kr8.png

Regards,

Phil.

Based-on: <20200131170233.14584-1-th...@redhat.com>
"tests/acceptance: Add a test for the integratorcp arm machine"
https://www.mail-archive.com/qemu-devel@nongnu.org/msg675828.html

Philippe Mathieu-Daudé (2):
  tests/acceptance: Extract boot_integratorcp() from test_integratorcp()
  tests/acceptance/integratorcp: Verify Tux is displayed on framebuffer

 tests/acceptance/machine_arm_integratorcp.py | 67 ++--
 1 file changed, 61 insertions(+), 6 deletions(-)

-- 
2.21.1




[PATCH 2/2] tests/acceptance/integratorcp: Verify Tux is displayed on framebuffer

2020-01-31 Thread Philippe Mathieu-Daudé
Add a test that verifies the Tux logo is displayed on the framebuffer.

We simply follow the OpenCV "Template Matching with Multiple Objects"
tutorial, replacing Lionel Messi by Tux:
https://docs.opencv.org/4.2.0/d4/dc6/tutorial_py_template_matching.html

When OpenCV and NumPy are installed, this test can be run using:

  $ AVOCADO_ALLOW_UNTRUSTED_CODE=hmmm \
avocado --show=app,framebuffer run -t device:framebuffer \
  tests/acceptance/machine_arm_integratorcp.py
  JOB ID : 8c46b0f8269242e87d738247883ea2a470df949e
  JOB LOG: avocado/job-results/job-2020-01-31T21.38-8c46b0f/job.log
   (1/1) 
tests/acceptance/machine_arm_integratorcp.py:IntegratorMachine.test_framebuffer_tux_logo:
  framebuffer: found Tux at position [x, y] = (0, 0)
  PASS (3.96 s)
  RESULTS: PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | 
CANCEL 0
  JOB TIME   : 4.23 s

Signed-off-by: Philippe Mathieu-Daudé 
---
The resulting match is https://pasteboard.co/ISz7kr8.png

For matching SMP machines, these suggestion might work:
https://stackoverflow.com/questions/50579050/template-matching-with-multiple-objects-in-opencv-python
---
 tests/acceptance/machine_arm_integratorcp.py | 51 
 1 file changed, 51 insertions(+)

diff --git a/tests/acceptance/machine_arm_integratorcp.py 
b/tests/acceptance/machine_arm_integratorcp.py
index 748819916d..a706fe1b44 100644
--- a/tests/acceptance/machine_arm_integratorcp.py
+++ b/tests/acceptance/machine_arm_integratorcp.py
@@ -9,11 +9,26 @@
 # later.  See the COPYING file in the top-level directory.
 
 import os
+import logging
 
 from avocado import skipUnless
 from avocado_qemu import Test
 from avocado_qemu import wait_for_console_pattern
 
+
+NUMPY_AVAILABLE = True
+try:
+import numpy as np
+except ImportError:
+NUMPY_AVAILABLE = False
+
+CV2_AVAILABLE = True
+try:
+import cv2
+except ImportError:
+CV2_AVAILABLE = False
+
+
 class IntegratorMachine(Test):
 """Boots the Linux kernel and checks that the console is operational"""
 
@@ -45,3 +60,39 @@ class IntegratorMachine(Test):
 """
 self.boot_integratorcp()
 wait_for_console_pattern(self, 'Log in as root')
+
+@skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed')
+@skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed')
+@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
+def test_framebuffer_tux_logo(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:integratorcp
+:avocado: tags=device:pl110
+:avocado: tags=device:framebuffer
+"""
+screendump_path = os.path.join(self.workdir, "screendump.pbm")
+tuxlogo_url = ('https://github.com/torvalds/linux/raw/v2.6.12/'
+   'drivers/video/logo/logo_linux_vga16.ppm')
+tuxlogo_hash = '3991c2ddbd1ddaecda7601f8aafbcf5b02dc86af'
+tuxlogo_path = self.fetch_asset(tuxlogo_url, asset_hash=tuxlogo_hash)
+
+self.boot_integratorcp()
+framebuffer_ready = 'Console: switching to colour frame buffer device'
+wait_for_console_pattern(self, framebuffer_ready)
+self.vm.command('human-monitor-command', command_line='stop')
+self.vm.command('human-monitor-command',
+command_line='screendump %s' % screendump_path)
+logger = logging.getLogger('framebuffer')
+
+cpu_count = 1
+match_threshold = 0.92
+screendump_bgr = cv2.imread(screendump_path)
+screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY)
+result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 
0),
+   cv2.TM_CCOEFF_NORMED)
+loc = np.where(result >= match_threshold)
+tux_count = 0
+for tux_count, pt in enumerate(zip(*loc[::-1]), start=1):
+logger.debug('found Tux at position [x, y] = %s', pt)
+self.assertGreaterEqual(tux_count, cpu_count)
-- 
2.21.1




[Bug 1823790] Re: QEMU mishandling of SO_PEERSEC forces systemd into tight loop

2020-01-31 Thread Laurent Vivier
Could you test the attached patch?

** Patch added: "Implement SO_PEERSEC"
   
https://bugs.launchpad.net/qemu/+bug/1823790/+attachment/5324494/+files/0001-linux-user-implement-TARGET_SO_PEERSEC.patch

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

Title:
  QEMU mishandling of SO_PEERSEC forces systemd into tight loop

Status in QEMU:
  Confirmed

Bug description:
  While building Debian images for embedded ARM target systems I
  detected that QEMU seems to force newer systemd daemons into a tight
  loop.

  My setup is the following:

  Host machine: Ubuntu 18.04, amd64
  LXD container: Debian Buster, arm64, systemd 241
  QEMU: qemu-aarch64-static, 4.0.0-rc2 (custom build) and 3.1.0 (Debian 
1:3.1+dfsg-7)

  To easily reproduce the issue I have created the following repository:
  https://github.com/lueschem/edi-qemu

  The call where systemd gets looping is the following:
  2837 getsockopt(3,1,31,274891889456,274887218756,274888927920) = -1 errno=34 
(Numerical result out of range)

  Furthermore I also verified that the issue is not related to LXD.
  The same behavior can be reproduced using systemd-nspawn.

  This issue reported against systemd seems to be related:
  https://github.com/systemd/systemd/issues/11557

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



Re: [RFC PATCH v1 5/8] vfio-ccw: Add support for the schib region

2020-01-31 Thread Eric Farman
[Had two un-addressed QEMU comments on my todo list; let's do that now.]

On 11/20/19 6:13 AM, Cornelia Huck wrote:
> On Fri, 15 Nov 2019 04:34:34 +0100
> Eric Farman  wrote:
> 
>> From: Farhan Ali 
>>
>> The schib region can be used to obtain the latest SCHIB from the host
>> passthrough subchannel. Since the guest SCHIB is virtualized,
>> we currently only update the path related information so that the
>> guest is aware of any path related changes when it issues the
>> 'stsch' instruction.
> 
> One important information here is that you tweak the generic stsch
> handling, although the behaviour remains the same for non-vfio
> subchannels.
> 
>>
>> Signed-off-by: Farhan Ali 
>> Signed-off-by: Eric Farman 
>> ---
>>
>> Notes:
>> v0->v1: [EF]
>>  - Change various incarnations of "update chp status" to
>>"handle_store", to reflect the STSCH instruction that will
>>drive this code
>>  - Remove temporary variable for casting/testing purposes in
>>s390_ccw_store(), and add a block comment of WHY its there.
>>  - Add a few comments to vfio_ccw_handle_store()
>>
>>  hw/s390x/css.c  |  8 --
>>  hw/s390x/s390-ccw.c | 20 +
>>  hw/vfio/ccw.c   | 57 +
>>  include/hw/s390x/css.h  |  3 +-
>>  include/hw/s390x/s390-ccw.h |  1 +
>>  target/s390x/ioinst.c   |  3 +-
>>  6 files changed, 87 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
>> index 844caab408..6ee6a96d75 100644
>> --- a/hw/s390x/css.c
>> +++ b/hw/s390x/css.c
>> @@ -1335,11 +1335,15 @@ static void copy_schib_to_guest(SCHIB *dest, const 
>> SCHIB *src)
>>  }
>>  }
>>  
>> -int css_do_stsch(SubchDev *sch, SCHIB *schib)
>> +IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib)
>>  {
>> +int ret = IOINST_CC_EXPECTED;
> 
> It's a bit useless initializing ret here, given that you use it right
> below :)
> 
>> +
> 
> Maybe add a comment here:
> 
>/*
> * For some subchannels, we may want to update parts of
> * the schib (e.g. update path masks from the host device
> * for passthrough subchannels).
> */
> 
>> +ret = s390_ccw_store(sch);
>> +
>>  /* Use current status. */
>>  copy_schib_to_guest(schib, >curr_status);
>> -return 0;
>> +return ret;
>>  }
>>  
>>  static void copy_pmcw_from_guest(PMCW *dest, const PMCW *src)
>> diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
>> index 0c5a5b60bd..be0b379338 100644
>> --- a/hw/s390x/s390-ccw.c
>> +++ b/hw/s390x/s390-ccw.c
>> @@ -51,6 +51,26 @@ int s390_ccw_clear(SubchDev *sch)
>>  return cdc->handle_clear(sch);
>>  }
>>  
>> +IOInstEnding s390_ccw_store(SubchDev *sch)
>> +{
>> +S390CCWDeviceClass *cdc = NULL;
>> +int ret = IOINST_CC_EXPECTED;
>> +
>> +/*
>> + * This only applies to passthrough devices, so we can't unconditionally
>> + * set this variable like we would for halt/clear.
> 
> Hm, can we maybe handle this differently? We have a generic ccw_cb in
> the subchannel structure for ccw interpretation; would it make sense to
> add a generic callback for stsch there as well?

Might make things a little cleaner, but I am not sure.  I'm going to
leave a todo here while we sort out the rest of the kernel code, so I
can try to put something more beneficial together.

> 
> (This works fine, though. Might want to add the check for halt/clear as
> well, but that might be a bit overkill.)
> 
>> + */
>> +if (object_dynamic_cast(OBJECT(sch->driver_data), TYPE_S390_CCW)) {
>> +cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data);
>> +}
>> +
>> +if (cdc && cdc->handle_store) {
>> +ret = cdc->handle_store(sch);
>> +}
>> +
>> +return ret;
>> +}
>> +
>>  static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
>>char *sysfsdev,
>>Error **errp)
>> diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
>> index 3e32bc1819..2ff223470f 100644
>> --- a/hw/vfio/ccw.c
>> +++ b/hw/vfio/ccw.c
>> @@ -41,6 +41,9 @@ struct VFIOCCWDevice {
>>  uint64_t async_cmd_region_size;
>>  uint64_t async_cmd_region_offset;
>>  struct ccw_cmd_region *async_cmd_region;
>> +uint64_t schib_region_size;
>> +uint64_t schib_region_offset;
>> +struct ccw_schib_region *schib_region;
>>  EventNotifier io_notifier;
>>  bool force_orb_pfch;
>>  bool warned_orb_pfch;
>> @@ -124,6 +127,45 @@ again:
>>  }
>>  }
>>  
>> +static IOInstEnding vfio_ccw_handle_store(SubchDev *sch)
>> +{
>> +S390CCWDevice *cdev = sch->driver_data;
>> +VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
>> +SCHIB *schib = >curr_status;
>> +struct ccw_schib_region *region = vcdev->schib_region;
>> +SCHIB *s = (SCHIB *)region->schib_area;
> 
> You probably don't want to access region until after you checked it's
> not NULL :)

:)

> 
>> +int ret;
>> +
>> +/* schib 

Re: [PATCH v5 30/41] target/arm: Flush tlb for ASID changes in EL2&0 translation regime

2020-01-31 Thread Richard Henderson
On 1/31/20 5:11 AM, Peter Maydell wrote:
>>  { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH,
>>.opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2,
>> -  .access = PL2_RW,
>> -  /* no .writefn needed as this can't cause an ASID change;
>> -   * no .raw_writefn or .resetfn needed as we never use mask/base_mask
>> -   */
>> +  .access = PL2_RW, .writefn = vmsa_tcr_el12_write,
> 
> This blows away the entire TLB on a TCR_EL2 write, which is
> safe but a bit overzealous; we could skip it if E2H was clear
> (and probably also be a bit more precise about which TLB
> indexes to clear). But it's not a big deal so I'm happy if
> we leave this as-is.

Yes, it is overzealous.

I once had a patch set that attempted to track actual ASID changes and also
contained the set of tlb indexes to clear.  I thought about incorporating that
here, but decided against.


r~



Re: [PATCH v5 02/41] target/arm: Enable HCR_E2H for VHE

2020-01-31 Thread Richard Henderson
On 1/31/20 5:06 AM, Peter Maydell wrote:
> On Wed, 29 Jan 2020 at 23:56, Richard Henderson
>  wrote:
>>
>> Reviewed-by: Alex Bennée 
>> Signed-off-by: Richard Henderson 
>> ---
>>  target/arm/cpu.h| 7 ---
>>  target/arm/helper.c | 6 +-
>>  2 files changed, 5 insertions(+), 8 deletions(-)
>>
>> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
>> index 0477cef1ea..239c9eb783 100644
>> --- a/target/arm/cpu.h
>> +++ b/target/arm/cpu.h
>> @@ -1417,13 +1417,6 @@ static inline void xpsr_write(CPUARMState *env, 
>> uint32_t val, uint32_t mask)
>>  #define HCR_ATA   (1ULL << 56)
>>  #define HCR_DCT   (1ULL << 57)
>>
>> -/*
>> - * When we actually implement ARMv8.1-VHE we should add HCR_E2H to
>> - * HCR_MASK and then clear it again if the feature bit is not set in
>> - * hcr_write().
>> - */
>> -#define HCR_MASK  ((1ULL << 34) - 1)
>> -
>>  #define SCR_NS(1U << 0)
>>  #define SCR_IRQ   (1U << 1)
>>  #define SCR_FIQ   (1U << 2)
>> diff --git a/target/arm/helper.c b/target/arm/helper.c
>> index 19a57a17da..f5ce05fdf3 100644
>> --- a/target/arm/helper.c
>> +++ b/target/arm/helper.c
>> @@ -4721,7 +4721,8 @@ static const ARMCPRegInfo el3_no_el2_v8_cp_reginfo[] = 
>> {
>>  static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t 
>> value)
>>  {
>>  ARMCPU *cpu = env_archcpu(env);
>> -uint64_t valid_mask = HCR_MASK;
>> +/* Begin with bits defined in base ARMv8.0.  */
>> +uint64_t valid_mask = MAKE_64BIT_MASK(0, 34);
>>
>>  if (arm_feature(env, ARM_FEATURE_EL3)) {
>>  valid_mask &= ~HCR_HCD;
>> @@ -4735,6 +4736,9 @@ static void hcr_write(CPUARMState *env, const 
>> ARMCPRegInfo *ri, uint64_t value)
>>   */
>>  valid_mask &= ~HCR_TSC;
>>  }
>> +if (cpu_isar_feature(aa64_vh, cpu)) {
>> +valid_mask |= HCR_E2H;
>> +}
>>  if (cpu_isar_feature(aa64_lor, cpu)) {
>>  valid_mask |= HCR_TLOR;
>>  }
> 
> Should HCR_E2H be in the list of bits for which we do
> a tlb_flush () in hcr_write()? (Currently we do this for
> VM, PTW and DC.) Given some of the later TLB-flushing
> changes have code that is "we only need to flush these
> TLB indexes when this register is written if E2H==1",
> it makes it easier to be sure we have the right behaviour
> if we don't need to think through scenarios of "write
> to the register, then set E2H==1"...

I don't think so, because when E2H changes, we change mmu_idx entirely.
Between E2 and E20_2 for el2, and (if TGE is also set) E10_0 and E20_0 for el0.


r~



Re: [PATCH rc4 01/29] target/avr: Add basic parameters for new AVR platform

2020-01-31 Thread Aleksandar Markovic
On Friday, January 31, 2020, Aleksandar Markovic <
aleksandar.marko...@rt-rk.com> wrote:

> From: Michael Rolnik 
>
> This includes definitions of various basic parameters needed
> for integration of a new platform into QEMU.
>
>
Hi, all.

Just to keep everyone in the loop:

I'll try to put together rc5 in next few days, with a number of relatvely
minor changes (Alex/Philippe improvments and some more). Let me know if
this doesn't work for you for any reason.

Igor, a special question to you:

You already gave Acked-by for former patch 1, which is now transformed to
patches 1-6. I gather you are familiar with all topics involved. Could you
perhaps taje a closer look at patches 1-6 now, and, if you are happy with
what you see, perhaps you can give Reviewed-by to them?

Thanks, Aleksandar



> [AM: Split a larger AVR introduction patch into logical units]
> Suggested-by: Aleksandar Markovic 
>
> Co-developed-by: Michael Rolnik 
> Co-developed-by: Sarah Harris 
> Signed-off-by: Michael Rolnik 
> Signed-off-by: Sarah Harris 
> Signed-off-by: Michael Rolnik 
> Acked-by: Igor Mammedov 
> Tested-by: Philippe Mathieu-Daudé 
> Signed-off-by: Richard Henderson 
> Signed-off-by: Aleksandar Markovic 
> ---
>  target/avr/cpu-param.h | 37 ++
>  target/avr/cpu.h   | 72 ++
> 
>  2 files changed, 109 insertions(+)
>  create mode 100644 target/avr/cpu-param.h
>  create mode 100644 target/avr/cpu.h
>
> diff --git a/target/avr/cpu-param.h b/target/avr/cpu-param.h
> new file mode 100644
> index 000..0c29ce4
> --- /dev/null
> +++ b/target/avr/cpu-param.h
> @@ -0,0 +1,37 @@
> +/*
> + * QEMU AVR CPU
> + *
> + * Copyright (c) 2019 Michael Rolnik
> + *
> + * 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
> + * 
> + */
> +
> +#ifndef AVR_CPU_PARAM_H
> +#define AVR_CPU_PARAM_H
> +
> +#define TARGET_LONG_BITS 32
> +/*
> + * TARGET_PAGE_BITS cannot be more than 8 bits because
> + * 1.  all IO registers occupy [0x .. 0x00ff] address range, and they
> + * should be implemented as a device and not memory
> + * 2.  SRAM starts at the address 0x0100
> + */
> +#define TARGET_PAGE_BITS 8
> +#define TARGET_PHYS_ADDR_SPACE_BITS 24
> +#define TARGET_VIRT_ADDR_SPACE_BITS 24
> +#define NB_MMU_MODES 2
> +
> +
> +#endif
> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
> new file mode 100644
> index 000..d122611
> --- /dev/null
> +++ b/target/avr/cpu.h
> @@ -0,0 +1,72 @@
> +/*
> + * QEMU AVR CPU
> + *
> + * Copyright (c) 2019 Michael Rolnik
> + *
> + * 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
> + * 
> + */
> +
> +#ifndef QEMU_AVR_CPU_H
> +#define QEMU_AVR_CPU_H
> +
> +#include "cpu-qom.h"
> +#include "exec/cpu-defs.h"
> +
> +#define TCG_GUEST_DEFAULT_MO 0
> +#define AVR_CPU_TYPE_SUFFIX "-" TYPE_AVR_CPU
> +#define AVR_CPU_TYPE_NAME(name) (name AVR_CPU_TYPE_SUFFIX)
> +#define CPU_RESOLVING_TYPE TYPE_AVR_CPU
> +
> +/*
> + * AVR has two memory spaces, data & code.
> + * e.g. both have 0 address
> + * ST/LD instructions access data space
> + * LPM/SPM and instruction fetching access code memory space
> + */
> +#define MMU_CODE_IDX 0
> +#define MMU_DATA_IDX 1
> +
> +#define EXCP_RESET 1
> +#define EXCP_INT(n) (EXCP_RESET + (n) + 1)
> +
> +/* Number of CPU registers */
> +#define NUMBER_OF_CPU_REGISTERS 32
> +/* Number of IO registers accessible by ld/st/in/out */
> +#define NUMBER_OF_IO_REGISTERS 64
> +
> +/*
> + * Offsets of AVR memory regions in host memory space.
> + *
> + * This is needed because the AVR has separate code and data address
> + * spaces that both have start from zero but have to go somewhere in
> + * host memory.
> + *
> + * It's also 

[Bug 1860610] Re: cap_disas_plugin leaks memory

2020-01-31 Thread Robert Henry
I run git blame in the capstone repository, and cs_free has been around
for at least 4 years in the capstone ABI. I can not tell if the need to
call cs_free is a (new) requirement. Documentation capstone is a little
informal...

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

Title:
  cap_disas_plugin leaks memory

Status in QEMU:
  New

Bug description:
  Looking at origin/master head, the function cap_disas_plugin leaks
  memory.

  per capstone's examples using their ABI, cs_free(insn, count); needs
  to called just before cs_close.

  I discovered this running qemu under valgrind.

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



Re: [PATCH] block/backup-top: fix flags handling

2020-01-31 Thread Eric Blake

On 1/31/20 12:48 PM, Vladimir Sementsov-Ogievskiy wrote:

backup-top "supports" write-unchanged, by skipping CBW operation in
backup_top_co_pwritev. But it forgets to do the same in
backup_top_co_pwrite_zeroes, as well as declare support for
BDRV_REQ_WRITE_UNCHANGED.

Fix this, and, while being here, declare also support for flags
supported by source child.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
  block/backup-top.c | 28 ++--
  1 file changed, 18 insertions(+), 10 deletions(-)




@@ -197,6 +201,10 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState 
*source,
  
  top->total_sectors = source->total_sectors;

  state = top->opaque;
+top->supported_write_flags =
+BDRV_REQ_WRITE_UNCHANGED | source->supported_write_flags;
+top->supported_zero_flags =
+BDRV_REQ_WRITE_UNCHANGED | source->supported_zero_flags;


Elsewhere, in block/filter-compress.c we do:

bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
(BDRV_REQ_FUA & bs->file->bs->supported_write_flags);

bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
bs->file->bs->supported_zero_flags);

That's slightly more robust (if the block layer adds new BDRV_REQ_ bits, 
we don't have to revisit filter-compress.c to decide if blindly exposing 
those bits breaks for some reason, but rahter DO have to amend the line 
to opt-in to supporting the new bits).  Whereas your code does NOT need 
editing if passing on the new bit is safe, but risks a subtle breakage 
if we forget to filter out the new bit when passing it on would be 
unsafe.  I tend to lean towards safety and opt-in over blind 
pass-through that works with the current set of defined bits, but not 
enough to withhold:


Reviewed-by: Eric Blake 

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v2 2/5] migretion/block-dirty-bitmap: refactor init_dirty_bitmap_migration

2020-01-31 Thread Eric Blake

On 12/19/19 2:51 AM, Vladimir Sementsov-Ogievskiy wrote:

In the subject: s/migretion/migration/


Split out handling one bs, it is needed for the following commit, which
will handle BlockBackends in separate.


s/in separate/separately/



Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
  migration/block-dirty-bitmap.c | 89 +++---
  1 file changed, 49 insertions(+), 40 deletions(-)




+++ b/migration/block-dirty-bitmap.c
@@ -268,57 +268,66 @@ static void dirty_bitmap_mig_cleanup(void)


  
-for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) {

-const char *name = bdrv_get_device_or_node_name(bs);
+if (!bs_name || strcmp(bs_name, "") == 0) {
+error_report("Found bitmap '%s' in unnamed node %p. It can't "
+ "be migrated", bdrv_dirty_bitmap_name(bitmap), bs);


error_report() generally avoids multiple sentences.


+return -1;
+}
  
-FOR_EACH_DIRTY_BITMAP(bs, bitmap) {

-if (!bdrv_dirty_bitmap_name(bitmap)) {
-continue;
-}
+if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, _err)) {
+error_report_err(local_err);
+return -1;
+}
  
-if (!name || strcmp(name, "") == 0) {

-error_report("Found bitmap '%s' in unnamed node %p. It can't "
- "be migrated", bdrv_dirty_bitmap_name(bitmap), 
bs);


But as this was just code motion,

Reviewed-by: Eric Blake 

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v2 1/5] block: Mark commit and mirror as filter drivers

2020-01-31 Thread Eric Blake

On 12/19/19 2:51 AM, Vladimir Sementsov-Ogievskiy wrote:

From: Max Reitz 

The commit and mirror block nodes are filters, so they should be marked
as such.

Signed-off-by: Max Reitz 
Signed-off-by: Vladimir Sementsov-Ogievskiy 
[squash comment fix from another Max's patch and adjust commit msg]
---
  include/block/block_int.h | 8 +---
  block/commit.c| 2 ++
  block/mirror.c| 2 ++
  3 files changed, 9 insertions(+), 3 deletions(-)


Reviewed-by: Eric Blake 

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH rc4 01/29] target/avr: Add basic parameters for new AVR platform

2020-01-31 Thread Aleksandar Markovic
On Friday, January 31, 2020, Aleksandar Markovic <
aleksandar.marko...@rt-rk.com> wrote:

> From: Michael Rolnik 
>
> This includes definitions of various basic parameters needed
> for integration of a new platform into QEMU.
>
> [AM: Split a larger AVR introduction patch into logical units]
> Suggested-by: Aleksandar Markovic 
>
> Co-developed-by: Michael Rolnik 
> Co-developed-by: Sarah Harris 
> Signed-off-by: Michael Rolnik 
> Signed-off-by: Sarah Harris 
> Signed-off-by: Michael Rolnik 
> Acked-by: Igor Mammedov 
> Tested-by: Philippe Mathieu-Daudé 
> Signed-off-by: Richard Henderson 
> Signed-off-by: Aleksandar Markovic 
> ---
>  target/avr/cpu-param.h | 37 ++
>  target/avr/cpu.h   | 72 ++
> 
>  2 files changed, 109 insertions(+)
>  create mode 100644 target/avr/cpu-param.h
>  create mode 100644 target/avr/cpu.h
>
> diff --git a/target/avr/cpu-param.h b/target/avr/cpu-param.h
> new file mode 100644
> index 000..0c29ce4
> --- /dev/null
> +++ b/target/avr/cpu-param.h
> @@ -0,0 +1,37 @@
> +/*
> + * QEMU AVR CPU
> + *
> + * Copyright (c) 2019 Michael Rolnik
> + *
> + * 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
> + * 
> + */
> +
> +#ifndef AVR_CPU_PARAM_H
> +#define AVR_CPU_PARAM_H
> +
> +#define TARGET_LONG_BITS 32
> +/*
> + * TARGET_PAGE_BITS cannot be more than 8 bits because
> + * 1.  all IO registers occupy [0x .. 0x00ff] address range, and they
> + * should be implemented as a device and not memory
> + * 2.  SRAM starts at the address 0x0100
> + */
> +#define TARGET_PAGE_BITS 8
> +#define TARGET_PHYS_ADDR_SPACE_BITS 24
> +#define TARGET_VIRT_ADDR_SPACE_BITS 24
> +#define NB_MMU_MODES 2
> +
> +
> +#endif
> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
> new file mode 100644
> index 000..d122611
> --- /dev/null
> +++ b/target/avr/cpu.h
> @@ -0,0 +1,72 @@
> +/*
> + * QEMU AVR CPU
> + *
> + * Copyright (c) 2019 Michael Rolnik
> + *
> + * 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
> + * 
> + */
> +
> +#ifndef QEMU_AVR_CPU_H
> +#define QEMU_AVR_CPU_H
> +
> +#include "cpu-qom.h"
> +#include "exec/cpu-defs.h"
> +
> +#define TCG_GUEST_DEFAULT_MO 0
> +#define AVR_CPU_TYPE_SUFFIX "-" TYPE_AVR_CPU
> +#define AVR_CPU_TYPE_NAME(name) (name AVR_CPU_TYPE_SUFFIX)
> +#define CPU_RESOLVING_TYPE TYPE_AVR_CPU
> +
> +/*
> + * AVR has two memory spaces, data & code.
> + * e.g. both have 0 address
> + * ST/LD instructions access data space
> + * LPM/SPM and instruction fetching access code memory space
> + */
> +#define MMU_CODE_IDX 0
> +#define MMU_DATA_IDX 1
> +
> +#define EXCP_RESET 1
> +#define EXCP_INT(n) (EXCP_RESET + (n) + 1)
> +
> +/* Number of CPU registers */
> +#define NUMBER_OF_CPU_REGISTERS 32
> +/* Number of IO registers accessible by ld/st/in/out */
> +#define NUMBER_OF_IO_REGISTERS 64
> +
> +/*
> + * Offsets of AVR memory regions in host memory space.
> + *
> + * This is needed because the AVR has separate code and data address
> + * spaces that both have start from zero but have to go somewhere in
> + * host memory.
> + *
> + * It's also useful to know where some things are, like the IO registers.
> + */
> +/* Flash program memory */
> +#define OFFSET_CODE 0x
> +/* CPU registers, IO registers, and SRAM */
> +#define OFFSET_DATA 0x0080
> +/* CPU registers specifically, these are mapped at the start of data */
> +#define OFFSET_CPU_REGISTERS OFFSET_DATA
> +/*
> + * IO registers, including status register, stack pointer, and memory
> + * mapped peripherals, mapped just after CPU registers
> + */
> +#define OFFSET_IO_REGISTERS (OFFSET_DATA + NUMBER_OF_CPU_REGISTERS)
> +
> +#define EF_AVR_MACH 0x7F

Re: [PULL 0/5] Tracing patches

2020-01-31 Thread Peter Maydell
On Thu, 30 Jan 2020 at 21:38, Stefan Hajnoczi  wrote:
>
> The following changes since commit 928173659d6e5dc368284f73f90ea1d129e1f57d:
>
>   Merge remote-tracking branch 
> 'remotes/pmaydell/tags/pull-target-arm-20200130' into staging (2020-01-30 
> 16:19:04 +)
>
> are available in the Git repository at:
>
>   https://github.com/stefanha/qemu.git tags/tracing-pull-request
>
> for you to fetch changes up to e144a605a614d22165000c69e8e1dc6986d45cd8:
>
>   qemu_set_log_filename: filename argument may be NULL (2020-01-30 21:33:50 
> +)
>
> 
> Pull request
>
> 
>


Applied, thanks.

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

-- PMM



[PATCH] block/backup-top: fix flags handling

2020-01-31 Thread Vladimir Sementsov-Ogievskiy
backup-top "supports" write-unchanged, by skipping CBW operation in
backup_top_co_pwritev. But it forgets to do the same in
backup_top_co_pwrite_zeroes, as well as declare support for
BDRV_REQ_WRITE_UNCHANGED.

Fix this, and, while being here, declare also support for flags
supported by source child.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
 block/backup-top.c | 28 ++--
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/block/backup-top.c b/block/backup-top.c
index 9aed2eb4c0..0e28fecc21 100644
--- a/block/backup-top.c
+++ b/block/backup-top.c
@@ -48,11 +48,17 @@ static coroutine_fn int backup_top_co_preadv(
 }
 
 static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
-   uint64_t bytes)
+   uint64_t bytes, BdrvRequestFlags flags)
 {
 BDRVBackupTopState *s = bs->opaque;
-uint64_t end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size);
-uint64_t off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size);
+uint64_t off, end;
+
+if (flags & BDRV_REQ_WRITE_UNCHANGED) {
+return 0;
+}
+
+off = QEMU_ALIGN_DOWN(offset, s->bcs->cluster_size);
+end = QEMU_ALIGN_UP(offset + bytes, s->bcs->cluster_size);
 
 return block_copy(s->bcs, off, end - off, NULL);
 }
@@ -60,7 +66,7 @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, 
uint64_t offset,
 static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
int64_t offset, int bytes)
 {
-int ret = backup_top_cbw(bs, offset, bytes);
+int ret = backup_top_cbw(bs, offset, bytes, 0);
 if (ret < 0) {
 return ret;
 }
@@ -71,7 +77,7 @@ static int coroutine_fn 
backup_top_co_pdiscard(BlockDriverState *bs,
 static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs,
 int64_t offset, int bytes, BdrvRequestFlags flags)
 {
-int ret = backup_top_cbw(bs, offset, bytes);
+int ret = backup_top_cbw(bs, offset, bytes, flags);
 if (ret < 0) {
 return ret;
 }
@@ -84,11 +90,9 @@ static coroutine_fn int 
backup_top_co_pwritev(BlockDriverState *bs,
   uint64_t bytes,
   QEMUIOVector *qiov, int flags)
 {
-if (!(flags & BDRV_REQ_WRITE_UNCHANGED)) {
-int ret = backup_top_cbw(bs, offset, bytes);
-if (ret < 0) {
-return ret;
-}
+int ret = backup_top_cbw(bs, offset, bytes, flags);
+if (ret < 0) {
+return ret;
 }
 
 return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
@@ -197,6 +201,10 @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState 
*source,
 
 top->total_sectors = source->total_sectors;
 state = top->opaque;
+top->supported_write_flags =
+BDRV_REQ_WRITE_UNCHANGED | source->supported_write_flags;
+top->supported_zero_flags =
+BDRV_REQ_WRITE_UNCHANGED | source->supported_zero_flags;
 
 bdrv_ref(target);
 state->target = bdrv_attach_child(top, target, "target", _file, 
errp);
-- 
2.21.0




Re: [PATCH rc4 01/29] target/avr: Add basic parameters for new AVR platform

2020-01-31 Thread Aleksandar Markovic
On Friday, January 31, 2020, Aleksandar Markovic <
aleksandar.marko...@rt-rk.com> wrote:

> From: Michael Rolnik 
>
> This includes definitions of various basic parameters needed
> for integration of a new platform into QEMU.
>
> [AM: Split a larger AVR introduction patch into logical units]
> Suggested-by: Aleksandar Markovic 
>
> Co-developed-by: Michael Rolnik 
> Co-developed-by: Sarah Harris 
> Signed-off-by: Michael Rolnik 
> Signed-off-by: Sarah Harris 
> Signed-off-by: Michael Rolnik 
> Acked-by: Igor Mammedov 
> Tested-by: Philippe Mathieu-Daudé 
> Signed-off-by: Richard Henderson 
> Signed-off-by: Aleksandar Markovic 
> ---
>  target/avr/cpu-param.h | 37 ++
>  target/avr/cpu.h   | 72 ++
> 
>  2 files changed, 109 insertions(+)
>  create mode 100644 target/avr/cpu-param.h
>  create mode 100644 target/avr/cpu.h
>
> diff --git a/target/avr/cpu-param.h b/target/avr/cpu-param.h
> new file mode 100644
> index 000..0c29ce4
> --- /dev/null
> +++ b/target/avr/cpu-param.h
> @@ -0,0 +1,37 @@
> +/*
> + * QEMU AVR CPU
> + *
> + * Copyright (c) 2019 Michael Rolnik
> + *
> + * 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
> + * 
> + */
> +
> +#ifndef AVR_CPU_PARAM_H
> +#define AVR_CPU_PARAM_H
> +
> +#define TARGET_LONG_BITS 32
> +/*
> + * TARGET_PAGE_BITS cannot be more than 8 bits because
> + * 1.  all IO registers occupy [0x .. 0x00ff] address range, and they
> + * should be implemented as a device and not memory
> + * 2.  SRAM starts at the address 0x0100
> + */
> +#define TARGET_PAGE_BITS 8
> +#define TARGET_PHYS_ADDR_SPACE_BITS 24
> +#define TARGET_VIRT_ADDR_SPACE_BITS 24
> +#define NB_MMU_MODES 2
> +
> +
> +#endif
> diff --git a/target/avr/cpu.h b/target/avr/cpu.h
> new file mode 100644
> index 000..d122611
> --- /dev/null
> +++ b/target/avr/cpu.h
> @@ -0,0 +1,72 @@
> +/*
> + * QEMU AVR CPU
> + *
> + * Copyright (c) 2019 Michael Rolnik
> + *
> + * 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
> + * 
> + */
> +
> +#ifndef QEMU_AVR_CPU_H
> +#define QEMU_AVR_CPU_H
> +
> +#include "cpu-qom.h"


This line should be a part of the next patch.


> +#include "exec/cpu-defs.h"
> +
> +#define TCG_GUEST_DEFAULT_MO 0
> +#define AVR_CPU_TYPE_SUFFIX "-" TYPE_AVR_CPU
> +#define AVR_CPU_TYPE_NAME(name) (name AVR_CPU_TYPE_SUFFIX)
> +#define CPU_RESOLVING_TYPE TYPE_AVR_CPU


Last three lines should be a part of the next patch.

+
> +/*
> + * AVR has two memory spaces, data & code.
> + * e.g. both have 0 address
> + * ST/LD instructions access data space
> + * LPM/SPM and instruction fetching access code memory space
> + */
> +#define MMU_CODE_IDX 0
> +#define MMU_DATA_IDX 1
> +
> +#define EXCP_RESET 1
> +#define EXCP_INT(n) (EXCP_RESET + (n) + 1)
> +
> +/* Number of CPU registers */
> +#define NUMBER_OF_CPU_REGISTERS 32
> +/* Number of IO registers accessible by ld/st/in/out */
> +#define NUMBER_OF_IO_REGISTERS 64
> +
> +/*
> + * Offsets of AVR memory regions in host memory space.
> + *
> + * This is needed because the AVR has separate code and data address
> + * spaces that both have start from zero but have to go somewhere in
> + * host memory.
> + *
> + * It's also useful to know where some things are, like the IO registers.
> + */
> +/* Flash program memory */
> +#define OFFSET_CODE 0x
> +/* CPU registers, IO registers, and SRAM */
> +#define OFFSET_DATA 0x0080
> +/* CPU registers specifically, these are mapped at the start of data */
> +#define OFFSET_CPU_REGISTERS OFFSET_DATA
> +/*
> + * IO registers, including status register, stack pointer, and memory
> + * mapped peripherals, mapped just after CPU registers
> + 

Re: [PATCH] tests/acceptance: Add a test for the integratorcp arm machine

2020-01-31 Thread Wainer dos Santos Moschetta



On 1/31/20 3:02 PM, Thomas Huth wrote:

There is a kernel and initrd available on github which we can use
for testing this machine.

Signed-off-by: Thomas Huth 
---
  MAINTAINERS  |  1 +
  tests/acceptance/machine_arm_integratorcp.py | 43 
  2 files changed, 44 insertions(+)
  create mode 100644 tests/acceptance/machine_arm_integratorcp.py


This was piece of cake! ;)

Reviewed-by: Wainer dos Santos Moschetta 



diff --git a/MAINTAINERS b/MAINTAINERS
index 6e4976d366..6a03835037 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -599,6 +599,7 @@ S: Maintained
  F: hw/arm/integratorcp.c
  F: hw/misc/arm_integrator_debug.c
  F: include/hw/misc/arm_integrator_debug.h
+F: tests/acceptance/machine_arm_integratorcp.py
  
  MCIMX6UL EVK / i.MX6ul

  M: Peter Maydell 
diff --git a/tests/acceptance/machine_arm_integratorcp.py 
b/tests/acceptance/machine_arm_integratorcp.py
new file mode 100644
index 00..4f9ab40f2f
--- /dev/null
+++ b/tests/acceptance/machine_arm_integratorcp.py
@@ -0,0 +1,43 @@
+# Functional test that boots a Linux kernel and checks the console
+#
+# Copyright (c) 2020 Red Hat, Inc.
+#
+# Author:
+#  Thomas Huth 
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
+
+import os
+
+from avocado import skipUnless
+from avocado_qemu import Test
+from avocado_qemu import wait_for_console_pattern
+
+class IntegratorMachine(Test):
+"""Boots the Linux kernel and checks that the console is operational"""
+
+timeout = 90
+
+@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
+def test_integratorcp(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:integratorcp
+"""
+kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
+  'arm-test/kernel/zImage.integrator')
+kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
+kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+initrd_url = ('https://github.com/zayac/qemu-arm/raw/master/'
+  'arm-test/kernel/arm_root.img')
+initrd_hash = 'b51e4154285bf784e017a37586428332d8c7bd8b'
+initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+
+self.vm.set_console()
+self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-append', 'printk.time=0 console=ttyAMA0')
+self.vm.launch()
+wait_for_console_pattern(self, 'Log in as root')





Re: [PATCH v11 2/2] docs: qcow2: introduce compression type feature

2020-01-31 Thread Vladimir Sementsov-Ogievskiy

31.01.2020 20:49, Eric Blake wrote:

On 1/31/20 11:34 AM, Alberto Garcia wrote:

On Fri 31 Jan 2020 03:46:12 PM CET, Eric Blake wrote:

+    If the incompatible bit "Compression type" is set: the 
field
+    must be present and non-zero (which means non-zlib
+    compression type). Otherwise, this field must not be 
present
+    or must be zero (which means zlib).


 If the incompatible bit "Compression type" is set: the field
 must be present. Otherwise, this field must not be present
 or must be zero (which means zlib).


But "not being present" and "being zero" is equivalent (as described in
the previous commit).

And if the incompatible bit is not present then the field can be safely
ignored (i.e. whether it is zero or not is irrelevant).

Let's try again:

    Defines the compression method used for compressed clusters. All
    compressed clusters in an image use the same type.

    The value of this field should only be used when the incompatible bit
    "Compression type" is set. If that bit is unset then this field is
    not used and the compression method is zlib.


I like that wording.



I'm OK with it too, as well as I'm OK with the stricter variant, when we don't 
allow incompatible images with zlib set. I don't see any serious difference.

But I need this to land somehow. Max likes stricter variant and he is 
maintainer of qcow2..

Max, will you merge it as is, or did you change your mind, or should we ask 
Kevin for his opinion?

--
Best regards,
Vladimir



Re: [PATCH 1/6] tests/boot_linux_console: add microvm acceptance test

2020-01-31 Thread Wainer dos Santos Moschetta



On 1/30/20 9:51 PM, Philippe Mathieu-Daudé wrote:

On 1/30/20 6:41 PM, Wainer dos Santos Moschetta wrote:

On 1/27/20 2:36 PM, Liam Merwick wrote:

Refactor test_x86_64_pc() to test_x86_64_machine() so that separate
functions which specify the Avocado tag of ':avocado: tags=machine:'
as being either 'pc' or 'microvm' can be used to test booting a
compressed kernel using either machine class.

Signed-off-by: Liam Merwick 
---
  tests/acceptance/boot_linux_console.py | 15 +--
  1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py

index e40b84651b0b..aa5b07b1c609 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -51,10 +51,9 @@ class BootLinuxConsole(Test):
  os.chdir(cwd)
  return self.workdir + path
-    def test_x86_64_pc(self):
+    def do_test_x86_64_machine(self):
  """
  :avocado: tags=arch:x86_64
-    :avocado: tags=machine:pc
  """
  kernel_url = 
('https://archives.fedoraproject.org/pub/archive/fedora'

'/linux/releases/29/Everything/x86_64/os/images/pxeboot'
@@ -70,6 +69,18 @@ class BootLinuxConsole(Test):
  console_pattern = 'Kernel command line: %s' % 
kernel_command_line

  self.wait_for_console_pattern(console_pattern)
+    def test_x86_64_pc(self):
+    """
+    :avocado: tags=machine:pc
+    """


The test method won't inherit the 'arch' tag from 
`do_test_x86_64_machine()`, so you need to explicitly 'arch' tag each 
test you created in this series. If you don't do so, Avocado won't 
filter out those x86_64 tests in case QEMU is built with non-x86_64 
targets.


Follows an example, I built QEMU with '--target-list=arm-softmmu'. I 
got:


```

(02/18) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_x86_64_pc: 
CANCEL: No QEMU binary defined or found in the source tree (0.00 s)
  (03/18) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_x86_64_microvm: 
CANCEL: No QEMU binary defined or found in the source tree (0.00 s)
  (04/18) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_arm_virt: 
PASS (1.25 s)


```

OK, avocado_qemu was smart enough to skip the tests, but ideally it 
should not even consider running them in the first place.


This should be solved by this patch:
https://lists.gnu.org/archive/html/qemu-devel/2020-01/msg07311.html
"tests/acceptance: Use 'machine' tag to check if available in QEMU binary"



That patch is useful**  but does not solve the problem that I point out 
here. If you have a test case which is arch-specific and the arch-QEMU 
was not built then it should not be executed. Tagging the test with 
'arch' ensures that.


** BTW, I'm going to review it soon

- Wainer




Thanks!

- Wainer


+    self.do_test_x86_64_machine()
+
+    def test_x86_64_microvm(self):
+    """
+    :avocado: tags=machine:microvm
+    """
+    self.do_test_x86_64_machine()
+
  def test_mips_malta(self):
  """
  :avocado: tags=arch:mips










Re: [PATCH 10/17] block: Add new BDRV_ZERO_OPEN flag

2020-01-31 Thread Eric Blake

On 1/31/20 11:44 AM, Eric Blake wrote:

Knowing that a file reads as all zeroes when created is useful, but
limited in scope to drivers that can create images.  However, there
are also situations where pre-existing images can quickly be
determined to read as all zeroes, even when the image was not just
created by the same process.  The optimization used in qemu-img
convert to avoid a pre-zeroing pass on the destination is just as
useful in such a scenario.  As such, it is worth the block layer
adding another bit to bdrv_known_zeroes().

Note that while BDRV_ZERO_CREATE cannot chase through backing layers
(because it only applies at creation time, but the backing layer was
not created at the same time as the active layer being created), it IS
okay for BDRV_ZERO_OPEN to chase through layers (as long as all layers
currently read as zero, the image reads as zero).

Upcoming patches will update the qcow2, file-posix, and nbd drivers to
advertise the new bit when appropriate.

Signed-off-by: Eric Blake 
---


[Is it bad when I review my own patches?]


+++ b/block.c
@@ -5078,7 +5078,7 @@ int bdrv_known_zeroes_truncate(BlockDriverState *bs)

  int bdrv_known_zeroes(BlockDriverState *bs)
  {
-int mask = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE;
+int mask = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE | BDRV_ZERO_OPEN;

  if (!bs->drv) {
  return 0;
@@ -5100,17 +5100,17 @@ int bdrv_known_zeroes(BlockDriverState *bs)
   * ZERO_CREATE is not viable.  If the current layer is smaller
   * than the backing layer, truncation may expose backing data,
   * restricting ZERO_TRUNCATE; treat failure to query size in the
- * same manner.  Otherwise, we can trust the driver.
+ * same manner.  For ZERO_OPEN, we insist that both backing and
+ * current layer report the bit.
   */
-
  if (bs->backing) {


Spurious line deletion caused by rebasing.



+++ b/include/block/block.h
@@ -105,6 +105,16 @@ typedef enum {
   * for drivers that set .bdrv_co_truncate.
   */
  BDRV_ZERO_TRUNCATE  = 0x2,
+
+/*
+ * bdrv_known_zeroes() should include this bit if an image is
+ * known to read as all zeroes when first opened; this bit should
+ * not be relied on after any writes to the image.  This can be
+ * set even if BDRV_ZERO_INIT is clear, but should only be set if


Rebasing snafu - I renamed that bit BDRV_ZERO_CREATE in patch 9.

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v11 2/2] docs: qcow2: introduce compression type feature

2020-01-31 Thread Eric Blake

On 1/31/20 11:34 AM, Alberto Garcia wrote:

On Fri 31 Jan 2020 03:46:12 PM CET, Eric Blake wrote:

+If the incompatible bit "Compression type" is set: the 
field
+must be present and non-zero (which means non-zlib
+compression type). Otherwise, this field must not be 
present
+or must be zero (which means zlib).


 If the incompatible bit "Compression type" is set: the field
 must be present. Otherwise, this field must not be present
 or must be zero (which means zlib).


But "not being present" and "being zero" is equivalent (as described in
the previous commit).

And if the incompatible bit is not present then the field can be safely
ignored (i.e. whether it is zero or not is irrelevant).

Let's try again:

Defines the compression method used for compressed clusters. All
compressed clusters in an image use the same type.

The value of this field should only be used when the incompatible bit
"Compression type" is set. If that bit is unset then this field is
not used and the compression method is zlib.


I like that wording.

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




[PATCH 17/17] qcow2: Let qemu-img check cover all-zero bit

2020-01-31 Thread Eric Blake
Since checking an images refcounts already visits every cluster, it's
basically free to also check that the all-zero bit is correctly set.
Only check for the active L1 table, and only output an error on the
first non-zero cluster found.

Signed-off-by: Eric Blake 
---
 block/qcow2-refcount.c | 60 +++---
 tests/qemu-iotests/060.out |  6 ++--
 tests/qemu-iotests/285 | 17 +++
 tests/qemu-iotests/285.out | 20 +
 4 files changed, 97 insertions(+), 6 deletions(-)

diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index f67ac6b2d893..95c8101df365 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1583,6 +1583,7 @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, 
BdrvCheckResult *res,
 /* Flags for check_refcounts_l1() and check_refcounts_l2() */
 enum {
 CHECK_FRAG_INFO = 0x2,  /* update BlockFragInfo counters */
+CHECK_ALL_ZERO = 0x4,   /* check autoclear all_zero bit */
 };

 /*
@@ -1596,12 +1597,14 @@ enum {
 static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
   void **refcount_table,
   int64_t *refcount_table_size, int64_t l2_offset,
-  int flags, BdrvCheckMode fix, bool active)
+  int flags, BdrvCheckMode fix, bool active,
+  bool *all_zero)
 {
 BDRVQcow2State *s = bs->opaque;
 uint64_t *l2_table, l2_entry;
 uint64_t next_contiguous_offset = 0;
 int i, l2_size, nb_csectors, ret;
+bool check_all_zero;

 /* Read L2 table from disk */
 l2_size = s->l2_size * sizeof(uint64_t);
@@ -1615,8 +1618,9 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 }

 /* Do the actual checks */
-for(i = 0; i < s->l2_size; i++) {
+for (i = 0; i < s->l2_size; i++) {
 l2_entry = be64_to_cpu(l2_table[i]);
+check_all_zero = *all_zero;

 switch (qcow2_get_cluster_type(bs, l2_entry)) {
 case QCOW2_CLUSTER_COMPRESSED:
@@ -1662,6 +1666,8 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 break;

 case QCOW2_CLUSTER_ZERO_ALLOC:
+check_all_zero = false;
+/* fall through */
 case QCOW2_CLUSTER_NORMAL:
 {
 uint64_t offset = l2_entry & L2E_OFFSET_MASK;
@@ -1740,12 +1746,51 @@ static int check_refcounts_l2(BlockDriverState *bs, 
BdrvCheckResult *res,
 }

 case QCOW2_CLUSTER_ZERO_PLAIN:
+check_all_zero = false;
+break;
+
 case QCOW2_CLUSTER_UNALLOCATED:
+if (!bs->backing) {
+check_all_zero = false;
+}
 break;

 default:
 abort();
 }
+
+if (check_all_zero) {
+fprintf(stderr, "%s: all zero bit set but L2 table at offset "
+"0x%" PRIx64" contains non-zero cluster at entry %d\n",
+fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
+l2_offset, i);
+*all_zero = false;
+if (fix & BDRV_FIX_ERRORS) {
+uint64_t feat;
+
+ret = bdrv_pread(bs->file,
+ offsetof(QCowHeader, autoclear_features),
+ , sizeof(feat));
+if (ret >= 0) {
+feat &= ~cpu_to_be64(QCOW2_AUTOCLEAR_ALL_ZERO);
+ret = bdrv_pwrite(bs->file,
+  offsetof(QCowHeader, autoclear_features),
+  , sizeof(feat));
+}
+if (ret < 0) {
+fprintf(stderr,
+"ERROR: Failed to update all zero bit: %s\n",
+strerror(-ret));
+res->check_errors++;
+/* Continue checking the rest of this L2 table */
+} else {
+res->corruptions_fixed++;
+}
+s->autoclear_features &= ~QCOW2_AUTOCLEAR_ALL_ZERO;
+} else {
+res->corruptions++;
+}
+}
 }

 g_free(l2_table);
@@ -1774,6 +1819,12 @@ static int check_refcounts_l1(BlockDriverState *bs,
 BDRVQcow2State *s = bs->opaque;
 uint64_t *l1_table = NULL, l2_offset, l1_size2;
 int i, ret;
+bool all_zero = false;
+
+if (flags & CHECK_ALL_ZERO &&
+s->autoclear_features & QCOW2_AUTOCLEAR_ALL_ZERO) {
+all_zero = true;
+}

 l1_size2 = l1_size * sizeof(uint64_t);

@@ -1825,7 +1876,7 @@ static int check_refcounts_l1(BlockDriverState *bs,
 /* Process and check L2 entries */
 ret = check_refcounts_l2(bs, res, refcount_table,
  refcount_table_size, l2_offset, flags,
- fix, active);
+ 

[PATCH 13/17] qcow2: Add new autoclear feature for all zero image

2020-01-31 Thread Eric Blake
With the recent introduction of BDRV_ZERO_OPEN, we can optimize
various qemu-img operations if we know the destination starts life
with all zero content.  For an image with no cluster allocations and
no backing file, this was already trivial with BDRV_ZERO_CREATE; but
for a fully preallocated image, it does not scale to crawl through the
entire L1/L2 tree to see if every cluster is currently marked as a
zero cluster.  But it is quite easy to add an autoclear bit to the
qcow2 file itself: the bit will be set after newly creating an image
or after qcow2_make_empty, and cleared on any other modification
(including by an older qemu that doesn't recognize the bit).

This patch documents the new bit, independently of implementing the
places in code that should set it (which means that for bisection
purposes, it is safer to still mask the bit out when opening an image
with the bit set).

A few iotests have updated output due to the larger number of named
header features.

Signed-off-by: Eric Blake 

---
RFC: As defined in this patch, I defined the bit to be clear if any
cluster defers to a backing file. But the block layer would handle
things just fine if we instead allowed the bit to be set if all
clusters allocated in this image are zero, even if there are other
clusters not allocated.  Or maybe we want TWO bits: one if all
clusters allocated here are known zero, and a second if we know that
there are any clusters that defer to a backing image.
---
 block/qcow2.c  |  9 +
 block/qcow2.h  |  3 +++
 docs/interop/qcow2.txt | 12 +++-
 qapi/block-core.json   |  4 
 tests/qemu-iotests/031.out |  8 
 tests/qemu-iotests/036.out |  4 ++--
 tests/qemu-iotests/061.out | 14 +++---
 7 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 9f2371925737..20cce9410c84 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2859,6 +2859,11 @@ int qcow2_update_header(BlockDriverState *bs)
 .bit  = QCOW2_AUTOCLEAR_DATA_FILE_RAW_BITNR,
 .name = "raw external data",
 },
+{
+.type = QCOW2_FEAT_TYPE_AUTOCLEAR,
+.bit  = QCOW2_AUTOCLEAR_ALL_ZERO_BITNR,
+.name = "all zero",
+},
 };

 ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,
@@ -4874,6 +4879,10 @@ static ImageInfoSpecific 
*qcow2_get_specific_info(BlockDriverState *bs,
 .corrupt= s->incompatible_features &
   QCOW2_INCOMPAT_CORRUPT,
 .has_corrupt= true,
+.all_zero   = s->autoclear_features &
+  QCOW2_AUTOCLEAR_ALL_ZERO,
+.has_all_zero   = s->autoclear_features &
+  QCOW2_AUTOCLEAR_ALL_ZERO,
 .refcount_bits  = s->refcount_bits,
 .has_bitmaps= !!bitmaps,
 .bitmaps= bitmaps,
diff --git a/block/qcow2.h b/block/qcow2.h
index 094212623257..6fc2d323d753 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -237,11 +237,14 @@ enum {
 enum {
 QCOW2_AUTOCLEAR_BITMAPS_BITNR   = 0,
 QCOW2_AUTOCLEAR_DATA_FILE_RAW_BITNR = 1,
+QCOW2_AUTOCLEAR_ALL_ZERO_BITNR  = 2,
 QCOW2_AUTOCLEAR_BITMAPS = 1 << QCOW2_AUTOCLEAR_BITMAPS_BITNR,
 QCOW2_AUTOCLEAR_DATA_FILE_RAW   = 1 << 
QCOW2_AUTOCLEAR_DATA_FILE_RAW_BITNR,
+QCOW2_AUTOCLEAR_ALL_ZERO= 1 << QCOW2_AUTOCLEAR_ALL_ZERO_BITNR,

 QCOW2_AUTOCLEAR_MASK= QCOW2_AUTOCLEAR_BITMAPS
 | QCOW2_AUTOCLEAR_DATA_FILE_RAW,
+/* TODO: Add _ALL_ZERO to _MASK once it is handled correctly */
 };

 enum qcow2_discard_type {
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
index 8510d74c8079..d435363a413c 100644
--- a/docs/interop/qcow2.txt
+++ b/docs/interop/qcow2.txt
@@ -153,7 +153,17 @@ in the description of a field.
 File bit (incompatible feature bit 1) is also
 set.

-Bits 2-63:  Reserved (set to 0)
+Bit 2:  All zero image bit
+If this bit is set, the entire image reads
+as all zeroes. This can be useful for
+detecting just-created images even when
+clusters are preallocated, which in turn
+can be used to optimize image copying.
+
+This bit should not be set if any cluster
+in the image defers to a backing file.
+
+Bits 3-63:  Reserved (set to 0)

  96 -  99:  refcount_order
 Describes the width of a reference count block entry (width
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 

[PATCH 12/17] gluster: Support BDRV_ZERO_OPEN

2020-01-31 Thread Eric Blake
Since gluster already copies file-posix for lseek usage in block
status, it also makes sense to copy it for learning if the image
currently reads as all zeroes.

Signed-off-by: Eric Blake 
---
 block/gluster.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/block/gluster.c b/block/gluster.c
index 9d952c70981b..0417a86547c8 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -1464,6 +1464,22 @@ exit:
 return -ENOTSUP;
 }

+static int qemu_gluster_known_zeroes(BlockDriverState *bs)
+{
+/*
+ * GlusterFS volume could be backed by a block device, with no way
+ * to query if regions added by creation or truncation will read
+ * as zeroes.  However, we can use lseek(SEEK_DATA) to check if
+ * contents currently read as zero.
+ */
+off_t data, hole;
+
+if (find_allocation(bs, 0, , ) == -ENXIO) {
+return BDRV_ZERO_OPEN;
+}
+return 0;
+}
+
 /*
  * Returns the allocation status of the specified offset.
  *
@@ -1561,6 +1577,7 @@ static BlockDriver bdrv_gluster = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
+.bdrv_known_zeroes= qemu_gluster_known_zeroes,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
@@ -1591,6 +1608,7 @@ static BlockDriver bdrv_gluster_tcp = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
+.bdrv_known_zeroes= qemu_gluster_known_zeroes,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
@@ -1621,6 +1639,7 @@ static BlockDriver bdrv_gluster_unix = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
+.bdrv_known_zeroes= qemu_gluster_known_zeroes,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
@@ -1657,6 +1676,7 @@ static BlockDriver bdrv_gluster_rdma = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
+.bdrv_known_zeroes= qemu_gluster_known_zeroes,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
-- 
2.24.1




[PATCH 09/17] block: Refactor bdrv_has_zero_init{,_truncate}

2020-01-31 Thread Eric Blake
Having two slightly-different function names for related purposes is
unwieldy, especially since I envision adding yet another notion of
zero support in an upcoming patch.  It doesn't help that
bdrv_has_zero_init() is a misleading name (I originally thought that a
driver could only return 1 when opening an already-existing image
known to be all zeroes; but in reality many drivers always return 1
because it only applies to a just-created image).  Refactor all uses
to instead have a single function that returns multiple bits of
information, with better naming and documentation.

No semantic change, although some of the changes (such as to qcow2.c)
require a careful reading to see how it remains the same.

Signed-off-by: Eric Blake 
---
 block.c| 49 ++
 block/file-posix.c |  3 +--
 block/file-win32.c |  3 +--
 block/nfs.c|  7 +++---
 block/parallels.c  |  4 ++--
 block/qcow.c   |  2 +-
 block/qcow2.c  | 10 
 block/qed.c|  3 +--
 block/raw-format.c | 12 +++---
 block/rbd.c|  3 +--
 block/sheepdog.c   |  9 +++
 block/ssh.c|  7 +++---
 block/vdi.c|  8 +++
 block/vhdx.c   | 16 ++---
 block/vmdk.c   |  9 +++
 block/vpc.c|  8 +++
 blockdev.c |  2 +-
 include/block/block.h  | 28 +++---
 include/block/block_int.h  | 15 ++--
 qemu-img.c |  3 ++-
 tests/qemu-iotests/122 |  2 +-
 tests/qemu-iotests/188 |  2 +-
 tests/qemu-iotests/188.out |  2 +-
 23 files changed, 96 insertions(+), 111 deletions(-)

diff --git a/block.c b/block.c
index d132662f3103..fac0813140aa 100644
--- a/block.c
+++ b/block.c
@@ -5066,38 +5066,20 @@ int bdrv_get_flags(BlockDriverState *bs)
 return bs->open_flags;
 }

-int bdrv_has_zero_init_1(BlockDriverState *bs)
+int bdrv_known_zeroes_create(BlockDriverState *bs)
 {
-return 1;
+return BDRV_ZERO_CREATE;
 }

-int bdrv_has_zero_init(BlockDriverState *bs)
+int bdrv_known_zeroes_truncate(BlockDriverState *bs)
 {
-if (!bs->drv) {
-return 0;
-}
-
-/*
- * If BS is a copy on write image, it is initialized to the
- * contents of the base image, which may not be zeroes.  Likewise,
- * encrypted images do not read as zero.
- */
-if (bs->backing || bs->encrypted) {
-return 0;
-}
-if (bs->drv->bdrv_has_zero_init) {
-return bs->drv->bdrv_has_zero_init(bs);
-}
-if (bs->file && bs->drv->is_filter) {
-return bdrv_has_zero_init(bs->file->bs);
-}
-
-/* safe default */
-return 0;
+return BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE;
 }

-int bdrv_has_zero_init_truncate(BlockDriverState *bs)
+int bdrv_known_zeroes(BlockDriverState *bs)
 {
+int mask = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE;
+
 if (!bs->drv) {
 return 0;
 }
@@ -5113,9 +5095,12 @@ int bdrv_has_zero_init_truncate(BlockDriverState *bs)
 }

 /*
- * If the current layer is smaller than the backing layer,
- * truncation may expose backing data; treat failure to query size
- * in the same manner. Otherwise, we can trust the driver.
+ * If BS is a copy on write image, it is initialized to the
+ * contents of the base image, which may not be zeroes, so
+ * ZERO_CREATE is not viable.  If the current layer is smaller
+ * than the backing layer, truncation may expose backing data,
+ * restricting ZERO_TRUNCATE; treat failure to query size in the
+ * same manner.  Otherwise, we can trust the driver.
  */

 if (bs->backing) {
@@ -5125,12 +5110,14 @@ int bdrv_has_zero_init_truncate(BlockDriverState *bs)
 if (back < 0 || curr < back) {
 return 0;
 }
+mask = BDRV_ZERO_TRUNCATE;
 }
-if (bs->drv->bdrv_has_zero_init_truncate) {
-return bs->drv->bdrv_has_zero_init_truncate(bs);
+
+if (bs->drv->bdrv_known_zeroes) {
+return bs->drv->bdrv_known_zeroes(bs) & mask;
 }
 if (bs->file && bs->drv->is_filter) {
-return bdrv_has_zero_init_truncate(bs->file->bs);
+return bdrv_known_zeroes(bs->file->bs) & mask;
 }

 /* safe default */
diff --git a/block/file-posix.c b/block/file-posix.c
index ab82ee1a6718..ff9e39ab882f 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -3071,8 +3071,7 @@ BlockDriver bdrv_file = {
 .bdrv_close = raw_close,
 .bdrv_co_create = raw_co_create,
 .bdrv_co_create_opts = raw_co_create_opts,
-.bdrv_has_zero_init = bdrv_has_zero_init_1,
-.bdrv_has_zero_init_truncate = bdrv_has_zero_init_1,
+.bdrv_known_zeroes = bdrv_known_zeroes_truncate,
 .bdrv_co_block_status = raw_co_block_status,
 .bdrv_co_invalidate_cache = raw_co_invalidate_cache,
 .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
diff --git a/block/file-win32.c 

[PATCH 15/17] qcow2: Implement all-zero autoclear bit

2020-01-31 Thread Eric Blake
Wire up the autoclear bit just defined in the previous patch. When we
create an image or clear it with .bdrv_make_empty, we know that it
reads as all zeroes.  Reading an image does not change the previous
status, nor does writing zeroes, trimming (because we specifically set
trimmed clusters to read as zero), or resize (because the new length
reads as zero).  This leaves normal writes, data copies, snapshot
reverts, and altering the backing file that can change the status.
Furthermore, it is not safe to claim that an encrypted image or an
image with a backing file reads as all zeroes.

Implementation-wise, we clear the bit from the file on the first
modification, and then rewrite it when marking the image clean; some
callers want to rewrite it (to either set or clear), while others want
to preserve the current value; the modifications to qemu_mark_clean
make it easier to consolidate the logic for when setting the bit is
safe.

A number of iotests have altered output, in situations where we have a
provably zero image at that point in the test.

Later, we may want to wire in further checks to qemu-img check that
validates if the bit is set correctly, and/or to set the bit in images
where it would be valid, but I did not do that here.

Signed-off-by: Eric Blake 
---
 block/qcow2-snapshot.c | 11 +
 block/qcow2.c  | 97 ++
 block/qcow2.h  |  5 +-
 tests/qemu-iotests/031.out |  6 +--
 tests/qemu-iotests/036.out |  6 +--
 tests/qemu-iotests/061.out | 12 +++--
 tests/qemu-iotests/065 | 12 ++---
 tests/qemu-iotests/082.out |  7 +++
 tests/qemu-iotests/206.out |  4 ++
 tests/qemu-iotests/242.out |  1 +
 10 files changed, 134 insertions(+), 27 deletions(-)

diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 5ab64da1ec36..e19f1b3ef5fa 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -781,6 +781,16 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char 
*snapshot_id)
 goto fail;
 }

+/*
+ * With modification to the qcow2 spec, snapshots could store
+ * whether they are in an all zero state. But for now, we assume
+ * all snapshots are nonzero.
+ */
+ret = qcow2_mark_nonzero(bs);
+if (ret < 0) {
+goto fail;
+}
+
 /*
  * Make sure that the current L1 table is big enough to contain the whole
  * L1 table of the snapshot. If the snapshot L1 table is smaller, the
@@ -1044,6 +1054,7 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
 s->l1_size = sn->l1_size;
 s->l1_table_offset = sn->l1_table_offset;
 s->l1_table = new_l1_table;
+s->autoclear_features &= ~QCOW2_AUTOCLEAR_ALL_ZERO;

 for(i = 0;i < s->l1_size; i++) {
 be64_to_cpus(>l1_table[i]);
diff --git a/block/qcow2.c b/block/qcow2.c
index 3f61d806a14b..6b1969e4d90a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -480,6 +480,40 @@ static void report_unsupported_feature(Error **errp, 
Qcow2Feature *table,
 g_free(features);
 }

+/*
+ * Clear the all zero bit and flushes afterwards if necessary.
+ *
+ * If updating the header fails, it is not safe to proceed with
+ * modifying the image.
+ */
+int qcow2_mark_nonzero(BlockDriverState *bs)
+{
+BDRVQcow2State *s = bs->opaque;
+uint64_t val;
+int ret;
+
+if (!(s->autoclear_features & QCOW2_AUTOCLEAR_ALL_ZERO)) {
+return 0; /* already marked non-zero, including version 2 */
+}
+
+assert(s->qcow_version >= 3);
+
+val = cpu_to_be64(s->autoclear_features & ~QCOW2_AUTOCLEAR_ALL_ZERO);
+ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, autoclear_features),
+  , sizeof(val));
+if (ret < 0) {
+return ret;
+}
+ret = bdrv_flush(bs->file->bs);
+if (ret < 0) {
+return ret;
+}
+
+/* Only clear the in-memory flag if the header was updated successfully */
+s->autoclear_features &= ~QCOW2_AUTOCLEAR_ALL_ZERO;
+return 0;
+}
+
 /*
  * Sets the dirty bit and flushes afterwards if necessary.
  *
@@ -518,16 +552,27 @@ int qcow2_mark_dirty(BlockDriverState *bs)
 /*
  * Clears the dirty bit and flushes before if necessary.  Only call this
  * function when there are no pending requests, it does not guard against
- * concurrent requests dirtying the image.
+ * concurrent requests dirtying the image. If all_zero is 0 or 1, adjust
+ * the value of s->autoclear; if -1, preserve the cached value.
  */
-static int qcow2_mark_clean(BlockDriverState *bs)
+static int qcow2_mark_clean(BlockDriverState *bs, int all_zero)
 {
 BDRVQcow2State *s = bs->opaque;

-if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY) {
+if (all_zero == -1) {
+all_zero = !!(s->autoclear_features & QCOW2_AUTOCLEAR_ALL_ZERO);
+}
+if (bs->backing || bs->encrypted || s->qcow_version < 3) {
+all_zero = 0;
+}
+if (s->incompatible_features & QCOW2_INCOMPAT_DIRTY ||
+(all_zero && !(s->autoclear_features & 

[PATCH 14/17] qcow2: Expose all zero bit through .bdrv_known_zeroes

2020-01-31 Thread Eric Blake
Now that qcow2 images have a way to track when the contents are known
to be all zero, it is worth exposing this to clients such as qemu-img
convert.  (Of course, until the next patch wires up qcow2 to actually
set the bit, this patch has no immediate effect; however, keeping it
as a separate patch allows for an easier revert when testing if the
bit makes a difference in qemu-img behavior).

Signed-off-by: Eric Blake 
---
 block/qcow2.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/block/qcow2.c b/block/qcow2.c
index 20cce9410c84..3f61d806a14b 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4938,6 +4938,9 @@ static int qcow2_known_zeroes(BlockDriverState *bs)
  * therefore enough to check the first one.
  */
 preallocated = s->l1_size > 0 && s->l1_table[0] != 0;
+if (s->autoclear_features & QCOW2_AUTOCLEAR_ALL_ZERO) {
+r |= BDRV_ZERO_OPEN;
+}
 if (qemu_in_coroutine()) {
 qemu_co_mutex_unlock(>lock);
 }
-- 
2.24.1




[PATCH 03/17] qcow2: Avoid feature name extension on small cluster size

2020-01-31 Thread Eric Blake
As the feature name table can be quite large (over 9k if all 64 bits
of all three feature fields have names; a mere 8 features leaves only
8 bytes for a backing file name in a 512-byte cluster), it is unwise
to emit this optional header in images with small cluster sizes.

Update iotest 036 to skip running on small cluster sizes; meanwhile,
note that iotest 061 never passed on alternative cluster sizes
(however, I limited this patch to tests with output affected by adding
feature names, rather than auditing for other tests that are not
robust to alternative cluster sizes).

Signed-off-by: Eric Blake 
---
 block/qcow2.c  | 11 +--
 tests/qemu-iotests/036 |  6 --
 tests/qemu-iotests/061 |  6 --
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index d3e7709ac2b4..6ea06dbdf48a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2819,8 +2819,15 @@ int qcow2_update_header(BlockDriverState *bs)
 buflen -= ret;
 }

-/* Feature table */
-if (s->qcow_version >= 3) {
+/*
+ * Feature table.  A mere 8 feature names occupies 392 bytes, and
+ * when coupled with the v3 minimum header of 104 bytes plus the
+ * 8-byte end-of-extension marker, that would leave only 8 bytes
+ * for a backing file name in an image with 512-byte clusters.
+ * Thus, we choose to omit this header for cluster sizes 4k and
+ * smaller.
+ */
+if (s->qcow_version >= 3 && s->cluster_size > 4096) {
 static const Qcow2Feature features[] = {
 {
 .type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
index 512598421c20..cf522de7a1aa 100755
--- a/tests/qemu-iotests/036
+++ b/tests/qemu-iotests/036
@@ -44,8 +44,10 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow2
 _supported_proto file
 # Only qcow2v3 and later supports feature bits;
-# qcow2.py does not support external data files
-_unsupported_imgopts 'compat=0.10' data_file
+# qcow2.py does not support external data files;
+# this test requires a cluster size large enough for the feature table
+_unsupported_imgopts 'compat=0.10' data_file \
+'cluster_size=\(512\|1024\|2048\|4096\)'

 echo
 echo === Image with unknown incompatible feature bit ===
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
index 36b040491fef..ce285d308408 100755
--- a/tests/qemu-iotests/061
+++ b/tests/qemu-iotests/061
@@ -44,8 +44,10 @@ _supported_os Linux
 # Conversion between different compat versions can only really work
 # with refcount_bits=16;
 # we have explicit tests for data_file here, but the whole test does
-# not work with it
-_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file
+# not work with it;
+# we have explicit tests for various cluster sizes, the remaining tests
+# require the default 64k cluster
+_unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)' data_file 
cluster_size

 echo
 echo "=== Testing version downgrade with zero expansion ==="
-- 
2.24.1




[PATCH 06/17] block: Improve bdrv_has_zero_init_truncate with backing file

2020-01-31 Thread Eric Blake
When we added bdrv_has_zero_init_truncate(), we chose to blindly
return 0 if a backing file was present, because we knew of the corner
case where a backing layer larger than the current layer might leak
the tail of the backing layer into the resized region.  But as this
setup is rare, it penalizes the more common case of a backing layer
smaller than the current layer.

Signed-off-by: Eric Blake 
---
 block.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/block.c b/block.c
index 296845040e59..d132662f3103 100644
--- a/block.c
+++ b/block.c
@@ -5112,9 +5112,19 @@ int bdrv_has_zero_init_truncate(BlockDriverState *bs)
 return 0;
 }

+/*
+ * If the current layer is smaller than the backing layer,
+ * truncation may expose backing data; treat failure to query size
+ * in the same manner. Otherwise, we can trust the driver.
+ */
+
 if (bs->backing) {
-/* Depends on the backing image length, but better safe than sorry */
-return 0;
+int64_t back = bdrv_getlength(bs->backing->bs);
+int64_t curr = bdrv_getlength(bs);
+
+if (back < 0 || curr < back) {
+return 0;
+}
 }
 if (bs->drv->bdrv_has_zero_init_truncate) {
 return bs->drv->bdrv_has_zero_init_truncate(bs);
-- 
2.24.1




[PATCH 11/17] file-posix: Support BDRV_ZERO_OPEN

2020-01-31 Thread Eric Blake
A single lseek(SEEK_DATA) is sufficient to tell us if a raw file is
completely sparse, in which case it reads as all zeroes.  Not done
here, but possible extension for the future: when working with block
devices instead of files, there may be various ways with ioctl or
similar to quickly probe if a given block device is known to be
completely unmapped where unmapped regions read as zero.  But for now,
block devices remain without a .bdrv_known_zeroes, because most block
devices have random content without an explicit pre-zeroing pass.

Signed-off-by: Eric Blake 
---
 block/file-posix.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index ff9e39ab882f..b4d73dd0363b 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2541,6 +2541,19 @@ static int find_allocation(BlockDriverState *bs, off_t 
start,
 #endif
 }

+static int raw_known_zeroes(BlockDriverState *bs)
+{
+/* This callback is only installed for files, not block devices. */
+int r = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE;
+off_t data, hole;
+
+if (find_allocation(bs, 0, , ) == -ENXIO) {
+r |= BDRV_ZERO_OPEN;
+}
+
+return r;
+}
+
 /*
  * Returns the allocation status of the specified offset.
  *
@@ -3071,7 +3084,7 @@ BlockDriver bdrv_file = {
 .bdrv_close = raw_close,
 .bdrv_co_create = raw_co_create,
 .bdrv_co_create_opts = raw_co_create_opts,
-.bdrv_known_zeroes = bdrv_known_zeroes_truncate,
+.bdrv_known_zeroes = raw_known_zeroes,
 .bdrv_co_block_status = raw_co_block_status,
 .bdrv_co_invalidate_cache = raw_co_invalidate_cache,
 .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
-- 
2.24.1




[PATCH 16/17] iotests: Add new test for qcow2 all-zero bit

2020-01-31 Thread Eric Blake
Cover various scenarios to show that the bit gets set even for
fully-allocated images, as well as scenarios where it is properly
cleared.

Signed-off-by: Eric Blake 
---
 tests/qemu-iotests/285 | 107 +++
 tests/qemu-iotests/285.out | 257 +
 tests/qemu-iotests/group   |   1 +
 3 files changed, 365 insertions(+)
 create mode 100755 tests/qemu-iotests/285
 create mode 100644 tests/qemu-iotests/285.out

diff --git a/tests/qemu-iotests/285 b/tests/qemu-iotests/285
new file mode 100755
index ..66037af237a1
--- /dev/null
+++ b/tests/qemu-iotests/285
@@ -0,0 +1,107 @@
+#!/usr/bin/env bash
+#
+# Test qcow2 all-zero autoclear bit
+#
+# Copyright (C) 2020 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+
+seq=$(basename $0)
+echo "QA output created by $seq"
+
+status=1   # failure is the default!
+
+_cleanup()
+{
+_cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+# Autoclear bit is not available in compat=0.10;
+# encrypted images never advertise all-zero bit
+_unsupported_imgopts 'compat=0.10' encrypt
+
+for mode in off metadata falloc full; do
+
+echo
+echo "=== preallocation=$mode ==="
+echo
+
+_make_test_img -o "preallocation=$mode" 32M
+
+# Actions that do not lose the all-zero nature of the image:
+$QEMU_IO -c 'w -z 0 16M' -c 'discard 8M 16M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG resize --preallocation=$mode "$TEST_IMG" +8M
+$QEMU_IO -c 'r -P 0 0 40M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+
+# Writing data must clear the all-zero bit:
+$QEMU_IO -c 'w -P 1 32M 1M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+
+# Alas, rewriting the image back to zero does not restore the bit
+# (checking if each write gets us back to zero does not scale)
+$QEMU_IO -c 'w -z 32M 1M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+
+done
+
+echo
+echo "=== backing files ==="
+echo
+
+# Even when a backing file is all zero, we do not set all-zero bit;
+# this is true whether we create with a backing file or rebase later
+TEST_IMG_SAVE=$TEST_IMG
+TEST_IMG=$TEST_IMG.base
+_make_test_img 32M
+TEST_IMG=$TEST_IMG_SAVE
+_make_test_img -b "$TEST_IMG.base" -F qcow2 32M
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+_make_test_img 32M
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+$QEMU_IMG rebase -u -F qcow2 -b "$TEST_IMG.base" "$TEST_IMG"
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+
+# qemu-img commit clears an image, but because it still has a backing file,
+# setting the all-zero bit is not correct
+$QEMU_IO -c 'w -P 1 0 1M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG commit "$TEST_IMG"
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+
+echo
+echo "=== internal snapshots ==="
+echo
+
+# For now, internal snapshots do not remember the all-zero bit
+_make_test_img 32M
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+$QEMU_IMG snapshot -c snap "$TEST_IMG"
+$QEMU_IO -c 'w -P 1 0 1M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG snapshot -l snap "$TEST_IMG"
+$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific \
+| _filter_date | _filter_vmstate_size
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/285.out b/tests/qemu-iotests/285.out
new file mode 100644
index ..e43ff9906b5f
--- /dev/null
+++ b/tests/qemu-iotests/285.out
@@ -0,0 +1,257 @@
+QA output created by 285
+
+=== preallocation=off ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 preallocation=off
+wrote 16777216/16777216 bytes at offset 0
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+discard 16777216/16777216 bytes at offset 8388608
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Image resized.
+read 41943040/41943040 bytes at offset 0
+40 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 40 MiB (41943040 bytes)
+disk size: 260 KiB
+Format specific information:
+  

[PATCH 10/17] block: Add new BDRV_ZERO_OPEN flag

2020-01-31 Thread Eric Blake
Knowing that a file reads as all zeroes when created is useful, but
limited in scope to drivers that can create images.  However, there
are also situations where pre-existing images can quickly be
determined to read as all zeroes, even when the image was not just
created by the same process.  The optimization used in qemu-img
convert to avoid a pre-zeroing pass on the destination is just as
useful in such a scenario.  As such, it is worth the block layer
adding another bit to bdrv_known_zeroes().

Note that while BDRV_ZERO_CREATE cannot chase through backing layers
(because it only applies at creation time, but the backing layer was
not created at the same time as the active layer being created), it IS
okay for BDRV_ZERO_OPEN to chase through layers (as long as all layers
currently read as zero, the image reads as zero).

Upcoming patches will update the qcow2, file-posix, and nbd drivers to
advertise the new bit when appropriate.

Signed-off-by: Eric Blake 
---
 block.c   | 12 ++--
 include/block/block.h | 10 ++
 qemu-img.c| 10 ++
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/block.c b/block.c
index fac0813140aa..d68f527dc41f 100644
--- a/block.c
+++ b/block.c
@@ -5078,7 +5078,7 @@ int bdrv_known_zeroes_truncate(BlockDriverState *bs)

 int bdrv_known_zeroes(BlockDriverState *bs)
 {
-int mask = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE;
+int mask = BDRV_ZERO_CREATE | BDRV_ZERO_TRUNCATE | BDRV_ZERO_OPEN;

 if (!bs->drv) {
 return 0;
@@ -5100,17 +5100,17 @@ int bdrv_known_zeroes(BlockDriverState *bs)
  * ZERO_CREATE is not viable.  If the current layer is smaller
  * than the backing layer, truncation may expose backing data,
  * restricting ZERO_TRUNCATE; treat failure to query size in the
- * same manner.  Otherwise, we can trust the driver.
+ * same manner.  For ZERO_OPEN, we insist that both backing and
+ * current layer report the bit.
  */
-
 if (bs->backing) {
 int64_t back = bdrv_getlength(bs->backing->bs);
 int64_t curr = bdrv_getlength(bs);

-if (back < 0 || curr < back) {
-return 0;
+mask = bdrv_known_zeroes(bs->backing->bs) & BDRV_ZERO_OPEN;
+if (back >= 0 && curr >= back) {
+mask |= BDRV_ZERO_TRUNCATE;
 }
-mask = BDRV_ZERO_TRUNCATE;
 }

 if (bs->drv->bdrv_known_zeroes) {
diff --git a/include/block/block.h b/include/block/block.h
index a6a227f50678..dafb8cc2bd80 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -105,6 +105,16 @@ typedef enum {
  * for drivers that set .bdrv_co_truncate.
  */
 BDRV_ZERO_TRUNCATE  = 0x2,
+
+/*
+ * bdrv_known_zeroes() should include this bit if an image is
+ * known to read as all zeroes when first opened; this bit should
+ * not be relied on after any writes to the image.  This can be
+ * set even if BDRV_ZERO_INIT is clear, but should only be set if
+ * making the determination is more efficient than looping over
+ * block status for the image.
+ */
+BDRV_ZERO_OPEN  = 0x4,
 } BdrvZeroFlags;

 typedef struct BlockSizes {
diff --git a/qemu-img.c b/qemu-img.c
index e60217e6c382..c8519a74f738 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1985,10 +1985,12 @@ static int convert_do_copy(ImgConvertState *s)
 int64_t sector_num = 0;

 /* Check whether we have zero initialisation or can get it efficiently */
-if (!s->has_zero_init && s->target_is_new && s->min_sparse &&
-!s->target_has_backing) {
-s->has_zero_init = !!(bdrv_known_zeroes(blk_bs(s->target)) &
-  BDRV_ZERO_CREATE);
+if (!s->has_zero_init && s->min_sparse && !s->target_has_backing) {
+ret = bdrv_known_zeroes(blk_bs(s->target));
+if (ret & BDRV_ZERO_OPEN ||
+(s->target_is_new && ret & BDRV_ZERO_CREATE)) {
+s->has_zero_init = true;
+}
 }

 if (!s->has_zero_init && !s->target_has_backing &&
-- 
2.24.1




[PATCH 00/17] Improve qcow2 all-zero detection

2020-01-31 Thread Eric Blake
Based-on: <20200124103458.1525982-2-david.edmond...@oracle.com>
([PATCH v2 1/2] qemu-img: Add --target-is-zero to convert)

I'm working on adding an NBD extension that reports whether an image
is already all zero when the client first connects.  I initially
thought I could write the NBD code to just call bdrv_has_zero_init(),
but that turned out to be a bad assumption that instead resulted in
this patch series.  The NBD patch will come later (and cross-posted to
the NBD protocol, libnbd, nbdkit, and qemu, as it will affect all four
repositories).

I do have an RFC question on patch 13 - as implemented here, I set a
qcow2 bit if the image has all clusters known zero and no backing
image.  But it may be more useful to instead report whether all
clusters _allocated in this layer_ are zero, at which point the
overall image is all-zero only if the backing file also has that
property (or even make it two bits).  The tweaks to subsequent patches
based on what we think makes the most useful semantics shouldn't be
hard.

[repo.or.cz appears to be down as I type this; I'll post a link to a
repository later when it comes back up]

Eric Blake (17):
  qcow2: Comment typo fixes
  qcow2: List autoclear bit names in header
  qcow2: Avoid feature name extension on small cluster size
  block: Improve documentation of .bdrv_has_zero_init
  block: Don't advertise zero_init_truncate with encryption
  block: Improve bdrv_has_zero_init_truncate with backing file
  gluster: Drop useless has_zero_init callback
  sheepdog: Consistently set bdrv_has_zero_init_truncate
  block: Refactor bdrv_has_zero_init{,_truncate}
  block: Add new BDRV_ZERO_OPEN flag
  file-posix: Support BDRV_ZERO_OPEN
  gluster: Support BDRV_ZERO_OPEN
  qcow2: Add new autoclear feature for all zero image
  qcow2: Expose all zero bit through .bdrv_known_zeroes
  qcow2: Implement all-zero autoclear bit
  iotests: Add new test for qcow2 all-zero bit
  qcow2: Let qemu-img check cover all-zero bit

 block.c|  62 +
 block/file-posix.c |  16 ++-
 block/file-win32.c |   3 +-
 block/gluster.c|  34 +++--
 block/nfs.c|   7 +-
 block/parallels.c  |   4 +-
 block/qcow.c   |   2 +-
 block/qcow2-refcount.c |  60 +++-
 block/qcow2-snapshot.c |  11 ++
 block/qcow2.c  | 150 +---
 block/qcow2.h  |   6 +-
 block/qed.c|   3 +-
 block/raw-format.c |  12 +-
 block/rbd.c|   3 +-
 block/sheepdog.c   |   7 +-
 block/ssh.c|   7 +-
 block/vdi.c|   8 +-
 block/vhdx.c   |  16 +--
 block/vmdk.c   |   9 +-
 block/vpc.c|   8 +-
 blockdev.c |   2 +-
 docs/interop/qcow2.txt |  15 +-
 include/block/block.h  |  38 -
 include/block/block_int.h  |  14 +-
 qapi/block-core.json   |   4 +
 qemu-img.c |   9 +-
 tests/qemu-iotests/031.out |  14 +-
 tests/qemu-iotests/036 |   6 +-
 tests/qemu-iotests/036.out |  10 +-
 tests/qemu-iotests/060.out |   6 +-
 tests/qemu-iotests/061 |   6 +-
 tests/qemu-iotests/061.out |  26 ++--
 tests/qemu-iotests/065 |  12 +-
 tests/qemu-iotests/082.out |   7 +
 tests/qemu-iotests/122 |   2 +-
 tests/qemu-iotests/188 |   2 +-
 tests/qemu-iotests/188.out |   2 +-
 tests/qemu-iotests/206.out |   4 +
 tests/qemu-iotests/242.out |   1 +
 tests/qemu-iotests/285 | 124 +
 tests/qemu-iotests/285.out | 277 +
 tests/qemu-iotests/group   |   1 +
 42 files changed, 832 insertions(+), 178 deletions(-)
 create mode 100755 tests/qemu-iotests/285
 create mode 100644 tests/qemu-iotests/285.out

-- 
2.24.1




[PATCH 02/17] qcow2: List autoclear bit names in header

2020-01-31 Thread Eric Blake
The feature table is supposed to advertise the name of all feature
bits that we support; however, we forgot to update the table for
autoclear bits.  While at it, move the table to read-only memory in
code, and tweak the qcow2 spec to name the second autoclear bit.
Update iotests that are affected by the longer header length.

Fixes: 88ddffae
Fixes: 93c24936
Signed-off-by: Eric Blake 
---
 block/qcow2.c  | 12 +++-
 docs/interop/qcow2.txt |  3 ++-
 tests/qemu-iotests/031.out |  8 
 tests/qemu-iotests/036.out |  4 ++--
 tests/qemu-iotests/061.out | 14 +++---
 5 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 30fd3d13032a..d3e7709ac2b4 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2821,7 +2821,7 @@ int qcow2_update_header(BlockDriverState *bs)

 /* Feature table */
 if (s->qcow_version >= 3) {
-Qcow2Feature features[] = {
+static const Qcow2Feature features[] = {
 {
 .type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
 .bit  = QCOW2_INCOMPAT_DIRTY_BITNR,
@@ -2842,6 +2842,16 @@ int qcow2_update_header(BlockDriverState *bs)
 .bit  = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
 .name = "lazy refcounts",
 },
+{
+.type = QCOW2_FEAT_TYPE_AUTOCLEAR,
+.bit  = QCOW2_AUTOCLEAR_BITMAPS_BITNR,
+.name = "consistent bitmaps",
+},
+{
+.type = QCOW2_FEAT_TYPE_AUTOCLEAR,
+.bit  = QCOW2_AUTOCLEAR_DATA_FILE_RAW_BITNR,
+.name = "raw external data",
+},
 };

 ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
index af5711e53371..8510d74c8079 100644
--- a/docs/interop/qcow2.txt
+++ b/docs/interop/qcow2.txt
@@ -138,7 +138,8 @@ in the description of a field.
 bit is unset, the bitmaps extension data must 
be
 considered inconsistent.

-Bit 1:  If this bit is set, the external data file can
+Bit 1:  Raw external data bit
+If this bit is set, the external data file can
 be read as a consistent standalone raw image
 without looking at the qcow2 metadata.

diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
index d535e407bc30..46f97c5a4ea4 100644
--- a/tests/qemu-iotests/031.out
+++ b/tests/qemu-iotests/031.out
@@ -117,7 +117,7 @@ header_length 104

 Header extension:
 magic 0x6803f857
-length192
+length288
 data  

 Header extension:
@@ -150,7 +150,7 @@ header_length 104

 Header extension:
 magic 0x6803f857
-length192
+length288
 data  

 Header extension:
@@ -164,7 +164,7 @@ No errors were found on the image.

 magic 0x514649fb
 version   3
-backing_file_offset   0x178
+backing_file_offset   0x1d8
 backing_file_size 0x17
 cluster_bits  16
 size  67108864
@@ -188,7 +188,7 @@ data  'host_device'

 Header extension:
 magic 0x6803f857
-length192
+length288
 data  

 Header extension:
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
index 0b52b934e115..23b699ce0622 100644
--- a/tests/qemu-iotests/036.out
+++ b/tests/qemu-iotests/036.out
@@ -26,7 +26,7 @@ compatible_features   []
 autoclear_features[63]
 Header extension:
 magic 0x6803f857
-length192
+length288
 data  


@@ -38,7 +38,7 @@ compatible_features   []
 autoclear_features[]
 Header extension:
 magic 0x6803f857
-length192
+length288
 data  

 *** done
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index 8b3091a412bc..413cc4e0f4ab 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -26,7 +26,7 @@ header_length 104

 Header extension:
 magic 0x6803f857
-length192
+length288
 data  

 magic 0x514649fb
@@ -84,7 +84,7 @@ header_length 104

 Header extension:
 magic 0x6803f857
-length192
+length288
 data  

 magic 0x514649fb
@@ -140,7 +140,7 @@ header_length 104

 Header extension:
 magic 0x6803f857

[PATCH 07/17] gluster: Drop useless has_zero_init callback

2020-01-31 Thread Eric Blake
block.c already defaults to 0 if we don't provide a callback; there's
no need to write a callback that always fails.

Signed-off-by: Eric Blake 
---
 block/gluster.c | 14 --
 1 file changed, 14 deletions(-)

diff --git a/block/gluster.c b/block/gluster.c
index 4fa4a77a4777..9d952c70981b 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -1357,12 +1357,6 @@ static int64_t 
qemu_gluster_allocated_file_size(BlockDriverState *bs)
 }
 }

-static int qemu_gluster_has_zero_init(BlockDriverState *bs)
-{
-/* GlusterFS volume could be backed by a block device */
-return 0;
-}
-
 /*
  * Find allocation range in @bs around offset @start.
  * May change underlying file descriptor's file offset.
@@ -1567,8 +1561,6 @@ static BlockDriver bdrv_gluster = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
-.bdrv_has_zero_init   = qemu_gluster_has_zero_init,
-.bdrv_has_zero_init_truncate  = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
@@ -1599,8 +1591,6 @@ static BlockDriver bdrv_gluster_tcp = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
-.bdrv_has_zero_init   = qemu_gluster_has_zero_init,
-.bdrv_has_zero_init_truncate  = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
@@ -1631,8 +1621,6 @@ static BlockDriver bdrv_gluster_unix = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
-.bdrv_has_zero_init   = qemu_gluster_has_zero_init,
-.bdrv_has_zero_init_truncate  = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
@@ -1669,8 +1657,6 @@ static BlockDriver bdrv_gluster_rdma = {
 .bdrv_co_readv= qemu_gluster_co_readv,
 .bdrv_co_writev   = qemu_gluster_co_writev,
 .bdrv_co_flush_to_disk= qemu_gluster_co_flush_to_disk,
-.bdrv_has_zero_init   = qemu_gluster_has_zero_init,
-.bdrv_has_zero_init_truncate  = qemu_gluster_has_zero_init,
 #ifdef CONFIG_GLUSTERFS_DISCARD
 .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
 #endif
-- 
2.24.1




[PATCH 01/17] qcow2: Comment typo fixes

2020-01-31 Thread Eric Blake
Various trivial typos noticed while working on this file.

Signed-off-by: Eric Blake 
---
 block/qcow2.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index cef9d72b3a16..30fd3d13032a 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -174,7 +174,7 @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock 
*block, size_t offset,
 }


-/* 
+/*
  * read qcow2 extension and fill bs
  * start reading from start_offset
  * finish reading upon magic of value 0 or when end_offset reached
@@ -3251,7 +3251,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
Error **errp)
  * inconsistency later.
  *
  * We do need a refcount table because growing the refcount table means
- * allocating two new refcount blocks - the seconds of which would be at
+ * allocating two new refcount blocks - the second of which would be at
  * 2 GB for 64k clusters, and we don't want to have a 2 GB initial file
  * size for any qcow2 image.
  */
@@ -3495,7 +3495,7 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
Error **errp)
 goto out;
 }

-/* Want a backing file? There you go.*/
+/* Want a backing file? There you go. */
 if (qcow2_opts->has_backing_file) {
 const char *backing_format = NULL;

-- 
2.24.1




[PATCH 08/17] sheepdog: Consistently set bdrv_has_zero_init_truncate

2020-01-31 Thread Eric Blake
block_int.h claims that .bdrv_has_zero_init must return 0 if
.bdrv_has_zero_init_truncate does likewise; but this is violated if
only the former callback is provided if .bdrv_co_truncate also exists.
When adding the latter callback, it was mistakenly added to only one
of the three possible sheepdog instantiations.

Fixes: 1dcaf527
Signed-off-by: Eric Blake 
---
 block/sheepdog.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/block/sheepdog.c b/block/sheepdog.c
index cfa84338a2d6..522c16a93676 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -3269,6 +3269,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
 .bdrv_co_create   = sd_co_create,
 .bdrv_co_create_opts  = sd_co_create_opts,
 .bdrv_has_zero_init   = bdrv_has_zero_init_1,
+.bdrv_has_zero_init_truncate  = bdrv_has_zero_init_1,
 .bdrv_getlength   = sd_getlength,
 .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
 .bdrv_co_truncate = sd_co_truncate,
@@ -3307,6 +3308,7 @@ static BlockDriver bdrv_sheepdog_unix = {
 .bdrv_co_create   = sd_co_create,
 .bdrv_co_create_opts  = sd_co_create_opts,
 .bdrv_has_zero_init   = bdrv_has_zero_init_1,
+.bdrv_has_zero_init_truncate  = bdrv_has_zero_init_1,
 .bdrv_getlength   = sd_getlength,
 .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
 .bdrv_co_truncate = sd_co_truncate,
-- 
2.24.1




[PATCH 04/17] block: Improve documentation of .bdrv_has_zero_init

2020-01-31 Thread Eric Blake
Several drivers supply .bdrv_has_zero_init that returns 1, but lack
the .bdrv_has_zero_init_truncate callback (parallels and qed outright,
vdi in some scenarios).  A literal reading of the existing
documentation says such drivers are broken, because
bdrv_has_zero_init_truncate() defaults to zero if the callback is
missing; but in practice, the tie between the two functions is only
relevant when truncate is supported.  Clarify the documentation to
make it obvious that this is okay.

Fixes: 1dcaf527
Signed-off-by: Eric Blake 
---
 include/block/block_int.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/block/block_int.h b/include/block/block_int.h
index 640fb82c789e..77ab45dc87cf 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -444,7 +444,8 @@ struct BlockDriver {
 /*
  * Returns 1 if newly created images are guaranteed to contain only
  * zeros, 0 otherwise.
- * Must return 0 if .bdrv_has_zero_init_truncate() returns 0.
+ * Must return 0 if .bdrv_co_truncate is set and
+ * .bdrv_has_zero_init_truncate() returns 0.
  */
 int (*bdrv_has_zero_init)(BlockDriverState *bs);

-- 
2.24.1




[PATCH 05/17] block: Don't advertise zero_init_truncate with encryption

2020-01-31 Thread Eric Blake
Commit 38841dcd correctly argued that having qcow2 blindly return 1
for .bdrv_has_zero_init() is wrong for preallocated images built on
block devices, while .bdrv_has_zero_init_truncate() can still return 1
because it is only relied on when changing size with PREALLOC_MODE_OFF
(and this is true even for v2 images which lack the notion of an
explicit zero cluster, since the block layer already filters out the
case of a larger backing file leaking through).  However, it missed
the fact that encrypted images do not default to reading as zero in
any case.

However, instead of changing qcow2's .bdrv_has_zero_init_truncate() to
point to a one-off function that special-cases bs->encryption, it is
smarter to just move the logic about encryption directly to the block
layer (that is, the driver callbacks will never be invoked for
encrypted images, just like they are already not called when a backing
file is present).  This solution fixes the qcow2 issue, has no effect
on the crypto driver (which already lacks .bdrv_has_zero_init*
callbacks), and no other driver currently uses bs->encrypted.

One other reason to fix this at the block layer: any information we
expose about an encrypted image that in turn may alter timing of
algorithms run on that image can be considered a (slight) information
leak; refusing to optimize zero handling of encrypted images thus
avoids the possibility of that being a security concern.

Signed-off-by: Eric Blake 
---
 block.c   | 19 ---
 block/qcow2.c |  2 --
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/block.c b/block.c
index 6c2b2bd2e292..296845040e59 100644
--- a/block.c
+++ b/block.c
@@ -5077,9 +5077,12 @@ int bdrv_has_zero_init(BlockDriverState *bs)
 return 0;
 }

-/* If BS is a copy on write image, it is initialized to
-   the contents of the base image, which may not be zeroes.  */
-if (bs->backing) {
+/*
+ * If BS is a copy on write image, it is initialized to the
+ * contents of the base image, which may not be zeroes.  Likewise,
+ * encrypted images do not read as zero.
+ */
+if (bs->backing || bs->encrypted) {
 return 0;
 }
 if (bs->drv->bdrv_has_zero_init) {
@@ -5099,6 +5102,16 @@ int bdrv_has_zero_init_truncate(BlockDriverState *bs)
 return 0;
 }

+/*
+ * Encrypted images never default to reading all zero; and even if
+ * they did, advertising that fact might lead to an information
+ * leak based on timing comparisons of algorithms that change if
+ * our result were dynamic.
+ */
+if (bs->encrypted) {
+return 0;
+}
+
 if (bs->backing) {
 /* Depends on the backing image length, but better safe than sorry */
 return 0;
diff --git a/block/qcow2.c b/block/qcow2.c
index 6ea06dbdf48a..40aa751d1de7 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4934,8 +4934,6 @@ static int qcow2_has_zero_init(BlockDriverState *bs)

 if (!preallocated) {
 return 1;
-} else if (bs->encrypted) {
-return 0;
 } else {
 return bdrv_has_zero_init(s->data_file->bs);
 }
-- 
2.24.1




Re: [PATCH v1 15/36] target/riscv: Convert mstatus to pointers

2020-01-31 Thread Alistair Francis
On Thu, Jan 30, 2020 at 6:48 AM Palmer Dabbelt  wrote:
>
> On Tue, 21 Jan 2020 11:02:01 GMT (+), alistai...@gmail.com wrote:
> > On Wed, Jan 8, 2020 at 11:30 AM Palmer Dabbelt  
> > wrote:
> >>
> >> On Mon, 09 Dec 2019 10:11:19 PST (-0800), Alistair Francis wrote:
> >> > To handle the new Hypervisor CSR register aliasing let's use pointers.
> >>
> >> For some reason I thought we were making this explicit?  In other words,
> >> requiring that all callers provide which privilege mode they're using when
> >> accessing these CSRs, as opposed to swapping around pointers.  I don't 
> >> actually
> >> care that much, but IIRC when we were talking with the ARM guys at Plumbers
> >> they were pretty adament that would end up being a much cleaner 
> >> implementation
> >> as they'd tried this way and later changed over.
> >
> > I think their implementation is different so it doesn't apply the same here.
> >
> > My main concern is that due to the modularity of RISC-V I don't expect
> > all future developers to keep track of the Hypervisor extensions. This
> > way we always have the correct state in the registers.
> >
> > There is only one pointer variable left, so we could drop the pointer
> > swapping part, but for now it's still here.
>
> OK, so in the interest of moving things forwards let's just
>
> Reviewed-by: Palmer Dabbelt 

Thanks

>
> so we can merge this -- it's too big of a patch set to wait around on 
> something
> so small for.  I think that was the last one missing a review, right?

I have made one small change and dismissed your review from a patch,
it also looks like one patch hasn't been reviewed either.

I'll send a v2 later today that has been rebased on master.

Alistair

>
> >
> > Alistair
> >
> >>
> >> > Signed-off-by: Alistair Francis 
> >> > ---
> >> >  target/riscv/cpu.c| 11 +--
> >> >  target/riscv/cpu.h|  9 -
> >> >  target/riscv/cpu_helper.c | 30 +++---
> >> >  target/riscv/csr.c| 20 ++--
> >> >  target/riscv/op_helper.c  | 14 +++---
> >> >  5 files changed, 49 insertions(+), 35 deletions(-)
> >> >
> >> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> > index a07c5689b3..e61cf46a73 100644
> >> > --- a/target/riscv/cpu.c
> >> > +++ b/target/riscv/cpu.c
> >> > @@ -236,7 +236,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE 
> >> > *f, int flags)
> >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc  ", env->pc);
> >> >  #ifndef CONFIG_USER_ONLY
> >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", 
> >> > env->mhartid);
> >> > -qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
> >> > env->mstatus);
> >> > +qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", 
> >> > *env->mstatus);
> >> >  if (riscv_has_ext(env, RVH)) {
> >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", 
> >> > env->hstatus);
> >> >  qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", 
> >> > env->vsstatus);
> >> > @@ -336,7 +336,7 @@ static void riscv_cpu_reset(CPUState *cs)
> >> >  mcc->parent_reset(cs);
> >> >  #ifndef CONFIG_USER_ONLY
> >> >  env->priv = PRV_M;
> >> > -env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> >> > +*env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
> >> >  env->mcause = 0;
> >> >  env->pc = env->resetvec;
> >> >  #endif
> >> > @@ -465,8 +465,15 @@ static void riscv_cpu_realize(DeviceState *dev, 
> >> > Error **errp)
> >> >  static void riscv_cpu_init(Object *obj)
> >> >  {
> >> >  RISCVCPU *cpu = RISCV_CPU(obj);
> >> > +#ifndef CONFIG_USER_ONLY
> >> > +CPURISCVState *env = >env;
> >> > +#endif
> >> >
> >> >  cpu_set_cpustate_pointers(cpu);
> >> > +
> >> > +#ifndef CONFIG_USER_ONLY
> >> > +env->mstatus = >mstatus_novirt;
> >> > +#endif
> >> >  }
> >> >
> >> >  static const VMStateDescription vmstate_riscv_cpu = {
> >> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >> > index 21ae5a8b19..9dc8303c62 100644
> >> > --- a/target/riscv/cpu.h
> >> > +++ b/target/riscv/cpu.h
> >> > @@ -122,7 +122,7 @@ struct CPURISCVState {
> >> >  target_ulong resetvec;
> >> >
> >> >  target_ulong mhartid;
> >> > -target_ulong mstatus;
> >> > +target_ulong *mstatus;
> >> >
> >> >  target_ulong mip;
> >> >  uint32_t miclaim;
> >> > @@ -145,6 +145,13 @@ struct CPURISCVState {
> >> >  target_ulong mcause;
> >> >  target_ulong mtval;  /* since: priv-1.10.0 */
> >> >
> >> > +/* The following registers are the "real" versions that the pointer
> >> > + * versions point to. These should never be used unless you know 
> >> > what you
> >> > + * are doing. To access these use the pointer versions instead. 
> >> > This is
> >> > + * required to handle the Hypervisor register swapping.
> >> > + */
> >> > +target_ulong mstatus_novirt;
> >> > +
> >> >  /* Hypervisor CSRs */
> >> >  target_ulong hstatus;
> >> >  target_ulong hedeleg;
> >> 

Re: [Bug 1861404] [NEW] AVX instruction VMOVDQU implementation error for YMM registers

2020-01-31 Thread Aleksandar Markovic
On Friday, January 31, 2020, Alex Bennée  wrote:

> ** Tags added: tcg testcase
>
> --
> You received this bug notification because you are a member of qemu-
> devel-ml, which is subscribed to QEMU.
> https://bugs.launchpad.net/bugs/1861404
>
> Title:
>   AVX instruction VMOVDQU implementation error for YMM registers
>
>
If I remember well, there is no support for AVX instructions in linux-user
mode.

If that is true, how come handling of unsupported instruction went that far?

Did you try other AVX instructions?

Aleksandar




> Status in QEMU:
>   New
>
> Bug description:
>   Hi,
>
>   Tested with Qemu 4.2.0, and with git version
>   bddff6f6787c916b0e9d63ef9e4d442114257739.
>
>   The x86 AVX instruction VMOVDQU doesn't work properly with YMM registers
> (32 bytes).
>   It works with XMM registers (16 bytes) though.
>
>   See the attached test case `ymm.c`: when copying from memory-to-ymm0
>   and then back from ymm0-to-memory using VMOVDQU, Qemu only copies the
>   first 16 of the total 32 bytes.
>
>   ```
>   user@ubuntu ~/Qemu % gcc -o ymm ymm.c -Wall -Wextra -Werror
>
>   user@ubuntu ~/Qemu % ./ymm
>   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
> 18 19 1A 1B 1C 1D 1E 1F
>
>   user@ubuntu ~/Qemu % ./x86_64-linux-user/qemu-x86_64 -cpu max ymm
>   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00
>   ```
>
>   This seems to be because in `translate.c > gen_sse()`, the case
>   handling the VMOVDQU instruction calls `gen_ldo_env_A0` which always
>   performs a 16 bytes copy using two 8 bytes load and store operations
>   (with `tcg_gen_qemu_ld_i64` and `tcg_gen_st_i64`).
>
>   Instead, the `gen_ldo_env_A0` function should generate a copy with a
>   size corresponding to the used register.
>
>
>   ```
>   static void gen_sse(CPUX86State *env, DisasContext *s, int b,
>   target_ulong pc_start, int rex_r)
>   {
>   [...]
>   case 0x26f: /* movdqu xmm, ea */
>   if (mod != 3) {
>   gen_lea_modrm(env, s, modrm);
>   gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
>   } else {
>   [...]
>   ```
>
>   ```
>   static inline void gen_ldo_env_A0(DisasContext *s, int offset)
>   {
>   int mem_index = s->mem_index;
>   tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
>   tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg,
> ZMM_Q(0)));
>   tcg_gen_addi_tl(s->tmp0, s->A0, 8);
>   tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
>   tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg,
> ZMM_Q(1)));
>   }
>   ```
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/qemu/+bug/1861404/+subscriptions
>
>


Re: [PATCH] target/arm: fix TCG leak for fcvt half->double

2020-01-31 Thread Peter Maydell
On Fri, 31 Jan 2020 at 16:50, Philippe Mathieu-Daudé  wrote:
>
> On 1/31/20 4:34 PM, Alex Bennée wrote:
> > When support for the AHP flag was added we inexplicably only freed the
> > new temps in one of the two legs. Move those tcg_temp_free to the same
> > level as the allocation to fix that leak.
>
> Probably too much code refactoring :/
>
> >
> > Fixes: 486624fcd3eac
>
> Maybe:
> Reported-by: Peter Maydell 
>
> > Signed-off-by: Alex Bennée 
>
> Reviewed-by: Philippe Mathieu-Daudé 

Thanks; applied to master as that will let me apply the
tracing pullreq without having to suppress or ignore the
warning.

-- PMM



Re: [PATCH v11 2/2] docs: qcow2: introduce compression type feature

2020-01-31 Thread Alberto Garcia
On Fri 31 Jan 2020 03:46:12 PM CET, Eric Blake wrote:
>> +If the incompatible bit "Compression type" is set: the 
>> field
>> +must be present and non-zero (which means non-zlib
>> +compression type). Otherwise, this field must not be 
>> present
>> +or must be zero (which means zlib).
>
> If the incompatible bit "Compression type" is set: the field
> must be present. Otherwise, this field must not be present
> or must be zero (which means zlib).

But "not being present" and "being zero" is equivalent (as described in
the previous commit).

And if the incompatible bit is not present then the field can be safely
ignored (i.e. whether it is zero or not is irrelevant).

Let's try again:

   Defines the compression method used for compressed clusters. All
   compressed clusters in an image use the same type.

   The value of this field should only be used when the incompatible bit
   "Compression type" is set. If that bit is unset then this field is
   not used and the compression method is zlib.

Berto



Re: [PATCH] tests/acceptance: Add a test for the integratorcp arm machine

2020-01-31 Thread Philippe Mathieu-Daudé

On 1/31/20 6:02 PM, Thomas Huth wrote:

There is a kernel and initrd available on github which we can use
for testing this machine.

Signed-off-by: Thomas Huth 
---
  MAINTAINERS  |  1 +
  tests/acceptance/machine_arm_integratorcp.py | 43 
  2 files changed, 44 insertions(+)
  create mode 100644 tests/acceptance/machine_arm_integratorcp.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 6e4976d366..6a03835037 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -599,6 +599,7 @@ S: Maintained
  F: hw/arm/integratorcp.c
  F: hw/misc/arm_integrator_debug.c
  F: include/hw/misc/arm_integrator_debug.h
+F: tests/acceptance/machine_arm_integratorcp.py
  
  MCIMX6UL EVK / i.MX6ul

  M: Peter Maydell 
diff --git a/tests/acceptance/machine_arm_integratorcp.py 
b/tests/acceptance/machine_arm_integratorcp.py
new file mode 100644
index 00..4f9ab40f2f
--- /dev/null
+++ b/tests/acceptance/machine_arm_integratorcp.py
@@ -0,0 +1,43 @@
+# Functional test that boots a Linux kernel and checks the console
+#
+# Copyright (c) 2020 Red Hat, Inc.
+#
+# Author:
+#  Thomas Huth 
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later.  See the COPYING file in the top-level directory.
+
+import os
+
+from avocado import skipUnless
+from avocado_qemu import Test
+from avocado_qemu import wait_for_console_pattern
+
+class IntegratorMachine(Test):
+"""Boots the Linux kernel and checks that the console is operational"""
+
+timeout = 90
+
+@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
+def test_integratorcp(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:integratorcp
+"""
+kernel_url = ('https://github.com/zayac/qemu-arm/raw/master/'
+  'arm-test/kernel/zImage.integrator')
+kernel_hash = '0d7adba893c503267c946a3cbdc63b4b54f25468'
+kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+initrd_url = ('https://github.com/zayac/qemu-arm/raw/master/'
+  'arm-test/kernel/arm_root.img')
+initrd_hash = 'b51e4154285bf784e017a37586428332d8c7bd8b'
+initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+
+self.vm.set_console()
+self.vm.add_args('-kernel', kernel_path,
+ '-initrd', initrd_path,
+ '-append', 'printk.time=0 console=ttyAMA0')
+self.vm.launch()
+wait_for_console_pattern(self, 'Log in as root')



Nice. I see the framebuffer is also working.

I'd add a test on the CPU, and device listed:

Log in as root with no password.
qemu login: root
login[724]: root login  on `ttyAMA0'



BusyBox v1.1.2 (2006.05.04-15:30+) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

# cat /proc/cpuinfo
Processor   : ARM926EJ-Sid(wb) rev 5 (v5l)
BogoMIPS: 930.61
Features: swp half thumb fastmult edsp java
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant : 0x0
CPU part: 0x926
CPU revision: 5
Cache type  : write-through
Cache clean : not required
Cache lockdown  : not supported
Cache format: Harvard
I size  : 4096
I assoc : 4
I line length   : 32
I sets  : 32
D size  : 65536
D assoc : 4
D line length   : 32
D sets  : 512

Hardware: ARM-IntegratorCP
Revision: 
Serial  : 
# cat /proc/io
/proc/iomem /proc/ioports
# cat /proc/iomem
-07ff : System RAM
  00022000-0020431f : Kernel text
  00206000-002670db : Kernel data
1500-15000fff : mb:15
1600-16000fff : mb:16
  1600-16000fff : uart-pl011
1700-17000fff : mb:17
  1700-17000fff : uart-pl011
1800-18000fff : mb:18
  1800-18000fff : kmi-pl050
1900-19000fff : mb:19
  1900-19000fff : kmi-pl050
1c00-1c000fff : mb:1c
  1c00-1c000fff : mmci-pl18x
2400-25ff : armflash.0
c000-cfff : mb:c0
  c000-cfff : clcd-pl11x
c800-c80f : smc91x.0
  c800-c80f : smc91x
#

Anyway this can be done in another patch on top, so:

Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 




[Bug 1860610] Re: cap_disas_plugin leaks memory

2020-01-31 Thread Alex Bennée
It looks like this will fail on all the other capstone cases as well. Is
this an API change across versions?

** Tags added: plugin tcg

** Changed in: qemu
 Assignee: (unassigned) => Alex Bennée (ajbennee)

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

Title:
  cap_disas_plugin leaks memory

Status in QEMU:
  New

Bug description:
  Looking at origin/master head, the function cap_disas_plugin leaks
  memory.

  per capstone's examples using their ABI, cs_free(insn, count); needs
  to called just before cs_close.

  I discovered this running qemu under valgrind.

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



Re: Improving QOM documentation [Was: Re: Making QEMU easier for management tools and applications]

2020-01-31 Thread Markus Armbruster
Kashyap Chamarthy  writes:

> On Fri, Jan 31, 2020 at 12:02:05PM +0100, Paolo Bonzini wrote:
>> Il ven 31 gen 2020, 11:36 Peter Maydell  ha
>> scritto:
>
> [...]
>
>> The advantage of putting them in the header is that you have them all in
>> one place (inline functions and structs must be in the header). In practice
>> that balances for me the disadvantage of having some comments far from the
>> code they document, which increases the risk of bitrot especially for
>> comments such as "called with lock X held".
>> 
>> I definitely agree that the overview/introduction/conventions
>> > side of things is where we'd benefit most if somebody wanted
>> > to try to tackle that. We could roll
>> > https://wiki.qemu.org/Documentation/QOMConventions
>> > into that if we had a better place to put that info.
>> >
>> 
>> I am travelling this weekend so I might try to do some kind of thread
>> summary and brain dump in the wiki. I'll leave to Kashyap to do the rST
>> conversion and patch submission. ;-)
>
> Thanks!  Happy to be the 'scribe' ;-)  I have a skeltal
> qemu-object-model.rst file sitting with some initial content based on
> various sources, including one of your presentations[*] from 2014.
> I'll wait for your new Wiki link to incorporate that content.
>
> (Minor aside: I'm not sure if this file should be in docs/interop/ dir,
> which IIRC, is for things that are 'external' interfaces.  And I learn
> that QOM is used both internally in and as an external interface, e.g.
> whenever a device is being created, machine types, CPU config, etc.)

docs/devel/qapi-code-gen.txt has the same problem: it's mostly internal
stuff, but there's also introspection, which is an external interface.

>
> - - -
>
> I've re-skimmed your scarily-titled "QOM exegesis and apocalypse" 2014
> KVM Forum talk slides[*], where the "Why QOM?" slide says:
>
> All device creation, device configuration, backend creation and
> backed configuration done through a single interface
> 
> Rigorous support for introspection both of runtime objects and type
> capabilities

For a value of "rigorous".

Let me propose QAPI's query-qmp-schema as the tin standard[*] of
introspection:

* It's documented

* It comes with something that can pass as a type system

* It actually tells you the full truth.

Now compare to QOM:

* Documentation

  QAPI: docs/devel/qapi-code-gen.txt section "Client JSON Protocol
  introspection"

  QOM: Nada

* Type system

  QAPI: A few built-in types specified in the documentation, type
  constructors for complex types.

  QOM: Types are strings, and you just need to know what they mean.
  Some string patterns are special: link, child, STR[INT], and
  you just need to know what that means, too.

* Full truth

  QAPI: If you can access it at the interface, you can also see it in
  introspection.

  QOM: Type introspection can show you only the properties of a freshly
  created object.  Properties that get created only later are invisible.
  Properties that depend on global state are unreliable.  Object
  introspection is reliable, but only for that object in its current
  state.

> Me wonders how much of the above "Why" still holds true today.  Although
> further slides give more clues on what worked and what didn't.
>
> I'll wait for fresher details from your upcoming Wiki :-)
>
> [*] http://www.linux-kvm.org/images/9/90/Kvmforum14-qom.pdf

[*] Gold was too expensive, but we had some tin on hand, so...




Re: [GSoC/Outreachy QEMU proposal] Extend support for ioctls in QEMU linux-user mode

2020-01-31 Thread Stefan Hajnoczi
On Thu, Jan 30, 2020 at 12:09:58PM +0100, Aleksandar Markovic wrote:
> Stefan, there was an idea in this thread that this project contributes
> (apart to QEMU) to another ooen source project (LTP). In my layman view,
> this is an advantage. But, how does that fit into GSoC/Outreachy rules?

That is fine for GSoC.  It will benefit the open source community and
the code being written will be under an approved open source license.

For Outreachy we focus on the QEMU codebase because the funding comes
for sponsors that may wish their donations to be used for QEMU
development.

Stefan


signature.asc
Description: PGP signature


[Bug 1861404] Re: AVX instruction VMOVDQU implementation error for YMM registers

2020-01-31 Thread Alex Bennée
** Tags added: tcg testcase

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

Title:
  AVX instruction VMOVDQU implementation error for YMM registers

Status in QEMU:
  New

Bug description:
  Hi,

  Tested with Qemu 4.2.0, and with git version
  bddff6f6787c916b0e9d63ef9e4d442114257739.

  The x86 AVX instruction VMOVDQU doesn't work properly with YMM registers (32 
bytes).
  It works with XMM registers (16 bytes) though.

  See the attached test case `ymm.c`: when copying from memory-to-ymm0
  and then back from ymm0-to-memory using VMOVDQU, Qemu only copies the
  first 16 of the total 32 bytes.

  ```
  user@ubuntu ~/Qemu % gcc -o ymm ymm.c -Wall -Wextra -Werror

  user@ubuntu ~/Qemu % ./ymm
  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 
1A 1B 1C 1D 1E 1F

  user@ubuntu ~/Qemu % ./x86_64-linux-user/qemu-x86_64 -cpu max ymm
  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00
  ```

  This seems to be because in `translate.c > gen_sse()`, the case
  handling the VMOVDQU instruction calls `gen_ldo_env_A0` which always
  performs a 16 bytes copy using two 8 bytes load and store operations
  (with `tcg_gen_qemu_ld_i64` and `tcg_gen_st_i64`).

  Instead, the `gen_ldo_env_A0` function should generate a copy with a
  size corresponding to the used register.

  
  ```
  static void gen_sse(CPUX86State *env, DisasContext *s, int b,
  target_ulong pc_start, int rex_r)
  {
  [...]
  case 0x26f: /* movdqu xmm, ea */
  if (mod != 3) {
  gen_lea_modrm(env, s, modrm);
  gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
  } else { 
  [...]
  ```

  ```
  static inline void gen_ldo_env_A0(DisasContext *s, int offset)
  {
  int mem_index = s->mem_index;
  tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ);
  tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0)));
  tcg_gen_addi_tl(s->tmp0, s->A0, 8);
  tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ);
  tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1)));
  }
  ```

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



Re: [PATCH v11 1/2] docs: improve qcow2 spec about extending image header

2020-01-31 Thread Alberto Garcia
On Fri 31 Jan 2020 03:22:18 PM CET, Vladimir Sementsov-Ogievskiy wrote:
> Make it more obvious how to add new fields to the version 3 header and
> how to interpret them.
>
> The specification is adjusted so that for new defined optional fields:
>
> 1. Software may support some of these optional fields and ignore the
>others, which means that features may be backported to downstream
>Qemu independently.
> 2. If we want to add incompatible field (or a field, for which some its
>values would be incompatible), it must be accompanied by
>incompatible feature bit.
>
> Also the concept of "default is zero" is clarified, as it's strange to
> say that the value of the field is assumed to be zero for the software
> version which don't know about the field at all and don't know how to
> treat it be it zero or not.
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Eric Blake 

Reviewed-by: Alberto Garcia 

Berto



  1   2   3   >