Re: [Qemu-devel] [PATCH v1.1 0/9] target/m68k: Convert to TranslatorOps

2018-05-11 Thread no-reply
Hi,

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

Type: series
Message-id: 20180512050250.12774-1-richard.hender...@linaro.org
Subject: [Qemu-devel] [PATCH v1.1 0/9] target/m68k: Convert to TranslatorOps

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]   
patchew/20180512050250.12774-1-richard.hender...@linaro.org -> 
patchew/20180512050250.12774-1-richard.hender...@linaro.org
Switched to a new branch 'test'
b396d1ea56 target/m68k: Merge disas_m68k_insn into m68k_tr_translate_insn
1454f7ac75 target/m68k: Improve ending TB at page boundaries
180209d486 target/m68k: Convert to TranslatorOps
838e40004e target/m68k: Convert to DisasContextBase
88f0d5dff1 target/m68k: Rename DISAS_UPDATE and gen_lookup_tb
78920794cd target/m68k: Use lookup_and_goto_tb for DISAS_JUMP
0ae1c99c4a target/m68k: Remove DISAS_JUMP_NEXT as unused
127bfcf989 target/m68k: Replace DISAS_TB_JUMP with DISAS_NORETURN
836179eaad target/m68k: Use DISAS_NORETURN for exceptions

=== OUTPUT BEGIN ===
Checking PATCH 1/9: target/m68k: Use DISAS_NORETURN for exceptions...
Checking PATCH 2/9: target/m68k: Replace DISAS_TB_JUMP with DISAS_NORETURN...
Checking PATCH 3/9: target/m68k: Remove DISAS_JUMP_NEXT as unused...
Checking PATCH 4/9: target/m68k: Use lookup_and_goto_tb for DISAS_JUMP...
Checking PATCH 5/9: target/m68k: Rename DISAS_UPDATE and gen_lookup_tb...
Checking PATCH 6/9: target/m68k: Convert to DisasContextBase...
ERROR: space required before the open parenthesis '('
#559: FILE: target/m68k/translate.c:6134:
+switch(dc->base.is_jmp) {

total: 1 errors, 0 warnings, 494 lines checked

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

Checking PATCH 7/9: target/m68k: Convert to TranslatorOps...
Checking PATCH 8/9: target/m68k: Improve ending TB at page boundaries...
Checking PATCH 9/9: target/m68k: Merge disas_m68k_insn into 
m68k_tr_translate_insn...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[Qemu-devel] [PATCH 9/9] target/m68k: Merge disas_m68k_insn into m68k_tr_translate_insn

2018-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 17 ++---
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 069558bc28..21eeebf4df 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -6049,16 +6049,6 @@ void register_m68k_insns (CPUM68KState *env)
 #undef INSN
 }
 
-/* ??? Some of this implementation is not exception safe.  We should always
-   write back the result to memory before setting the condition codes.  */
-static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
-{
-uint16_t insn = read_im16(env, s);
-opcode_table[insn](env, s, insn);
-do_writebacks(s);
-do_release(s);
-}
-
 static void m68k_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
 {
 DisasContext *dc = container_of(dcbase, DisasContext, base);
@@ -6101,8 +6091,13 @@ static bool m68k_tr_breakpoint_check(DisasContextBase 
*dcbase, CPUState *cpu,
 static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
 {
 DisasContext *dc = container_of(dcbase, DisasContext, base);
+CPUM68KState *env = cpu->env_ptr;
+uint16_t insn = read_im16(env, dc);
+
+opcode_table[insn](env, dc, insn);
+do_writebacks(dc);
+do_release(dc);
 
-disas_m68k_insn(cpu->env_ptr, dc);
 dc->base.pc_next = dc->pc;
 
 if (dc->base.is_jmp == DISAS_NEXT) {
-- 
2.17.0




[Qemu-devel] [PATCH 8/9] target/m68k: Improve ending TB at page boundaries

2018-05-11 Thread Richard Henderson
Rather than limit total TB size to PAGE-32 bytes, end the TB when
near the end of a page.  This should provide proper semantics of
SIGSEGV when executing near the end of a page.

Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 0ab9ab1148..069558bc28 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -6105,9 +6105,25 @@ static void m68k_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cpu)
 disas_m68k_insn(cpu->env_ptr, dc);
 dc->base.pc_next = dc->pc;
 
-if (dc->base.is_jmp == DISAS_NEXT
-&& dc->pc - dc->base.pc_first >= TARGET_PAGE_SIZE - 32) {
-dc->base.is_jmp = DISAS_TOO_MANY;
+if (dc->base.is_jmp == DISAS_NEXT) {
+/* Stop translation when the next insn might touch a new page.
+ * This ensures that prefetch aborts at the right place.
+ *
+ * We cannot determine the size of the next insn without
+ * completely decoding it.  However, the maximum insn size
+ * is 32 bytes, so end if we do not have that much remaining.
+ * This may produce several small TBs at the end of each page,
+ * but they will all be linked with goto_tb.
+ *
+ * ??? ColdFire maximum is 4 bytes; MC68000's maximum is also
+ * smaller than MC68020's.
+ */
+target_ulong start_page_offset
+= dc->pc - (dc->base.pc_first & TARGET_PAGE_MASK);
+
+if (start_page_offset >= TARGET_PAGE_SIZE - 32) {
+dc->base.is_jmp = DISAS_TOO_MANY;
+}
 }
 }
 
-- 
2.17.0




[Qemu-devel] [PATCH 4/9] target/m68k: Use lookup_and_goto_tb for DISAS_JUMP

2018-05-11 Thread Richard Henderson
These are all indirect or out-of-page direct jumps.
We can indirectly chain to the next TB without going
back to the main loop.

Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index c795d8e64f..80712ed0af 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -6139,8 +6139,11 @@ void gen_intermediate_code(CPUState *cs, 
TranslationBlock *tb)
 update_cc_op(dc);
 gen_jmp_tb(dc, 0, dc->pc);
 break;
-default:
 case DISAS_JUMP:
+/* We updated CC_OP and PC in gen_jmp/gen_jmp_im.  */
+tcg_gen_lookup_and_goto_ptr();
+break;
+default:
 case DISAS_UPDATE:
 update_cc_op(dc);
 /* indicate that the hash table must be used to find the next TB */
-- 
2.17.0




[Qemu-devel] [PATCH 5/9] target/m68k: Rename DISAS_UPDATE and gen_lookup_tb

2018-05-11 Thread Richard Henderson
The name gen_lookup_tb is at odds with tcg_gen_lookup_and_goto_tb.
For these cases, we do indeed want to exit back to the main loop.
Similarly, DISAS_UPDATE performs no actual update, whereas DISAS_EXIT
does what it says.

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

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 80712ed0af..ff1a8d58f4 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -198,7 +198,7 @@ static void do_writebacks(DisasContext *s)
 
 /* is_jmp field values */
 #define DISAS_JUMP  DISAS_TARGET_0 /* only pc was modified dynamically */
-#define DISAS_UPDATEDISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_EXIT  DISAS_TARGET_1 /* cpu state was modified dynamically */
 
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(s) 1
@@ -1446,11 +1446,11 @@ static void gen_jmpcc(DisasContext *s, int cond, 
TCGLabel *l1)
 }
 
 /* Force a TB lookup after an instruction that changes the CPU state.  */
-static void gen_lookup_tb(DisasContext *s)
+static void gen_exit_tb(DisasContext *s)
 {
 update_cc_op(s);
 tcg_gen_movi_i32(QREG_PC, s->pc);
-s->is_jmp = DISAS_UPDATE;
+s->is_jmp = DISAS_EXIT;
 }
 
 #define SRC_EA(env, result, opsize, op_sign, addrp) do {\
@@ -4604,7 +4604,7 @@ DISAS_INSN(move_to_sr)
 return;
 }
 gen_move_to_sr(env, s, insn, false);
-gen_lookup_tb(s);
+gen_exit_tb(s);
 }
 
 DISAS_INSN(move_from_usp)
@@ -4680,7 +4680,7 @@ DISAS_INSN(cf_movec)
 reg = DREG(ext, 12);
 }
 gen_helper_cf_movec_to(cpu_env, tcg_const_i32(ext & 0xfff), reg);
-gen_lookup_tb(s);
+gen_exit_tb(s);
 }
 
 DISAS_INSN(m68k_movec)
@@ -4705,7 +4705,7 @@ DISAS_INSN(m68k_movec)
 } else {
 gen_helper_m68k_movec_from(reg, cpu_env, tcg_const_i32(ext & 0xfff));
 }
-gen_lookup_tb(s);
+gen_exit_tb(s);
 }
 
 DISAS_INSN(intouch)
@@ -5749,7 +5749,7 @@ DISAS_INSN(to_macsr)
 TCGv val;
 SRC_EA(env, val, OS_LONG, 0, NULL);
 gen_helper_set_macsr(cpu_env, val);
-gen_lookup_tb(s);
+gen_exit_tb(s);
 }
 
 DISAS_INSN(to_mask)
@@ -6144,9 +6144,9 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock 
*tb)
 tcg_gen_lookup_and_goto_ptr();
 break;
 default:
-case DISAS_UPDATE:
-update_cc_op(dc);
-/* indicate that the hash table must be used to find the next TB */
+case DISAS_EXIT:
+/* We updated CC_OP and PC in gen_exit_tb, but also modified
+   other state that may require returning to the main loop.  */
 tcg_gen_exit_tb(0);
 break;
 case DISAS_NORETURN:
-- 
2.17.0




[Qemu-devel] [PATCH 4/9] target/m68k: Use lookup_and_goto_tb for DISAS_JUMP

2018-05-11 Thread Richard Henderson
These are all indirect or out-of-page direct jumps.
We can indirectly chain to the next TB without going
back to the main loop.

Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index c795d8e64f..80712ed0af 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -6139,8 +6139,11 @@ void gen_intermediate_code(CPUState *cs, 
TranslationBlock *tb)
 update_cc_op(dc);
 gen_jmp_tb(dc, 0, dc->pc);
 break;
-default:
 case DISAS_JUMP:
+/* We updated CC_OP and PC in gen_jmp/gen_jmp_im.  */
+tcg_gen_lookup_and_goto_ptr();
+break;
+default:
 case DISAS_UPDATE:
 update_cc_op(dc);
 /* indicate that the hash table must be used to find the next TB */
-- 
2.17.0




[Qemu-devel] [PATCH 3/9] target/m68k: Remove DISAS_JUMP_NEXT as unused

2018-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 6ab24fac0b..c795d8e64f 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -199,7 +199,6 @@ static void do_writebacks(DisasContext *s)
 /* is_jmp field values */
 #define DISAS_JUMP  DISAS_TARGET_0 /* only pc was modified dynamically */
 #define DISAS_UPDATEDISAS_TARGET_1 /* cpu state was modified dynamically */
-#define DISAS_JUMP_NEXT DISAS_TARGET_3
 
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(s) 1
-- 
2.17.0




[Qemu-devel] [PATCH 7/9] target/m68k: Convert to TranslatorOps

2018-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 176 
 1 file changed, 86 insertions(+), 90 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 01d3265437..0ab9ab1148 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -6059,113 +6059,109 @@ static void disas_m68k_insn(CPUM68KState * env, 
DisasContext *s)
 do_release(s);
 }
 
-/* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+static void m68k_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
 {
-CPUM68KState *env = cs->env_ptr;
-DisasContext dc1, *dc = 
-target_ulong pc_start;
-int pc_offset;
-int num_insns;
-int max_insns;
-
-/* generate intermediate code */
-pc_start = tb->pc;
-
-dc->base.tb = tb;
+DisasContext *dc = container_of(dcbase, DisasContext, base);
+CPUM68KState *env = cpu->env_ptr;
 
 dc->env = env;
-dc->base.is_jmp = DISAS_NEXT;
-dc->pc = pc_start;
+dc->pc = dc->base.pc_first;
 dc->cc_op = CC_OP_DYNAMIC;
 dc->cc_op_synced = 1;
-dc->base.singlestep_enabled = cs->singlestep_enabled;
 dc->done_mac = 0;
 dc->writeback_mask = 0;
-num_insns = 0;
-max_insns = tb_cflags(tb) & CF_COUNT_MASK;
-if (max_insns == 0) {
-max_insns = CF_COUNT_MASK;
-}
-if (max_insns > TCG_MAX_INSNS) {
-max_insns = TCG_MAX_INSNS;
-}
-
 init_release_array(dc);
+}
 
-gen_tb_start(tb);
-do {
-pc_offset = dc->pc - pc_start;
-tcg_gen_insn_start(dc->pc, dc->cc_op);
-num_insns++;
+static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+}
 
-if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
-gen_exception(dc, dc->pc, EXCP_DEBUG);
-/* The address covered by the breakpoint must be included in
-   [tb->pc, tb->pc + tb->size) in order to for it to be
-   properly cleared -- thus we increment the PC here so that
-   the logic setting tb->size below does the right thing.  */
-dc->pc += 2;
-break;
-}
+static void m68k_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+DisasContext *dc = container_of(dcbase, DisasContext, base);
+tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
+}
 
-if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
-gen_io_start();
-}
+static bool m68k_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+ const CPUBreakpoint *bp)
+{
+DisasContext *dc = container_of(dcbase, DisasContext, base);
 
-dc->base.pc_next = dc->pc;
-   disas_m68k_insn(env, dc);
-} while (!dc->base.is_jmp && !tcg_op_buf_full() &&
- !cs->singlestep_enabled &&
- !singlestep &&
- (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
- num_insns < max_insns);
+gen_exception(dc, dc->base.pc_next, EXCP_DEBUG);
+/* The address covered by the breakpoint must be included in
+   [tb->pc, tb->pc + tb->size) in order to for it to be
+   properly cleared -- thus we increment the PC here so that
+   the logic setting tb->size below does the right thing.  */
+dc->base.pc_next += 2;
 
-if (tb_cflags(tb) & CF_LAST_IO)
-gen_io_end();
-if (unlikely(cs->singlestep_enabled)) {
-/* Make sure the pc is updated, and raise a debug exception.  */
-if (!dc->base.is_jmp) {
-update_cc_op(dc);
-tcg_gen_movi_i32(QREG_PC, dc->pc);
-}
+return true;
+}
+
+static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+{
+DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+disas_m68k_insn(cpu->env_ptr, dc);
+dc->base.pc_next = dc->pc;
+
+if (dc->base.is_jmp == DISAS_NEXT
+&& dc->pc - dc->base.pc_first >= TARGET_PAGE_SIZE - 32) {
+dc->base.is_jmp = DISAS_TOO_MANY;
+}
+}
+
+static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+if (dc->base.is_jmp == DISAS_NORETURN) {
+return;
+}
+if (dc->base.singlestep_enabled) {
 gen_helper_raise_exception(cpu_env, tcg_const_i32(EXCP_DEBUG));
-} else {
-switch(dc->base.is_jmp) {
-case DISAS_NEXT:
-update_cc_op(dc);
-gen_jmp_tb(dc, 0, dc->pc);
-break;
-case DISAS_JUMP:
-/* We updated CC_OP and PC in gen_jmp/gen_jmp_im.  */
-tcg_gen_lookup_and_goto_ptr();
-break;
-default:
-case DISAS_EXIT:
-/* We updated CC_OP and PC in gen_exit_tb, but also modified
-   other state that may require returning to the main loop.  */
-tcg_gen_exit_tb(0);
-  

[Qemu-devel] [PATCH 2/9] target/m68k: Replace DISAS_TB_JUMP with DISAS_NORETURN

2018-05-11 Thread Richard Henderson
We have exited the TB after using goto_tb; there is no
distinction from DISAS_NORETURN.

Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 86404906e0..6ab24fac0b 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -199,7 +199,6 @@ static void do_writebacks(DisasContext *s)
 /* is_jmp field values */
 #define DISAS_JUMP  DISAS_TARGET_0 /* only pc was modified dynamically */
 #define DISAS_UPDATEDISAS_TARGET_1 /* cpu state was modified dynamically */
-#define DISAS_TB_JUMP   DISAS_TARGET_2 /* only pc was modified statically */
 #define DISAS_JUMP_NEXT DISAS_TARGET_3
 
 #if defined(CONFIG_USER_ONLY)
@@ -1496,7 +1495,7 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t 
dest)
 gen_jmp_im(s, dest);
 tcg_gen_exit_tb(0);
 }
-s->is_jmp = DISAS_TB_JUMP;
+s->is_jmp = DISAS_NORETURN;
 }
 
 DISAS_INSN(scc)
@@ -6148,7 +6147,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock 
*tb)
 /* indicate that the hash table must be used to find the next TB */
 tcg_gen_exit_tb(0);
 break;
-case DISAS_TB_JUMP:
 case DISAS_NORETURN:
 /* nothing more to generate */
 break;
-- 
2.17.0




[Qemu-devel] [PATCH v1.1 0/9] target/m68k: Convert to TranslatorOps

2018-05-11 Thread Richard Henderson
[ Ho, hum.  I didn't clear out my scratch directory before sending v1.0. ]

FYI, I've only tested this with linux-user-test-0.3 and
our qemu coldfire testing kernel.


r~


Richard Henderson (9):
  target/m68k: Use DISAS_NORETURN for exceptions
  target/m68k: Replace DISAS_TB_JUMP with DISAS_NORETURN
  target/m68k: Remove DISAS_JUMP_NEXT as unused
  target/m68k: Use lookup_and_goto_tb for DISAS_JUMP
  target/m68k: Rename DISAS_UPDATE and gen_lookup_tb
  target/m68k: Convert to DisasContextBase
  target/m68k: Convert to TranslatorOps
  target/m68k: Improve ending TB at page boundaries
  target/m68k: Merge disas_m68k_insn into m68k_tr_translate_insn

 target/m68k/translate.c | 354 
 1 file changed, 179 insertions(+), 175 deletions(-)

-- 
2.17.0




[Qemu-devel] [PATCH 3/9] target/m68k: Remove DISAS_JUMP_NEXT as unused

2018-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 6ab24fac0b..c795d8e64f 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -199,7 +199,6 @@ static void do_writebacks(DisasContext *s)
 /* is_jmp field values */
 #define DISAS_JUMP  DISAS_TARGET_0 /* only pc was modified dynamically */
 #define DISAS_UPDATEDISAS_TARGET_1 /* cpu state was modified dynamically */
-#define DISAS_JUMP_NEXT DISAS_TARGET_3
 
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(s) 1
-- 
2.17.0




[Qemu-devel] [PATCH 6/9] target/m68k: Convert to DisasContextBase

2018-05-11 Thread Richard Henderson
Removed ctx->insn_pc in favour of ctx->base.pc_next.
Yes, it is annoying, but didn't want to waste its 4 bytes.

Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 137 
 1 file changed, 67 insertions(+), 70 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ff1a8d58f4..01d3265437 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -111,14 +111,11 @@ void m68k_tcg_init(void)
 
 /* internal defines */
 typedef struct DisasContext {
+DisasContextBase base;
 CPUM68KState *env;
-target_ulong insn_pc; /* Start of the current instruction.  */
 target_ulong pc;
-int is_jmp;
 CCOp cc_op; /* Current CC operation */
 int cc_op_synced;
-struct TranslationBlock *tb;
-int singlestep_enabled;
 TCGv_i64 mactmp;
 int done_mac;
 int writeback_mask;
@@ -203,10 +200,10 @@ static void do_writebacks(DisasContext *s)
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(s) 1
 #else
-#define IS_USER(s)   (!(s->tb->flags & TB_FLAGS_MSR_S))
-#define SFC_INDEX(s) ((s->tb->flags & TB_FLAGS_SFC_S) ? \
+#define IS_USER(s)   (!(s->base.tb->flags & TB_FLAGS_MSR_S))
+#define SFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_SFC_S) ? \
   MMU_KERNEL_IDX : MMU_USER_IDX)
-#define DFC_INDEX(s) ((s->tb->flags & TB_FLAGS_DFC_S) ? \
+#define DFC_INDEX(s) ((s->base.tb->flags & TB_FLAGS_DFC_S) ? \
   MMU_KERNEL_IDX : MMU_USER_IDX)
 #endif
 
@@ -278,7 +275,7 @@ static void gen_jmp_im(DisasContext *s, uint32_t dest)
 {
 update_cc_op(s);
 tcg_gen_movi_i32(QREG_PC, dest);
-s->is_jmp = DISAS_JUMP;
+s->base.is_jmp = DISAS_JUMP;
 }
 
 /* Generate a jump to the address in qreg DEST.  */
@@ -286,7 +283,7 @@ static void gen_jmp(DisasContext *s, TCGv dest)
 {
 update_cc_op(s);
 tcg_gen_mov_i32(QREG_PC, dest);
-s->is_jmp = DISAS_JUMP;
+s->base.is_jmp = DISAS_JUMP;
 }
 
 static void gen_exception(DisasContext *s, uint32_t dest, int nr)
@@ -300,12 +297,12 @@ static void gen_exception(DisasContext *s, uint32_t dest, 
int nr)
 gen_helper_raise_exception(cpu_env, tmp);
 tcg_temp_free_i32(tmp);
 
-s->is_jmp = DISAS_NORETURN;
+s->base.is_jmp = DISAS_NORETURN;
 }
 
 static inline void gen_addr_fault(DisasContext *s)
 {
-gen_exception(s, s->insn_pc, EXCP_ADDRESS);
+gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
 }
 
 /* Generate a load from the specified address.  Narrow values are
@@ -1003,7 +1000,7 @@ static void gen_load_fp(DisasContext *s, int opsize, TCGv 
addr, TCGv_ptr fp,
 break;
 case OS_EXTENDED:
 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
-gen_exception(s, s->insn_pc, EXCP_FP_UNIMP);
+gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
 break;
 }
 tcg_gen_qemu_ld32u(tmp, addr, index);
@@ -1017,7 +1014,7 @@ static void gen_load_fp(DisasContext *s, int opsize, TCGv 
addr, TCGv_ptr fp,
 /* unimplemented data type on 68040/ColdFire
  * FIXME if needed for another FPU
  */
-gen_exception(s, s->insn_pc, EXCP_FP_UNIMP);
+gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
 break;
 default:
 g_assert_not_reached();
@@ -1057,7 +1054,7 @@ static void gen_store_fp(DisasContext *s, int opsize, 
TCGv addr, TCGv_ptr fp,
 break;
 case OS_EXTENDED:
 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
-gen_exception(s, s->insn_pc, EXCP_FP_UNIMP);
+gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
 break;
 }
 tcg_gen_ld16u_i32(tmp, fp, offsetof(FPReg, l.upper));
@@ -1071,7 +1068,7 @@ static void gen_store_fp(DisasContext *s, int opsize, 
TCGv addr, TCGv_ptr fp,
 /* unimplemented data type on 68040/ColdFire
  * FIXME if needed for another FPU
  */
-gen_exception(s, s->insn_pc, EXCP_FP_UNIMP);
+gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
 break;
 default:
 g_assert_not_reached();
@@ -1203,7 +1200,7 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext 
*s, int mode,
 break;
 case OS_EXTENDED:
 if (m68k_feature(s->env, M68K_FEATURE_CF_FPU)) {
-gen_exception(s, s->insn_pc, EXCP_FP_UNIMP);
+gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
 break;
 }
 tmp = tcg_const_i32(read_im32(env, s) >> 16);
@@ -1217,7 +1214,7 @@ static int gen_ea_mode_fp(CPUM68KState *env, DisasContext 
*s, int mode,
 /* unimplemented data type on 68040/ColdFire
  * FIXME if needed for another FPU
  */
-gen_exception(s, s->insn_pc, EXCP_FP_UNIMP);
+gen_exception(s, s->base.pc_next, EXCP_FP_UNIMP);
 break;
 default:
 

[Qemu-devel] [PATCH 2/9] target/m68k: Replace DISAS_TB_JUMP with DISAS_NORETURN

2018-05-11 Thread Richard Henderson
We have exited the TB after using goto_tb; there is no
distinction from DISAS_NORETURN.

Signed-off-by: Richard Henderson 
---
 target/m68k/translate.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 86404906e0..6ab24fac0b 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -199,7 +199,6 @@ static void do_writebacks(DisasContext *s)
 /* is_jmp field values */
 #define DISAS_JUMP  DISAS_TARGET_0 /* only pc was modified dynamically */
 #define DISAS_UPDATEDISAS_TARGET_1 /* cpu state was modified dynamically */
-#define DISAS_TB_JUMP   DISAS_TARGET_2 /* only pc was modified statically */
 #define DISAS_JUMP_NEXT DISAS_TARGET_3
 
 #if defined(CONFIG_USER_ONLY)
@@ -1496,7 +1495,7 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t 
dest)
 gen_jmp_im(s, dest);
 tcg_gen_exit_tb(0);
 }
-s->is_jmp = DISAS_TB_JUMP;
+s->is_jmp = DISAS_NORETURN;
 }
 
 DISAS_INSN(scc)
@@ -6148,7 +6147,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock 
*tb)
 /* indicate that the hash table must be used to find the next TB */
 tcg_gen_exit_tb(0);
 break;
-case DISAS_TB_JUMP:
 case DISAS_NORETURN:
 /* nothing more to generate */
 break;
-- 
2.17.0




[Qemu-devel] [PATCH 2/2] target/s390x: Fix brace Werror with clang 6.0.0

2018-05-11 Thread Richard Henderson
The warning is

target/s390x/misc_helper.c:209:21: error: suggest
  braces around initialization of subobject [-Werror,-Wmissing-braces]
SysIB sysib = { 0 };
^
{}

While the original code is correct, and technically exactly correct
as per ISO C89, both GCC and Clang support plain empty set of braces
as an extension.

Cc: Alexander Graf 
Cc: David Hildenbrand 
Cc: Cornelia Huck 
Signed-off-by: Richard Henderson 
---
 target/s390x/misc_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index e0b23c1fd1..1f834f35ef 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -206,7 +206,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, 
uint64_t r0, uint64_t r1)
 const MachineState *ms = MACHINE(qdev_get_machine());
 uint16_t total_cpus = 0, conf_cpus = 0, reserved_cpus = 0;
 S390CPU *cpu = s390_env_get_cpu(env);
-SysIB sysib = { 0 };
+SysIB sysib = { };
 int i, cc = 0;
 
 if ((r0 & STSI_R0_FC_MASK) > STSI_R0_FC_LEVEL_3) {
-- 
2.17.0




[Qemu-devel] [PATCH 1/9] target/m68k: Use DISAS_NORETURN for exceptions

2018-05-11 Thread Richard Henderson
The raise_exception helper does not return.  Do not generate
any code following that.

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

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 44a0ac4e2e..86404906e0 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -291,18 +291,18 @@ static void gen_jmp(DisasContext *s, TCGv dest)
 s->is_jmp = DISAS_JUMP;
 }
 
-static void gen_raise_exception(int nr)
+static void gen_exception(DisasContext *s, uint32_t dest, int nr)
 {
-TCGv_i32 tmp = tcg_const_i32(nr);
+TCGv_i32 tmp;
 
+update_cc_op(s);
+tcg_gen_movi_i32(QREG_PC, dest);
+
+tmp = tcg_const_i32(nr);
 gen_helper_raise_exception(cpu_env, tmp);
 tcg_temp_free_i32(tmp);
-}
 
-static void gen_exception(DisasContext *s, uint32_t where, int nr)
-{
-gen_jmp_im(s, where);
-gen_raise_exception(nr);
+s->is_jmp = DISAS_NORETURN;
 }
 
 static inline void gen_addr_fault(DisasContext *s)
@@ -6106,7 +6106,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock 
*tb)
 
 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
 gen_exception(dc, dc->pc, EXCP_DEBUG);
-dc->is_jmp = DISAS_JUMP;
 /* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that
@@ -6150,6 +6149,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock 
*tb)
 tcg_gen_exit_tb(0);
 break;
 case DISAS_TB_JUMP:
+case DISAS_NORETURN:
 /* nothing more to generate */
 break;
 }
-- 
2.17.0




[Qemu-devel] [PATCH 0/9] target/m68k: Convert to TranslatorOps

2018-05-11 Thread Richard Henderson
FYI, I've only tested this with linux-user-test-0.3 and
our qemu coldfire testing kernel.


r~


Richard Henderson (9):
  target/m68k: Use DISAS_NORETURN for exceptions
  target/m68k: Replace DISAS_TB_JUMP with DISAS_NORETURN
  target/m68k: Remove DISAS_JUMP_NEXT as unused
  target/m68k: Use lookup_and_goto_tb for DISAS_JUMP
  target/m68k: Rename DISAS_UPDATE and gen_lookup_tb
  target/m68k: Convert to DisasContextBase
  target/m68k: Convert to TranslatorOps
  target/m68k: Improve ending TB at page boundaries
  target/m68k: Merge disas_m68k_insn into m68k_tr_translate_insn

 target/m68k/translate.c | 354 
 1 file changed, 179 insertions(+), 175 deletions(-)

-- 
2.17.0




[Qemu-devel] [PATCH 1/2] hw/virtio: Fix brace Werror with clang 6.0.0

2018-05-11 Thread Richard Henderson
The warning is

hw/virtio/vhost-user.c:1319:26: error: suggest braces
  around initialization of subobject [-Werror,-Wmissing-braces]
VhostUserMsg msg = { 0 };
 ^
 {}

While the original code is correct, and technically exactly correct
as per ISO C89, both GCC and Clang support plain empty set of braces
as an extension.

Cc: Michael S. Tsirkin 
Signed-off-by: Richard Henderson 
---
 hw/virtio/vhost-user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 38da8692bb..b455fca394 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1316,7 +1316,7 @@ static bool vhost_user_requires_shm_log(struct vhost_dev 
*dev)
 
 static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
 {
-VhostUserMsg msg = { 0 };
+VhostUserMsg msg = { };
 
 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
 
-- 
2.17.0




[Qemu-devel] [PATCH 1/9] target/m68k: Use DISAS_NORETURN for exceptions

2018-05-11 Thread Richard Henderson
The raise_exception helper does not return.  Do not generate
any code following that.

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

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 44a0ac4e2e..86404906e0 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -291,18 +291,18 @@ static void gen_jmp(DisasContext *s, TCGv dest)
 s->is_jmp = DISAS_JUMP;
 }
 
-static void gen_raise_exception(int nr)
+static void gen_exception(DisasContext *s, uint32_t dest, int nr)
 {
-TCGv_i32 tmp = tcg_const_i32(nr);
+TCGv_i32 tmp;
 
+update_cc_op(s);
+tcg_gen_movi_i32(QREG_PC, dest);
+
+tmp = tcg_const_i32(nr);
 gen_helper_raise_exception(cpu_env, tmp);
 tcg_temp_free_i32(tmp);
-}
 
-static void gen_exception(DisasContext *s, uint32_t where, int nr)
-{
-gen_jmp_im(s, where);
-gen_raise_exception(nr);
+s->is_jmp = DISAS_NORETURN;
 }
 
 static inline void gen_addr_fault(DisasContext *s)
@@ -6106,7 +6106,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock 
*tb)
 
 if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
 gen_exception(dc, dc->pc, EXCP_DEBUG);
-dc->is_jmp = DISAS_JUMP;
 /* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that
@@ -6150,6 +6149,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock 
*tb)
 tcg_gen_exit_tb(0);
 break;
 case DISAS_TB_JUMP:
+case DISAS_NORETURN:
 /* nothing more to generate */
 break;
 }
-- 
2.17.0




[Qemu-devel] [PATCH 1/2] hw/virtio: Fix brace Werror with clang 6.0.0

2018-05-11 Thread Richard Henderson
The warning is

hw/virtio/vhost-user.c:1319:26: error: suggest braces
  around initialization of subobject [-Werror,-Wmissing-braces]
VhostUserMsg msg = { 0 };
 ^
 {}

While the original code is correct, and technically exactly correct
as per ISO C89, both GCC and Clang support plain empty set of braces
as an extension.

Cc: Michael S. Tsirkin 
Signed-off-by: Richard Henderson 
---
 hw/virtio/vhost-user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 38da8692bb..b455fca394 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1316,7 +1316,7 @@ static bool vhost_user_requires_shm_log(struct vhost_dev 
*dev)
 
 static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr)
 {
-VhostUserMsg msg = { 0 };
+VhostUserMsg msg = { };
 
 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
 
-- 
2.17.0




[Qemu-devel] [PATCH 2/2] target/s390x: Fix brace Werror with clang 6.0.0

2018-05-11 Thread Richard Henderson
The warning is

target/s390x/misc_helper.c:209:21: error: suggest
  braces around initialization of subobject [-Werror,-Wmissing-braces]
SysIB sysib = { 0 };
^
{}

While the original code is correct, and technically exactly correct
as per ISO C89, both GCC and Clang support plain empty set of braces
as an extension.

Cc: Alexander Graf 
Cc: David Hildenbrand 
Cc: Cornelia Huck 
Signed-off-by: Richard Henderson 
---
 target/s390x/misc_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index e0b23c1fd1..1f834f35ef 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -206,7 +206,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, 
uint64_t r0, uint64_t r1)
 const MachineState *ms = MACHINE(qdev_get_machine());
 uint16_t total_cpus = 0, conf_cpus = 0, reserved_cpus = 0;
 S390CPU *cpu = s390_env_get_cpu(env);
-SysIB sysib = { 0 };
+SysIB sysib = { };
 int i, cc = 0;
 
 if ((r0 & STSI_R0_FC_MASK) > STSI_R0_FC_LEVEL_3) {
-- 
2.17.0




Re: [Qemu-devel] [RFC PATCH 00/12] qemu-img: add bitmap queries

2018-05-11 Thread no-reply
Hi,

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

Type: series
Message-id: 20180512012537.22478-1-js...@redhat.com
Subject: [Qemu-devel] [RFC PATCH 00/12] qemu-img: add bitmap queries

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]   patchew/20180512012537.22478-1-js...@redhat.com -> 
patchew/20180512012537.22478-1-js...@redhat.com
Switched to a new branch 'test'
98c78cde32 qemu-img: add bitmap clear
64b46d376f qemu-img: add bitmap dump
e820e6d20d qemu-img: split off common chunk of map command
15894bec9b qapi/block-core: add BitmapMapping and BitmapEntry structs
a09d1c3a65 qjson: allow caller to ask for arbitrary indent
384e244766 qcow2-bitmap: add basic bitmaps info
35cf9ace22 qapi: add bitmap info
36be89af25 qcow2-bitmap: track bitmap type
d347564ea3 qcow2/dirty-bitmaps: load IN_USE bitmaps if disk is RO
c554bff42b block/qcow2-bitmap: avoid adjusting bm->flags for RO bitmaps
9d00c36fba qcow2/dirty-bitmap: cache loaded bitmaps
7f34c78783 qcow2-bitmap: cache bm_list

=== OUTPUT BEGIN ===
Checking PATCH 1/12: qcow2-bitmap: cache bm_list...
Checking PATCH 2/12: qcow2/dirty-bitmap: cache loaded bitmaps...
Checking PATCH 3/12: block/qcow2-bitmap: avoid adjusting bm->flags for RO 
bitmaps...
Checking PATCH 4/12: qcow2/dirty-bitmaps: load IN_USE bitmaps if disk is RO...
Checking PATCH 5/12: qcow2-bitmap: track bitmap type...
Checking PATCH 6/12: qapi: add bitmap info...
Checking PATCH 7/12: qcow2-bitmap: add basic bitmaps info...
WARNING: line over 80 characters
#43: FILE: block/qcow2-bitmap.c:72:
+[BME_FLAG_BIT_EXTRA]  = { BME_FLAG_EXTRA,  
BITMAP_FLAG_ENUM_EXTRA_DATA_COMPATIBLE },

total: 0 errors, 1 warnings, 118 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 8/12: qjson: allow caller to ask for arbitrary indent...
Checking PATCH 9/12: qapi/block-core: add BitmapMapping and BitmapEntry 
structs...
Checking PATCH 10/12: qemu-img: split off common chunk of map command...
WARNING: line over 80 characters
#74: FILE: qemu-img.c:2781:
+error_report("--output must be used with human or json as 
argument.");

ERROR: open brace '{' following function declarations go on the next line
#127: FILE: qemu-img.c:2816:
+static void parse_unexpected(int argc, char *argv[]) {

total: 1 errors, 1 warnings, 173 lines checked

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

Checking PATCH 11/12: qemu-img: add bitmap dump...
ERROR: space prohibited after that '*' (ctx:BxW)
#179: FILE: qemu-img.c:3029:
+int (* handler)(BlockDriverState *b, BitmapOpts *opts);
  ^

total: 1 errors, 0 warnings, 203 lines checked

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

Checking PATCH 12/12: qemu-img: add bitmap clear...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

[Qemu-devel] [RFC PATCH 00/12] qemu-img: add bitmap queries

2018-05-11 Thread John Snow
Allow qemu-img to show information about bitmaps stored in qcow2 images.
Add a 'bitmap' meta-command with 'dump' sub-command to retrieve a list of
dirty regions in bitmaps stored in a qcow2 image.

RFC:
- I am not 1000% convinced the bm_list caching is perfectly safe,
  especially with respect to migration and inactivation. There are
  more efficiencies and tweaks I can make, but I think this is the
  minimal set.

- I decided not to gate bitmap info in the "info" command behind
  extra flags.

- Bitmap data-gathering in "bitmap dump" could be made more
  space-efficient by just reporting one segment at a time,
  probably.

- `bitmap rm` and `bitmap mk` need extra work, so I am not submitting
  them just yet: rm needs more work around the remove persistence API,
  and make needs more work around the "can add" API.

- None of these commands will work with "in use" bitmaps; we need
  qemu-img check -r bitmaps support for this. I'm not sure what the
  right behavior to "fix" in-use bitmaps should be:
- Cleared: This might be dangerous.
- Fully Set: This is safer, but stupid.
- Deleted: This might be the best option.
- Un-set in-use: VERY dangerous; would rather not.

John Snow (12):
  qcow2-bitmap: cache bm_list
  qcow2/dirty-bitmap: cache loaded bitmaps
  block/qcow2-bitmap: avoid adjusting bm->flags for RO bitmaps
  qcow2/dirty-bitmaps: load IN_USE bitmaps if disk is RO
  qcow2-bitmap: track bitmap type
  qapi: add bitmap info
  qcow2-bitmap: add basic bitmaps info
  qjson: allow caller to ask for arbitrary indent
  qapi/block-core: add BitmapMapping and BitmapEntry structs
  qemu-img: split off common chunk of map command
  qemu-img: add bitmap dump
  qemu-img: add bitmap clear

 block/qcow2-bitmap.c | 220 +
 block/qcow2.c|   9 +
 block/qcow2.h|   3 +
 include/qapi/qmp/qjson.h |   1 +
 qapi/block-core.json |  92 ++-
 qemu-img-cmds.hx |   6 +
 qemu-img.c   | 419 +--
 qobject/qjson.c  |  21 +--
 8 files changed, 612 insertions(+), 159 deletions(-)

-- 
2.14.3




[Qemu-devel] [RFC PATCH 11/12] qemu-img: add bitmap dump

2018-05-11 Thread John Snow
Signed-off-by: John Snow 
---
 qemu-img-cmds.hx |   6 ++
 qemu-img.c   | 185 +++
 2 files changed, 191 insertions(+)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 2fe31893cf..d25f359f5a 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -22,6 +22,12 @@ STEXI
 @item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] 
[--flush-interval=@var{flush_interval}] [-n] [--no-drain] [-o @var{offset}] 
[--pattern=@var{pattern}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t 
@var{cache}] [-w] [-U] @var{filename}
 ETEXI
 
+DEF("bitmap", img_bitmap,
+"bitmap dump [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] 
[-U] filename [bitmap]")
+STEXI
+@item bitmap dump [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] 
[--output=@var{ofmt}] [-U] @var{filename} [@var{bitmap}]
+ETEXI
+
 DEF("check", img_check,
 "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] 
[-r [leaks | all]] [-T src_cache] [-U] filename")
 STEXI
diff --git a/qemu-img.c b/qemu-img.c
index e31e38f674..1141216617 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2881,6 +2881,191 @@ out1:
 return ret < 0;
 }
 
+static BitmapMapping *get_bitmap_mapping(BdrvDirtyBitmap *bitmap)
+{
+BdrvDirtyBitmapIter *it = bdrv_dirty_iter_new(bitmap);
+BitmapMapping *bm = g_new0(BitmapMapping, 1);
+BitmapEntry *entry;
+BitmapEntryList *tmp, **last;
+int64_t offset;
+int64_t zero_offset;
+
+bm->name = g_strdup(bdrv_dirty_bitmap_name(bitmap));
+bm->entries = NULL;
+last = >entries;
+
+while (true) {
+offset = bdrv_dirty_iter_next(it);
+if (offset == -1) {
+break;
+}
+
+zero_offset = bdrv_dirty_bitmap_next_zero(bitmap, offset);
+if (zero_offset == -1) {
+zero_offset = bdrv_dirty_bitmap_size(bitmap);
+}
+
+entry = g_new0(BitmapEntry, 1);
+entry->offset = offset;
+entry->length = zero_offset - offset;
+
+tmp = g_new0(BitmapEntryList, 1);
+tmp->value = entry;
+*last = tmp;
+last = >next;
+
+if (zero_offset >= bdrv_dirty_bitmap_size(bitmap)) {
+break;
+}
+bdrv_set_dirty_iter(it, zero_offset);
+}
+
+bdrv_dirty_iter_free(it);
+return bm;
+}
+
+static void dump_bitmap_mapping_json(BitmapMapping *bm, int indent,
+ FILE *stream)
+{
+QString *str;
+QObject *obj;
+Visitor *v = qobject_output_visitor_new();
+const int pretty = 1;
+
+visit_type_BitmapMapping(v, NULL, , _abort);
+visit_complete(v, );
+str = qobject_to_json_opt(obj, pretty, indent);
+assert(str != NULL);
+fprintf(stream, "%*s%s", 4 * indent, "", qstring_get_str(str));
+qobject_unref(obj);
+visit_free(v);
+qobject_unref(str);
+}
+
+static void dump_bitmap_mapping_human(BitmapMapping *bm, FILE *stream)
+{
+BitmapEntryList *bl = bm->entries;
+
+fprintf(stream, "# %s\n", bm->name);
+fprintf(stream, "%-16s%-16s\n", "Offset", "Length");
+for ( ; bl; bl = bl->next) {
+BitmapEntry *be = bl->value;
+fprintf(stream, "%-16"PRId64"%-16"PRId64"\n", be->offset, be->length);
+}
+}
+
+static void dump_bitmap_mapping(BitmapMapping *bm, OutputFormat output_format,
+int indent, FILE *stream)
+{
+switch (output_format) {
+case OFORMAT_JSON:
+dump_bitmap_mapping_json(bm, indent, stream);
+return;
+case OFORMAT_HUMAN:
+dump_bitmap_mapping_human(bm, stream);
+return;
+}
+}
+
+/* img_bitmap subcommands: dump */
+
+typedef struct BitmapOpts {
+CommonOpts base;
+const char *name;
+uint32_t granularity;
+} BitmapOpts;
+
+static int bitmap_cmd_dump(BlockDriverState *bs, BitmapOpts *opts)
+{
+BdrvDirtyBitmap *bitmap;
+BitmapMapping *bm;
+bool printed;
+OutputFormat ofmt = opts->base.output_format;
+
+if (opts->name) {
+bitmap = bdrv_find_dirty_bitmap(bs, opts->name);
+if (bitmap) {
+bm = get_bitmap_mapping(bitmap);
+dump_bitmap_mapping(bm, ofmt, 0, stdout);
+qapi_free_BitmapMapping(bm);
+} else {
+if (ofmt == OFORMAT_HUMAN) {
+fprintf(stdout, "Bitmap '%s' not found\n", opts->name);
+}
+}
+} else {
+if (ofmt == OFORMAT_JSON) {
+fprintf(stdout, "[\n");
+}
+for (bitmap = NULL, printed = false;
+ (bitmap = bdrv_dirty_bitmap_next(bs, bitmap)); printed = true) {
+if (printed) {
+fprintf(stdout, ofmt == OFORMAT_JSON ? ",\n" : "\n");
+}
+bm = get_bitmap_mapping(bitmap);
+dump_bitmap_mapping(bm, ofmt, 1, stdout);
+qapi_free_BitmapMapping(bm);
+}
+if (ofmt == OFORMAT_JSON) {
+fprintf(stdout, "%s%s", printed ? "\n" : "", 

[Qemu-devel] [RFC PATCH 03/12] block/qcow2-bitmap: avoid adjusting bm->flags for RO bitmaps

2018-05-11 Thread John Snow
Instead of always setting IN_USE, handle whether or not the bitmap
is read-only instead of a two-loop pass. This will allow us to show
the flags exactly as they appear for bitmaps in `qemu-img info`.

Signed-off-by: John Snow 
---
 block/qcow2-bitmap.c | 48 
 1 file changed, 20 insertions(+), 28 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index d89758f235..fc8d52fc3e 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -942,13 +942,6 @@ fail:
 return ret;
 }
 
-/* for g_slist_foreach for GSList of BdrvDirtyBitmap* elements */
-static void release_dirty_bitmap_helper(gpointer bitmap,
-gpointer bs)
-{
-bdrv_release_dirty_bitmap(bs, bitmap);
-}
-
 /* for g_slist_foreach for GSList of BdrvDirtyBitmap* elements */
 static void set_readonly_helper(gpointer bitmap, gpointer value)
 {
@@ -967,8 +960,8 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error 
**errp)
 BDRVQcow2State *s = bs->opaque;
 Qcow2BitmapList *bm_list;
 Qcow2Bitmap *bm;
-GSList *created_dirty_bitmaps = NULL;
 bool header_updated = false;
+bool needs_update = false;
 
 if (s->nb_bitmaps == 0) {
 /* No bitmaps - nothing to do */
@@ -992,33 +985,32 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error 
**errp)
 bdrv_disable_dirty_bitmap(bitmap);
 }
 bdrv_dirty_bitmap_set_persistance(bitmap, true);
-bm->flags |= BME_FLAG_IN_USE;
-created_dirty_bitmaps =
-g_slist_append(created_dirty_bitmaps, bitmap);
-}
-}
-
-if (created_dirty_bitmaps != NULL) {
-if (can_write(bs)) {
-/* in_use flags must be updated */
-int ret = update_ext_header_and_dir_in_place(bs, bm_list);
-if (ret < 0) {
-error_setg_errno(errp, -ret, "Can't update bitmap directory");
-goto fail;
+if (can_write(bs)) {
+bm->flags |= BME_FLAG_IN_USE;
+needs_update = true;
+} else {
+bdrv_dirty_bitmap_set_readonly(bitmap, true);
 }
-header_updated = true;
-} else {
-g_slist_foreach(created_dirty_bitmaps, set_readonly_helper,
-(gpointer)true);
 }
 }
 
-g_slist_free(created_dirty_bitmaps);
+/* in_use flags must be updated */
+if (needs_update) {
+int ret = update_ext_header_and_dir_in_place(bs, bm_list);
+if (ret < 0) {
+error_setg_errno(errp, -ret, "Can't update bitmap directory");
+goto fail;
+}
+header_updated = true;
+}
 return header_updated;
 
 fail:
-g_slist_foreach(created_dirty_bitmaps, release_dirty_bitmap_helper, bs);
-g_slist_free(created_dirty_bitmaps);
+QSIMPLEQ_FOREACH(bm, bm_list, entry) {
+if (bm->dirty_bitmap) {
+bdrv_release_dirty_bitmap(bs, bm->dirty_bitmap);
+}
+}
 del_bitmap_list(bs);
 
 return false;
-- 
2.14.3




[Qemu-devel] [RFC PATCH 10/12] qemu-img: split off common chunk of map command

2018-05-11 Thread John Snow
It will be re-used for a bitmap listing command.

Signed-off-by: John Snow 
---
 qemu-img.c | 192 +++--
 1 file changed, 110 insertions(+), 82 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index ea62d2d61e..e31e38f674 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -69,8 +69,8 @@ enum {
 };
 
 typedef enum OutputFormat {
-OFORMAT_JSON,
 OFORMAT_HUMAN,
+OFORMAT_JSON,
 } OutputFormat;
 
 /* Default to cache=writeback as data integrity is not important for qemu-img 
*/
@@ -2728,96 +2728,122 @@ static inline bool entry_mergeable(const MapEntry 
*curr, const MapEntry *next)
 return true;
 }
 
+typedef struct CommonOpts {
+OutputFormat output_format;
+const char *filename;
+const char *fmt;
+bool force_share;
+bool image_opts;
+} CommonOpts;
+
+static int parse_opts_common(CommonOpts *opts, int argc, char **argv)
+{
+int c;
+
+for (;;) {
+int option_index = 0;
+static const struct option long_options[] = {
+{"help", no_argument, 0, 'h'},
+{"format", required_argument, 0, 'f'},
+{"output", required_argument, 0, OPTION_OUTPUT},
+{"object", required_argument, 0, OPTION_OBJECT},
+{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+{"force-share", no_argument, 0, 'U'},
+{0, 0, 0, 0}
+};
+c = getopt_long(argc, argv, ":f:hU",
+long_options, _index);
+if (c == -1) {
+break;
+}
+switch (c) {
+case ':':
+missing_argument(argv[optind - 1]);
+break;
+case '?':
+unrecognized_option(argv[optind - 1]);
+break;
+case 'h':
+help();
+break;
+case 'f':
+opts->fmt = optarg;
+break;
+case 'U':
+opts->force_share = true;
+break;
+case OPTION_OUTPUT:
+if (optarg && !strcmp(optarg, "json")) {
+opts->output_format = OFORMAT_JSON;
+} else if (optarg && !strcmp(optarg, "human")) {
+opts->output_format = OFORMAT_HUMAN;
+} else {
+error_report("--output must be used with human or json as 
argument.");
+return -EINVAL;
+}
+break;
+case OPTION_OBJECT: {
+QemuOpts *opts;
+opts = qemu_opts_parse_noisily(_object_opts,
+   optarg, true);
+if (!opts) {
+return -EINVAL;
+}
+}   break;
+case OPTION_IMAGE_OPTS:
+opts->image_opts = true;
+break;
+}
+}
+if (qemu_opts_foreach(_object_opts,
+  user_creatable_add_opts_foreach,
+  NULL, NULL)) {
+return -EINVAL;
+}
+
+return 0;
+}
+
+static void parse_positional(int argc, char *argv[],
+ bool opt, const char **str, const char *name) {
+if (!opt && optind >= argc) {
+error_exit("Expecting '%s' positional parameter", name);
+} else if (optind < argc) {
+*str = argv[optind++];
+}
+}
+
+static void parse_unexpected(int argc, char *argv[]) {
+if (optind != argc) {
+error_exit("Unexpected argument '%s'\n", argv[optind]);
+}
+}
+
 static int img_map(int argc, char **argv)
 {
-int c;
-OutputFormat output_format = OFORMAT_HUMAN;
 BlockBackend *blk;
 BlockDriverState *bs;
-const char *filename, *fmt, *output;
 int64_t length;
+int ret = 0;
 MapEntry curr = { .length = 0 }, next;
-int ret = 0;
-bool image_opts = false;
-bool force_share = false;
+CommonOpts *opts;
 
-fmt = NULL;
-output = NULL;
-for (;;) {
-int option_index = 0;
-static const struct option long_options[] = {
-{"help", no_argument, 0, 'h'},
-{"format", required_argument, 0, 'f'},
-{"output", required_argument, 0, OPTION_OUTPUT},
-{"object", required_argument, 0, OPTION_OBJECT},
-{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
-{"force-share", no_argument, 0, 'U'},
-{0, 0, 0, 0}
-};
-c = getopt_long(argc, argv, ":f:hU",
-long_options, _index);
-if (c == -1) {
-break;
-}
-switch (c) {
-case ':':
-missing_argument(argv[optind - 1]);
-break;
-case '?':
-unrecognized_option(argv[optind - 1]);
-break;
-case 'h':
-help();
-break;
-case 'f':
-fmt = optarg;
-break;
-case 'U':
-force_share = true;
-break;
-case OPTION_OUTPUT:
-output = optarg;
-break;
-

[Qemu-devel] [RFC PATCH 07/12] qcow2-bitmap: add basic bitmaps info

2018-05-11 Thread John Snow
Add functions for querying the basic information inside of bitmaps.
Restructure the bitmaps flags masks to facilitate providing a list of
flags belonging to the bitmap(s) being queried.

Signed-off-by: John Snow 
---
 block/qcow2-bitmap.c | 81 ++--
 block/qcow2.c|  7 +
 block/qcow2.h|  1 +
 3 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 60e01abfd7..811b82743a 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -49,8 +49,28 @@
 
 /* Bitmap directory entry flags */
 #define BME_RESERVED_FLAGS 0xfffcU
-#define BME_FLAG_IN_USE (1U << 0)
-#define BME_FLAG_AUTO   (1U << 1)
+
+enum BME_FLAG_BITS {
+BME_FLAG_BIT__BEGIN = 0,
+BME_FLAG_BIT_IN_USE = BME_FLAG_BIT__BEGIN,
+BME_FLAG_BIT_AUTO   = 1,
+BME_FLAG_BIT_EXTRA  = 2,
+BME_FLAG_BIT__MAX,
+};
+
+#define BME_FLAG_IN_USE (1U << BME_FLAG_BIT_IN_USE)
+#define BME_FLAG_AUTO   (1U << BME_FLAG_BIT_AUTO)
+#define BME_FLAG_EXTRA  (1U << BME_FLAG_BIT_EXTRA)
+
+/* Correlate canonical spec values to autogenerated QAPI values */
+struct {
+uint32_t mask;
+int qapi_value;
+} BMEFlagMap[BME_FLAG_BIT__MAX] = {
+[BME_FLAG_BIT_IN_USE] = { BME_FLAG_IN_USE, BITMAP_FLAG_ENUM_IN_USE },
+[BME_FLAG_BIT_AUTO]   = { BME_FLAG_AUTO,   BITMAP_FLAG_ENUM_AUTO },
+[BME_FLAG_BIT_EXTRA]  = { BME_FLAG_EXTRA,  
BITMAP_FLAG_ENUM_EXTRA_DATA_COMPATIBLE },
+};
 
 /* bits [1, 8] U [56, 63] are reserved */
 #define BME_TABLE_ENTRY_RESERVED_MASK 0xff0001feULL
@@ -663,6 +683,63 @@ static void del_bitmap_list(BlockDriverState *bs)
 }
 }
 
+static BitmapFlagEnumList *get_bitmap_flags(uint32_t flags)
+{
+int i;
+BitmapFlagEnumList *flist = NULL;
+BitmapFlagEnumList *ftmp;
+
+while (flags) {
+i = ctz32(flags);
+ftmp = g_new0(BitmapFlagEnumList, 1);
+if (i >= BME_FLAG_BIT__BEGIN && i < BME_FLAG_BIT__MAX) {
+ftmp->value = BMEFlagMap[i].qapi_value;
+} else {
+ftmp->value = BITMAP_FLAG_ENUM_UNKNOWN;
+}
+ftmp->next = flist;
+flist = ftmp;
+flags &= ~(1 << i);
+}
+
+return flist;
+}
+
+BitmapInfoList *qcow2_get_bitmap_info(BlockDriverState *bs)
+{
+Qcow2BitmapList *bm_list;
+Qcow2Bitmap *bm;
+BitmapInfoList *info_list = NULL;
+BitmapInfoList *tmp;
+BitmapInfo *bitmap_info;
+
+bm_list = get_bitmap_list(bs, NULL);
+if (!bm_list) {
+return info_list;
+}
+
+QSIMPLEQ_FOREACH(bm, bm_list, entry) {
+bitmap_info = g_new0(BitmapInfo, 1);
+bitmap_info->name = g_strdup(bm->name);
+if (bm->type == BT_DIRTY_TRACKING_BITMAP) {
+bitmap_info->type = BITMAP_TYPE_ENUM_DIRTY_TRACKING;
+} else {
+bitmap_info->type = BITMAP_TYPE_ENUM_UNKNOWN;
+}
+bitmap_info->granularity = 1 << bm->granularity_bits;
+bitmap_info->count = bdrv_get_dirty_count(bm->dirty_bitmap);
+bitmap_info->flags = get_bitmap_flags(bm->flags);
+bitmap_info->has_flags = !!bitmap_info->flags;
+
+tmp = g_new0(BitmapInfoList, 1);
+tmp->value = bitmap_info;
+tmp->next = info_list;
+info_list = tmp;
+}
+
+return info_list;
+}
+
 int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
   void **refcount_table,
   int64_t *refcount_table_size)
diff --git a/block/qcow2.c b/block/qcow2.c
index 7ae9000656..0b24ecb6b2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3960,6 +3960,7 @@ static ImageInfoSpecific 
*qcow2_get_specific_info(BlockDriverState *bs)
 BDRVQcow2State *s = bs->opaque;
 ImageInfoSpecific *spec_info;
 QCryptoBlockInfo *encrypt_info = NULL;
+BitmapInfoList *bitmap_list = NULL;
 
 if (s->crypto != NULL) {
 encrypt_info = qcrypto_block_get_info(s->crypto, _abort);
@@ -4016,6 +4017,12 @@ static ImageInfoSpecific 
*qcow2_get_specific_info(BlockDriverState *bs)
 spec_info->u.qcow2.data->encrypt = qencrypt;
 }
 
+bitmap_list = qcow2_get_bitmap_info(bs);
+if (bitmap_list) {
+spec_info->u.qcow2.data->has_bitmaps = true;
+spec_info->u.qcow2.data->bitmaps = bitmap_list;
+}
+
 return spec_info;
 }
 
diff --git a/block/qcow2.h b/block/qcow2.h
index 796a8c914b..76bf5fa55d 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -686,5 +686,6 @@ bool qcow2_can_store_new_dirty_bitmap(BlockDriverState *bs,
 void qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs,
   const char *name,
   Error **errp);
+BitmapInfoList *qcow2_get_bitmap_info(BlockDriverState *bs);
 
 #endif
-- 
2.14.3




[Qemu-devel] [RFC PATCH 01/12] qcow2-bitmap: cache bm_list

2018-05-11 Thread John Snow
We don't need to re-read this list every time, exactly. We can keep it cached
and delete our copy when we flush to disk.

Because we don't try to flush bitmaps on close if there's nothing to flush,
add a new conditional to delete the state anyway for a clean exit.

Signed-off-by: John Snow 
---
 block/qcow2-bitmap.c | 74 
 block/qcow2.c|  2 ++
 block/qcow2.h|  2 ++
 3 files changed, 50 insertions(+), 28 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index 6e93ec43e1..fb0a4f3ec4 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -536,8 +536,7 @@ static uint32_t bitmap_list_count(Qcow2BitmapList *bm_list)
  * Get bitmap list from qcow2 image. Actually reads bitmap directory,
  * checks it and convert to bitmap list.
  */
-static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset,
- uint64_t size, Error **errp)
+static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, Error **errp)
 {
 int ret;
 BDRVQcow2State *s = bs->opaque;
@@ -545,6 +544,8 @@ static Qcow2BitmapList *bitmap_list_load(BlockDriverState 
*bs, uint64_t offset,
 Qcow2BitmapDirEntry *e;
 uint32_t nb_dir_entries = 0;
 Qcow2BitmapList *bm_list = NULL;
+uint64_t offset = s->bitmap_directory_offset;
+uint64_t size = s->bitmap_directory_size;
 
 if (size == 0) {
 error_setg(errp, "Requested bitmap directory size is zero");
@@ -636,6 +637,30 @@ fail:
 return NULL;
 }
 
+static Qcow2BitmapList *get_bitmap_list(BlockDriverState *bs, Error **errp)
+{
+BDRVQcow2State *s = bs->opaque;
+Qcow2BitmapList *bm_list;
+
+if (s->bitmap_list) {
+return (Qcow2BitmapList *)s->bitmap_list;
+}
+
+bm_list = bitmap_list_load(bs, errp);
+s->bitmap_list = bm_list;
+return bm_list;
+}
+
+static void del_bitmap_list(BlockDriverState *bs)
+{
+BDRVQcow2State *s = bs->opaque;
+
+if (s->bitmap_list) {
+bitmap_list_free(s->bitmap_list);
+s->bitmap_list = NULL;
+}
+}
+
 int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
   void **refcount_table,
   int64_t *refcount_table_size)
@@ -656,8 +681,7 @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, 
BdrvCheckResult *res,
 return ret;
 }
 
-bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
-   s->bitmap_directory_size, NULL);
+bm_list = get_bitmap_list(bs, NULL);
 if (bm_list == NULL) {
 res->corruptions++;
 return -EINVAL;
@@ -707,8 +731,6 @@ int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, 
BdrvCheckResult *res,
 }
 
 out:
-bitmap_list_free(bm_list);
-
 return ret;
 }
 
@@ -953,8 +975,7 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error 
**errp)
 return false;
 }
 
-bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
-   s->bitmap_directory_size, errp);
+bm_list = get_bitmap_list(bs, errp);
 if (bm_list == NULL) {
 return false;
 }
@@ -992,14 +1013,12 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, 
Error **errp)
 }
 
 g_slist_free(created_dirty_bitmaps);
-bitmap_list_free(bm_list);
-
 return header_updated;
 
 fail:
 g_slist_foreach(created_dirty_bitmaps, release_dirty_bitmap_helper, bs);
 g_slist_free(created_dirty_bitmaps);
-bitmap_list_free(bm_list);
+del_bitmap_list(bs);
 
 return false;
 }
@@ -1027,8 +1046,7 @@ int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, 
bool *header_updated,
 return -EINVAL;
 }
 
-bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
-   s->bitmap_directory_size, errp);
+bm_list = get_bitmap_list(bs, errp);
 if (bm_list == NULL) {
 return -EINVAL;
 }
@@ -1068,7 +1086,6 @@ int qcow2_reopen_bitmaps_rw_hint(BlockDriverState *bs, 
bool *header_updated,
 
 out:
 g_slist_free(ro_dirty_bitmaps);
-bitmap_list_free(bm_list);
 
 return ret;
 }
@@ -1277,8 +1294,7 @@ void 
qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs,
 return;
 }
 
-bm_list = bitmap_list_load(bs, s->bitmap_directory_offset,
-   s->bitmap_directory_size, errp);
+bm_list = get_bitmap_list(bs, errp);
 if (bm_list == NULL) {
 return;
 }
@@ -1300,7 +1316,11 @@ void 
qcow2_remove_persistent_dirty_bitmap(BlockDriverState *bs,
 
 fail:
 bitmap_free(bm);
-bitmap_list_free(bm_list);
+}
+
+void qcow2_persistent_dirty_bitmaps_cache_destroy(BlockDriverState *bs)
+{
+del_bitmap_list(bs);
 }
 
 void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
@@ -1317,12 +1337,12 @@ void 
qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
 
 if 

[Qemu-devel] [RFC PATCH 12/12] qemu-img: add bitmap clear

2018-05-11 Thread John Snow
Signed-off-by: John Snow 
---
 qemu-img-cmds.hx |  4 ++--
 qemu-img.c   | 46 --
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index d25f359f5a..7b6ec73488 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -23,9 +23,9 @@ STEXI
 ETEXI
 
 DEF("bitmap", img_bitmap,
-"bitmap dump [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] 
[-U] filename [bitmap]")
+"bitmap  [--object objectdef] [--image-opts] [-f fmt] 
[--output=ofmt] [-U] filename [bitmap]")
 STEXI
-@item bitmap dump [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] 
[--output=@var{ofmt}] [-U] @var{filename} [@var{bitmap}]
+@item bitmap  [--object @var{objectdef}] [--image-opts] [-f 
@var{fmt}] [--output=@var{ofmt}] [-U] @var{filename} [@var{bitmap}]
 ETEXI
 
 DEF("check", img_check,
diff --git a/qemu-img.c b/qemu-img.c
index 1141216617..b5ab8a3837 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2967,7 +2967,22 @@ static void dump_bitmap_mapping(BitmapMapping *bm, 
OutputFormat output_format,
 }
 }
 
-/* img_bitmap subcommands: dump */
+static int do_bitmap_clear(BlockDriverState *bs, BdrvDirtyBitmap *bitmap)
+{
+bool enabled = bdrv_dirty_bitmap_enabled(bitmap);
+
+if (!enabled) {
+bdrv_enable_dirty_bitmap(bitmap);
+}
+bdrv_clear_dirty_bitmap(bitmap, NULL);
+if (!enabled) {
+bdrv_disable_dirty_bitmap(bitmap);
+}
+
+return 0;
+}
+
+/* img_bitmap subcommands: dump, clear */
 
 typedef struct BitmapOpts {
 CommonOpts base;
@@ -3017,6 +3032,30 @@ static int bitmap_cmd_dump(BlockDriverState *bs, 
BitmapOpts *opts)
 return 0;
 }
 
+static int bitmap_cmd_clear(BlockDriverState *bs, BitmapOpts *opts)
+{
+BdrvDirtyBitmap *bitmap = NULL;
+
+if (opts->name) {
+bitmap = bdrv_find_dirty_bitmap(bs, opts->name);
+if (!bitmap) {
+error_report("No bitmap named '%s' found", opts->name);
+return -1;
+}
+if (do_bitmap_clear(bs, bitmap)) {
+return -1;
+}
+} else {
+while ((bitmap = bdrv_dirty_bitmap_next(bs, bitmap))) {
+if (do_bitmap_clear(bs, bitmap)) {
+return -1;
+}
+}
+}
+
+return 0;
+}
+
 static int img_bitmap(int argc, char **argv)
 {
 const char *cmd;
@@ -3029,12 +3068,15 @@ static int img_bitmap(int argc, char **argv)
 int (* handler)(BlockDriverState *b, BitmapOpts *opts);
 
 if (argc < 2) {
-error_report("Expected a bitmap subcommand: ");
+error_report("Expected a bitmap subcommand: ");
 return EXIT_FAILURE;
 }
 cmd = argv[1];
 if (strcmp(cmd, "dump") == 0) {
 handler = bitmap_cmd_dump;
+} else if (strcmp(cmd, "clear") == 0) {
+flags |= BDRV_O_RDWR;
+handler = bitmap_cmd_clear;
 } else {
 error_report("Unrecognized bitmap subcommand '%s'", cmd);
 return EXIT_FAILURE;
-- 
2.14.3




[Qemu-devel] [RFC PATCH 08/12] qjson: allow caller to ask for arbitrary indent

2018-05-11 Thread John Snow
The function already exists, just expose it.

Signed-off-by: John Snow 
---
 include/qapi/qmp/qjson.h |  1 +
 qobject/qjson.c  | 21 +++--
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h
index b274ac3a86..0e8624c1fa 100644
--- a/include/qapi/qmp/qjson.h
+++ b/include/qapi/qmp/qjson.h
@@ -19,6 +19,7 @@ QObject *qobject_from_jsonf(const char *string, ...) 
GCC_FMT_ATTR(1, 2);
 QObject *qobject_from_jsonv(const char *string, va_list *ap, Error **errp)
 GCC_FMT_ATTR(1, 0);
 
+QString *qobject_to_json_opt(const QObject *obj, int pretty, int indent);
 QString *qobject_to_json(const QObject *obj);
 QString *qobject_to_json_pretty(const QObject *obj);
 
diff --git a/qobject/qjson.c b/qobject/qjson.c
index 9816a65c7d..d603e1cce1 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -252,20 +252,21 @@ static void to_json(const QObject *obj, QString *str, int 
pretty, int indent)
 }
 }
 
+QString *qobject_to_json_opt(const QObject *obj, int pretty, int indent)
+{
+QString *str = qstring_new();
+
+to_json(obj, str, pretty, indent);
+
+return str;
+}
+
 QString *qobject_to_json(const QObject *obj)
 {
-QString *str = qstring_new();
-
-to_json(obj, str, 0, 0);
-
-return str;
+return qobject_to_json_opt(obj, 0, 0);
 }
 
 QString *qobject_to_json_pretty(const QObject *obj)
 {
-QString *str = qstring_new();
-
-to_json(obj, str, 1, 0);
-
-return str;
+return qobject_to_json_opt(obj, 1, 0);
 }
-- 
2.14.3




[Qemu-devel] [RFC PATCH 05/12] qcow2-bitmap: track bitmap type

2018-05-11 Thread John Snow
We only have one type of persistent bitmap right now, but I'd like the
qemu-img tool to be able to give good diagnostic information if it sees
an unknown/unsupported type.

We do enforce it to be the dirty tracking type in check_dir_entry, but
I wanted positive affirmation of the type in the forthcoming info script.

Signed-off-by: John Snow 
---
 block/qcow2-bitmap.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index b556dbdccd..60e01abfd7 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -83,6 +83,7 @@ typedef QSIMPLEQ_HEAD(Qcow2BitmapTableList, Qcow2BitmapTable)
 typedef struct Qcow2Bitmap {
 Qcow2BitmapTable table;
 uint32_t flags;
+uint8_t type;
 uint8_t granularity_bits;
 char *name;
 
@@ -608,6 +609,7 @@ static Qcow2BitmapList *bitmap_list_load(BlockDriverState 
*bs, Error **errp)
 bm->table.offset = e->bitmap_table_offset;
 bm->table.size = e->bitmap_table_size;
 bm->flags = e->flags;
+bm->type = e->type;
 bm->granularity_bits = e->granularity_bits;
 bm->name = dir_entry_copy_name(e);
 QSIMPLEQ_INSERT_TAIL(bm_list, bm, entry);
-- 
2.14.3




[Qemu-devel] [RFC PATCH 09/12] qapi/block-core: add BitmapMapping and BitmapEntry structs

2018-05-11 Thread John Snow
Add two new structures for detailing the marked regions of bitmaps as
saved in e.g. qcow2 files.

Signed-off-by: John Snow 
---
 qapi/block-core.json | 32 
 1 file changed, 32 insertions(+)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 8f33f41ce7..de8ad73a78 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -298,6 +298,38 @@
'zero': 'bool', 'depth': 'int', '*offset': 'int',
'*filename': 'str' } }
 
+##
+# @BitmapEntry:
+#
+# Dirty Bitmap region information for a virtual block range
+#
+# @offset: the start byte of the dirty virtual range
+#
+# @length: the number of bytes of the dirty virtual range
+#
+# Since: 2.13
+#
+##
+{ 'struct': 'BitmapEntry',
+  'data': { 'offset': 'int', 'length': 'int' } }
+
+##
+# @BitmapMapping:
+#
+# List of described regions correlated to a named bitmap.
+#
+# @name: The name of the bitmap whose range is described here
+#
+# @entries: A list of zero or more @BitmapEntry elements representing
+#   the range(s) described by the bitmap.
+#
+# Since: 2.13
+#
+##
+{ 'struct': 'BitmapMapping',
+  'data': { 'name': 'str',
+'entries': [ 'BitmapEntry' ] } }
+
 ##
 # @BlockdevCacheInfo:
 #
-- 
2.14.3




[Qemu-devel] [RFC PATCH 04/12] qcow2/dirty-bitmaps: load IN_USE bitmaps if disk is RO

2018-05-11 Thread John Snow
For the purposes of qemu-img manipulation and querying of bitmaps, load
bitmaps that are "in use" -- if the image is read only. This will allow
us to diagnose problems with this flag using the qemu-img tool.

Signed-off-by: John Snow 
---
 block/qcow2-bitmap.c | 32 +++-
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index fc8d52fc3e..b556dbdccd 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -346,7 +346,7 @@ static BdrvDirtyBitmap *load_bitmap(BlockDriverState *bs,
 uint32_t granularity;
 BdrvDirtyBitmap *bitmap = NULL;
 
-if (bm->flags & BME_FLAG_IN_USE) {
+if (can_write(bs) && (bm->flags & BME_FLAG_IN_USE)) {
 error_setg(errp, "Bitmap '%s' is in use", bm->name);
 goto fail;
 }
@@ -974,23 +974,21 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error 
**errp)
 }
 
 QSIMPLEQ_FOREACH(bm, bm_list, entry) {
-if (!(bm->flags & BME_FLAG_IN_USE)) {
-BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
-if (bitmap == NULL) {
-goto fail;
-}
-bm->dirty_bitmap = bitmap;
+BdrvDirtyBitmap *bitmap = load_bitmap(bs, bm, errp);
+if (bitmap == NULL) {
+goto fail;
+}
+bm->dirty_bitmap = bitmap;
 
-if (!(bm->flags & BME_FLAG_AUTO)) {
-bdrv_disable_dirty_bitmap(bitmap);
-}
-bdrv_dirty_bitmap_set_persistance(bitmap, true);
-if (can_write(bs)) {
-bm->flags |= BME_FLAG_IN_USE;
-needs_update = true;
-} else {
-bdrv_dirty_bitmap_set_readonly(bitmap, true);
-}
+if (!(bm->flags & BME_FLAG_AUTO)) {
+bdrv_disable_dirty_bitmap(bitmap);
+}
+bdrv_dirty_bitmap_set_persistance(bitmap, true);
+if (can_write(bs)) {
+bm->flags |= BME_FLAG_IN_USE;
+needs_update = true;
+} else {
+bdrv_dirty_bitmap_set_readonly(bitmap, true);
 }
 }
 
-- 
2.14.3




[Qemu-devel] [RFC PATCH 06/12] qapi: add bitmap info

2018-05-11 Thread John Snow
Add some of the necessary scaffolding for reporting bitmap information.

Signed-off-by: John Snow 
---
 qapi/block-core.json | 60 +++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index c50517bff3..8f33f41ce7 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -33,6 +33,61 @@
 'date-sec': 'int', 'date-nsec': 'int',
 'vm-clock-sec': 'int', 'vm-clock-nsec': 'int' } }
 
+##
+# @BitmapTypeEnum:
+#
+# An enumeration of possible serialized bitmap types.
+#
+# @dirty-tracking: This bitmap records information on dirty
+#  segments within the file.
+#
+# @unknown: This bitmap is of an unknown or reserved type.
+#
+# Since: 2.13
+##
+{ 'enum': 'BitmapTypeEnum', 'data': [ 'dirty-tracking', 'unknown' ] }
+
+##
+# @BitmapFlagEnum:
+#
+# An enumeration of possible flags for serialized bitmaps.
+#
+# @in-use: This bitmap is considered to be in-use, and may now be inconsistent.
+#
+# @auto: This bitmap must reflect any and all changes to the file it describes.
+#The type of this bitmap must be @DirtyTrackingBitmap.
+#
+# @extra-data-compatible: This bitmap has extra information associated with it.
+#
+# @unknown: This bitmap has unknown or reserved properties.
+#
+# Since: 2.13
+##
+{ 'enum': 'BitmapFlagEnum', 'data': [ 'in-use', 'auto',
+  'extra-data-compatible', 'unknown' ] }
+
+##
+# @BitmapInfo:
+#
+# @name: The name of the bitmap.
+#
+# @type: The type of bitmap.
+#
+# @granularity: Bitmap granularity, in bytes.
+#
+# @count: Overall bitmap dirtiness, in bytes.
+#
+# @flags: Bitmap flags, if any.
+#
+# Since: 2.13
+#
+##
+{ 'struct': 'BitmapInfo',
+  'data': { 'name': 'str', 'type': 'BitmapTypeEnum', 'granularity': 'int',
+'count': 'int', '*flags': ['BitmapFlagEnum']
+  }
+}
+
 ##
 # @ImageInfoSpecificQCow2EncryptionBase:
 #
@@ -69,6 +124,8 @@
 # @encrypt: details about encryption parameters; only set if image
 #   is encrypted (since 2.10)
 #
+# @bitmaps: list of image bitmaps (since 2.13)
+#
 # Since: 1.7
 ##
 { 'struct': 'ImageInfoSpecificQCow2',
@@ -77,7 +134,8 @@
   '*lazy-refcounts': 'bool',
   '*corrupt': 'bool',
   'refcount-bits': 'int',
-  '*encrypt': 'ImageInfoSpecificQCow2Encryption'
+  '*encrypt': 'ImageInfoSpecificQCow2Encryption',
+  '*bitmaps': ['BitmapInfo']
   } }
 
 ##
-- 
2.14.3




[Qemu-devel] [RFC PATCH 02/12] qcow2/dirty-bitmap: cache loaded bitmaps

2018-05-11 Thread John Snow
For bitmaps that we succeeded in loading, we can cache a reference
to that object. This will let us iterate over the more convenient
form of in-memory bitmaps for qemu-img bitmap manipulation tools.

Signed-off-by: John Snow 
---
 block/qcow2-bitmap.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index fb0a4f3ec4..d89758f235 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -986,6 +986,7 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, Error 
**errp)
 if (bitmap == NULL) {
 goto fail;
 }
+bm->dirty_bitmap = bitmap;
 
 if (!(bm->flags & BME_FLAG_AUTO)) {
 bdrv_disable_dirty_bitmap(bitmap);
-- 
2.14.3




[Qemu-devel] [PATCH v2 25/27] fpu/softfloat: Make is_nan et al available to softfloat-specialize.h

2018-05-11 Thread Richard Henderson
We will need these helpers within softfloat-specialize.h, so move
the definitions above the include.  After specialization, they will
not always be used so mark them to avoid the Werror.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 15a272759d..bafb3b17ec 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -181,6 +181,22 @@ typedef enum __attribute__ ((__packed__)) {
 float_class_snan,
 } FloatClass;
 
+/* Simple helpers for checking if what NaN we have */
+static inline __attribute__((unused)) bool is_nan(FloatClass c)
+{
+return unlikely(c >= float_class_qnan);
+}
+
+static inline __attribute__((unused)) bool is_snan(FloatClass c)
+{
+return c == float_class_snan;
+}
+
+static inline __attribute__((unused)) bool is_qnan(FloatClass c)
+{
+return c == float_class_qnan;
+}
+
 /*
  * Structure holding all of the decomposed parts of a float. The
  * exponent is unbiased and the fraction is normalized. All
@@ -536,20 +552,6 @@ static float64 float64_round_pack_canonical(FloatParts p, 
float_status *s)
 return float64_pack_raw(round_canonical(p, s, _params));
 }
 
-/* Simple helpers for checking if what NaN we have */
-static bool is_nan(FloatClass c)
-{
-return unlikely(c >= float_class_qnan);
-}
-static bool is_snan(FloatClass c)
-{
-return c == float_class_snan;
-}
-static bool is_qnan(FloatClass c)
-{
-return c == float_class_qnan;
-}
-
 static FloatParts return_nan(FloatParts a, float_status *s)
 {
 switch (a.cls) {
-- 
2.17.0




[Qemu-devel] [PATCH v2 24/27] fpu/softfloat: Specialize on snan_bit_is_one

2018-05-11 Thread Richard Henderson
Only MIPS requires snan_bit_is_one to be variable.  While we are
specializing softfloat behaviour, allow other targets to eliminate
this runtime check.

Cc: Aurelien Jarno 
Cc: Yongbok Kim 
Cc: David Gibson 
Cc: Alexander Graf 
Cc: Guan Xuetao 
Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h| 68 ++-
 include/fpu/softfloat-types.h |  1 +
 include/fpu/softfloat.h   |  4 ---
 target/mips/cpu.h |  4 +--
 target/hppa/cpu.c |  1 -
 target/mips/translate_init.c  |  4 +--
 target/ppc/fpu_helper.c   |  1 -
 target/sh4/cpu.c  |  1 -
 target/unicore32/cpu.c|  2 --
 9 files changed, 48 insertions(+), 38 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index d7033b7757..5cd9c2eedc 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -79,13 +79,31 @@ this code that are retained.
  * version 2 or later. See the COPYING file in the top-level directory.
  */
 
-#if defined(TARGET_XTENSA)
 /* Define for architectures which deviate from IEEE in not supporting
  * signaling NaNs (so all NaNs are treated as quiet).
  */
+#if defined(TARGET_XTENSA)
 #define NO_SIGNALING_NANS 1
 #endif
 
+/* Define how the architecture discriminates signaling NaNs.
+ * This done with the most significant bit of the fraction.
+ * In the original IEEE754 spec this was implementation defined;
+ * in the 2008 revision the msb is zero.  MIPS is (so far) unique
+ * in supporting both the 2008 revision and backward compatibility
+ * with their original choice and thus must make the choice at runtime.
+ */
+static inline flag snan_bit_is_one(float_status *status)
+{
+#if defined(TARGET_MIPS)
+return status->snan_bit_is_one;
+#elif defined(TARGET_HPPA) || defined(TARGET_UNICORE32) || defined(TARGET_SH4)
+return 1;
+#else
+return 0;
+#endif
+}
+
 /*
 | For the deconstructed floating-point with fraction FRAC, return true
 | if the fraction represents a signalling NaN; otherwise false.
@@ -97,7 +115,7 @@ static bool parts_is_snan_frac(uint64_t frac, float_status 
*status)
 return false;
 #else
 flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
-return msb == status->snan_bit_is_one;
+return msb == snan_bit_is_one(status);
 #endif
 }
 
@@ -118,7 +136,7 @@ static FloatParts parts_default_nan(float_status *status)
 #elif defined(TARGET_HPPA)
 frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
 #else
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
 } else {
 #if defined(TARGET_MIPS)
@@ -151,7 +169,7 @@ static FloatParts parts_silence_nan(FloatParts a, 
float_status *status)
 a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1));
 a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2);
 #else
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 return parts_default_nan(status);
 } else {
 a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1);
@@ -169,7 +187,7 @@ float16 float16_default_nan(float_status *status)
 #if defined(TARGET_ARM)
 return const_float16(0x7E00);
 #else
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 return const_float16(0x7DFF);
 } else {
 #if defined(TARGET_MIPS)
@@ -195,7 +213,7 @@ float32 float32_default_nan(float_status *status)
 #elif defined(TARGET_HPPA)
 return const_float32(0x7FA0);
 #else
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 return const_float32(0x7FBF);
 } else {
 #if defined(TARGET_MIPS)
@@ -220,7 +238,7 @@ float64 float64_default_nan(float_status *status)
 #elif defined(TARGET_HPPA)
 return const_float64(LIT64(0x7FF4));
 #else
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 return const_float64(LIT64(0x7FF7));
 } else {
 #if defined(TARGET_MIPS)
@@ -242,7 +260,7 @@ floatx80 floatx80_default_nan(float_status *status)
 r.low = LIT64(0x);
 r.high = 0x7FFF;
 #else
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 r.low = LIT64(0xBFFF);
 r.high = 0x7FFF;
 } else {
@@ -274,7 +292,7 @@ float128 float128_default_nan(float_status *status)
 {
 float128 r;
 
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 r.low = LIT64(0x);
 r.high = LIT64(0x7FFF7FFF);
 } else {
@@ -319,7 +337,7 @@ int float16_is_quiet_nan(float16 a_, float_status *status)
 return float16_is_any_nan(a_);
 #else
 uint16_t a = float16_val(a_);
-if (status->snan_bit_is_one) {
+if (snan_bit_is_one(status)) {
 

[Qemu-devel] [PATCH v2 17/27] target/hppa: Remove floatX_maybe_silence_nan from conversions

2018-05-11 Thread Richard Henderson
This is now handled properly by the generic softfloat code.

Signed-off-by: Richard Henderson 
---
 target/hppa/op_helper.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index a3af62daf7..912e8d5be4 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -341,7 +341,6 @@ float64 HELPER(fdiv_d)(CPUHPPAState *env, float64 a, 
float64 b)
 float64 HELPER(fcnv_s_d)(CPUHPPAState *env, float32 arg)
 {
 float64 ret = float32_to_float64(arg, >fp_status);
-ret = float64_maybe_silence_nan(ret, >fp_status);
 update_fr0_op(env, GETPC());
 return ret;
 }
@@ -349,7 +348,6 @@ float64 HELPER(fcnv_s_d)(CPUHPPAState *env, float32 arg)
 float32 HELPER(fcnv_d_s)(CPUHPPAState *env, float64 arg)
 {
 float32 ret = float64_to_float32(arg, >fp_status);
-ret = float32_maybe_silence_nan(ret, >fp_status);
 update_fr0_op(env, GETPC());
 return ret;
 }
-- 
2.17.0




[Qemu-devel] [PATCH v2 13/27] target/arm: convert conversion helpers to fpst/ahp_flag

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

Instead of passing env and leaving it up to the helper to get the
right fpstatus we pass it explicitly. There was already a get_fpstatus
helper for neon for the 32 bit code. We also add an get_ahp_flag() for
passing the state of the alternative FP16 format flag. This leaves
scope for later tracking the AHP state in translation flags.

Signed-off-by: Alex Bennée 
Signed-off-by: Richard Henderson 

---
v4
  - remove neon_fcvt_*; they are now identical to vfp_fcvt_*.
  - add flags to vfp_fcvt_* helper decls.
  - add some missing tcg_temp_free_*.
---
 target/arm/helper.h| 10 +++---
 target/arm/translate.h | 12 +++
 target/arm/helper.c| 56 +
 target/arm/translate-a64.c | 38 
 target/arm/translate.c | 74 +-
 5 files changed, 113 insertions(+), 77 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index ce89968b2d..047f3bc1ca 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -187,12 +187,10 @@ DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
 DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
 DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
 
-DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
-DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
-DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
-DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
-DEF_HELPER_FLAGS_2(vfp_fcvt_f16_to_f64, TCG_CALL_NO_RWG, f64, i32, env)
-DEF_HELPER_FLAGS_2(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, i32, f64, env)
+DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f32, TCG_CALL_NO_RWG, f32, f16, ptr, i32)
+DEF_HELPER_FLAGS_3(vfp_fcvt_f32_to_f16, TCG_CALL_NO_RWG, f16, f32, ptr, i32)
+DEF_HELPER_FLAGS_3(vfp_fcvt_f16_to_f64, TCG_CALL_NO_RWG, f64, f16, ptr, i32)
+DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32)
 
 DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
 DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 37a1bba056..45f04244be 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -177,4 +177,16 @@ void arm_free_cc(DisasCompare *cmp);
 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
 void arm_gen_test_cc(int cc, TCGLabel *label);
 
+/* Return state of Alternate Half-precision flag, caller frees result */
+static inline TCGv_i32 get_ahp_flag(void)
+{
+TCGv_i32 ret = tcg_temp_new_i32();
+
+tcg_gen_ld_i32(ret, cpu_env,
+   offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPSCR]));
+tcg_gen_extract_i32(ret, ret, 26, 1);
+
+return ret;
+}
+
 #endif /* TARGET_ARM_TRANSLATE_H */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 3df5cf30e4..a1c1dc5bbe 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11540,64 +11540,24 @@ uint32_t HELPER(set_neon_rmode)(uint32_t rmode, 
CPUARMState *env)
 }
 
 /* Half precision conversions.  */
-static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status 
*s)
+float32 HELPER(vfp_fcvt_f16_to_f32)(float16 a, void *fpstp, uint32_t ahp_mode)
 {
-int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
-float32 r = float16_to_float32(make_float16(a), ieee, s);
-if (ieee) {
-return float32_maybe_silence_nan(r, s);
-}
-return r;
+return float16_to_float32(a, !ahp_mode, fpstp);
 }
 
-static uint32_t do_fcvt_f32_to_f16(float32 a, CPUARMState *env, float_status 
*s)
+float16 HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
 {
-int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
-float16 r = float32_to_float16(a, ieee, s);
-if (ieee) {
-r = float16_maybe_silence_nan(r, s);
-}
-return float16_val(r);
+return float32_to_float16(a, !ahp_mode, fpstp);
 }
 
-float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
+float64 HELPER(vfp_fcvt_f16_to_f64)(float16 a, void *fpstp, uint32_t ahp_mode)
 {
-return do_fcvt_f16_to_f32(a, env, >vfp.standard_fp_status);
+return float16_to_float64(a, !ahp_mode, fpstp);
 }
 
-uint32_t HELPER(neon_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
+float16 HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
 {
-return do_fcvt_f32_to_f16(a, env, >vfp.standard_fp_status);
-}
-
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUARMState *env)
-{
-return do_fcvt_f16_to_f32(a, env, >vfp.fp_status);
-}
-
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUARMState *env)
-{
-return do_fcvt_f32_to_f16(a, env, >vfp.fp_status);
-}
-
-float64 HELPER(vfp_fcvt_f16_to_f64)(uint32_t a, CPUARMState *env)
-{
-int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
-float64 r = float16_to_float64(make_float16(a), ieee, >vfp.fp_status);
-if (ieee) {
-return float64_maybe_silence_nan(r, >vfp.fp_status);
-}
-return r;
-}

Re: [Qemu-devel] [PATCH RESEND v2] i386/kvm: add support for KVM_CAP_X86_DISABLE_EXITS

2018-05-11 Thread Wanpeng Li
2018-05-12 5:57 GMT+08:00 Michael S. Tsirkin :
> On Wed, Apr 18, 2018 at 09:09:19AM +0800, Wanpeng Li wrote:
>> 2018-04-18 2:08 GMT+08:00 Michael S. Tsirkin :
>> > On Tue, Apr 17, 2018 at 01:24:15AM -0700, Wanpeng Li wrote:
>> >> From: Wanpeng Li 
>> >>
>> >> This patch adds support for KVM_CAP_X86_DISABLE_EXITS. Provides userspace 
>> >> with
>> >> per-VM capability(KVM_CAP_X86_DISABLE_EXITS) to not intercept 
>> >> MWAIT/HLT/PAUSE
>> >> in order that to improve latency in some workloads.
>> >>
>> >> Cc: Paolo Bonzini 
>> >> Cc: Radim Krčmář 
>> >> Cc: Eduardo Habkost 
>> >> Signed-off-by: Wanpeng Li 
>> >> ---
>> >>
>> >>  linux-headers/linux/kvm.h |  6 +-
>> >>  target/i386/cpu.h |  2 ++
>> >>  target/i386/kvm.c | 16 
>> >>  3 files changed, 23 insertions(+), 1 deletion(-)
>> >>
>> >> diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
>> >> index a167be8..857df15 100644
>> >> --- a/linux-headers/linux/kvm.h
>> >> +++ b/linux-headers/linux/kvm.h
>> >> @@ -925,7 +925,7 @@ struct kvm_ppc_resize_hpt {
>> >>  #define KVM_CAP_S390_GS 140
>> >>  #define KVM_CAP_S390_AIS 141
>> >>  #define KVM_CAP_SPAPR_TCE_VFIO 142
>> >> -#define KVM_CAP_X86_GUEST_MWAIT 143
>> >> +#define KVM_CAP_X86_DISABLE_EXITS 143
>> >>  #define KVM_CAP_ARM_USER_IRQ 144
>> >>  #define KVM_CAP_S390_CMMA_MIGRATION 145
>> >>  #define KVM_CAP_PPC_FWNMI 146
>> >> @@ -1508,6 +1508,10 @@ struct kvm_assigned_msix_entry {
>> >>  #define KVM_X2APIC_API_USE_32BIT_IDS(1ULL << 0)
>> >>  #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
>> >>
>> >> +#define KVM_X86_DISABLE_EXITS_MWAIT  (1 << 0)
>> >> +#define KVM_X86_DISABLE_EXITS_HLT(1 << 1)
>> >> +#define KVM_X86_DISABLE_EXITS_PAUSE  (1 << 2)
>> >> +
>> >>  /* Available with KVM_CAP_ARM_USER_IRQ */
>> >>
>> >>  /* Bits for run->s.regs.device_irq_level */
>> >> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
>> >> index 1b219fa..965de1b 100644
>> >> --- a/target/i386/cpu.h
>> >> +++ b/target/i386/cpu.h
>> >> @@ -685,6 +685,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
>> >>  #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply 
>> >> Accumulation Single Precision */
>> >>  #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */
>> >>
>> >> +#define KVM_PV_UNHALT (1U << 7)
>> >> +
>> >
>> > Why don't we use KVM_FEATURE_PV_UNHALT from kvm_para.h?
>> >
>> >>  #define KVM_HINTS_DEDICATED (1U << 0)
>> >>
>> >
>> > BTW I wonder whether we should switch to a value from
>> > kvm_para.h? I'll send a version to do it, pls take a look.
>>
>> Yeah, your patchset looks good.
>>
>> Regards,
>> Wanpeng Li
>
> Do you plan to rebase your patch and upstream it or do you expect me to
> do it?

You can pick it since I am too busy recently. Thanks Michael!

Regards,
Wanpeng Li



Re: [Qemu-devel] [PATCH 1/1] Fix conversion from uint64 to float128

2018-05-11 Thread Richard Henderson
On 05/11/2018 12:10 AM, Petr Tesarik wrote:
> The significand is passed to normalizeRoundAndPackFloat128() as high
> first, low second. The current code passes the integer first, so the
> result is incorrectly shifted left by 64 bits.
> 
> This bug affects the emulation of s390x instruction CXLGBR (convert
> from logical 64-bit binary-integer operand to extended BFP result).
> 
> Cc: qemu-sta...@nongnu.org
> Signed-off-by: Petr Tesarik 
> ---
>  fpu/softfloat.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Queued, thanks.


r~



[Qemu-devel] [PATCH v2 14/27] target/arm: squash FZ16 behaviour for conversions

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

The ARM ARM specifies FZ16 is suppressed for conversions. Rather than
pushing this logic into the softfloat code we can simply save the FZ
state and temporarily disable it for the softfloat call.

Signed-off-by: Alex Bennée 
Signed-off-by: Richard Henderson 

---
v4
  - float16_to_floatX squished the wrong softfloat bit for FZ16;
need to adjust input denormals in this case.
---
 target/arm/helper.c | 40 
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index a1c1dc5bbe..e05c7230d4 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11542,22 +11542,54 @@ uint32_t HELPER(set_neon_rmode)(uint32_t rmode, 
CPUARMState *env)
 /* Half precision conversions.  */
 float32 HELPER(vfp_fcvt_f16_to_f32)(float16 a, void *fpstp, uint32_t ahp_mode)
 {
-return float16_to_float32(a, !ahp_mode, fpstp);
+/* Squash FZ16 to 0 for the duration of conversion.  In this case,
+ * it would affect flushing input denormals.
+ */
+float_status *fpst = fpstp;
+flag save = get_flush_inputs_to_zero(fpst);
+set_flush_inputs_to_zero(false, fpst);
+float32 r = float16_to_float32(a, !ahp_mode, fpst);
+set_flush_inputs_to_zero(save, fpst);
+return r;
 }
 
 float16 HELPER(vfp_fcvt_f32_to_f16)(float32 a, void *fpstp, uint32_t ahp_mode)
 {
-return float32_to_float16(a, !ahp_mode, fpstp);
+/* Squash FZ16 to 0 for the duration of conversion.  In this case,
+ * it would affect flushing output denormals.
+ */
+float_status *fpst = fpstp;
+flag save = get_flush_to_zero(fpst);
+set_flush_to_zero(false, fpst);
+float16 r = float32_to_float16(a, !ahp_mode, fpst);
+set_flush_to_zero(save, fpst);
+return r;
 }
 
 float64 HELPER(vfp_fcvt_f16_to_f64)(float16 a, void *fpstp, uint32_t ahp_mode)
 {
-return float16_to_float64(a, !ahp_mode, fpstp);
+/* Squash FZ16 to 0 for the duration of conversion.  In this case,
+ * it would affect flushing input denormals.
+ */
+float_status *fpst = fpstp;
+flag save = get_flush_inputs_to_zero(fpst);
+set_flush_inputs_to_zero(false, fpst);
+float64 r = float16_to_float64(a, !ahp_mode, fpst);
+set_flush_inputs_to_zero(save, fpst);
+return r;
 }
 
 float16 HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
 {
-return float64_to_float16(a, !ahp_mode, fpstp);
+/* Squash FZ16 to 0 for the duration of conversion.  In this case,
+ * it would affect flushing output denormals.
+ */
+float_status *fpst = fpstp;
+flag save = get_flush_to_zero(fpst);
+set_flush_to_zero(false, fpst);
+float16 r = float64_to_float16(a, !ahp_mode, fpst);
+set_flush_to_zero(save, fpst);
+return r;
 }
 
 #define float32_two make_float32(0x4000)
-- 
2.17.0




[Qemu-devel] [PATCH v2 27/27] fpu/softfloat: Pass FloatClass to pickNaNMulAdd

2018-05-11 Thread Richard Henderson
For each operand, pass a single enumeration instead of a pair of booleans.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 70 +++---
 fpu/softfloat.c|  5 +--
 2 files changed, 28 insertions(+), 47 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 47c67caec6..85c59c20d8 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -594,15 +594,14 @@ static int pickNaN(FloatClass a_cls, FloatClass b_cls,
 | information.
 | Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
 **/
-#if defined(TARGET_ARM)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag 
bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
+static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
+ bool infzero, float_status *status)
 {
+#if defined(TARGET_ARM)
 /* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
  * the default NaN
  */
-if (infzero && cIsQNaN) {
+if (infzero && is_qnan(c_cls)) {
 float_raise(float_flag_invalid, status);
 return 3;
 }
@@ -610,25 +609,20 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
 /* This looks different from the ARM ARM pseudocode, because the ARM ARM
  * puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
  */
-if (cIsSNaN) {
+if (is_snan(c_cls)) {
 return 2;
-} else if (aIsSNaN) {
+} else if (is_snan(a_cls)) {
 return 0;
-} else if (bIsSNaN) {
+} else if (is_snan(b_cls)) {
 return 1;
-} else if (cIsQNaN) {
+} else if (is_qnan(c_cls)) {
 return 2;
-} else if (aIsQNaN) {
+} else if (is_qnan(a_cls)) {
 return 0;
 } else {
 return 1;
 }
-}
 #elif defined(TARGET_MIPS)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag 
bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
-{
 /* For MIPS, the (inf,zero,qnan) case sets InvalidOp and returns
  * the default NaN
  */
@@ -639,41 +633,36 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
 
 if (snan_bit_is_one(status)) {
 /* Prefer sNaN over qNaN, in the a, b, c order. */
-if (aIsSNaN) {
+if (is_snan(a_cls)) {
 return 0;
-} else if (bIsSNaN) {
+} else if (is_snan(b_cls)) {
 return 1;
-} else if (cIsSNaN) {
+} else if (is_snan(c_cls)) {
 return 2;
-} else if (aIsQNaN) {
+} else if (is_qnan(a_cls)) {
 return 0;
-} else if (bIsQNaN) {
+} else if (is_qnan(b_cls)) {
 return 1;
 } else {
 return 2;
 }
 } else {
 /* Prefer sNaN over qNaN, in the c, a, b order. */
-if (cIsSNaN) {
+if (is_snan(c_cls)) {
 return 2;
-} else if (aIsSNaN) {
+} else if (is_snan(a_cls)) {
 return 0;
-} else if (bIsSNaN) {
+} else if (is_snan(b_cls)) {
 return 1;
-} else if (cIsQNaN) {
+} else if (is_qnan(c_cls)) {
 return 2;
-} else if (aIsQNaN) {
+} else if (is_qnan(a_cls)) {
 return 0;
 } else {
 return 1;
 }
 }
-}
 #elif defined(TARGET_PPC)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag 
bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
-{
 /* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
  * to return an input NaN if we have one (ie c) rather than generating
  * a default NaN
@@ -686,31 +675,26 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
 /* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
  * otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
  */
-if (aIsSNaN || aIsQNaN) {
+if (is_nan(a_cls)) {
 return 0;
-} else if (cIsSNaN || cIsQNaN) {
+} else if (is_nan(c_cls)) {
 return 2;
 } else {
 return 1;
 }
-}
 #else
-/* A default implementation: prefer a to b to c.
- * This is unlikely to actually match any real implementation.
- */
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag 
bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
-{
-if (aIsSNaN || aIsQNaN) {
+/* A default implementation: prefer a to b to c.
+ * This is unlikely to actually match any real 

[Qemu-devel] [PATCH v2 26/27] fpu/softfloat: Pass FloatClass to pickNaN

2018-05-11 Thread Richard Henderson
For each operand, pass a single enumeration instead of a pair of booleans.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 168 ++---
 fpu/softfloat.c|   3 +-
 2 files changed, 82 insertions(+), 89 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 5cd9c2eedc..47c67caec6 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -501,10 +501,10 @@ static float32 commonNaNToFloat32(commonNaNT a, 
float_status *status)
 | tie-break rule.
 **/
 
-#if defined(TARGET_ARM)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+static int pickNaN(FloatClass a_cls, FloatClass b_cls,
flag aIsLargerSignificand)
 {
+#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA)
 /* ARM mandated NaN propagation rules (see FPProcessNaNs()), take
  * the first of:
  *  1. A if it is signaling
@@ -513,20 +513,6 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
  *  4. B (quiet)
  * A signaling NaN is always quietened before returning it.
  */
-if (aIsSNaN) {
-return 0;
-} else if (bIsSNaN) {
-return 1;
-} else if (aIsQNaN) {
-return 0;
-} else {
-return 1;
-}
-}
-#elif defined(TARGET_MIPS) || defined(TARGET_HPPA)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-flag aIsLargerSignificand)
-{
 /* According to MIPS specifications, if one of the two operands is
  * a sNaN, a new qNaN has to be generated. This is done in
  * floatXX_silence_nan(). For qNaN inputs the specifications
@@ -540,35 +526,21 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
  *  4. B (quiet)
  * A signaling NaN is always silenced before returning it.
  */
-if (aIsSNaN) {
+if (is_snan(a_cls)) {
 return 0;
-} else if (bIsSNaN) {
+} else if (is_snan(b_cls)) {
 return 1;
-} else if (aIsQNaN) {
+} else if (is_qnan(a_cls)) {
 return 0;
 } else {
 return 1;
 }
-}
-#elif defined(TARGET_PPC) || defined(TARGET_XTENSA)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-   flag aIsLargerSignificand)
-{
+#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K)
 /* PowerPC propagation rules:
  *  1. A if it sNaN or qNaN
  *  2. B if it sNaN or qNaN
  * A signaling NaN is always silenced before returning it.
  */
-if (aIsSNaN || aIsQNaN) {
-return 0;
-} else {
-return 1;
-}
-}
-#elif defined(TARGET_M68K)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-   flag aIsLargerSignificand)
-{
 /* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
  * 3.4 FLOATING-POINT INSTRUCTION DETAILS
  * If either operand, but not both operands, of an operation is a
@@ -583,16 +555,12 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
  * a nonsignaling NaN. The operation then continues as described in the
  * preceding paragraph for nonsignaling NaNs.
  */
-if (aIsQNaN || aIsSNaN) { /* a is the destination operand */
-return 0; /* return the destination operand */
+if (is_nan(a_cls)) {
+return 0;
 } else {
-return 1; /* return b */
+return 1;
 }
-}
 #else
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
-flag aIsLargerSignificand)
-{
 /* This implements x87 NaN propagation rules:
  * SNaN + QNaN => return the QNaN
  * two SNaNs => return the one with the larger significand, silenced
@@ -603,13 +571,13 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
  * If we get down to comparing significands and they are the same,
  * return the NaN with the positive sign bit (if any).
  */
-if (aIsSNaN) {
-if (bIsSNaN) {
+if (is_snan(a_cls)) {
+if (is_snan(b_cls)) {
 return aIsLargerSignificand ? 0 : 1;
 }
-return bIsQNaN ? 1 : 0;
-} else if (aIsQNaN) {
-if (bIsSNaN || !bIsQNaN) {
+return is_qnan(b_cls) ? 1 : 0;
+} else if (is_qnan(a_cls)) {
+if (is_snan(b_cls) || !is_qnan(b_cls)) {
 return 0;
 } else {
 return aIsLargerSignificand ? 0 : 1;
@@ -617,8 +585,8 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
 } else {
 return 1;
 }
-}
 #endif
+}
 
 /*
 | Select which NaN to propagate for a three-input operation.
@@ -752,18 +720,26 @@ static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag 

[Qemu-devel] [PATCH v2 11/27] fpu/softfloat: support ARM Alternative half-precision

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

For float16 ARM supports an alternative half-precision format which
sacrifices the ability to represent NaN/Inf in return for a higher
dynamic range. To support this I've added an additional
FloatFmt (float16_params_ahp).

The new FloatFmt flag (arm_althp) is then used to modify the behaviour
of canonicalize and round_canonical with respect to representation and
exception raising.

Finally the float16_to_floatN and floatN_to_float16 conversion
routines select the new alternative FloatFmt when !ieee.

Signed-off-by: Alex Bennée 
Signed-off-by: Richard Henderson 

---
v3
  - squash NaN to 0 if destination is AHP F16
v4
  - handle inf -> ahp max in float_to_float not round_canonical
  - assert no nan and inf for ahp in round_canonical
  - check ahp before snan in float_to_float
---
 fpu/softfloat.c | 95 +
 1 file changed, 81 insertions(+), 14 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index aa219223ff..15a272759d 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -211,8 +211,10 @@ typedef struct {
  *   frac_shift: shift to normalise the fraction with DECOMPOSED_BINARY_POINT
  * The following are computed based the size of fraction
  *   frac_lsb: least significant bit of fraction
- *   fram_lsbm1: the bit bellow the least significant bit (for rounding)
+ *   frac_lsbm1: the bit bellow the least significant bit (for rounding)
  *   round_mask/roundeven_mask: masks used for rounding
+ * The following optional modifiers are available:
+ *   arm_althp: handle ARM Alternative Half Precision
  */
 typedef struct {
 int exp_size;
@@ -224,6 +226,7 @@ typedef struct {
 uint64_t frac_lsbm1;
 uint64_t round_mask;
 uint64_t roundeven_mask;
+bool arm_althp;
 } FloatFmt;
 
 /*
@@ -252,6 +255,11 @@ static const FloatFmt float16_params = {
 FLOAT_PARAMS(5, 10)
 };
 
+static const FloatFmt float16_params_ahp = {
+FLOAT_PARAMS(5, 10),
+.arm_althp = true
+};
+
 static const FloatFmt float32_params = {
 FLOAT_PARAMS(8, 23)
 };
@@ -315,7 +323,7 @@ static inline float64 float64_pack_raw(FloatParts p)
 static FloatParts canonicalize(FloatParts part, const FloatFmt *parm,
float_status *status)
 {
-if (part.exp == parm->exp_max) {
+if (part.exp == parm->exp_max && !parm->arm_althp) {
 if (part.frac == 0) {
 part.cls = float_class_inf;
 } else {
@@ -404,7 +412,15 @@ static FloatParts round_canonical(FloatParts p, 
float_status *s,
 }
 frac >>= frac_shift;
 
-if (unlikely(exp >= exp_max)) {
+if (parm->arm_althp) {
+/* ARM Alt HP eschews Inf and NaN for a wider exponent.  */
+if (unlikely(exp > exp_max)) {
+/* Overflow.  Return the maximum normal.  */
+flags = float_flag_invalid;
+exp = exp_max;
+frac = -1;
+}
+} else if (unlikely(exp >= exp_max)) {
 flags |= float_flag_overflow | float_flag_inexact;
 if (overflow_norm) {
 exp = exp_max - 1;
@@ -455,12 +471,14 @@ static FloatParts round_canonical(FloatParts p, 
float_status *s,
 
 case float_class_inf:
 do_inf:
+assert(!parm->arm_althp);
 exp = exp_max;
 frac = 0;
 break;
 
 case float_class_qnan:
 case float_class_snan:
+assert(!parm->arm_althp);
 exp = exp_max;
 frac >>= parm->frac_shift;
 break;
@@ -475,14 +493,27 @@ static FloatParts round_canonical(FloatParts p, 
float_status *s,
 return p;
 }
 
+/* Explicit FloatFmt version */
+static FloatParts float16a_unpack_canonical(float16 f, float_status *s,
+const FloatFmt *params)
+{
+return canonicalize(float16_unpack_raw(f), params, s);
+}
+
 static FloatParts float16_unpack_canonical(float16 f, float_status *s)
 {
-return canonicalize(float16_unpack_raw(f), _params, s);
+return float16a_unpack_canonical(f, s, _params);
+}
+
+static float16 float16a_round_pack_canonical(FloatParts p, float_status *s,
+ const FloatFmt *params)
+{
+return float16_pack_raw(round_canonical(p, s, params));
 }
 
 static float16 float16_round_pack_canonical(FloatParts p, float_status *s)
 {
-return float16_pack_raw(round_canonical(p, s, _params));
+return float16a_round_pack_canonical(p, s, _params);
 }
 
 static FloatParts float32_unpack_canonical(float32 f, float_status *s)
@@ -1174,7 +1205,33 @@ static FloatParts float_to_float(FloatParts a,
  const FloatFmt *srcf, const FloatFmt *dstf,
  float_status *s)
 {
-if 

[Qemu-devel] [PATCH v2 10/27] fpu/softfloat: re-factor float to float conversions

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

This allows us to delete a lot of additional boilerplate code which is
no longer needed. Currently the ieee flag is ignored (everything is
assumed to be ieee). Handling for ARM AHP will be in the next patch.

Signed-off-by: Alex Bennée 
Signed-off-by: Richard Henderson 

---
v2
  - pass FloatFmt to float_to_float instead of sizes
  - split AHP handling to another patch
  - use rth's suggested re-packing (+ setting .exp)
v3
  - also rm extractFloat16Sign
v4
  - update for canonical nan handling
---
 fpu/softfloat-specialize.h |  40 
 include/fpu/softfloat.h|   8 +-
 fpu/softfloat.c| 437 ++---
 3 files changed, 73 insertions(+), 412 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 571d1df378..995a0132c6 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -377,46 +377,6 @@ float16 float16_maybe_silence_nan(float16 a, float_status 
*status)
 return a;
 }
 
-/*
-| Returns the result of converting the half-precision floating-point NaN
-| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
-| exception is raised.
-**/
-
-static commonNaNT float16ToCommonNaN(float16 a, float_status *status)
-{
-commonNaNT z;
-
-if (float16_is_signaling_nan(a, status)) {
-float_raise(float_flag_invalid, status);
-}
-z.sign = float16_val(a) >> 15;
-z.low = 0;
-z.high = ((uint64_t) float16_val(a)) << 54;
-return z;
-}
-
-/*
-| Returns the result of converting the canonical NaN `a' to the half-
-| precision floating-point format.
-**/
-
-static float16 commonNaNToFloat16(commonNaNT a, float_status *status)
-{
-uint16_t mantissa = a.high >> 54;
-
-if (status->default_nan_mode) {
-return float16_default_nan(status);
-}
-
-if (mantissa) {
-return make_float16(uint16_t) a.sign) << 15)
- | (0x1F << 10) | mantissa));
-} else {
-return float16_default_nan(status);
-}
-}
-
 /*
 | Returns 1 if the single-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 43962dc3f5..a6860e858d 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -211,10 +211,10 @@ float128 uint64_to_float128(uint64_t, float_status 
*status);
 /*
 | Software half-precision conversion routines.
 **/
-float16 float32_to_float16(float32, flag, float_status *status);
-float32 float16_to_float32(float16, flag, float_status *status);
-float16 float64_to_float16(float64 a, flag ieee, float_status *status);
-float64 float16_to_float64(float16 a, flag ieee, float_status *status);
+float16 float32_to_float16(float32, bool ieee, float_status *status);
+float32 float16_to_float32(float16, bool ieee, float_status *status);
+float16 float64_to_float16(float64 a, bool ieee, float_status *status);
+float64 float16_to_float64(float16 a, bool ieee, float_status *status);
 int16_t float16_to_int16(float16, float_status *status);
 uint16_t float16_to_uint16(float16 a, float_status *status);
 int16_t float16_to_int16_round_to_zero(float16, float_status *status);
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c8f683963f..aa219223ff 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -113,15 +113,6 @@ static inline int extractFloat16Exp(float16 a)
 return (float16_val(a) >> 10) & 0x1f;
 }
 
-/*
-| Returns the sign bit of the single-precision floating-point value `a'.
-**/
-
-static inline flag extractFloat16Sign(float16 a)
-{
-return float16_val(a)>>15;
-}
-
 /*
 | Returns the fraction bits of the single-precision floating-point value `a'.
 **/
@@ -1168,6 +1159,75 @@ float64 float64_div(float64 a, float64 b, float_status 
*status)
 return float64_round_pack_canonical(pr, status);
 }
 
+/*
+ * Float to Float conversions
+ *
+ * Returns the result of converting one float format to another. The
+ * conversion is performed according to the IEC/IEEE Standard for
+ * Binary Floating-Point Arithmetic.
+ *
+ * 

[Qemu-devel] [PATCH v2 22/27] fpu/softfloat: Use float*_silence_nan in propagateFloat*NaN

2018-05-11 Thread Richard Henderson
We have already checked the arguments for SNaN;
we don't need to do it again.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 44 +-
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 995a0132c6..4fa068a5dc 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -498,7 +498,7 @@ static float32 commonNaNToFloat32(commonNaNT a, 
float_status *status)
 | The routine is passed various bits of information about the
 | two NaNs and should return 0 to select NaN a and 1 for NaN b.
 | Note that signalling NaNs are always squashed to quiet NaNs
-| by the caller, by calling floatXX_maybe_silence_nan() before
+| by the caller, by calling floatXX_silence_nan() before
 | returning them.
 |
 | aIsLargerSignificand is only valid if both a and b are NaNs
@@ -536,7 +536,7 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag 
bIsQNaN, flag bIsSNaN,
 {
 /* According to MIPS specifications, if one of the two operands is
  * a sNaN, a new qNaN has to be generated. This is done in
- * floatXX_maybe_silence_nan(). For qNaN inputs the specifications
+ * floatXX_silence_nan(). For qNaN inputs the specifications
  * says: "When possible, this QNaN result is one of the operand QNaN
  * values." In practice it seems that most implementations choose
  * the first operand if both operands are qNaN. In short this gives
@@ -788,9 +788,15 @@ static float32 propagateFloat32NaN(float32 a, float32 b, 
float_status *status)
 
 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
 aIsLargerSignificand)) {
-return float32_maybe_silence_nan(b, status);
+if (bIsSignalingNaN) {
+return float32_silence_nan(b, status);
+}
+return b;
 } else {
-return float32_maybe_silence_nan(a, status);
+if (aIsSignalingNaN) {
+return float32_silence_nan(a, status);
+}
+return a;
 }
 }
 
@@ -950,9 +956,15 @@ static float64 propagateFloat64NaN(float64 a, float64 b, 
float_status *status)
 
 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
 aIsLargerSignificand)) {
-return float64_maybe_silence_nan(b, status);
+if (bIsSignalingNaN) {
+return float64_silence_nan(b, status);
+}
+return b;
 } else {
-return float64_maybe_silence_nan(a, status);
+if (aIsSignalingNaN) {
+return float64_silence_nan(a, status);
+}
+return a;
 }
 }
 
@@ -1121,9 +1133,15 @@ floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, 
float_status *status)
 
 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
 aIsLargerSignificand)) {
-return floatx80_maybe_silence_nan(b, status);
+if (bIsSignalingNaN) {
+return floatx80_silence_nan(b, status);
+}
+return b;
 } else {
-return floatx80_maybe_silence_nan(a, status);
+if (aIsSignalingNaN) {
+return floatx80_silence_nan(a, status);
+}
+return a;
 }
 }
 
@@ -1270,8 +1288,14 @@ static float128 propagateFloat128NaN(float128 a, 
float128 b,
 
 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
 aIsLargerSignificand)) {
-return float128_maybe_silence_nan(b, status);
+if (bIsSignalingNaN) {
+return float128_silence_nan(b, status);
+}
+return b;
 } else {
-return float128_maybe_silence_nan(a, status);
+if (aIsSignalingNaN) {
+return float128_silence_nan(a, status);
+}
+return a;
 }
 }
-- 
2.17.0




[Qemu-devel] [PATCH v2 23/27] fpu/softfloat: Remove floatX_maybe_silence_nan

2018-05-11 Thread Richard Henderson
These functions are now unused.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 63 --
 include/fpu/softfloat.h|  5 ---
 2 files changed, 68 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 4fa068a5dc..d7033b7757 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -364,19 +364,6 @@ float16 float16_silence_nan(float16 a, float_status 
*status)
 #endif
 }
 
-/*
-| Returns a quiet NaN if the half-precision floating point value `a' is a
-| signaling NaN; otherwise returns `a'.
-**/
-
-float16 float16_maybe_silence_nan(float16 a, float_status *status)
-{
-if (float16_is_signaling_nan(a, status)) {
-return float16_silence_nan(a, status);
-}
-return a;
-}
-
 /*
 | Returns 1 if the single-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -438,18 +425,6 @@ float32 float32_silence_nan(float32 a, float_status 
*status)
 }
 #endif
 }
-/*
-| Returns a quiet NaN if the single-precision floating point value `a' is a
-| signaling NaN; otherwise returns `a'.
-**/
-
-float32 float32_maybe_silence_nan(float32 a, float_status *status)
-{
-if (float32_is_signaling_nan(a, status)) {
-return float32_silence_nan(a, status);
-}
-return a;
-}
 
 /*
 | Returns the result of converting the single-precision floating-point NaN
@@ -864,18 +839,6 @@ float64 float64_silence_nan(float64 a, float_status 
*status)
 #endif
 }
 
-/*
-| Returns a quiet NaN if the double-precision floating point value `a' is a
-| signaling NaN; otherwise returns `a'.
-**/
-
-float64 float64_maybe_silence_nan(float64 a, float_status *status)
-{
-if (float64_is_signaling_nan(a, status)) {
-return float64_silence_nan(a, status);
-}
-return a;
-}
 
 /*
 | Returns the result of converting the double-precision floating-point NaN
@@ -1037,19 +1000,6 @@ floatx80 floatx80_silence_nan(floatx80 a, float_status 
*status)
 #endif
 }
 
-/*
-| Returns a quiet NaN if the extended double-precision floating point value
-| `a' is a signaling NaN; otherwise returns `a'.
-**/
-
-floatx80 floatx80_maybe_silence_nan(floatx80 a, float_status *status)
-{
-if (floatx80_is_signaling_nan(a, status)) {
-return floatx80_silence_nan(a, status);
-}
-return a;
-}
-
 /*
 | Returns the result of converting the extended double-precision floating-
 | point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
@@ -1204,19 +1154,6 @@ float128 float128_silence_nan(float128 a, float_status 
*status)
 #endif
 }
 
-/*
-| Returns a quiet NaN if the quadruple-precision floating point value `a' is
-| a signaling NaN; otherwise returns `a'.
-**/
-
-float128 float128_maybe_silence_nan(float128 a, float_status *status)
-{
-if (float128_is_signaling_nan(a, status)) {
-return float128_silence_nan(a, status);
-}
-return a;
-}
-
 /*
 | Returns the result of converting the quadruple-precision floating-point NaN
 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index a6860e858d..69f4dbc4db 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -258,7 +258,6 @@ int float16_compare_quiet(float16, float16, float_status 
*status);
 int float16_is_quiet_nan(float16, float_status *status);
 int float16_is_signaling_nan(float16, float_status *status);
 float16 float16_silence_nan(float16, float_status *status);
-float16 float16_maybe_silence_nan(float16, float_status *status);
 
 static inline int float16_is_any_nan(float16 a)
 {
@@ -370,7 +369,6 @@ float32 float32_maxnummag(float32, float32, float_status 
*status);
 int float32_is_quiet_nan(float32, float_status *status);
 int 

[Qemu-devel] [PATCH v2 18/27] target/m68k: Use floatX_silence_nan when we have already checked for SNaN

2018-05-11 Thread Richard Henderson
Reviewed-by: Laurent Vivier 
Signed-off-by: Richard Henderson 
---
 target/m68k/softfloat.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index e41b07d042..6ec227e20f 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -31,13 +31,14 @@ static floatx80 propagateFloatx80NaNOneArg(floatx80 a, 
float_status *status)
 {
 if (floatx80_is_signaling_nan(a, status)) {
 float_raise(float_flag_invalid, status);
+a = floatx80_silence_nan(a, status);
 }
 
 if (status->default_nan_mode) {
 return floatx80_default_nan(status);
 }
 
-return floatx80_maybe_silence_nan(a, status);
+return a;
 }
 
 /*
-- 
2.17.0




[Qemu-devel] [PATCH v2 21/27] target/s390x: Remove floatX_maybe_silence_nan from conversions

2018-05-11 Thread Richard Henderson
This is now handled properly by the generic softfloat code.

Cc: Alexander Graf 
Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 target/s390x/fpu_helper.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 43f8bf1c94..5c5b451b3b 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -269,7 +269,7 @@ uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
 {
 float64 ret = float32_to_float64(f2, >fpu_status);
 handle_exceptions(env, GETPC());
-return float64_maybe_silence_nan(ret, >fpu_status);
+return ret;
 }
 
 /* convert 128-bit float to 64-bit float */
@@ -277,7 +277,7 @@ uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, 
uint64_t al)
 {
 float64 ret = float128_to_float64(make_float128(ah, al), >fpu_status);
 handle_exceptions(env, GETPC());
-return float64_maybe_silence_nan(ret, >fpu_status);
+return ret;
 }
 
 /* convert 64-bit float to 128-bit float */
@@ -285,7 +285,7 @@ uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
 {
 float128 ret = float64_to_float128(f2, >fpu_status);
 handle_exceptions(env, GETPC());
-return RET128(float128_maybe_silence_nan(ret, >fpu_status));
+return RET128(ret);
 }
 
 /* convert 32-bit float to 128-bit float */
@@ -293,7 +293,7 @@ uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
 {
 float128 ret = float32_to_float128(f2, >fpu_status);
 handle_exceptions(env, GETPC());
-return RET128(float128_maybe_silence_nan(ret, >fpu_status));
+return RET128(ret);
 }
 
 /* convert 64-bit float to 32-bit float */
@@ -301,7 +301,7 @@ uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
 {
 float32 ret = float64_to_float32(f2, >fpu_status);
 handle_exceptions(env, GETPC());
-return float32_maybe_silence_nan(ret, >fpu_status);
+return ret;
 }
 
 /* convert 128-bit float to 32-bit float */
@@ -309,7 +309,7 @@ uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, 
uint64_t al)
 {
 float32 ret = float128_to_float32(make_float128(ah, al), >fpu_status);
 handle_exceptions(env, GETPC());
-return float32_maybe_silence_nan(ret, >fpu_status);
+return ret;
 }
 
 /* 32-bit FP compare */
-- 
2.17.0




[Qemu-devel] [PATCH v2 09/27] fpu/softfloat: Replace float_class_msnan with parts_silence_nan

2018-05-11 Thread Richard Henderson
With a canonical representation of NaNs, we can silence an SNaN
immediately rather than delay until the final format is known.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 23 ++
 fpu/softfloat.c| 40 ++
 2 files changed, 33 insertions(+), 30 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 0d3d81a52b..571d1df378 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -138,6 +138,29 @@ static FloatParts parts_default_nan(float_status *status)
 };
 }
 
+/*
+| Returns a quiet NaN from a signalling NaN for the deconstructed
+| floating-point parts.
+**/
+
+static FloatParts parts_silence_nan(FloatParts a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+g_assert_not_reached();
+#elif defined(TARGET_HPPA)
+a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1));
+a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2);
+#else
+if (status->snan_bit_is_one) {
+return parts_default_nan(status);
+} else {
+a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+}
+#endif
+a.cls = float_class_qnan;
+return a;
+}
+
 /*
 | The pattern for a default generated half-precision NaN.
 **/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index d16b11a85b..c8f683963f 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -188,7 +188,6 @@ typedef enum __attribute__ ((__packed__)) {
 float_class_inf,
 float_class_qnan,  /* all NaNs from here */
 float_class_snan,
-float_class_msnan, /* maybe silenced */
 } FloatClass;
 
 /*
@@ -492,14 +491,7 @@ static FloatParts float16_unpack_canonical(float16 f, 
float_status *s)
 
 static float16 float16_round_pack_canonical(FloatParts p, float_status *s)
 {
-switch (p.cls) {
-case float_class_msnan:
-p.frac >>= float16_params.frac_shift;
-return float16_maybe_silence_nan(float16_pack_raw(p), s);
-default:
-p = round_canonical(p, s, _params);
-return float16_pack_raw(p);
-}
+return float16_pack_raw(round_canonical(p, s, _params));
 }
 
 static FloatParts float32_unpack_canonical(float32 f, float_status *s)
@@ -509,14 +501,7 @@ static FloatParts float32_unpack_canonical(float32 f, 
float_status *s)
 
 static float32 float32_round_pack_canonical(FloatParts p, float_status *s)
 {
-switch (p.cls) {
-case float_class_msnan:
-p.frac >>= float32_params.frac_shift;
-return float32_maybe_silence_nan(float32_pack_raw(p), s);
-default:
-p = round_canonical(p, s, _params);
-return float32_pack_raw(p);
-}
+return float32_pack_raw(round_canonical(p, s, _params));
 }
 
 static FloatParts float64_unpack_canonical(float64 f, float_status *s)
@@ -526,14 +511,7 @@ static FloatParts float64_unpack_canonical(float64 f, 
float_status *s)
 
 static float64 float64_round_pack_canonical(FloatParts p, float_status *s)
 {
-switch (p.cls) {
-case float_class_msnan:
-p.frac >>= float64_params.frac_shift;
-return float64_maybe_silence_nan(float64_pack_raw(p), s);
-default:
-p = round_canonical(p, s, _params);
-return float64_pack_raw(p);
-}
+return float64_pack_raw(round_canonical(p, s, _params));
 }
 
 /* Simple helpers for checking if what NaN we have */
@@ -555,7 +533,7 @@ static FloatParts return_nan(FloatParts a, float_status *s)
 switch (a.cls) {
 case float_class_snan:
 s->float_exception_flags |= float_flag_invalid;
-a.cls = float_class_msnan;
+a = parts_silence_nan(a, s);
 /* fall through */
 case float_class_qnan:
 if (s->default_nan_mode) {
@@ -584,7 +562,9 @@ static FloatParts pick_nan(FloatParts a, FloatParts b, 
float_status *s)
 (a.frac == b.frac && a.sign < b.sign))) {
 a = b;
 }
-a.cls = float_class_msnan;
+if (is_snan(a.cls)) {
+return parts_silence_nan(a, s);
+}
 }
 return a;
 }
@@ -624,8 +604,10 @@ static FloatParts pick_nan_muladd(FloatParts a, FloatParts 
b, FloatParts c,
 default:
 g_assert_not_reached();
 }
-a.cls = float_class_msnan;
 
+if (is_snan(a.cls)) {
+return parts_silence_nan(a, s);
+}
 return a;
 }
 
@@ -1334,7 +1316,6 @@ static int64_t round_to_int_and_pack(FloatParts in, int 
rmode,
 switch (p.cls) {
 case float_class_snan:
 case float_class_qnan:
-case float_class_msnan:
 s->float_exception_flags = orig_flags | float_flag_invalid;
 return max;
 case float_class_inf:
@@ -1425,7 +1406,6 @@ static 

[Qemu-devel] [PATCH v2 15/27] target/arm: Fix fp_status_f16 tininess before rounding

2018-05-11 Thread Richard Henderson
From: Peter Maydell 

In commit d81ce0ef2c4f105 we added an extra float_status field
fp_status_fp16 for Arm, but forgot to initialize it correctly
by setting it to float_tininess_before_rounding. This currently
will only cause problems for the new V8_FP16 feature, since the
float-to-float conversion code doesn't use it yet. The effect
would be that we failed to set the Underflow IEEE exception flag
in all the cases where we should.

Add the missing initialization.

Fixes: d81ce0ef2c4f105
Cc: qemu-sta...@nongnu.org
Signed-off-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d175c5e94f..7939c6b8ae 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -324,6 +324,8 @@ static void arm_cpu_reset(CPUState *s)
   >vfp.fp_status);
 set_float_detect_tininess(float_tininess_before_rounding,
   >vfp.standard_fp_status);
+set_float_detect_tininess(float_tininess_before_rounding,
+  >vfp.fp_status_f16);
 #ifndef CONFIG_USER_ONLY
 if (kvm_enabled()) {
 kvm_arm_reset_vcpu(cpu);
-- 
2.17.0




[Qemu-devel] [PATCH v2 20/27] target/riscv: Remove floatX_maybe_silence_nan from conversions

2018-05-11 Thread Richard Henderson
This is now handled properly by the generic softfloat code.

Cc: Michael Clark 
Cc: Palmer Dabbelt 
Cc: Sagar Karandikar 
Cc: Bastian Koppelmann 
Signed-off-by: Richard Henderson 
---
 target/riscv/fpu_helper.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index abbadead5c..fdb87d8d82 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -279,14 +279,12 @@ uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, 
uint64_t frs2)
 
 uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
 {
-rs1 = float64_to_float32(rs1, >fp_status);
-return float32_maybe_silence_nan(rs1, >fp_status);
+return float64_to_float32(rs1, >fp_status);
 }
 
 uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
 {
-rs1 = float32_to_float64(rs1, >fp_status);
-return float64_maybe_silence_nan(rs1, >fp_status);
+return float32_to_float64(rs1, >fp_status);
 }
 
 uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
-- 
2.17.0




[Qemu-devel] [PATCH v2 07/27] fpu/softfloat: Introduce parts_is_snan_frac

2018-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 15 +++
 fpu/softfloat.c| 12 ++--
 2 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 4fc9ea4ac0..515cb12cfa 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -86,6 +86,21 @@ this code that are retained.
 #define NO_SIGNALING_NANS 1
 #endif
 
+/*
+| For the deconstructed floating-point with fraction FRAC, return true
+| if the fraction represents a signalling NaN; otherwise false.
+**/
+
+static bool parts_is_snan_frac(uint64_t frac, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+return false;
+#else
+flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
+return msb == status->snan_bit_is_one;
+#endif
+}
+
 /*
 | The pattern for a default generated half-precision NaN.
 **/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index a56d3d975b..cb68f2eb20 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -331,16 +331,8 @@ static FloatParts canonicalize(FloatParts part, const 
FloatFmt *parm,
 part.cls = float_class_inf;
 } else {
 part.frac <<= parm->frac_shift;
-#ifdef NO_SIGNALING_NANS
-part.cls = float_class_qnan;
-#else
-int64_t msb = part.frac << 2;
-if ((msb < 0) == status->snan_bit_is_one) {
-part.cls = float_class_snan;
-} else {
-part.cls = float_class_qnan;
-}
-#endif
+part.cls = (parts_is_snan_frac(part.frac, status)
+? float_class_snan : float_class_qnan);
 }
 } else if (part.exp == 0) {
 if (likely(part.frac == 0)) {
-- 
2.17.0




[Qemu-devel] [PATCH v2 16/27] target/arm: Remove floatX_maybe_silence_nan from conversions

2018-05-11 Thread Richard Henderson
This is now handled properly by the generic softfloat code.

Signed-off-by: Richard Henderson 
---
 target/arm/helper-a64.c |  1 -
 target/arm/helper.c | 12 ++--
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 6f0eb83661..f92bdea732 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -466,7 +466,6 @@ float32 HELPER(fcvtx_f64_to_f32)(float64 a, CPUARMState 
*env)
 set_float_rounding_mode(float_round_to_zero, );
 set_float_exception_flags(0, );
 r = float64_to_float32(a, );
-r = float32_maybe_silence_nan(r, );
 exflags = get_float_exception_flags();
 if (exflags & float_flag_inexact) {
 r = make_float32(float32_val(r) | 1);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e05c7230d4..db8bbe52a6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11348,20 +11348,12 @@ FLOAT_CONVS(ui, d, 64, u)
 /* floating point conversion */
 float64 VFP_HELPER(fcvtd, s)(float32 x, CPUARMState *env)
 {
-float64 r = float32_to_float64(x, >vfp.fp_status);
-/* ARM requires that S<->D conversion of any kind of NaN generates
- * a quiet NaN by forcing the most significant frac bit to 1.
- */
-return float64_maybe_silence_nan(r, >vfp.fp_status);
+return float32_to_float64(x, >vfp.fp_status);
 }
 
 float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
 {
-float32 r =  float64_to_float32(x, >vfp.fp_status);
-/* ARM requires that S<->D conversion of any kind of NaN generates
- * a quiet NaN by forcing the most significant frac bit to 1.
- */
-return float32_maybe_silence_nan(r, >vfp.fp_status);
+return float64_to_float32(x, >vfp.fp_status);
 }
 
 /* VFP3 fixed point conversion.  */
-- 
2.17.0




[Qemu-devel] [PATCH v2 05/27] fpu/softfloat: Move softfloat-specialize.h below FloatParts definition

2018-05-11 Thread Richard Henderson
We want to be able to specialize on the canonical representation.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 fpu/softfloat.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index bc0f52fa54..353893aaea 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -95,16 +95,6 @@ this code that are retained.
 **/
 #include "fpu/softfloat-macros.h"
 
-/*
-| Functions and definitions to determine:  (1) whether tininess for underflow
-| is detected before or after rounding by default, (2) what (if anything)
-| happens when exceptions are raised, (3) how signaling NaNs are distinguished
-| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
-| are propagated from function inputs to output.  These details are target-
-| specific.
-**/
-#include "softfloat-specialize.h"
-
 /*
 | Returns the fraction bits of the half-precision floating-point value `a'.
 **/
@@ -247,6 +237,16 @@ typedef struct {
 uint64_t roundeven_mask;
 } FloatFmt;
 
+/*
+| Functions and definitions to determine:  (1) whether tininess for underflow
+| is detected before or after rounding by default, (2) what (if anything)
+| happens when exceptions are raised, (3) how signaling NaNs are distinguished
+| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
+| are propagated from function inputs to output.  These details are target-
+| specific.
+**/
+#include "softfloat-specialize.h"
+
 /* Expand fields based on the size of exponent and fraction */
 #define FLOAT_PARAMS(E, F)   \
 .exp_size   = E, \
-- 
2.17.0




[Qemu-devel] [PATCH v2 19/27] target/mips: Remove floatX_maybe_silence_nan from conversions

2018-05-11 Thread Richard Henderson
This is now handled properly by the generic softfloat code.

Cc: Aurelien Jarno 
Cc: Yongbok Kim 
Signed-off-by: Richard Henderson 
---
 target/mips/msa_helper.c | 4 
 target/mips/op_helper.c  | 2 --
 2 files changed, 6 deletions(-)

diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 8fb7a369ca..c74e3cdc65 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -1615,7 +1615,6 @@ static inline float16 float16_from_float32(int32_t a, 
flag ieee,
   float16 f_val;
 
   f_val = float32_to_float16((float32)a, ieee, status);
-  f_val = float16_maybe_silence_nan(f_val, status);
 
   return a < 0 ? (f_val | (1 << 15)) : f_val;
 }
@@ -1625,7 +1624,6 @@ static inline float32 float32_from_float64(int64_t a, 
float_status *status)
   float32 f_val;
 
   f_val = float64_to_float32((float64)a, status);
-  f_val = float32_maybe_silence_nan(f_val, status);
 
   return a < 0 ? (f_val | (1 << 31)) : f_val;
 }
@@ -1636,7 +1634,6 @@ static inline float32 float32_from_float16(int16_t a, 
flag ieee,
   float32 f_val;
 
   f_val = float16_to_float32((float16)a, ieee, status);
-  f_val = float32_maybe_silence_nan(f_val, status);
 
   return a < 0 ? (f_val | (1 << 31)) : f_val;
 }
@@ -1646,7 +1643,6 @@ static inline float64 float64_from_float32(int32_t a, 
float_status *status)
   float64 f_val;
 
   f_val = float32_to_float64((float64)a, status);
-  f_val = float64_maybe_silence_nan(f_val, status);
 
   return a < 0 ? (f_val | (1ULL << 63)) : f_val;
 }
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index 798cdad030..9025f42366 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -2700,7 +2700,6 @@ uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t 
fst0)
 uint64_t fdt2;
 
 fdt2 = float32_to_float64(fst0, >active_fpu.fp_status);
-fdt2 = float64_maybe_silence_nan(fdt2, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
 return fdt2;
 }
@@ -2790,7 +2789,6 @@ uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t 
fdt0)
 uint32_t fst2;
 
 fst2 = float64_to_float32(fdt0, >active_fpu.fp_status);
-fst2 = float32_maybe_silence_nan(fst2, >active_fpu.fp_status);
 update_fcr31(env, GETPC());
 return fst2;
 }
-- 
2.17.0




[Qemu-devel] [PATCH v2 04/27] fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan

2018-05-11 Thread Richard Henderson
The new function assumes that the input is an SNaN and
does not double-check.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 174 +
 include/fpu/softfloat.h|   5 ++
 2 files changed, 123 insertions(+), 56 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 58b05718c8..4fc9ea4ac0 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -271,22 +271,35 @@ int float16_is_signaling_nan(float16 a_, float_status 
*status)
 #endif
 }
 
+/*
+| Returns a quiet NaN from a signalling NaN for the half-precision
+| floating point value `a'.
+**/
+
+float16 float16_silence_nan(float16 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+g_assert_not_reached();
+#else
+if (status->snan_bit_is_one) {
+return float16_default_nan(status);
+} else {
+return a | (1 << 9);
+}
+#endif
+}
+
 /*
 | Returns a quiet NaN if the half-precision floating point value `a' is a
 | signaling NaN; otherwise returns `a'.
 **/
-float16 float16_maybe_silence_nan(float16 a_, float_status *status)
+
+float16 float16_maybe_silence_nan(float16 a, float_status *status)
 {
-if (float16_is_signaling_nan(a_, status)) {
-if (status->snan_bit_is_one) {
-return float16_default_nan(status);
-} else {
-uint16_t a = float16_val(a_);
-a |= (1 << 9);
-return make_float16(a);
-}
+if (float16_is_signaling_nan(a, status)) {
+return float16_silence_nan(a, status);
 }
-return a_;
+return a;
 }
 
 /*
@@ -367,30 +380,40 @@ int float32_is_signaling_nan(float32 a_, float_status 
*status)
 #endif
 }
 
+/*
+| Returns a quiet NaN from a signalling NaN for the single-precision
+| floating point value `a'.
+**/
+
+float32 float32_silence_nan(float32 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+g_assert_not_reached();
+#else
+if (status->snan_bit_is_one) {
+# ifdef TARGET_HPPA
+a &= ~0x0040;
+a |=  0x0020;
+return a;
+# else
+return float32_default_nan(status);
+# endif
+} else {
+return a | (1 << 22);
+}
+#endif
+}
 /*
 | Returns a quiet NaN if the single-precision floating point value `a' is a
 | signaling NaN; otherwise returns `a'.
 **/
 
-float32 float32_maybe_silence_nan(float32 a_, float_status *status)
+float32 float32_maybe_silence_nan(float32 a, float_status *status)
 {
-if (float32_is_signaling_nan(a_, status)) {
-if (status->snan_bit_is_one) {
-#ifdef TARGET_HPPA
-uint32_t a = float32_val(a_);
-a &= ~0x0040;
-a |=  0x0020;
-return make_float32(a);
-#else
-return float32_default_nan(status);
-#endif
-} else {
-uint32_t a = float32_val(a_);
-a |= (1 << 22);
-return make_float32(a);
-}
+if (float32_is_signaling_nan(a, status)) {
+return float32_silence_nan(a, status);
 }
-return a_;
+return a;
 }
 
 /*
@@ -776,30 +799,41 @@ int float64_is_signaling_nan(float64 a_, float_status 
*status)
 #endif
 }
 
+/*
+| Returns a quiet NaN from a signalling NaN for the double-precision
+| floating point value `a'.
+**/
+
+float64 float64_silence_nan(float64 a, float_status *status)
+{
+#ifdef NO_SIGNALING_NANS
+g_assert_not_reached();
+#else
+if (status->snan_bit_is_one) {
+# ifdef TARGET_HPPA
+a &= ~0x0008ULL;
+a |=  0x0004ULL;
+return a;
+# else
+return float64_default_nan(status);
+# endif
+} else {
+return a | LIT64(0x0008);
+}
+#endif
+}
+
 /*
 | Returns a quiet NaN if the double-precision floating point value `a' is a
 | signaling NaN; otherwise returns `a'.
 **/
 
-float64 

[Qemu-devel] [PATCH v2 12/27] target/arm: Use floatX_silence_nan when we have already checked for SNaN

2018-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/arm/helper-a64.c |  6 +++---
 target/arm/helper.c | 12 ++--
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 4f8034c513..6f0eb83661 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -376,7 +376,7 @@ float16 HELPER(frecpx_f16)(float16 a, void *fpstp)
 float16 nan = a;
 if (float16_is_signaling_nan(a, fpst)) {
 float_raise(float_flag_invalid, fpst);
-nan = float16_maybe_silence_nan(a, fpst);
+nan = float16_silence_nan(a, fpst);
 }
 if (fpst->default_nan_mode) {
 nan = float16_default_nan(fpst);
@@ -405,7 +405,7 @@ float32 HELPER(frecpx_f32)(float32 a, void *fpstp)
 float32 nan = a;
 if (float32_is_signaling_nan(a, fpst)) {
 float_raise(float_flag_invalid, fpst);
-nan = float32_maybe_silence_nan(a, fpst);
+nan = float32_silence_nan(a, fpst);
 }
 if (fpst->default_nan_mode) {
 nan = float32_default_nan(fpst);
@@ -434,7 +434,7 @@ float64 HELPER(frecpx_f64)(float64 a, void *fpstp)
 float64 nan = a;
 if (float64_is_signaling_nan(a, fpst)) {
 float_raise(float_flag_invalid, fpst);
-nan = float64_maybe_silence_nan(a, fpst);
+nan = float64_silence_nan(a, fpst);
 }
 if (fpst->default_nan_mode) {
 nan = float64_default_nan(fpst);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index c6fd7f9479..3df5cf30e4 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11739,7 +11739,7 @@ float16 HELPER(recpe_f16)(float16 input, void *fpstp)
 float16 nan = f16;
 if (float16_is_signaling_nan(f16, fpst)) {
 float_raise(float_flag_invalid, fpst);
-nan = float16_maybe_silence_nan(f16, fpst);
+nan = float16_silence_nan(f16, fpst);
 }
 if (fpst->default_nan_mode) {
 nan =  float16_default_nan(fpst);
@@ -11787,7 +11787,7 @@ float32 HELPER(recpe_f32)(float32 input, void *fpstp)
 float32 nan = f32;
 if (float32_is_signaling_nan(f32, fpst)) {
 float_raise(float_flag_invalid, fpst);
-nan = float32_maybe_silence_nan(f32, fpst);
+nan = float32_silence_nan(f32, fpst);
 }
 if (fpst->default_nan_mode) {
 nan =  float32_default_nan(fpst);
@@ -11835,7 +11835,7 @@ float64 HELPER(recpe_f64)(float64 input, void *fpstp)
 float64 nan = f64;
 if (float64_is_signaling_nan(f64, fpst)) {
 float_raise(float_flag_invalid, fpst);
-nan = float64_maybe_silence_nan(f64, fpst);
+nan = float64_silence_nan(f64, fpst);
 }
 if (fpst->default_nan_mode) {
 nan =  float64_default_nan(fpst);
@@ -11934,7 +11934,7 @@ float16 HELPER(rsqrte_f16)(float16 input, void *fpstp)
 float16 nan = f16;
 if (float16_is_signaling_nan(f16, s)) {
 float_raise(float_flag_invalid, s);
-nan = float16_maybe_silence_nan(f16, s);
+nan = float16_silence_nan(f16, s);
 }
 if (s->default_nan_mode) {
 nan =  float16_default_nan(s);
@@ -11978,7 +11978,7 @@ float32 HELPER(rsqrte_f32)(float32 input, void *fpstp)
 float32 nan = f32;
 if (float32_is_signaling_nan(f32, s)) {
 float_raise(float_flag_invalid, s);
-nan = float32_maybe_silence_nan(f32, s);
+nan = float32_silence_nan(f32, s);
 }
 if (s->default_nan_mode) {
 nan =  float32_default_nan(s);
@@ -12021,7 +12021,7 @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
 float64 nan = f64;
 if (float64_is_signaling_nan(f64, s)) {
 float_raise(float_flag_invalid, s);
-nan = float64_maybe_silence_nan(f64, s);
+nan = float64_silence_nan(f64, s);
 }
 if (s->default_nan_mode) {
 nan =  float64_default_nan(s);
-- 
2.17.0




[Qemu-devel] [PATCH v2 06/27] fpu/softfloat: Canonicalize NaN fraction

2018-05-11 Thread Richard Henderson
Shift the NaN fraction to a canonical position, much like we do
for the fraction of normal numbers.  Immediately, this simplifies
the float-to-float conversion.  Later, this will facilitate
manipulation of NaNs within the shared code paths.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 353893aaea..a56d3d975b 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -330,10 +330,11 @@ static FloatParts canonicalize(FloatParts part, const 
FloatFmt *parm,
 if (part.frac == 0) {
 part.cls = float_class_inf;
 } else {
+part.frac <<= parm->frac_shift;
 #ifdef NO_SIGNALING_NANS
 part.cls = float_class_qnan;
 #else
-int64_t msb = part.frac << (parm->frac_shift + 2);
+int64_t msb = part.frac << 2;
 if ((msb < 0) == status->snan_bit_is_one) {
 part.cls = float_class_snan;
 } else {
@@ -480,6 +481,7 @@ static FloatParts round_canonical(FloatParts p, 
float_status *s,
 case float_class_qnan:
 case float_class_snan:
 exp = exp_max;
+frac >>= parm->frac_shift;
 break;
 
 default:
@@ -503,6 +505,7 @@ static float16 float16_round_pack_canonical(FloatParts p, 
float_status *s)
 case float_class_dnan:
 return float16_default_nan(s);
 case float_class_msnan:
+p.frac >>= float16_params.frac_shift;
 return float16_maybe_silence_nan(float16_pack_raw(p), s);
 default:
 p = round_canonical(p, s, _params);
@@ -521,6 +524,7 @@ static float32 float32_round_pack_canonical(FloatParts p, 
float_status *s)
 case float_class_dnan:
 return float32_default_nan(s);
 case float_class_msnan:
+p.frac >>= float32_params.frac_shift;
 return float32_maybe_silence_nan(float32_pack_raw(p), s);
 default:
 p = round_canonical(p, s, _params);
@@ -539,6 +543,7 @@ static float64 float64_round_pack_canonical(FloatParts p, 
float_status *s)
 case float_class_dnan:
 return float64_default_nan(s);
 case float_class_msnan:
+p.frac >>= float64_params.frac_shift;
 return float64_maybe_silence_nan(float64_pack_raw(p), s);
 default:
 p = round_canonical(p, s, _params);
-- 
2.17.0




[Qemu-devel] [PATCH v2 08/27] fpu/softfloat: Replace float_class_dnan with parts_default_nan

2018-05-11 Thread Richard Henderson
With a canonical representation of NaNs, we can return the
default nan directly rather than delay the expansion until
the final format is known.

Note one case where we uselessly assigned to a.sign, which was
overwritten/ignored later when expanding float_class_dnan.

Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 37 +
 fpu/softfloat.c| 38 +++---
 2 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 515cb12cfa..0d3d81a52b 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -101,6 +101,43 @@ static bool parts_is_snan_frac(uint64_t frac, float_status 
*status)
 #endif
 }
 
+/*
+| The pattern for a default generated deconstructed floating-point NaN.
+**/
+
+static FloatParts parts_default_nan(float_status *status)
+{
+bool sign = 0;
+uint64_t frac;
+
+#if defined(TARGET_SPARC) || defined(TARGET_M68K)
+frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
+  defined(TARGET_S390X) || defined(TARGET_RISCV)
+frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+#elif defined(TARGET_HPPA)
+frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
+#else
+if (status->snan_bit_is_one) {
+frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
+} else {
+#if defined(TARGET_MIPS)
+frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+#else
+frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+sign = 1;
+#endif
+}
+#endif
+
+return (FloatParts) {
+.cls = float_class_qnan,
+.sign = sign,
+.exp = INT_MAX,
+.frac = frac
+};
+}
+
 /*
 | The pattern for a default generated half-precision NaN.
 **/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index cb68f2eb20..d16b11a85b 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -188,7 +188,6 @@ typedef enum __attribute__ ((__packed__)) {
 float_class_inf,
 float_class_qnan,  /* all NaNs from here */
 float_class_snan,
-float_class_dnan,
 float_class_msnan, /* maybe silenced */
 } FloatClass;
 
@@ -494,8 +493,6 @@ static FloatParts float16_unpack_canonical(float16 f, 
float_status *s)
 static float16 float16_round_pack_canonical(FloatParts p, float_status *s)
 {
 switch (p.cls) {
-case float_class_dnan:
-return float16_default_nan(s);
 case float_class_msnan:
 p.frac >>= float16_params.frac_shift;
 return float16_maybe_silence_nan(float16_pack_raw(p), s);
@@ -513,8 +510,6 @@ static FloatParts float32_unpack_canonical(float32 f, 
float_status *s)
 static float32 float32_round_pack_canonical(FloatParts p, float_status *s)
 {
 switch (p.cls) {
-case float_class_dnan:
-return float32_default_nan(s);
 case float_class_msnan:
 p.frac >>= float32_params.frac_shift;
 return float32_maybe_silence_nan(float32_pack_raw(p), s);
@@ -532,8 +527,6 @@ static FloatParts float64_unpack_canonical(float64 f, 
float_status *s)
 static float64 float64_round_pack_canonical(FloatParts p, float_status *s)
 {
 switch (p.cls) {
-case float_class_dnan:
-return float64_default_nan(s);
 case float_class_msnan:
 p.frac >>= float64_params.frac_shift;
 return float64_maybe_silence_nan(float64_pack_raw(p), s);
@@ -566,7 +559,7 @@ static FloatParts return_nan(FloatParts a, float_status *s)
 /* fall through */
 case float_class_qnan:
 if (s->default_nan_mode) {
-a.cls = float_class_dnan;
+return parts_default_nan(s);
 }
 break;
 
@@ -583,7 +576,7 @@ static FloatParts pick_nan(FloatParts a, FloatParts b, 
float_status *s)
 }
 
 if (s->default_nan_mode) {
-a.cls = float_class_dnan;
+return parts_default_nan(s);
 } else {
 if (pickNaN(is_qnan(a.cls), is_snan(a.cls),
 is_qnan(b.cls), is_snan(b.cls),
@@ -614,8 +607,7 @@ static FloatParts pick_nan_muladd(FloatParts a, FloatParts 
b, FloatParts c,
 /* Note that this check is after pickNaNMulAdd so that function
  * has an opportunity to set the Invalid flag.
  */
-a.cls = float_class_dnan;
-return a;
+which = 3;
 }
 
 switch (which) {
@@ -628,8 +620,7 @@ static FloatParts pick_nan_muladd(FloatParts a, FloatParts 
b, FloatParts c,
 a = c;
 break;
 case 3:
-a.cls = float_class_dnan;
-return a;
+return parts_default_nan(s);
 default:
 g_assert_not_reached();
 

[Qemu-devel] [PATCH v2 02/27] fpu/softfloat: Don't set Invalid for float-to-int(MAXINT)

2018-05-11 Thread Richard Henderson
From: Peter Maydell 

In float-to-integer conversion, if the floating point input
converts exactly to the largest or smallest integer that
fits in to the result type, this is not an overflow.
In this situation we were producing the correct result value,
but were incorrectly setting the Invalid flag.
For example for Arm A64, "FCVTAS w0, d0" on an input of
0x41dfffc0 should produce 0x7fff and set no flags.

Fix the boundary case to take the right half of the if()
statements.

This fixes a regression from 2.11 introduced by the softfloat
refactoring.

Cc: qemu-sta...@nongnu.org
Fixes: ab52f973a50
Signed-off-by: Peter Maydell 
---
 fpu/softfloat.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index b39c0c6fbb..bc0f52fa54 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1368,14 +1368,14 @@ static int64_t round_to_int_and_pack(FloatParts in, int 
rmode,
 r = UINT64_MAX;
 }
 if (p.sign) {
-if (r < -(uint64_t) min) {
+if (r <= -(uint64_t) min) {
 return -r;
 } else {
 s->float_exception_flags = orig_flags | float_flag_invalid;
 return min;
 }
 } else {
-if (r < max) {
+if (r <= max) {
 return r;
 } else {
 s->float_exception_flags = orig_flags | float_flag_invalid;
-- 
2.17.0




[Qemu-devel] [PATCH v4 11/11] target/arm: Fix sqrt_f16 exception raising

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

We are meant to explicitly pass fpst, not cpu_env.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Alex Bennée 
Reviewed-by: Richard Henderson 
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 35997969b4..a0b0c43d12 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -4976,7 +4976,8 @@ static void handle_fp_1src_half(DisasContext *s, int 
opcode, int rd, int rn)
 tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
 break;
 case 0x3: /* FSQRT */
-gen_helper_sqrt_f16(tcg_res, tcg_op, cpu_env);
+fpst = get_fpstatus_ptr(true);
+gen_helper_sqrt_f16(tcg_res, tcg_op, fpst);
 break;
 case 0x8: /* FRINTN */
 case 0x9: /* FRINTP */
-- 
2.17.0




[Qemu-devel] [PATCH v2 03/27] fpu/softfloat: Merge NO_SIGNALING_NANS definitions

2018-05-11 Thread Richard Henderson
Move the ifdef inside the relevant functions instead of
duplicating the function declarations.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 fpu/softfloat-specialize.h | 100 +++--
 1 file changed, 40 insertions(+), 60 deletions(-)

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 27834af0de..58b05718c8 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -233,17 +233,6 @@ typedef struct {
 uint64_t high, low;
 } commonNaNT;
 
-#ifdef NO_SIGNALING_NANS
-int float16_is_quiet_nan(float16 a_, float_status *status)
-{
-return float16_is_any_nan(a_);
-}
-
-int float16_is_signaling_nan(float16 a_, float_status *status)
-{
-return 0;
-}
-#else
 /*
 | Returns 1 if the half-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -251,12 +240,16 @@ int float16_is_signaling_nan(float16 a_, float_status 
*status)
 
 int float16_is_quiet_nan(float16 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+return float16_is_any_nan(a_);
+#else
 uint16_t a = float16_val(a_);
 if (status->snan_bit_is_one) {
 return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
 } else {
 return ((a & ~0x8000) >= 0x7C80);
 }
+#endif
 }
 
 /*
@@ -266,14 +259,17 @@ int float16_is_quiet_nan(float16 a_, float_status *status)
 
 int float16_is_signaling_nan(float16 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+return 0;
+#else
 uint16_t a = float16_val(a_);
 if (status->snan_bit_is_one) {
 return ((a & ~0x8000) >= 0x7C80);
 } else {
 return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
 }
-}
 #endif
+}
 
 /*
 | Returns a quiet NaN if the half-precision floating point value `a' is a
@@ -333,17 +329,6 @@ static float16 commonNaNToFloat16(commonNaNT a, 
float_status *status)
 }
 }
 
-#ifdef NO_SIGNALING_NANS
-int float32_is_quiet_nan(float32 a_, float_status *status)
-{
-return float32_is_any_nan(a_);
-}
-
-int float32_is_signaling_nan(float32 a_, float_status *status)
-{
-return 0;
-}
-#else
 /*
 | Returns 1 if the single-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -351,12 +336,16 @@ int float32_is_signaling_nan(float32 a_, float_status 
*status)
 
 int float32_is_quiet_nan(float32 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+return float32_is_any_nan(a_);
+#else
 uint32_t a = float32_val(a_);
 if (status->snan_bit_is_one) {
 return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003F);
 } else {
 return ((uint32_t)(a << 1) >= 0xFF80);
 }
+#endif
 }
 
 /*
@@ -366,14 +355,17 @@ int float32_is_quiet_nan(float32 a_, float_status *status)
 
 int float32_is_signaling_nan(float32 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+return 0;
+#else
 uint32_t a = float32_val(a_);
 if (status->snan_bit_is_one) {
 return ((uint32_t)(a << 1) >= 0xFF80);
 } else {
 return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003F);
 }
-}
 #endif
+}
 
 /*
 | Returns a quiet NaN if the single-precision floating point value `a' is a
@@ -744,17 +736,6 @@ static float32 propagateFloat32NaN(float32 a, float32 b, 
float_status *status)
 }
 }
 
-#ifdef NO_SIGNALING_NANS
-int float64_is_quiet_nan(float64 a_, float_status *status)
-{
-return float64_is_any_nan(a_);
-}
-
-int float64_is_signaling_nan(float64 a_, float_status *status)
-{
-return 0;
-}
-#else
 /*
 | Returns 1 if the double-precision floating-point value `a' is a quiet
 | NaN; otherwise returns 0.
@@ -762,6 +743,9 @@ int float64_is_signaling_nan(float64 a_, float_status 
*status)
 
 int float64_is_quiet_nan(float64 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+return float64_is_any_nan(a_);
+#else
 uint64_t a = float64_val(a_);
 if (status->snan_bit_is_one) {
 return (((a >> 51) & 0xFFF) == 0xFFE)
@@ -769,6 +753,7 @@ int float64_is_quiet_nan(float64 a_, float_status *status)
 } else {
 return ((a << 1) >= 0xFFF0ULL);
 }
+#endif
 }
 
 /*
@@ -778,6 +763,9 @@ int float64_is_quiet_nan(float64 a_, float_status *status)
 
 int float64_is_signaling_nan(float64 a_, float_status *status)
 {
+#ifdef NO_SIGNALING_NANS
+return 0;
+#else
 uint64_t a = 

[Qemu-devel] [PATCH v2 00/27] softfloat patch roundup

2018-05-11 Thread Richard Henderson
This is my SNaN patch set, Alex's float-float refactor, and a couple
of other random outstanding fpu patches.  This has been reordered so
as to be bisectable, since the float-float refactor requires the snan
work to avoid breakage.

It probably doesn't matter, but this was built on top of my arm fp16
patch set simply to make it easier to test.  The whole tree is

  git://github.com/rth7680/qemu.git fpu-roundup


r~


Alex Bennée (5):
  fpu/softfloat: int_to_float ensure r fully initialised
  fpu/softfloat: re-factor float to float conversions
  fpu/softfloat: support ARM Alternative half-precision
  target/arm: convert conversion helpers to fpst/ahp_flag
  target/arm: squash FZ16 behaviour for conversions

Peter Maydell (2):
  fpu/softfloat: Don't set Invalid for float-to-int(MAXINT)
  target/arm: Fix fp_status_f16 tininess before rounding

Richard Henderson (20):
  fpu/softfloat: Merge NO_SIGNALING_NANS definitions
  fpu/softfloat: Split floatXX_silence_nan from floatXX_maybe_silence_nan
  fpu/softfloat: Move softfloat-specialize.h below FloatParts definition
  fpu/softfloat: Canonicalize NaN fraction
  fpu/softfloat: Introduce parts_is_snan_frac
  fpu/softfloat: Replace float_class_dnan with parts_default_nan
  fpu/softfloat: Replace float_class_msnan with parts_silence_nan
  target/arm: Use floatX_silence_nan when we have already checked for SNaN
  target/arm: Remove floatX_maybe_silence_nan from conversions
  target/hppa: Remove floatX_maybe_silence_nan from conversions
  target/m68k: Use floatX_silence_nan when we have already checked for SNaN
  target/mips: Remove floatX_maybe_silence_nan from conversions
  target/riscv: Remove floatX_maybe_silence_nan from conversions
  target/s390x: Remove floatX_maybe_silence_nan from conversions
  fpu/softfloat: Use float*_silence_nan in propagateFloat*NaN
  fpu/softfloat: Remove floatX_maybe_silence_nan
  fpu/softfloat: Specialize on snan_bit_is_one
  fpu/softfloat: Make is_nan et al available to softfloat-specialize.h
  fpu/softfloat: Pass FloatClass to pickNaN
  fpu/softfloat: Pass FloatClass to pickNaNMulAdd

 fpu/softfloat-specialize.h| 668 ++
 include/fpu/softfloat-types.h |   1 +
 include/fpu/softfloat.h   |  22 +-
 target/arm/helper.h   |  10 +-
 target/arm/translate.h|  12 +
 target/mips/cpu.h |   4 +-
 fpu/softfloat.c   | 665 ++---
 target/arm/cpu.c  |   2 +
 target/arm/helper-a64.c   |   7 +-
 target/arm/helper.c   | 114 +++---
 target/arm/translate-a64.c|  38 +-
 target/arm/translate.c|  74 +++-
 target/hppa/cpu.c |   1 -
 target/hppa/op_helper.c   |   2 -
 target/m68k/softfloat.c   |   3 +-
 target/mips/msa_helper.c  |   4 -
 target/mips/op_helper.c   |   2 -
 target/mips/translate_init.c  |   4 +-
 target/ppc/fpu_helper.c   |   1 -
 target/riscv/fpu_helper.c |   6 +-
 target/s390x/fpu_helper.c |  12 +-
 target/sh4/cpu.c  |   1 -
 target/unicore32/cpu.c|   2 -
 23 files changed, 730 insertions(+), 925 deletions(-)

-- 
2.17.0




[Qemu-devel] [PATCH v2 01/27] fpu/softfloat: int_to_float ensure r fully initialised

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

Reported by Coverity (CID1390635). We ensure this for uint_to_float
later on so we might as well mirror that.

Signed-off-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 fpu/softfloat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 8401b37bd4..b39c0c6fbb 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1525,7 +1525,7 @@ FLOAT_TO_UINT(64, 64)
 
 static FloatParts int_to_float(int64_t a, float_status *status)
 {
-FloatParts r;
+FloatParts r = {};
 if (a == 0) {
 r.cls = float_class_zero;
 r.sign = false;
-- 
2.17.0




[Qemu-devel] [PATCH v4 06/11] target/arm: Implement FP data-processing (2 source) for fp16

2018-05-11 Thread Richard Henderson
We missed all of the scalar fp16 binary operations.

Cc: qemu-sta...@nongnu.org
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 65 ++
 1 file changed, 65 insertions(+)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 78f12daaf6..66607668ce 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5299,6 +5299,61 @@ static void handle_fp_2src_double(DisasContext *s, int 
opcode,
 tcg_temp_free_i64(tcg_res);
 }
 
+/* Floating-point data-processing (2 source) - half precision */
+static void handle_fp_2src_half(DisasContext *s, int opcode,
+int rd, int rn, int rm)
+{
+TCGv_i32 tcg_op1;
+TCGv_i32 tcg_op2;
+TCGv_i32 tcg_res;
+TCGv_ptr fpst;
+
+tcg_res = tcg_temp_new_i32();
+fpst = get_fpstatus_ptr(true);
+tcg_op1 = read_fp_hreg(s, rn);
+tcg_op2 = read_fp_hreg(s, rm);
+
+switch (opcode) {
+case 0x0: /* FMUL */
+gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x1: /* FDIV */
+gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x2: /* FADD */
+gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x3: /* FSUB */
+gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x4: /* FMAX */
+gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x5: /* FMIN */
+gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x6: /* FMAXNM */
+gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x7: /* FMINNM */
+gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
+break;
+case 0x8: /* FNMUL */
+gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
+tcg_gen_xori_i32(tcg_res, tcg_res, 0x8000);
+break;
+default:
+g_assert_not_reached();
+}
+
+write_fp_sreg(s, rd, tcg_res);
+
+tcg_temp_free_ptr(fpst);
+tcg_temp_free_i32(tcg_op1);
+tcg_temp_free_i32(tcg_op2);
+tcg_temp_free_i32(tcg_res);
+}
+
 /* Floating point data-processing (2 source)
  *   31  30  29 28   24 23  22  21 20  16 1512 11 10 95 40
  * +---+---+---+---+--+---+--++-+--+--+
@@ -5331,6 +5386,16 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn)
 }
 handle_fp_2src_double(s, opcode, rd, rn, rm);
 break;
+case 3:
+if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
+unallocated_encoding(s);
+return;
+}
+if (!fp_access_check(s)) {
+return;
+}
+handle_fp_2src_half(s, opcode, rd, rn, rm);
+break;
 default:
 unallocated_encoding(s);
 }
-- 
2.17.0




[Qemu-devel] [PATCH v4 09/11] target/arm: Implement FCSEL for fp16

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

These were missed out from the rest of the half-precision work.

Cc: qemu-sta...@nongnu.org
Reviewed-by: Peter Maydell 
Signed-off-by: Alex Bennée 
[rth: Fix erroneous check vs type]
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 31 +--
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c078a54fa5..9dacb583ae 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -4903,15 +4903,34 @@ static void disas_fp_csel(DisasContext *s, uint32_t 
insn)
 unsigned int mos, type, rm, cond, rn, rd;
 TCGv_i64 t_true, t_false, t_zero;
 DisasCompare64 c;
+TCGMemOp sz;
 
 mos = extract32(insn, 29, 3);
-type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
+type = extract32(insn, 22, 2);
 rm = extract32(insn, 16, 5);
 cond = extract32(insn, 12, 4);
 rn = extract32(insn, 5, 5);
 rd = extract32(insn, 0, 5);
 
-if (mos || type > 1) {
+if (mos) {
+unallocated_encoding(s);
+return;
+}
+
+switch (type) {
+case 0:
+sz = MO_32;
+break;
+case 1:
+sz = MO_64;
+break;
+case 3:
+sz = MO_16;
+if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
+break;
+}
+/* fallthru */
+default:
 unallocated_encoding(s);
 return;
 }
@@ -4920,11 +4939,11 @@ static void disas_fp_csel(DisasContext *s, uint32_t 
insn)
 return;
 }
 
-/* Zero extend sreg inputs to 64 bits now.  */
+/* Zero extend sreg & hreg inputs to 64 bits now.  */
 t_true = tcg_temp_new_i64();
 t_false = tcg_temp_new_i64();
-read_vec_element(s, t_true, rn, 0, type ? MO_64 : MO_32);
-read_vec_element(s, t_false, rm, 0, type ? MO_64 : MO_32);
+read_vec_element(s, t_true, rn, 0, sz);
+read_vec_element(s, t_false, rm, 0, sz);
 
 a64_test_cc(, cond);
 t_zero = tcg_const_i64(0);
@@ -4933,7 +4952,7 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
 tcg_temp_free_i64(t_false);
 a64_free_cc();
 
-/* Note that sregs write back zeros to the high bits,
+/* Note that sregs & hregs write back zeros to the high bits,
and we've already done the zero-extension.  */
 write_fp_dreg(s, rd, t_true);
 tcg_temp_free_i64(t_true);
-- 
2.17.0




[Qemu-devel] [PATCH v4 10/11] target/arm: Implement FMOV (immediate) for fp16

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

All the hard work is already done by vfp_expand_imm, we just need to
make sure we pick up the correct size.

Cc: qemu-sta...@nongnu.org
Reviewed-by: Peter Maydell 
Signed-off-by: Alex Bennée 
[rth: Merge unallocated_encoding check with TCGMemOp conversion.]
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 20 +---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 9dacb583ae..35997969b4 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5674,11 +5674,25 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
 {
 int rd = extract32(insn, 0, 5);
 int imm8 = extract32(insn, 13, 8);
-int is_double = extract32(insn, 22, 2);
+int type = extract32(insn, 22, 2);
 uint64_t imm;
 TCGv_i64 tcg_res;
+TCGMemOp sz;
 
-if (is_double > 1) {
+switch (type) {
+case 0:
+sz = MO_32;
+break;
+case 1:
+sz = MO_64;
+break;
+case 3:
+sz = MO_16;
+if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
+break;
+}
+/* fallthru */
+default:
 unallocated_encoding(s);
 return;
 }
@@ -5687,7 +5701,7 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
 return;
 }
 
-imm = vfp_expand_imm(MO_32 + is_double, imm8);
+imm = vfp_expand_imm(sz, imm8);
 
 tcg_res = tcg_const_i64(imm);
 write_fp_dreg(s, rd, tcg_res);
-- 
2.17.0




[Qemu-devel] [PATCH v4 04/11] target/arm: Implement FCVT (scalar, fixed-point) for fp16

2018-05-11 Thread Richard Henderson
Cc: qemu-sta...@nongnu.org
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 93fb15d185..d0ed125442 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5697,8 +5697,21 @@ static void disas_fp_fixed_conv(DisasContext *s, 
uint32_t insn)
 bool sf = extract32(insn, 31, 1);
 bool itof;
 
-if (sbit || (type > 1)
-|| (!sf && scale < 32)) {
+if (sbit || (!sf && scale < 32)) {
+unallocated_encoding(s);
+return;
+}
+
+switch (type) {
+case 0: /* float32 */
+case 1: /* float64 */
+break;
+case 3: /* float16 */
+if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
+break;
+}
+/* fallthru */
+default:
 unallocated_encoding(s);
 return;
 }
-- 
2.17.0




[Qemu-devel] [PATCH v4 08/11] target/arm: Implement FCMP for fp16

2018-05-11 Thread Richard Henderson
From: Alex Bennée 

These where missed out from the rest of the half-precision work.

Cc: qemu-sta...@nongnu.org
Reviewed-by: Peter Maydell 
Signed-off-by: Alex Bennée 
[rth: Diagnose lack of FP16 before fp_access_check]
Signed-off-by: Richard Henderson 
---
 target/arm/helper-a64.h|  2 +
 target/arm/helper-a64.c| 10 +
 target/arm/translate-a64.c | 88 ++
 3 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
index b8028ac98c..9d3a907049 100644
--- a/target/arm/helper-a64.h
+++ b/target/arm/helper-a64.h
@@ -19,6 +19,8 @@
 DEF_HELPER_FLAGS_2(udiv64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(sdiv64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
 DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64)
+DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr)
+DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr)
 DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
 DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
 DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 549ed3513e..4f8034c513 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -85,6 +85,16 @@ static inline uint32_t float_rel_to_flags(int res)
 return flags;
 }
 
+uint64_t HELPER(vfp_cmph_a64)(float16 x, float16 y, void *fp_status)
+{
+return float_rel_to_flags(float16_compare_quiet(x, y, fp_status));
+}
+
+uint64_t HELPER(vfp_cmpeh_a64)(float16 x, float16 y, void *fp_status)
+{
+return float_rel_to_flags(float16_compare(x, y, fp_status));
+}
+
 uint64_t HELPER(vfp_cmps_a64)(float32 x, float32 y, void *fp_status)
 {
 return float_rel_to_flags(float32_compare_quiet(x, y, fp_status));
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index a79c09eda2..c078a54fa5 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -4712,14 +4712,14 @@ static void disas_data_proc_reg(DisasContext *s, 
uint32_t insn)
 }
 }
 
-static void handle_fp_compare(DisasContext *s, bool is_double,
+static void handle_fp_compare(DisasContext *s, int size,
   unsigned int rn, unsigned int rm,
   bool cmp_with_zero, bool signal_all_nans)
 {
 TCGv_i64 tcg_flags = tcg_temp_new_i64();
-TCGv_ptr fpst = get_fpstatus_ptr(false);
+TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
 
-if (is_double) {
+if (size == MO_64) {
 TCGv_i64 tcg_vn, tcg_vm;
 
 tcg_vn = read_fp_dreg(s, rn);
@@ -4736,19 +4736,35 @@ static void handle_fp_compare(DisasContext *s, bool 
is_double,
 tcg_temp_free_i64(tcg_vn);
 tcg_temp_free_i64(tcg_vm);
 } else {
-TCGv_i32 tcg_vn, tcg_vm;
+TCGv_i32 tcg_vn = tcg_temp_new_i32();
+TCGv_i32 tcg_vm = tcg_temp_new_i32();
 
-tcg_vn = read_fp_sreg(s, rn);
+read_vec_element_i32(s, tcg_vn, rn, 0, size);
 if (cmp_with_zero) {
-tcg_vm = tcg_const_i32(0);
+tcg_gen_movi_i32(tcg_vm, 0);
 } else {
-tcg_vm = read_fp_sreg(s, rm);
+read_vec_element_i32(s, tcg_vm, rm, 0, size);
 }
-if (signal_all_nans) {
-gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
-} else {
-gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+
+switch (size) {
+case MO_32:
+if (signal_all_nans) {
+gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+} else {
+gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+}
+break;
+case MO_16:
+if (signal_all_nans) {
+gen_helper_vfp_cmpeh_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+} else {
+gen_helper_vfp_cmph_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
+}
+break;
+default:
+g_assert_not_reached();
 }
+
 tcg_temp_free_i32(tcg_vn);
 tcg_temp_free_i32(tcg_vm);
 }
@@ -4769,16 +4785,35 @@ static void handle_fp_compare(DisasContext *s, bool 
is_double,
 static void disas_fp_compare(DisasContext *s, uint32_t insn)
 {
 unsigned int mos, type, rm, op, rn, opc, op2r;
+int size;
 
 mos = extract32(insn, 29, 3);
-type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
+type = extract32(insn, 22, 2);
 rm = extract32(insn, 16, 5);
 op = extract32(insn, 14, 2);
 rn = extract32(insn, 5, 5);
 opc = extract32(insn, 3, 2);
 op2r = extract32(insn, 0, 3);
 
-if (mos || op || op2r || type > 1) {
+if (mos || op || op2r) {
+unallocated_encoding(s);
+return;
+}
+
+switch (type) {
+case 0:
+size = MO_32;
+break;
+case 1:
+size = MO_64;
+break;
+case 

[Qemu-devel] [PATCH v4 05/11] target/arm: Introduce and use read_fp_hreg

2018-05-11 Thread Richard Henderson
Cc: qemu-sta...@nongnu.org
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 30 ++
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d0ed125442..78f12daaf6 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -615,6 +615,14 @@ static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
 return v;
 }
 
+static TCGv_i32 read_fp_hreg(DisasContext *s, int reg)
+{
+TCGv_i32 v = tcg_temp_new_i32();
+
+tcg_gen_ld16u_i32(v, cpu_env, fp_reg_offset(s, reg, MO_16));
+return v;
+}
+
 /* Clear the bits above an N-bit vector, for N = (is_q ? 128 : 64).
  * If SVE is not enabled, then there are only 128 bits in the vector.
  */
@@ -4881,11 +4889,9 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
 static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
 {
 TCGv_ptr fpst = NULL;
-TCGv_i32 tcg_op = tcg_temp_new_i32();
+TCGv_i32 tcg_op = read_fp_hreg(s, rn);
 TCGv_i32 tcg_res = tcg_temp_new_i32();
 
-read_vec_element_i32(s, tcg_op, rn, 0, MO_16);
-
 switch (opcode) {
 case 0x0: /* FMOV */
 tcg_gen_mov_i32(tcg_res, tcg_op);
@@ -7784,13 +7790,10 @@ static void 
disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
 tcg_temp_free_i64(tcg_op2);
 tcg_temp_free_i64(tcg_res);
 } else {
-TCGv_i32 tcg_op1 = tcg_temp_new_i32();
-TCGv_i32 tcg_op2 = tcg_temp_new_i32();
+TCGv_i32 tcg_op1 = read_fp_hreg(s, rn);
+TCGv_i32 tcg_op2 = read_fp_hreg(s, rm);
 TCGv_i64 tcg_res = tcg_temp_new_i64();
 
-read_vec_element_i32(s, tcg_op1, rn, 0, MO_16);
-read_vec_element_i32(s, tcg_op2, rm, 0, MO_16);
-
 gen_helper_neon_mull_s16(tcg_res, tcg_op1, tcg_op2);
 gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, tcg_res, tcg_res);
 
@@ -8331,13 +8334,10 @@ static void 
disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
 
 fpst = get_fpstatus_ptr(true);
 
-tcg_op1 = tcg_temp_new_i32();
-tcg_op2 = tcg_temp_new_i32();
+tcg_op1 = read_fp_hreg(s, rn);
+tcg_op2 = read_fp_hreg(s, rm);
 tcg_res = tcg_temp_new_i32();
 
-read_vec_element_i32(s, tcg_op1, rn, 0, MO_16);
-read_vec_element_i32(s, tcg_op2, rm, 0, MO_16);
-
 switch (fpopcode) {
 case 0x03: /* FMULX */
 gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
@@ -12235,11 +12235,9 @@ static void disas_simd_two_reg_misc_fp16(DisasContext 
*s, uint32_t insn)
 }
 
 if (is_scalar) {
-TCGv_i32 tcg_op = tcg_temp_new_i32();
+TCGv_i32 tcg_op = read_fp_hreg(s, rn);
 TCGv_i32 tcg_res = tcg_temp_new_i32();
 
-read_vec_element_i32(s, tcg_op, rn, 0, MO_16);
-
 switch (fpop) {
 case 0x1a: /* FCVTNS */
 case 0x1b: /* FCVTMS */
-- 
2.17.0




[Qemu-devel] [PATCH v4 01/11] target/arm: Implement FMOV (general) for fp16

2018-05-11 Thread Richard Henderson
Adding the fp16 moves to/from general registers.

Cc: qemu-sta...@nongnu.org
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 4d1b220cc6..5b8cf75e9f 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5700,6 +5700,15 @@ static void handle_fmov(DisasContext *s, int rd, int rn, 
int type, bool itof)
 tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
 clear_vec_high(s, true, rd);
 break;
+case 3:
+/* 16 bit */
+tmp = tcg_temp_new_i64();
+tcg_gen_ext16u_i64(tmp, tcg_rn);
+write_fp_dreg(s, rd, tmp);
+tcg_temp_free_i64(tmp);
+break;
+default:
+g_assert_not_reached();
 }
 } else {
 TCGv_i64 tcg_rd = cpu_reg(s, rd);
@@ -5717,6 +5726,12 @@ static void handle_fmov(DisasContext *s, int rd, int rn, 
int type, bool itof)
 /* 64 bits from top half */
 tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
 break;
+case 3:
+/* 16 bit */
+tcg_gen_ld16u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_16));
+break;
+default:
+g_assert_not_reached();
 }
 }
 }
@@ -5756,6 +5771,12 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t 
insn)
 case 0xa: /* 64 bit */
 case 0xd: /* 64 bit to top half of quad */
 break;
+case 0x6: /* 16-bit float, 32-bit int */
+case 0xe: /* 16-bit float, 64-bit int */
+if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
+break;
+}
+/* fallthru */
 default:
 /* all other sf/type/rmode combinations are invalid */
 unallocated_encoding(s);
-- 
2.17.0




[Qemu-devel] [PATCH v4 03/11] target/arm: Implement FCVT (scalar, integer) for fp16

2018-05-11 Thread Richard Henderson
Cc: qemu-sta...@nongnu.org
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h|  6 +++
 target/arm/helper.c| 38 ++-
 target/arm/translate-a64.c | 96 +++---
 3 files changed, 122 insertions(+), 18 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 1969b37f2d..ce89968b2d 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -151,6 +151,10 @@ DEF_HELPER_3(vfp_touhd_round_to_zero, i64, f64, i32, ptr)
 DEF_HELPER_3(vfp_tould_round_to_zero, i64, f64, i32, ptr)
 DEF_HELPER_3(vfp_touhh, i32, f16, i32, ptr)
 DEF_HELPER_3(vfp_toshh, i32, f16, i32, ptr)
+DEF_HELPER_3(vfp_toulh, i32, f16, i32, ptr)
+DEF_HELPER_3(vfp_toslh, i32, f16, i32, ptr)
+DEF_HELPER_3(vfp_touqh, i64, f16, i32, ptr)
+DEF_HELPER_3(vfp_tosqh, i64, f16, i32, ptr)
 DEF_HELPER_3(vfp_toshs, i32, f32, i32, ptr)
 DEF_HELPER_3(vfp_tosls, i32, f32, i32, ptr)
 DEF_HELPER_3(vfp_tosqs, i64, f32, i32, ptr)
@@ -177,6 +181,8 @@ DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
 DEF_HELPER_3(vfp_sltoh, f16, i32, i32, ptr)
 DEF_HELPER_3(vfp_ultoh, f16, i32, i32, ptr)
+DEF_HELPER_3(vfp_sqtoh, f16, i64, i32, ptr)
+DEF_HELPER_3(vfp_uqtoh, f16, i64, i32, ptr)
 
 DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, ptr)
 DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 817f9d81a0..c6fd7f9479 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11427,8 +11427,12 @@ VFP_CONV_FIX_A64(uq, s, 32, 64, uint64)
 #undef VFP_CONV_FIX_A64
 
 /* Conversion to/from f16 can overflow to infinity before/after scaling.
- * Therefore we convert to f64 (which does not round), scale,
- * and then convert f64 to f16 (which may round).
+ * Therefore we convert to f64, scale, and then convert f64 to f16; or
+ * vice versa for conversion to integer.
+ *
+ * For 16- and 32-bit integers, the conversion to f64 never rounds.
+ * For 64-bit integers, any integer that would cause rounding will also
+ * overflow to f16 infinity, so there is no double rounding problem.
  */
 
 static float16 do_postscale_fp16(float64 f, int shift, float_status *fpst)
@@ -11446,6 +11450,16 @@ float16 HELPER(vfp_ultoh)(uint32_t x, uint32_t shift, 
void *fpst)
 return do_postscale_fp16(uint32_to_float64(x, fpst), shift, fpst);
 }
 
+float16 HELPER(vfp_sqtoh)(uint64_t x, uint32_t shift, void *fpst)
+{
+return do_postscale_fp16(int64_to_float64(x, fpst), shift, fpst);
+}
+
+float16 HELPER(vfp_uqtoh)(uint64_t x, uint32_t shift, void *fpst)
+{
+return do_postscale_fp16(uint64_to_float64(x, fpst), shift, fpst);
+}
+
 static float64 do_prescale_fp16(float16 f, int shift, float_status *fpst)
 {
 if (unlikely(float16_is_any_nan(f))) {
@@ -11475,6 +11489,26 @@ uint32_t HELPER(vfp_touhh)(float16 x, uint32_t shift, 
void *fpst)
 return float64_to_uint16(do_prescale_fp16(x, shift, fpst), fpst);
 }
 
+uint32_t HELPER(vfp_toslh)(float16 x, uint32_t shift, void *fpst)
+{
+return float64_to_int32(do_prescale_fp16(x, shift, fpst), fpst);
+}
+
+uint32_t HELPER(vfp_toulh)(float16 x, uint32_t shift, void *fpst)
+{
+return float64_to_uint32(do_prescale_fp16(x, shift, fpst), fpst);
+}
+
+uint64_t HELPER(vfp_tosqh)(float16 x, uint32_t shift, void *fpst)
+{
+return float64_to_int64(do_prescale_fp16(x, shift, fpst), fpst);
+}
+
+uint64_t HELPER(vfp_touqh)(float16 x, uint32_t shift, void *fpst)
+{
+return float64_to_uint64(do_prescale_fp16(x, shift, fpst), fpst);
+}
+
 /* Set the current fp rounding mode and return the old one.
  * The argument is a softfloat float_round_ value.
  */
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 11d8c07943..93fb15d185 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5511,11 +5511,11 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int 
rn, int opcode,
bool itof, int rmode, int scale, int sf, int type)
 {
 bool is_signed = !(opcode & 1);
-bool is_double = type;
 TCGv_ptr tcg_fpstatus;
-TCGv_i32 tcg_shift;
+TCGv_i32 tcg_shift, tcg_single;
+TCGv_i64 tcg_double;
 
-tcg_fpstatus = get_fpstatus_ptr(false);
+tcg_fpstatus = get_fpstatus_ptr(type == 3);
 
 tcg_shift = tcg_const_i32(64 - scale);
 
@@ -5533,8 +5533,9 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int 
rn, int opcode,
 tcg_int = tcg_extend;
 }
 
-if (is_double) {
-TCGv_i64 tcg_double = tcg_temp_new_i64();
+switch (type) {
+case 1: /* float64 */
+tcg_double = tcg_temp_new_i64();
 if (is_signed) {
 gen_helper_vfp_sqtod(tcg_double, tcg_int,
  tcg_shift, tcg_fpstatus);
@@ -5544,8 +5545,10 @@ static void handle_fpfpcvt(DisasContext *s, int rd, int 
rn, int 

[Qemu-devel] [PATCH v4 00/11] target/arm: Fixups for ARM_FEATURE_V8_FP16

2018-05-11 Thread Richard Henderson
Changes since v3:
  * Fixup rebase vs target-arm.next.  One of the middle
patches had conflicts resolved incorrectly, so the
patch set was non-bisectable.

Changes since v2:
  * Rebased vs target-arm.next.
  * Merged Peter's review.
  * Split out return fix as a separate patch.

Changes since v1:
  * Rebased vs master instead of tgt-arm-sve-9.
  * Alex did some additional digging through the ARM xhtml
and came up with some additional missing instructions.
  * Everything cc'd to qemu-stable.


r~


Alex Bennée (4):
  target/arm: Implement FCMP for fp16
  target/arm: Implement FCSEL for fp16
  target/arm: Implement FMOV (immediate) for fp16
  target/arm: Fix sqrt_f16 exception raising

Richard Henderson (7):
  target/arm: Implement FMOV (general) for fp16
  target/arm: Early exit after unallocated_encoding in disas_fp_int_conv
  target/arm: Implement FCVT (scalar,integer) for fp16
  target/arm: Implement FCVT (scalar,fixed-point) for fp16
  target/arm: Introduce and use read_fp_hreg
  target/arm: Implement FP data-processing (2 source) for fp16
  target/arm: Implement FP data-processing (3 source) for fp16

 target/arm/helper-a64.h|   2 +
 target/arm/helper.h|   6 +
 target/arm/helper-a64.c|  10 +
 target/arm/helper.c|  38 +++-
 target/arm/translate-a64.c | 421 +++--
 5 files changed, 413 insertions(+), 64 deletions(-)

-- 
2.17.0




[Qemu-devel] [PATCH v4 02/11] target/arm: Early exit after unallocated_encoding in disas_fp_int_conv

2018-05-11 Thread Richard Henderson
No sense in emitting code after the exception.

Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 5b8cf75e9f..11d8c07943 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5780,7 +5780,7 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t 
insn)
 default:
 /* all other sf/type/rmode combinations are invalid */
 unallocated_encoding(s);
-break;
+return;
 }
 
 if (!fp_access_check(s)) {
-- 
2.17.0




[Qemu-devel] [PATCH v4 07/11] target/arm: Implement FP data-processing (3 source) for fp16

2018-05-11 Thread Richard Henderson
We missed all of the scalar fp16 fma operations.

Cc: qemu-sta...@nongnu.org
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 target/arm/translate-a64.c | 48 ++
 1 file changed, 48 insertions(+)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 66607668ce..a79c09eda2 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -5477,6 +5477,44 @@ static void handle_fp_3src_double(DisasContext *s, bool 
o0, bool o1,
 tcg_temp_free_i64(tcg_res);
 }
 
+/* Floating-point data-processing (3 source) - half precision */
+static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
+int rd, int rn, int rm, int ra)
+{
+TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
+TCGv_i32 tcg_res = tcg_temp_new_i32();
+TCGv_ptr fpst = get_fpstatus_ptr(true);
+
+tcg_op1 = read_fp_hreg(s, rn);
+tcg_op2 = read_fp_hreg(s, rm);
+tcg_op3 = read_fp_hreg(s, ra);
+
+/* These are fused multiply-add, and must be done as one
+ * floating point operation with no rounding between the
+ * multiplication and addition steps.
+ * NB that doing the negations here as separate steps is
+ * correct : an input NaN should come out with its sign bit
+ * flipped if it is a negated-input.
+ */
+if (o1 == true) {
+tcg_gen_xori_i32(tcg_op3, tcg_op3, 0x8000);
+}
+
+if (o0 != o1) {
+tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
+}
+
+gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
+
+write_fp_sreg(s, rd, tcg_res);
+
+tcg_temp_free_ptr(fpst);
+tcg_temp_free_i32(tcg_op1);
+tcg_temp_free_i32(tcg_op2);
+tcg_temp_free_i32(tcg_op3);
+tcg_temp_free_i32(tcg_res);
+}
+
 /* Floating point data-processing (3 source)
  *   31  30  29 28   24 23  22  21  20  16  15  14  10 95 40
  * +---+---+---+---+--++--++--+--+--+
@@ -5506,6 +5544,16 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
 }
 handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
 break;
+case 3:
+if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
+unallocated_encoding(s);
+return;
+}
+if (!fp_access_check(s)) {
+return;
+}
+handle_fp_3src_half(s, o0, o1, rd, rn, rm, ra);
+break;
 default:
 unallocated_encoding(s);
 }
-- 
2.17.0




[Qemu-devel] [PATCH RFC v2 2/2] PC Chipset: Send serial bytes at correct rate

2018-05-11 Thread Calvin Lee
This fixes bug in QEMU such that UART bytes would be sent immediatly
after being put in the THR regardless of the UART frequency (and divisor).
Now they will be sent at the appropriate rate.

Signed-off-by: Calvin Lee 
---
I am not sure about VM migration here. I want to move a struct field
from one VMStateDescription to a new one. I did this by bumping the
version number on the old VMStateDescription, and kept the field as
`_TEST`. If this is incorrect please let me know.

 hw/char/serial.c | 51 +++-
 include/hw/char/serial.h |  2 ++
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/hw/char/serial.c b/hw/char/serial.c
index 4159a46a2f..542d949ccd 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -359,9 +359,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, 
uint64_t val,
 s->lsr &= ~UART_LSR_THRE;
 s->lsr &= ~UART_LSR_TEMT;
 serial_update_irq(s);
-if (s->tsr_retry == 0) {
-serial_xmit(s);
-}
+timer_mod(s->xmit_timeout_timer,
+qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time);
 }
 break;
 case 1:
@@ -586,6 +585,15 @@ static void serial_receive_break(SerialState *s)
 serial_update_irq(s);
 }
 
+/* There is data to be sent in xmit_fifo or the thr */
+static void xmit_timeout_int(void *opaque)
+{
+SerialState *s = opaque;
+if (s->tsr_retry == 0) {
+serial_xmit(s);
+}
+}
+
 /* There's data in recv_fifo and s->rbr has not been read for 4 char transmit 
times */
 static void fifo_timeout_int (void *opaque) {
 SerialState *s = opaque;
@@ -723,15 +731,20 @@ static bool serial_tsr_needed(void *opaque)
 SerialState *s = (SerialState *)opaque;
 return s->tsr_retry != 0;
 }
+static bool serial_tsr_thr_exists(void *opaque, int version_id)
+{
+return version_id < 2;
+}
 
 static const VMStateDescription vmstate_serial_tsr = {
 .name = "serial/tsr",
-.version_id = 1,
+.version_id = 2,
 .minimum_version_id = 1,
 .needed = serial_tsr_needed,
 .fields = (VMStateField[]) {
 VMSTATE_UINT32(tsr_retry, SerialState),
-VMSTATE_UINT8(thr, SerialState),
+/* Moved to `xmit_timeout_timer` */
+VMSTATE_UINT8_TEST(thr, SerialState, serial_tsr_thr_exists),
 VMSTATE_UINT8(tsr, SerialState),
 VMSTATE_END_OF_LIST()
 }
@@ -772,6 +785,24 @@ static const VMStateDescription vmstate_serial_xmit_fifo = 
{
 }
 };
 
+static bool serial_xmit_timeout_timer_needed(void *opaque)
+{
+SerialState *s = (SerialState *)opaque;
+return timer_pending(s->xmit_timeout_timer);
+}
+
+static const VMStateDescription vmstate_serial_xmit_timeout_timer = {
+.name = "serial/xmit_timeout_timer",
+.version_id = 1,
+.minimum_version_id = 1,
+.needed = serial_xmit_timeout_timer_needed,
+.fields = (VMStateField[]) {
+VMSTATE_UINT8(thr, SerialState),
+VMSTATE_TIMER_PTR(xmit_timeout_timer, SerialState),
+VMSTATE_END_OF_LIST()
+}
+};
+
 static bool serial_fifo_timeout_timer_needed(void *opaque)
 {
 SerialState *s = (SerialState *)opaque;
@@ -849,6 +880,7 @@ const VMStateDescription vmstate_serial = {
 _serial_tsr,
 _serial_recv_fifo,
 _serial_xmit_fifo,
+_serial_xmit_timeout_timer,
 _serial_fifo_timeout_timer,
 _serial_timeout_ipending,
 _serial_poll,
@@ -880,6 +912,7 @@ static void serial_reset(void *opaque)
 s->poll_msl = 0;
 
 s->timeout_ipending = 0;
+timer_del(s->xmit_timeout_timer);
 timer_del(s->fifo_timeout_timer);
 timer_del(s->modem_status_poll);
 
@@ -928,7 +961,10 @@ void serial_realize_core(SerialState *s, Error **errp)
 {
 s->modem_status_poll = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) 
serial_update_msl, s);
 
-s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) 
fifo_timeout_int, s);
+s->xmit_timeout_timer =
+timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) xmit_timeout_int, s);
+s->fifo_timeout_timer =
+timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s);
 qemu_register_reset(serial_reset, s);
 
 qemu_chr_fe_set_handlers(>chr, serial_can_receive1, serial_receive1,
@@ -945,6 +981,9 @@ void serial_exit_core(SerialState *s)
 timer_del(s->modem_status_poll);
 timer_free(s->modem_status_poll);
 
+timer_del(s->xmit_timeout_timer);
+timer_free(s->xmit_timeout_timer);
+
 timer_del(s->fifo_timeout_timer);
 timer_free(s->fifo_timeout_timer);
 
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index 0acfbbc382..09aece90fb 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -65,6 +65,8 @@ struct SerialState {
 /* Time when the last byte was successfully sent out of the tsr */
 uint64_t last_xmit_ts;
 Fifo8 recv_fifo;
+/* Time to 

[Qemu-devel] [PATCH RFC v2 0/2] Fix UART serial implementation

2018-05-11 Thread Calvin Lee
Hello,

While developing a serial implementation for my OS, I found several bugs
in QEMU's serial device. I confirmed (by testing on my x64 laptop) that
there are several inconsistancies between QEMU and hardware in this
regard. For both patches, I used "http://www.sci.muni.cz/docs/pc/serport.txt;
for reference.

First, QEMU has several errors for setting the UART divisor that are
fixed in my first patch. Second, (and more importantly) QEMU does not
transmit serial bytes at the correct rate, and this is fixed in my
second patch.

I have neither contributed to QEMU nor sent patches to a mailing list
before, so I marked this patch-series as RFC. I would appreciate any
comments you have. Also, I am not very confident in VM migration between
versions, so I would appreciate if someone could help me make sure this
is correct in my patches.

v2:
fix build

Calvin Lee (2):
  PC Chipset: Improve serial divisor calculation
  PC Chipset: Send serial bytes at correct rate

 hw/char/serial.c | 74 +++-
 include/hw/char/serial.h |  2 ++
 2 files changed, 60 insertions(+), 16 deletions(-)

-- 
2.17.0




[Qemu-devel] [PATCH RFC v2 1/2] PC Chipset: Improve serial divisor calculation

2018-05-11 Thread Calvin Lee
This fixes several problems I found in the UART serial implementation.
Now all divisor values are allowed, while before divisor values of zero
and below the base baud rate were rejected. All changes are in reference
to http://www.sci.muni.cz/docs/pc/serport.txt

Signed-off-by: Calvin Lee 
---
I included a slight code-style change in this commit because it seemed
close enough to the code I was editing to be relevant. If not, I can
change the commit to not include this change.

 hw/char/serial.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/hw/char/serial.c b/hw/char/serial.c
index 2c080c9862..4159a46a2f 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -150,13 +150,10 @@ static void serial_update_irq(SerialState *s)
 
 static void serial_update_parameters(SerialState *s)
 {
-int speed, parity, data_bits, stop_bits, frame_size;
+float speed;
+int parity, data_bits, stop_bits, frame_size;
 QEMUSerialSetParams ssp;
 
-if (s->divider == 0 || s->divider > s->baudbase) {
-return;
-}
-
 /* Start bit. */
 frame_size = 1;
 if (s->lcr & 0x08) {
@@ -169,14 +166,16 @@ static void serial_update_parameters(SerialState *s)
 } else {
 parity = 'N';
 }
-if (s->lcr & 0x04)
+if (s->lcr & 0x04) {
 stop_bits = 2;
-else
+} else {
 stop_bits = 1;
+}
 
 data_bits = (s->lcr & 0x03) + 5;
 frame_size += data_bits + stop_bits;
-speed = s->baudbase / s->divider;
+/* Zero divisor should give about 3500 baud */
+speed = (s->divider == 0) ? 3500 : (float) s->baudbase / s->divider;
 ssp.speed = speed;
 ssp.parity = parity;
 ssp.data_bits = data_bits;
@@ -184,7 +183,7 @@ static void serial_update_parameters(SerialState *s)
 s->char_transmit_time =  (NANOSECONDS_PER_SECOND / speed) * frame_size;
 qemu_chr_fe_ioctl(>chr, CHR_IOCTL_SERIAL_SET_PARAMS, );
 
-DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
+DPRINTF("speed=%.2f parity=%c data=%d stop=%d\n",
speed, parity, data_bits, stop_bits);
 }
 
@@ -341,7 +340,11 @@ static void serial_ioport_write(void *opaque, hwaddr addr, 
uint64_t val,
 default:
 case 0:
 if (s->lcr & UART_LCR_DLAB) {
-s->divider = (s->divider & 0xff00) | val;
+if (size == 2) {
+s->divider = (s->divider & 0xff00) | val;
+} else if (size == 4) {
+s->divider = val;
+}
 serial_update_parameters(s);
 } else {
 s->thr = (uint8_t) val;
-- 
2.17.0




[Qemu-devel] [PATCH v2 7/7] hw/riscv/sifive_u: Connect the Cadence GEM Ethernet device

2018-05-11 Thread Alistair Francis
Connect the Cadence GEM ethernet device. This also requires us to
expose the plic interrupt lines.

Signed-off-by: Alistair Francis 
---
 default-configs/riscv32-softmmu.mak |  1 +
 default-configs/riscv64-softmmu.mak |  1 +
 hw/riscv/sifive_u.c | 50 +
 include/hw/riscv/sifive_u.h |  9 --
 4 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/default-configs/riscv32-softmmu.mak 
b/default-configs/riscv32-softmmu.mak
index f9e742120c..9a1c42e8b2 100644
--- a/default-configs/riscv32-softmmu.mak
+++ b/default-configs/riscv32-softmmu.mak
@@ -2,3 +2,4 @@
 
 CONFIG_SERIAL=y
 CONFIG_VIRTIO=y
+CONFIG_CADENCE=y
diff --git a/default-configs/riscv64-softmmu.mak 
b/default-configs/riscv64-softmmu.mak
index f9e742120c..9a1c42e8b2 100644
--- a/default-configs/riscv64-softmmu.mak
+++ b/default-configs/riscv64-softmmu.mak
@@ -2,3 +2,4 @@
 
 CONFIG_SERIAL=y
 CONFIG_VIRTIO=y
+CONFIG_CADENCE=y
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 540d53bf2f..fff36bd04d 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -60,8 +60,11 @@ static const struct MemmapEntry {
 [SIFIVE_U_UART0] ={ 0x10013000, 0x1000 },
 [SIFIVE_U_UART1] ={ 0x10023000, 0x1000 },
 [SIFIVE_U_DRAM] = { 0x8000,0x0 },
+[SIFIVE_U_GEM] =  { 0x100900FC, 0x2000 },
 };
 
+#define GEM_REVISION0x10070109
+
 static uint64_t load_kernel(const char *kernel_filename)
 {
 uint64_t kernel_entry, kernel_high;
@@ -194,6 +197,27 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 g_free(cells);
 g_free(nodename);
 
+nodename = g_strdup_printf("/soc/ethernet@%lx",
+(long)memmap[SIFIVE_U_GEM].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_string(fdt, nodename, "compatible", "cdns,macb");
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+0x0, memmap[SIFIVE_U_GEM].base,
+0x0, memmap[SIFIVE_U_GEM].size);
+qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control");
+qemu_fdt_setprop_string(fdt, nodename, "phy-mode", "gmii");
+qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle);
+qemu_fdt_setprop_cells(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ);
+qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 1);
+qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0);
+g_free(nodename);
+
+nodename = g_strdup_printf("/soc/ethernet@%lx/ethernet-phy@0",
+(long)memmap[SIFIVE_U_GEM].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x0);
+g_free(nodename);
+
 nodename = g_strdup_printf("/soc/uart@%lx",
 (long)memmap[SIFIVE_U_UART0].base);
 qemu_fdt_add_subnode(fdt, nodename);
@@ -296,6 +320,9 @@ static void riscv_sifive_u54_init(Object *obj)
memmap[SIFIVE_U_MROM].size, _fatal);
 memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base,
 mask_rom);
+
+object_initialize(>gem, sizeof(s->gem), TYPE_CADENCE_GEM);
+qdev_set_parent_bus(DEVICE(>gem), sysbus_get_default());
 }
 
 static void riscv_sifive_u54_realize(DeviceState *dev, Error **errp)
@@ -303,6 +330,10 @@ static void riscv_sifive_u54_realize(DeviceState *dev, 
Error **errp)
 SiFiveU54State *s = RISCV_U54_SOC(dev);
 const struct MemmapEntry *memmap = sifive_u_memmap;
 MemoryRegion *system_memory = get_system_memory();
+qemu_irq plic_gpios[SIFIVE_U_PLIC_NUM_SOURCES];
+int i;
+Error *err = NULL;
+NICInfo *nd = _table[0];
 
 object_property_set_bool(OBJECT(>cpus), true, "realized",
  _abort);
@@ -327,6 +358,25 @@ static void riscv_sifive_u54_realize(DeviceState *dev, 
Error **errp)
 sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
 memmap[SIFIVE_U_CLINT].size, smp_cpus,
 SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
+
+for (i = 0; i < SIFIVE_U_PLIC_NUM_SOURCES; i++) {
+plic_gpios[i] = qdev_get_gpio_in(DEVICE(s->plic), i);
+}
+
+if (nd->used) {
+qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
+qdev_set_nic_properties(DEVICE(>gem), nd);
+}
+object_property_set_int(OBJECT(>gem), GEM_REVISION, "revision",
+_abort);
+object_property_set_bool(OBJECT(>gem), true, "realized", );
+if (err) {
+error_propagate(errp, err);
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>gem), 0, memmap[SIFIVE_U_GEM].base);
+sysbus_connect_irq(SYS_BUS_DEVICE(>gem), 0,
+   plic_gpios[SIFIVE_U_GEM_IRQ]);
 }
 
 static void riscv_sifive_u_machine_init(MachineClass *mc)
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index 0f8bdd8fab..ee1a9e291f 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -19,6 +19,8 @@
 #ifndef HW_SIFIVE_U_H
 

[Qemu-devel] [PATCH v2 4/7] hw/riscv/sifive_u: Set the soc device tree node as a simple-bus

2018-05-11 Thread Alistair Francis
To allow Linux to ennumerate devices on the /soc/ node set it as a
"simple-bus".

Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index d1008c42f4..859f43c6f9 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -97,7 +97,7 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 
 qemu_fdt_add_subnode(fdt, "/soc");
 qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
-qemu_fdt_setprop_string(fdt, "/soc", "compatible", 
"ucbbar,spike-bare-soc");
+qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus");
 qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
 qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
 
-- 
2.17.0




[Qemu-devel] [PATCH v2 6/7] hw/riscv/sifive_u: Move the uart device tree node under /soc/

2018-05-11 Thread Alistair Francis
Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 50389cdc90..540d53bf2f 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -194,7 +194,7 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 g_free(cells);
 g_free(nodename);
 
-nodename = g_strdup_printf("/uart@%lx",
+nodename = g_strdup_printf("/soc/uart@%lx",
 (long)memmap[SIFIVE_U_UART0].base);
 qemu_fdt_add_subnode(fdt, nodename);
 qemu_fdt_setprop_string(fdt, nodename, "compatible", "sifive,uart0");
-- 
2.17.0




[Qemu-devel] [PATCH v2 5/7] hw/riscv/sifive_u: Set the interrupt controler number of interrupts

2018-05-11 Thread Alistair Francis
Set the interrupt-controller ndev to the correct number taken from the
HiFive Unleashed board.

Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 859f43c6f9..50389cdc90 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -187,7 +187,7 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 0x0, memmap[SIFIVE_U_PLIC].size);
 qemu_fdt_setprop_string(fdt, nodename, "reg-names", "control");
 qemu_fdt_setprop_cell(fdt, nodename, "riscv,max-priority", 7);
-qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 4);
+qemu_fdt_setprop_cell(fdt, nodename, "riscv,ndev", 0x35);
 qemu_fdt_setprop_cells(fdt, nodename, "phandle", 2);
 qemu_fdt_setprop_cells(fdt, nodename, "linux,phandle", 2);
 plic_phandle = qemu_fdt_get_phandle(fdt, nodename);
-- 
2.17.0




[Qemu-devel] [PATCH v2 2/7] hw/riscv/sifive_e: Create a E31 SoC object

2018-05-11 Thread Alistair Francis
Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_e.c | 97 +++--
 include/hw/riscv/sifive_e.h | 16 +-
 2 files changed, 86 insertions(+), 27 deletions(-)

diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index e4ecb7aa4b..0ab5e3ca45 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -102,18 +102,12 @@ static void riscv_sifive_e_init(MachineState *machine)
 SiFiveEState *s = g_new0(SiFiveEState, 1);
 MemoryRegion *sys_mem = get_system_memory();
 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
-MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
-MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
 int i;
 
-/* Initialize SOC */
-object_initialize(>soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
+/* Initialize SoC */
+object_initialize(>soc, sizeof(s->soc), TYPE_RISCV_E31_SOC);
 object_property_add_child(OBJECT(machine), "soc", OBJECT(>soc),
   _abort);
-object_property_set_str(OBJECT(>soc), SIFIVE_E_CPU, "cpu-type",
-_abort);
-object_property_set_int(OBJECT(>soc), smp_cpus, "num-harts",
-_abort);
 object_property_set_bool(OBJECT(>soc), true, "realized",
 _abort);
 
@@ -123,11 +117,57 @@ static void riscv_sifive_e_init(MachineState *machine)
 memory_region_add_subregion(sys_mem,
 memmap[SIFIVE_E_DTIM].base, main_mem);
 
+/* Mask ROM reset vector */
+uint32_t reset_vec[2] = {
+0x204002b7,/* 0x1000: lui t0,0x20400 */
+0x00028067,/* 0x1004: jr  t0 */
+};
+
+/* copy in the reset vector in little_endian byte order */
+for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+reset_vec[i] = cpu_to_le32(reset_vec[i]);
+}
+rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
+  memmap[SIFIVE_E_MROM].base, _space_memory);
+
+if (machine->kernel_filename) {
+load_kernel(machine->kernel_filename);
+}
+}
+
+static void riscv_sifive_e31_init(Object *obj)
+{
+const struct MemmapEntry *memmap = sifive_e_memmap;
+
+SiFiveE31State *s = RISCV_E31_SOC(obj);
+MemoryRegion *sys_mem = get_system_memory();
+MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
+
+object_initialize(>cpus, sizeof(s->cpus), TYPE_RISCV_HART_ARRAY);
+object_property_add_child(obj, "cpus", OBJECT(>cpus),
+  _abort);
+object_property_set_str(OBJECT(>cpus), SIFIVE_E_CPU, "cpu-type",
+_abort);
+object_property_set_int(OBJECT(>cpus), smp_cpus, "num-harts",
+_abort);
+
 /* Mask ROM */
 memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom",
 memmap[SIFIVE_E_MROM].size, _fatal);
 memory_region_add_subregion(sys_mem,
 memmap[SIFIVE_E_MROM].base, mask_rom);
+}
+
+static void riscv_sifive_e31_realize(DeviceState *dev, Error **errp)
+{
+const struct MemmapEntry *memmap = sifive_e_memmap;
+
+SiFiveE31State *s = RISCV_E31_SOC(dev);
+MemoryRegion *sys_mem = get_system_memory();
+MemoryRegion *xip_mem = g_new(MemoryRegion, 1);
+
+object_property_set_bool(OBJECT(>cpus), true, "realized",
+_abort);
 
 /* MMIO */
 s->plic = sifive_plic_create(memmap[SIFIVE_E_PLIC].base,
@@ -171,23 +211,6 @@ static void riscv_sifive_e_init(MachineState *machine)
 memmap[SIFIVE_E_XIP].size, _fatal);
 memory_region_set_readonly(xip_mem, true);
 memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_XIP].base, xip_mem);
-
-/* Mask ROM reset vector */
-uint32_t reset_vec[2] = {
-0x204002b7,/* 0x1000: lui t0,0x20400 */
-0x00028067,/* 0x1004: jr  t0 */
-};
-
-/* copy in the reset vector in little_endian byte order */
-for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
-reset_vec[i] = cpu_to_le32(reset_vec[i]);
-}
-rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
-  memmap[SIFIVE_E_MROM].base, _space_memory);
-
-if (machine->kernel_filename) {
-load_kernel(machine->kernel_filename);
-}
 }
 
 static void riscv_sifive_e_machine_init(MachineClass *mc)
@@ -198,3 +221,27 @@ static void riscv_sifive_e_machine_init(MachineClass *mc)
 }
 
 DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init)
+
+static void riscv_sifive_e31_class_init(ObjectClass *oc, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(oc);
+
+dc->realize = riscv_sifive_e31_realize;
+/* Reason: Uses serial_hds in realize function, thus can't be used twice */
+dc->user_creatable = false;
+}
+
+static const TypeInfo riscv_sifive_e31_type_info = {
+.name = TYPE_RISCV_E31_SOC,
+.parent = TYPE_DEVICE,
+.instance_size = sizeof(SiFiveE31State),
+.instance_init = riscv_sifive_e31_init,
+.class_init 

[Qemu-devel] [PATCH v2 0/7] RISC-V: SoCify SiFive boards and connect GEM

2018-05-11 Thread Alistair Francis

This series has three tasks:
 1. To convert the SiFive U and E machines into SoCs and boards
 2. To connect the Cadence GEM device to the SiFive U board
 3. Fix some device tree problems with the SiFive U board

After this series the SiFive E and U boards have their SoCs split into
seperate QEMU objects, which can be used on future boards if desired.

The RISC-V Virt and Spike boards have not been converted. They haven't
been converted as they aren't physical boards, so it doesn't make a
whole lot of sense to split them into an SoC and board. The only
disadvantage with this is that they now differ to the SiFive boards.

This series also connect the Cadence GEM device to the SiFive U board.
There are some interrupt line changes requried before this is possible.

V2:
 - Use the new GPIOs everywhere in the board
 - Add the GEM device tree node
 - Fix some device tree problems identified



Alistair Francis (7):
  hw/riscv/sifive_u: Create a U54 SoC object
  hw/riscv/sifive_e: Create a E31 SoC object
  hw/riscv/sifive_plic: Use gpios instead of irqs
  hw/riscv/sifive_u: Set the soc device tree node as a simple-bus
  hw/riscv/sifive_u: Set the interrupt controler number of interrupts
  hw/riscv/sifive_u: Move the uart device tree node under /soc/
  hw/riscv/sifive_u: Connect the Cadence GEM Ethernet device

 default-configs/riscv32-softmmu.mak |   1 +
 default-configs/riscv64-softmmu.mak |   1 +
 hw/riscv/sifive_e.c | 102 ++-
 hw/riscv/sifive_plic.c  |   6 +-
 hw/riscv/sifive_u.c | 151 +++-
 hw/riscv/virt.c |   4 +-
 include/hw/riscv/sifive_e.h |  16 ++-
 include/hw/riscv/sifive_plic.h  |   1 -
 include/hw/riscv/sifive_u.h |  25 -
 9 files changed, 239 insertions(+), 68 deletions(-)

-- 
2.17.0




[Qemu-devel] [PATCH v2 1/7] hw/riscv/sifive_u: Create a U54 SoC object

2018-05-11 Thread Alistair Francis
Create a SiFive Unleashed U54 SoC and use that in the sifive_u machine.

We leave the SoC, RAM, device tree and reset/fdt loading as part of the
machine. All the other device creation has been moved to the SoC.

Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 90 -
 include/hw/riscv/sifive_u.h | 16 ++-
 2 files changed, 82 insertions(+), 24 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index c05dcbba95..26155e932d 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -116,10 +116,10 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
 qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
 
-for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) {
+for (cpu = s->soc.cpus.num_harts - 1; cpu >= 0; cpu--) {
 nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
 char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
-char *isa = riscv_isa_string(>soc.harts[cpu]);
+char *isa = riscv_isa_string(>soc.cpus.harts[cpu]);
 qemu_fdt_add_subnode(fdt, nodename);
 qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
   SIFIVE_U_CLOCK_FREQ);
@@ -140,8 +140,8 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 g_free(nodename);
 }
 
-cells =  g_new0(uint32_t, s->soc.num_harts * 4);
-for (cpu = 0; cpu < s->soc.num_harts; cpu++) {
+cells =  g_new0(uint32_t, s->soc.cpus.num_harts * 4);
+for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) {
 nodename =
 g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
 uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename);
@@ -159,12 +159,12 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 0x0, memmap[SIFIVE_U_CLINT].base,
 0x0, memmap[SIFIVE_U_CLINT].size);
 qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
-cells, s->soc.num_harts * sizeof(uint32_t) * 4);
+cells, s->soc.cpus.num_harts * sizeof(uint32_t) * 4);
 g_free(cells);
 g_free(nodename);
 
-cells =  g_new0(uint32_t, s->soc.num_harts * 4);
-for (cpu = 0; cpu < s->soc.num_harts; cpu++) {
+cells =  g_new0(uint32_t, s->soc.cpus.num_harts * 4);
+for (cpu = 0; cpu < s->soc.cpus.num_harts; cpu++) {
 nodename =
 g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
 uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename);
@@ -181,7 +181,7 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0");
 qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
-cells, s->soc.num_harts * sizeof(uint32_t) * 4);
+cells, s->soc.cpus.num_harts * sizeof(uint32_t) * 4);
 qemu_fdt_setprop_cells(fdt, nodename, "reg",
 0x0, memmap[SIFIVE_U_PLIC].base,
 0x0, memmap[SIFIVE_U_PLIC].size);
@@ -217,17 +217,12 @@ static void riscv_sifive_u_init(MachineState *machine)
 SiFiveUState *s = g_new0(SiFiveUState, 1);
 MemoryRegion *system_memory = get_system_memory();
 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
-MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
 int i;
 
-/* Initialize SOC */
-object_initialize(>soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
+/* Initialize SoC */
+object_initialize(>soc, sizeof(s->soc), TYPE_RISCV_U54_SOC);
 object_property_add_child(OBJECT(machine), "soc", OBJECT(>soc),
   _abort);
-object_property_set_str(OBJECT(>soc), SIFIVE_U_CPU, "cpu-type",
-_abort);
-object_property_set_int(OBJECT(>soc), smp_cpus, "num-harts",
-_abort);
 object_property_set_bool(OBJECT(>soc), true, "realized",
 _abort);
 
@@ -235,17 +230,11 @@ static void riscv_sifive_u_init(MachineState *machine)
 memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
machine->ram_size, _fatal);
 memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base,
-main_mem);
+main_mem);
 
 /* create device tree */
 create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
 
-/* boot rom */
-memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom",
-   memmap[SIFIVE_U_MROM].size, _fatal);
-memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base,
-mask_rom);
-
 if (machine->kernel_filename) {
 load_kernel(machine->kernel_filename);
 }
@@ -284,6 +273,39 @@ static void 

[Qemu-devel] [PATCH v2 3/7] hw/riscv/sifive_plic: Use gpios instead of irqs

2018-05-11 Thread Alistair Francis
Instead of creating the interrupt in lines with qemu_allocate_irq() use
qdev_init_gpio_in() as this gives us the ability to use the qdev*gpio*()
helpers later on.

Signed-off-by: Alistair Francis 
Suggested-by: Philippe Mathieu-Daudé 
---
 hw/riscv/sifive_e.c| 5 +++--
 hw/riscv/sifive_plic.c | 6 +-
 hw/riscv/sifive_u.c| 5 +++--
 hw/riscv/virt.c| 4 ++--
 include/hw/riscv/sifive_plic.h | 1 -
 5 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 0ab5e3ca45..a0e9d500bc 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -190,13 +190,14 @@ static void riscv_sifive_e31_realize(DeviceState *dev, 
Error **errp)
 sifive_mmio_emulate(sys_mem, "riscv.sifive.e.gpio0",
 memmap[SIFIVE_E_GPIO0].base, memmap[SIFIVE_E_GPIO0].size);
 sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART0].base,
-serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART0_IRQ]);
+serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART0_IRQ));
 sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi0",
 memmap[SIFIVE_E_QSPI0].base, memmap[SIFIVE_E_QSPI0].size);
 sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm0",
 memmap[SIFIVE_E_PWM0].base, memmap[SIFIVE_E_PWM0].size);
 /* sifive_uart_create(sys_mem, memmap[SIFIVE_E_UART1].base,
-serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_E_UART1_IRQ]); */
+serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic),
+   SIFIVE_E_UART1_IRQ)); */
 sifive_mmio_emulate(sys_mem, "riscv.sifive.e.qspi1",
 memmap[SIFIVE_E_QSPI1].base, memmap[SIFIVE_E_QSPI1].size);
 sifive_mmio_emulate(sys_mem, "riscv.sifive.e.pwm1",
diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
index 874de2ebaf..a91aeb97ab 100644
--- a/hw/riscv/sifive_plic.c
+++ b/hw/riscv/sifive_plic.c
@@ -435,7 +435,6 @@ static void sifive_plic_irq_request(void *opaque, int irq, 
int level)
 static void sifive_plic_realize(DeviceState *dev, Error **errp)
 {
 SiFivePLICState *plic = SIFIVE_PLIC(dev);
-int i;
 
 memory_region_init_io(>mmio, OBJECT(dev), _plic_ops, plic,
   TYPE_SIFIVE_PLIC, plic->aperture_size);
@@ -448,10 +447,7 @@ static void sifive_plic_realize(DeviceState *dev, Error 
**errp)
 plic->claimed = g_new0(uint32_t, plic->bitfield_words);
 plic->enable = g_new0(uint32_t, plic->bitfield_words * plic->num_addrs);
 sysbus_init_mmio(SYS_BUS_DEVICE(dev), >mmio);
-plic->irqs = g_new0(qemu_irq, plic->num_sources + 1);
-for (i = 0; i <= plic->num_sources; i++) {
-plic->irqs[i] = qemu_allocate_irq(sifive_plic_irq_request, plic, i);
-}
+qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
 }
 
 static void sifive_plic_class_init(ObjectClass *klass, void *data)
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 26155e932d..d1008c42f4 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -320,9 +320,10 @@ static void riscv_sifive_u54_realize(DeviceState *dev, 
Error **errp)
 SIFIVE_U_PLIC_CONTEXT_STRIDE,
 memmap[SIFIVE_U_PLIC].size);
 sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base,
-serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]);
+serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_U_UART0_IRQ));
 /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base,
-serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART1_IRQ]); */
+serial_hd(1), qdev_get_gpio_in(DEVICE(s->plic),
+   SIFIVE_U_UART1_IRQ)); */
 sifive_clint_create(memmap[SIFIVE_U_CLINT].base,
 memmap[SIFIVE_U_CLINT].size, smp_cpus,
 SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ad03113e0f..bdd75722eb 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -379,11 +379,11 @@ static void riscv_virt_board_init(MachineState *machine)
 for (i = 0; i < VIRTIO_COUNT; i++) {
 sysbus_create_simple("virtio-mmio",
 memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size,
-SIFIVE_PLIC(s->plic)->irqs[VIRTIO_IRQ + i]);
+qdev_get_gpio_in(DEVICE(s->plic), VIRTIO_IRQ + i));
 }
 
 serial_mm_init(system_memory, memmap[VIRT_UART0].base,
-0, SIFIVE_PLIC(s->plic)->irqs[UART0_IRQ], 399193,
+0, qdev_get_gpio_in(DEVICE(s->plic), UART0_IRQ), 399193,
 serial_hd(0), DEVICE_LITTLE_ENDIAN);
 }
 
diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h
index 11a5a98df1..2f2af7e686 100644
--- a/include/hw/riscv/sifive_plic.h
+++ b/include/hw/riscv/sifive_plic.h
@@ -56,7 +56,6 @@ typedef struct SiFivePLICState {
 uint32_t *claimed;
 uint32_t *enable;
 QemuMutex lock;
-qemu_irq *irqs;
 
 /* config */
 char *hart_config;
-- 

Re: [Qemu-devel] [PATCH RFC 0/2] Fix UART serial implementation

2018-05-11 Thread no-reply
Hi,

This series failed build test on s390x host. Please find the details below.

Type: series
Message-id: 20180511205724.4039-1-cyrus...@gmail.com
Subject: [Qemu-devel] [PATCH RFC 0/2] Fix UART serial implementation

=== TEST SCRIPT BEGIN ===
#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
set -e
echo "=== ENV ==="
env
echo "=== PACKAGES ==="
rpm -qa
echo "=== TEST BEGIN ==="
CC=$HOME/bin/cc
INSTALL=$PWD/install
BUILD=$PWD/build
echo -n "Using CC: "
realpath $CC
mkdir -p $BUILD $INSTALL
SRC=$PWD
cd $BUILD
$SRC/configure --cc=$CC --prefix=$INSTALL
make -j4
# XXX: we need reliable clean up
# make check -j4 V=1
make install
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]   patchew/20180511205724.4039-1-cyrus...@gmail.com -> 
patchew/20180511205724.4039-1-cyrus...@gmail.com
Switched to a new branch 'test'
397846f288 PC Chipset: Send serial bytes at correct rate
3a85174d55 PC Chipset: Improve serial divisor calculation

=== OUTPUT BEGIN ===
=== ENV ===
LANG=en_US.UTF-8
XDG_SESSION_ID=180239
USER=fam
PWD=/var/tmp/patchew-tester-tmp-fg_kvl0a/src
HOME=/home/fam
SHELL=/bin/sh
SHLVL=2
PATCHEW=/home/fam/patchew/patchew-cli -s http://patchew.org --nodebug
LOGNAME=fam
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1012/bus
XDG_RUNTIME_DIR=/run/user/1012
PATH=/usr/bin:/bin
_=/usr/bin/env
=== PACKAGES ===
gpg-pubkey-873529b8-54e386ff
glibc-debuginfo-common-2.24-10.fc25.s390x
fedora-release-26-1.noarch
dejavu-sans-mono-fonts-2.35-4.fc26.noarch
xemacs-filesystem-21.5.34-22.20170124hgf412e9f093d4.fc26.noarch
bash-4.4.12-7.fc26.s390x
libSM-1.2.2-5.fc26.s390x
libmpc-1.0.2-6.fc26.s390x
libaio-0.3.110-7.fc26.s390x
libverto-0.2.6-7.fc26.s390x
perl-Scalar-List-Utils-1.48-1.fc26.s390x
iptables-libs-1.6.1-2.fc26.s390x
tcl-8.6.6-2.fc26.s390x
libxshmfence-1.2-4.fc26.s390x
expect-5.45-23.fc26.s390x
perl-Thread-Queue-3.12-1.fc26.noarch
perl-encoding-2.19-6.fc26.s390x
keyutils-1.5.10-1.fc26.s390x
gmp-devel-6.1.2-4.fc26.s390x
enchant-1.6.0-16.fc26.s390x
python-gobject-base-3.24.1-1.fc26.s390x
python3-enchant-1.6.10-1.fc26.noarch
python-lockfile-0.11.0-6.fc26.noarch
python2-pyparsing-2.1.10-3.fc26.noarch
python2-lxml-4.1.1-1.fc26.s390x
librados2-10.2.7-2.fc26.s390x
trousers-lib-0.3.13-7.fc26.s390x
libdatrie-0.2.9-4.fc26.s390x
libsoup-2.58.2-1.fc26.s390x
passwd-0.79-9.fc26.s390x
bind99-libs-9.9.10-3.P3.fc26.s390x
python3-rpm-4.13.0.2-1.fc26.s390x
systemd-233-7.fc26.s390x
virglrenderer-0.6.0-1.20170210git76b3da97b.fc26.s390x
s390utils-ziomon-1.36.1-3.fc26.s390x
s390utils-osasnmpd-1.36.1-3.fc26.s390x
libXrandr-1.5.1-2.fc26.s390x
libglvnd-glx-1.0.0-1.fc26.s390x
texlive-ifxetex-svn19685.0.5-33.fc26.2.noarch
texlive-psnfss-svn33946.9.2a-33.fc26.2.noarch
texlive-dvipdfmx-def-svn40328-33.fc26.2.noarch
texlive-natbib-svn20668.8.31b-33.fc26.2.noarch
texlive-xdvi-bin-svn40750-33.20160520.fc26.2.s390x
texlive-cm-svn32865.0-33.fc26.2.noarch
texlive-beton-svn15878.0-33.fc26.2.noarch
texlive-fpl-svn15878.1.002-33.fc26.2.noarch
texlive-mflogo-svn38628-33.fc26.2.noarch
texlive-texlive-docindex-svn41430-33.fc26.2.noarch
texlive-luaotfload-bin-svn34647.0-33.20160520.fc26.2.noarch
texlive-koma-script-svn41508-33.fc26.2.noarch
texlive-pst-tree-svn24142.1.12-33.fc26.2.noarch
texlive-breqn-svn38099.0.98d-33.fc26.2.noarch
texlive-xetex-svn41438-33.fc26.2.noarch
gstreamer1-plugins-bad-free-1.12.3-1.fc26.s390x
xorg-x11-font-utils-7.5-33.fc26.s390x
ghostscript-fonts-5.50-36.fc26.noarch
libXext-devel-1.3.3-5.fc26.s390x
libusbx-devel-1.0.21-2.fc26.s390x
libglvnd-devel-1.0.0-1.fc26.s390x
emacs-25.3-3.fc26.s390x
alsa-lib-devel-1.1.4.1-1.fc26.s390x
kbd-2.0.4-2.fc26.s390x
dconf-0.26.0-2.fc26.s390x
mc-4.8.19-5.fc26.s390x
doxygen-1.8.13-9.fc26.s390x
dpkg-1.18.24-1.fc26.s390x
libtdb-1.3.13-1.fc26.s390x
python2-pynacl-1.1.1-1.fc26.s390x
perl-Filter-1.58-1.fc26.s390x
python2-pip-9.0.1-11.fc26.noarch
dnf-2.7.5-2.fc26.noarch
bind-license-9.11.2-1.P1.fc26.noarch
libtasn1-4.13-1.fc26.s390x
cpp-7.3.1-2.fc26.s390x
pkgconf-1.3.12-2.fc26.s390x
python2-fedora-0.10.0-1.fc26.noarch
cmake-filesystem-3.10.1-11.fc26.s390x
python3-requests-kerberos-0.12.0-1.fc26.noarch
libmicrohttpd-0.9.59-1.fc26.s390x
GeoIP-GeoLite-data-2018.01-1.fc26.noarch
python2-libs-2.7.14-7.fc26.s390x
libidn2-2.0.4-3.fc26.s390x
p11-kit-devel-0.23.10-1.fc26.s390x
perl-Errno-1.25-396.fc26.s390x
libdrm-2.4.90-2.fc26.s390x
sssd-common-1.16.1-1.fc26.s390x
boost-random-1.63.0-11.fc26.s390x
urw-fonts-2.4-24.fc26.noarch
ccache-3.3.6-1.fc26.s390x
glibc-debuginfo-2.24-10.fc25.s390x
dejavu-fonts-common-2.35-4.fc26.noarch
bind99-license-9.9.10-3.P3.fc26.noarch
ncurses-libs-6.0-8.20170212.fc26.s390x
libpng-1.6.28-2.fc26.s390x
libICE-1.0.9-9.fc26.s390x
perl-Text-ParseWords-3.30-366.fc26.noarch
libtool-ltdl-2.4.6-17.fc26.s390x
libselinux-utils-2.6-7.fc26.s390x
userspace-rcu-0.9.3-2.fc26.s390x

Re: [Qemu-devel] [PATCH 11/42] job: Add job_delete()

2018-05-11 Thread Max Reitz
On 2018-05-09 18:26, Kevin Wolf wrote:
> This moves freeing the Job object and its fields from block_job_unref()
> to job_delete().
> 
> Signed-off-by: Kevin Wolf 
> ---
>  include/qemu/job.h | 3 +++
>  blockjob.c | 3 +--
>  job.c  | 6 ++
>  3 files changed, 10 insertions(+), 2 deletions(-)

Reviewed-by: Max Reitz 



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH 10/42] job: Add JobDriver.job_type

2018-05-11 Thread Max Reitz
On 2018-05-09 18:26, Kevin Wolf wrote:
> This moves the job_type field from BlockJobDriver to JobDriver.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  include/block/blockjob_int.h |  3 ---
>  include/qemu/job.h   | 11 +++
>  block/backup.c   |  2 +-
>  block/commit.c   |  2 +-
>  block/mirror.c   |  4 ++--
>  block/stream.c   |  2 +-
>  blockjob.c   | 16 +++-
>  job.c| 10 ++
>  8 files changed, 33 insertions(+), 17 deletions(-)
> 

[...]

> diff --git a/include/qemu/job.h b/include/qemu/job.h
> index b4b49f19e1..c87e951c8a 100644
> --- a/include/qemu/job.h
> +++ b/include/qemu/job.h

[...]

> @@ -57,4 +62,10 @@ struct JobDriver {
>   */
>  void *job_create(const char *job_id, const JobDriver *driver, Error **errp);
>  
> +/** Returns the JobType of a given Job. */
> +JobType job_type(Job *job);
> +
> +/** Returns the enum string for the JobType of a given Job. */
> +const char *job_type_str(Job *job);
> +

Is there a good reason for these not to take a const Job *?

Depending on the answer:

Reviewed-by: Max Reitz 

>  #endif



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH 09/42] job: Rename BlockJobType into JobType

2018-05-11 Thread Max Reitz
On 2018-05-09 18:26, Kevin Wolf wrote:
> QAPI types aren't externally visible, so we can rename them without
> causing problems. Before we add a job type to Job, rename the enum
> so it can be used for more than just block jobs.
> 
> Signed-off-by: Kevin Wolf 
> Reviewed-by: Eric Blake 
> ---
>  qapi/block-core.json | 14 +++---
>  include/block/blockjob_int.h |  2 +-
>  block/backup.c   |  2 +-
>  block/commit.c   |  2 +-
>  block/mirror.c   |  4 ++--
>  block/stream.c   |  2 +-
>  blockjob.c   |  6 +++---
>  7 files changed, 16 insertions(+), 16 deletions(-)

Reviewed-by: Max Reitz 



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] Requiring Python 2.7+ (was Re: [PATCH 0/3] Document intent for supported build platforms and bump min glib to 2.42)

2018-05-11 Thread Eduardo Habkost
On Fri, May 04, 2018 at 05:00:23PM +0100, Daniel P. Berrangé wrote:
[...]
> Based on that doc and https://repology.org/metapackage/glib/versions,
> I identified that we could feasibly set min glib to 2.42. Note that
> this would be dropping RHEL-6 as a build host (RHEL-6.0 came out in
> 2010 so that's reasonable to drop IMHO). It would still cover 2 major
> Debian versions and 2 most recent Ubuntu LTS (16.04, 18.04, but *not*
> 14.04). This min glib lets us remove almost all our compat code.

If we're dropping RHEL-6, is there anything else blocking us from
bumping the minimum required Python versino to 2.7?

>From the wording on patch 1/3, it looks like we will drop support
for SLES-11 too?

-- 
Eduardo



Re: [Qemu-devel] [PATCH 08/42] job: Create Job, JobDriver and job_create()

2018-05-11 Thread Max Reitz
On 2018-05-09 18:26, Kevin Wolf wrote:
> This is the first step towards creating an infrastructure for generic
> background jobs that aren't tied to a block device. For now, Job only
> stores its ID and JobDriver, the rest stays in BlockJob.
> 
> The following patches will move over more parts of BlockJob to Job if
> they are meaningful outside the context of a block job.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  include/block/blockjob.h |  9 +++
>  include/block/blockjob_int.h |  4 +--
>  include/qemu/job.h   | 60 
> 
>  block/backup.c   |  4 ++-
>  block/commit.c   |  4 ++-
>  block/mirror.c   | 10 +---
>  block/stream.c   |  4 ++-
>  blockjob.c   | 46 -
>  job.c| 48 +++
>  tests/test-bdrv-drain.c  |  4 ++-
>  tests/test-blockjob-txn.c|  4 ++-
>  tests/test-blockjob.c| 12 ++---
>  MAINTAINERS  |  2 ++
>  Makefile.objs|  2 +-
>  14 files changed, 169 insertions(+), 44 deletions(-)
>  create mode 100644 include/qemu/job.h
>  create mode 100644 job.c
> 
> diff --git a/include/block/blockjob.h b/include/block/blockjob.h
> index 0b57d53084..8acc1a236a 100644
> --- a/include/block/blockjob.h
> +++ b/include/block/blockjob.h

[...]

> @@ -40,6 +41,9 @@ typedef struct BlockJobTxn BlockJobTxn;
>   * Long-running operation on a BlockDriverState.
>   */
>  typedef struct BlockJob {
> +/** Data belonging to the generic Job infrastructure */
> +Job job;
> +
>  /** The job type, including the job vtable.  */
>  const BlockJobDriver *driver;

Any reason why you keep this field around?  Shouldn't it be just
DO_UPCAST(const BlockJobDriver, job_driver, job.driver)?

>  
> @@ -47,11 +51,6 @@ typedef struct BlockJob {
>  BlockBackend *blk;
>  
>  /**
> - * The ID of the block job. May be NULL for internal jobs.
> - */
> -char *id;
> -
> -/**
>   * The coroutine that executes the job.  If not NULL, it is
>   * reentered when busy is false and the job is cancelled.
>   */

[...]

> diff --git a/blockjob.c b/blockjob.c
> index 9943218a34..35d604d05a 100644
> --- a/blockjob.c
> +++ b/blockjob.c

[...]

> @@ -247,7 +247,7 @@ void block_job_unref(BlockJob *job)
>  block_job_detach_aio_context, job);
>  blk_unref(job->blk);
>  error_free(job->blocker);
> -g_free(job->id);
> +g_free(job->job.id);

Err.  OK.  I put my faith in patch 11.

Reviewed-by: Max Reitz 

Although I do wonder about BlockJob.driver.  It seems to stay even after
this series...

>  assert(!timer_pending(>sleep_timer));
>  g_free(job);
>  }

[...]

> diff --git a/MAINTAINERS b/MAINTAINERS
> index 459e3594e1..a97f60d104 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1369,6 +1369,8 @@ L: qemu-bl...@nongnu.org

(Cut off here:

M: Jeff Cody 

Clever!)

>  S: Supported
>  F: blockjob.c
>  F: include/block/blockjob.h
> +F: job.c
> +F: include/block/job.h
>  F: block/backup.c
>  F: block/commit.c
>  F: block/stream.c



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [RFC 00/10] [TESTING NEEDED] python: futurize --stage1 (Python 3 compatibility)

2018-05-11 Thread no-reply
Hi,

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

Type: series
Message-id: 20180511222052.8734-1-ehabk...@redhat.com
Subject: [Qemu-devel] [RFC 00/10] [TESTING NEEDED] python: futurize --stage1 
(Python 3 compatibility)

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 t [tag update]patchew/20180510204148.11687-1-babu.mo...@amd.com -> 
patchew/20180510204148.11687-1-babu.mo...@amd.com
 * [new tag]   patchew/20180511222052.8734-1-ehabk...@redhat.com -> 
patchew/20180511222052.8734-1-ehabk...@redhat.com
Switched to a new branch 'test'
29e77f7e45 python: futurize -f lib2to3.fixes.fix_numliterals
06044c1048 python: futurize -f lib2to3.fixes.fix_except
aecdedee26 python: futurize -f lib2to3.fixes.fix_renames
2be7292f53 python: futurize -f lib2to3.fixes.fix_tuple_params
0b3e5f083c python: futurize -f lib2to3.fixes.fix_reduce
6d7a39f3c6 python: futurize -f lib2to3.fixes.fix_standarderror
0c8beeea09 python: futurize -f lib2to3.fixes.fix_has_key
4f0075d69d python: futurize -f libfuturize.fixes.fix_next_call
66698bae73 python: futurize -f libfuturize.fixes.fix_absolute_import
b48c4f449d python: futurize -f libfuturize.fixes.fix_print_with_import

=== OUTPUT BEGIN ===
Checking PATCH 1/10: python: futurize -f 
libfuturize.fixes.fix_print_with_import...
ERROR: line over 90 characters
#40: FILE: scripts/analyse-9p-simpletrace.py:86:
+print("RERROR (tag =", tag, ", id =", symbol_9p[id], ", err = 
\"", os.strerror(err), "\")")

ERROR: line over 90 characters
#44: FILE: scripts/analyse-9p-simpletrace.py:89:
+print("TVERSION (tag =", tag, ", msize =", msize, ", version 
=", version, ")")

ERROR: line over 90 characters
#48: FILE: scripts/analyse-9p-simpletrace.py:92:
+print("RVERSION (tag =", tag, ", msize =", msize, ", version 
=", version, ")")

ERROR: line over 90 characters
#52: FILE: scripts/analyse-9p-simpletrace.py:95:
+print("TATTACH (tag =", tag, ", fid =", fid, ", afid =", afid, 
", uname =", uname, ", aname =", aname, ")")

ERROR: line over 90 characters
#56: FILE: scripts/analyse-9p-simpletrace.py:98:
+print("RATTACH (tag =", tag, ", qid={type =", type, ", version 
=", version, ", path =", path, "})")

ERROR: line over 90 characters
#64: FILE: scripts/analyse-9p-simpletrace.py:104:
+print("RSTAT (tag =", tag, ", mode =", mode, ", atime =", 
atime, ", mtime =", mtime, ", length =", length, ")")

ERROR: line over 90 characters
#68: FILE: scripts/analyse-9p-simpletrace.py:107:
+print("TGETATTR (tag =", tag, ", fid =", fid, ", request_mask 
=", hex(request_mask), ")")

ERROR: line over 90 characters
#72: FILE: scripts/analyse-9p-simpletrace.py:110:
+print("RGETATTR (tag =", tag, ", result_mask =", 
hex(result_mask), ", mode =", oct(mode), ", uid =", uid, ", gid =", gid, ")")

ERROR: line over 90 characters
#76: FILE: scripts/analyse-9p-simpletrace.py:113:
+print("TWALK (tag =", tag, ", fid =", fid, ", newfid =", 
newfid, ", nwnames =", nwnames, ")")

ERROR: line over 90 characters
#80: FILE: scripts/analyse-9p-simpletrace.py:116:
+print("RWALK (tag =", tag, ", nwnames =", nwnames, ", qids =", 
hex(qids), ")")

WARNING: line over 80 characters
#84: FILE: scripts/analyse-9p-simpletrace.py:119:
+print("TOPEN (tag =", tag, ", fid =", fid, ", mode =", 
oct(mode), ")")

ERROR: line over 90 characters
#88: FILE: scripts/analyse-9p-simpletrace.py:122:
+print("ROPEN (tag =", tag,  ", qid={type =", type, ", version 
=", version, ", path =", path, "}, iounit =", iounit, ")")

ERROR: line over 90 characters
#92: FILE: scripts/analyse-9p-simpletrace.py:125:
+print("TLCREATE (tag =", tag, ", dfid =", dfid, ", flags =", 
oct(flags), ", mode =", oct(mode), ", gid =", gid, ")")

ERROR: line over 90 characters
#96: FILE: scripts/analyse-9p-simpletrace.py:128:
+print("RLCREATE (tag =", tag,  ", qid={type =", type, ", 
version =", version, ", path =", path, "}, iounit =", iounit, ")")

WARNING: line over 80 characters
#100: FILE: scripts/analyse-9p-simpletrace.py:131:
+print("TFSYNC (tag =", tag, ", fid =", fid, ", datasync =", 
datasync, ")")

ERROR: line over 90 characters
#108: FILE: scripts/analyse-9p-simpletrace.py:137:
+

[Qemu-devel] [PATCH RFC 0/2] Fix UART serial implementation

2018-05-11 Thread Calvin Lee
Hello,

While developing a serial implementation for my OS, I found several bugs
in QEMU's serial device. I confirmed (by testing on my x64 laptop) that
there are several inconsistancies between QEMU and hardware in this
regard. For both patches, I used "http://www.sci.muni.cz/docs/pc/serport.txt;
for reference.

First, QEMU has several errors for setting the UART divisor that are
fixed in my first patch. Second, (and more importantly) QEMU does not
transmit serial bytes at the correct rate, and this is fixed in my
second patch.

I have neither contributed to QEMU nor sent patches to a mailing list
before, so I marked this patch-series as RFC. I would appreciate any
comments you have. Also, I am not very confident in VM migration between
versions, so I would appreciate if someone could help me make sure this
is correct in my patches.

Much thanks,
Calvin Lee

Calvin Lee (2):
  PC Chipset: Improve serial divisor calculation
  PC Chipset: Send serial bytes at correct rate

 hw/char/serial.c | 70 +++-
 include/hw/char/serial.h |  2 ++
 2 files changed, 56 insertions(+), 16 deletions(-)

-- 
2.17.0




Re: [Qemu-devel] [PATCH 07/42] blockjob: Remove block_job_pause/resume_all()

2018-05-11 Thread Max Reitz
On 2018-05-09 18:26, Kevin Wolf wrote:
> Commit 81193349 removed the only use of block_job_pause/resume_all(),
> which was in bdrv_drain_all(). The functions are now unused and can be
> removed.

I have a strange liking for all-digit commit hash prefixes.

> Signed-off-by: Kevin Wolf 
> ---
>  include/block/blockjob_int.h | 14 --
>  blockjob.c   | 27 ---
>  2 files changed, 41 deletions(-)

Reviewed-by: Max Reitz 



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH 01/42] blockjob: Fix assertion in block_job_finalize()

2018-05-11 Thread John Snow


On 05/09/2018 12:25 PM, Kevin Wolf wrote:
> Every job gets a non-NULL job->txn on creation, but it doesn't
> necessarily keep it until it is decommissioned: Finalising a job removes
> it from its transaction. Therefore, calling 'blockdev-job-finalize' a
> second time on an already concluded job causes an assertion failure.
> 
> Remove job->txn from the assertion in block_job_finalize() to fix this.
> block_job_do_finalize() still has the same assertion, but if a job is
> already removed from its transaction, block_job_apply_verb() will
> already error out before we run into that assertion.
> 
> Signed-off-by: Kevin Wolf 

Reviewed-by: John Snow 

> ---
>  blockjob.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/blockjob.c b/blockjob.c
> index 4de48166b2..b38ed7e265 100644
> --- a/blockjob.c
> +++ b/blockjob.c
> @@ -702,7 +702,7 @@ void block_job_complete(BlockJob *job, Error **errp)
>  
>  void block_job_finalize(BlockJob *job, Error **errp)
>  {
> -assert(job && job->id && job->txn);
> +assert(job && job->id);
>  if (block_job_apply_verb(job, BLOCK_JOB_VERB_FINALIZE, errp)) {
>  return;
>  }
> 

Oh, ack. Good catch.



[Qemu-devel] [PATCH RFC 1/2] PC Chipset: Improve serial divisor calculation

2018-05-11 Thread Calvin Lee
This fixes several problems I found in the UART serial implementation.
Now all divisor values are allowed, while before divisor values of zero
and below the base baud rate were rejected. All changes are in reference
to http://www.sci.muni.cz/docs/pc/serport.txt

Signed-off-by: Calvin Lee 
---
I included a slight code-style change in this commit because it seemed
close enough to the code I was editing to be relevant. If not, I can
change the commit to not include this change.

 hw/char/serial.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/hw/char/serial.c b/hw/char/serial.c
index 2c080c9862..4159a46a2f 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -150,13 +150,10 @@ static void serial_update_irq(SerialState *s)
 
 static void serial_update_parameters(SerialState *s)
 {
-int speed, parity, data_bits, stop_bits, frame_size;
+float speed;
+int parity, data_bits, stop_bits, frame_size;
 QEMUSerialSetParams ssp;
 
-if (s->divider == 0 || s->divider > s->baudbase) {
-return;
-}
-
 /* Start bit. */
 frame_size = 1;
 if (s->lcr & 0x08) {
@@ -169,14 +166,16 @@ static void serial_update_parameters(SerialState *s)
 } else {
 parity = 'N';
 }
-if (s->lcr & 0x04)
+if (s->lcr & 0x04) {
 stop_bits = 2;
-else
+} else {
 stop_bits = 1;
+}
 
 data_bits = (s->lcr & 0x03) + 5;
 frame_size += data_bits + stop_bits;
-speed = s->baudbase / s->divider;
+/* Zero divisor should give about 3500 baud */
+speed = (s->divider == 0) ? 3500 : (float) s->baudbase / s->divider;
 ssp.speed = speed;
 ssp.parity = parity;
 ssp.data_bits = data_bits;
@@ -184,7 +183,7 @@ static void serial_update_parameters(SerialState *s)
 s->char_transmit_time =  (NANOSECONDS_PER_SECOND / speed) * frame_size;
 qemu_chr_fe_ioctl(>chr, CHR_IOCTL_SERIAL_SET_PARAMS, );
 
-DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
+DPRINTF("speed=%.2f parity=%c data=%d stop=%d\n",
speed, parity, data_bits, stop_bits);
 }
 
@@ -341,7 +340,11 @@ static void serial_ioport_write(void *opaque, hwaddr addr, 
uint64_t val,
 default:
 case 0:
 if (s->lcr & UART_LCR_DLAB) {
-s->divider = (s->divider & 0xff00) | val;
+if (size == 2) {
+s->divider = (s->divider & 0xff00) | val;
+} else if (size == 4) {
+s->divider = val;
+}
 serial_update_parameters(s);
 } else {
 s->thr = (uint8_t) val;
-- 
2.17.0




Re: [Qemu-devel] [PATCH 06/42] blockjob: Add block_job_driver()

2018-05-11 Thread Max Reitz
On 2018-05-09 18:26, Kevin Wolf wrote:
> The backup block job directly accesses the driver field in BlockJob. Add
> a wrapper for getting it.
> 
> Signed-off-by: Kevin Wolf 
> Reviewed-by: Eric Blake 
> ---
>  include/block/blockjob.h | 7 +++
>  block/backup.c   | 8 +---
>  blockjob.c   | 5 +
>  3 files changed, 17 insertions(+), 3 deletions(-)

Reviewed-by: Max Reitz 



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [RFC 07/10] python: futurize -f lib2to3.fixes.fix_tuple_params

2018-05-11 Thread Eduardo Habkost
Remove implicit tuple parameter unpacking.

This is necessary for Python 3 compatibility.

Done using:

  $ py=$( (g grep -l -E '^#!.*python';find -name '*.py' -printf '%P\n';) | \
sort -u | grep -v README.sh4)
  $ futurize -w -f lib2to3.fixes.fix_tuple_params $py

Signed-off-by: Eduardo Habkost 
---
 scripts/analyse-locks-simpletrace.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/analyse-locks-simpletrace.py 
b/scripts/analyse-locks-simpletrace.py
index 352bc9c22d..30090bdfff 100755
--- a/scripts/analyse-locks-simpletrace.py
+++ b/scripts/analyse-locks-simpletrace.py
@@ -78,7 +78,7 @@ if __name__ == '__main__':
 
 # Now dump the individual lock stats
 for key, val in sorted(analyser.mutex_records.iteritems(),
-   key=lambda (k,v): v["locks"]):
+   key=lambda k_v: k_v[1]["locks"]):
 print ("Lock: %#x locks: %d, locked: %d, unlocked: %d" %
(key, val["locks"], val["locked"], val["unlocked"]))
 
-- 
2.14.3




  1   2   3   >