* [PATCH v9 2/4] x86/elf: use HWCAP2 to expose ring 3 MWAIT
From: Grzegorz Andrejczuk @ 2016-11-09 13:46 UTC (permalink / raw)
To: tglx, mingo, hpa, x86
Cc: bp, dave.hansen, lukasz.daniluk, james.h.cownie, jacob.jun.pan,
Piotr.Luc, linux-kernel, Grzegorz Andrejczuk
In-Reply-To: <1478699194-30946-1-git-send-email-grzegorz.andrejczuk@intel.com>
Add HWCAP2 for x86 and reserve its bit 0 to expose
ring 3 mwait.
Signed-off-by: Grzegorz Andrejczuk <grzegorz.andrejczuk@intel.com>
---
arch/x86/include/asm/elf.h | 9 +++++++++
arch/x86/include/uapi/asm/hwcap2.h | 7 +++++++
arch/x86/kernel/cpu/common.c | 3 +++
3 files changed, 19 insertions(+)
create mode 100644 arch/x86/include/uapi/asm/hwcap2.h
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index e7f155c..59703aa 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -258,6 +258,15 @@ extern int force_personality32;
#define ELF_HWCAP (boot_cpu_data.x86_capability[CPUID_1_EDX])
+extern unsigned int elf_hwcap2;
+
+/*
+ * HWCAP2 supplies mask with kernel enabled CPU features, so that
+ * the application can discover that it can safely use them.
+ * The bits are defined in uapi/asm/hwcap2.h.
+ */
+#define ELF_HWCAP2 elf_hwcap2
+
/* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in
intent than poking at uname or /proc/cpuinfo.
diff --git a/arch/x86/include/uapi/asm/hwcap2.h b/arch/x86/include/uapi/asm/hwcap2.h
new file mode 100644
index 0000000..116cab3
--- /dev/null
+++ b/arch/x86/include/uapi/asm/hwcap2.h
@@ -0,0 +1,7 @@
+#ifndef _ASM_X86_HWCAP2_H
+#define _ASM_X86_HWCAP2_H
+
+/* Kernel enabled Ring 3 MONITOR/MWAIT*/
+#define HWCAP2_RING3MWAIT (1 << 0)
+
+#endif
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index bcc9ccc..fdbf708 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -35,6 +35,7 @@
#include <asm/desc.h>
#include <asm/fpu/internal.h>
#include <asm/mtrr.h>
+#include <asm/hwcap2.h>
#include <linux/numa.h>
#include <asm/asm.h>
#include <asm/bugs.h>
@@ -51,6 +52,8 @@
#include "cpu.h"
+unsigned int elf_hwcap2 __read_mostly;
+
/* all of these masks are initialized in setup_cpu_local_masks() */
cpumask_var_t cpu_initialized_mask;
cpumask_var_t cpu_callout_mask;
--
2.5.1
^ permalink raw reply related
* [Qemu-devel] [PATCH v2 0/5] target-m68k-patches
From: Richard Henderson @ 2016-11-09 13:46 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent
Changes since v1:
* Tweaked local variable decls for movem.
* Fixed the bitfield patches such that they work with linux-user-test-0.3.
(Along with the whole passle of extra patches required to make that work.)
The register bitfield patch still depends on the patches posted
here in another thread implementing extract and sextract.
r~
Laurent Vivier (1):
target-m68k: Implement 680x0 movem
Richard Henderson (4):
target-m68k: Do not cpu_abort on undefined insns
target-m68k: Inline shifts
target-m68k: Implement bitfield ops for registers
target-m68k: Implement bitfield ops for memory
target-m68k/cpu.h | 1 +
target-m68k/helper.c | 52 ----
target-m68k/helper.h | 10 +-
target-m68k/op_helper.c | 185 +++++++++++++
target-m68k/translate.c | 702 ++++++++++++++++++++++++++++++++++++++++++++----
5 files changed, 843 insertions(+), 107 deletions(-)
--
2.7.4
^ permalink raw reply
* [Qemu-devel] [PATCH v2 2/5] target-m68k: Do not cpu_abort on undefined insns
From: Richard Henderson @ 2016-11-09 13:46 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent
In-Reply-To: <1478699171-10637-1-git-send-email-rth@twiddle.net>
Report this properly via exception and, importantly, allow
the disassembler the chance to tell us what insn is not handled.
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-m68k/translate.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index ca99072..4f224d7 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1577,10 +1577,12 @@ DISAS_INSN(undef_fpu)
DISAS_INSN(undef)
{
- M68kCPU *cpu = m68k_env_get_cpu(env);
-
+ /* ??? This is both instructions that are as yet unimplemented
+ for the 680x0 series, as well as those that are implemented
+ but actually illegal for CPU32 or pre-68020. */
+ qemu_log_mask(LOG_UNIMP, "Illegal instruction: %04x @ %08x",
+ insn, s->pc - 2);
gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
- cpu_abort(CPU(cpu), "Illegal instruction: %04x @ %08x", insn, s->pc - 2);
}
DISAS_INSN(mulw)
--
2.7.4
^ permalink raw reply related
* [Qemu-devel] [PATCH v2 1/5] target-m68k: Implement 680x0 movem
From: Richard Henderson @ 2016-11-09 13:46 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent
In-Reply-To: <1478699171-10637-1-git-send-email-rth@twiddle.net>
From: Laurent Vivier <laurent@vivier.eu>
680x0 movem can load/store words and long words and can use more
addressing modes. Coldfire can only use long words with (Ax) and
(d16,Ax) addressing modes.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-m68k/translate.c | 130 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 107 insertions(+), 23 deletions(-)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 5d91e4e..ca99072 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1793,40 +1793,122 @@ static void gen_push(DisasContext *s, TCGv val)
tcg_gen_mov_i32(QREG_SP, tmp);
}
+static TCGv mreg(int reg)
+{
+ if (reg < 8) {
+ /* Dx */
+ return cpu_dregs[reg];
+ }
+ /* Ax */
+ return cpu_aregs[reg & 7];
+}
+
DISAS_INSN(movem)
{
- TCGv addr;
+ TCGv addr, incr, tmp, r[16];
+ int is_load = (insn & 0x0400) != 0;
+ int opsize = (insn & 0x40) != 0 ? OS_LONG : OS_WORD;
+ uint16_t mask = read_im16(env, s);
+ int mode = extract32(insn, 3, 3);
+ int reg0 = REG(insn, 0);
int i;
- uint16_t mask;
- TCGv reg;
- TCGv tmp;
- int is_load;
- mask = read_im16(env, s);
- tmp = gen_lea(env, s, insn, OS_LONG);
- if (IS_NULL_QREG(tmp)) {
+ tmp = cpu_aregs[reg0];
+
+ switch (mode) {
+ case 0: /* data register direct */
+ case 1: /* addr register direct */
+ do_addr_fault:
gen_addr_fault(s);
return;
+
+ case 2: /* indirect */
+ break;
+
+ case 3: /* indirect post-increment */
+ if (!is_load) {
+ /* post-increment is not allowed */
+ goto do_addr_fault;
+ }
+ break;
+
+ case 4: /* indirect pre-decrement */
+ if (is_load) {
+ /* pre-decrement is not allowed */
+ goto do_addr_fault;
+ }
+ /* We want a bare copy of the address reg, without any pre-decrement
+ adjustment, as gen_lea would provide. */
+ break;
+
+ default:
+ tmp = gen_lea_mode(env, s, mode, reg0, opsize);
+ if (IS_NULL_QREG(tmp)) {
+ goto do_addr_fault;
+ }
+ break;
}
+
addr = tcg_temp_new();
tcg_gen_mov_i32(addr, tmp);
- is_load = ((insn & 0x0400) != 0);
- for (i = 0; i < 16; i++, mask >>= 1) {
- if (mask & 1) {
- if (i < 8)
- reg = DREG(i, 0);
- else
- reg = AREG(i, 0);
- if (is_load) {
- tmp = gen_load(s, OS_LONG, addr, 0);
- tcg_gen_mov_i32(reg, tmp);
- } else {
- gen_store(s, OS_LONG, addr, reg);
+ incr = tcg_const_i32(opsize_bytes(opsize));
+
+ if (is_load) {
+ /* memory to register */
+ for (i = 0; i < 16; i++) {
+ if (mask & (1 << i)) {
+ r[i] = gen_load(s, opsize, addr, 1);
+ tcg_gen_add_i32(addr, addr, incr);
+ }
+ }
+ for (i = 0; i < 16; i++) {
+ if (mask & (1 << i)) {
+ tcg_gen_mov_i32(mreg(i), r[i]);
+ tcg_temp_free(r[i]);
+ }
+ }
+ if (mode == 3) {
+ /* post-increment: movem (An)+,X */
+ tcg_gen_mov_i32(cpu_aregs[reg0], addr);
+ }
+ } else {
+ /* register to memory */
+ if (mode == 4) {
+ /* pre-decrement: movem X,-(An) */
+ for (i = 15; i >= 0; i--) {
+ if ((mask << i) & 0x8000) {
+ tcg_gen_sub_i32(addr, addr, incr);
+ if (reg0 + 8 == i &&
+ m68k_feature(s->env, M68K_FEATURE_EXT_FULL)) {
+ /* M68020+: if the addressing register is the
+ * register moved to memory, the value written
+ * is the initial value decremented by the size of
+ * the operation, regardless of how many actual
+ * stores have been performed until this point.
+ * M68000/M68010: the value is the initial value.
+ */
+ tmp = tcg_temp_new();
+ tcg_gen_sub_i32(tmp, cpu_aregs[reg0], incr);
+ gen_store(s, opsize, addr, tmp);
+ tcg_temp_free(tmp);
+ } else {
+ gen_store(s, opsize, addr, mreg(i));
+ }
+ }
+ }
+ tcg_gen_mov_i32(cpu_aregs[reg0], addr);
+ } else {
+ for (i = 0; i < 16; i++) {
+ if (mask & (1 << i)) {
+ gen_store(s, opsize, addr, mreg(i));
+ tcg_gen_add_i32(addr, addr, incr);
+ }
}
- if (mask != 1)
- tcg_gen_addi_i32(addr, addr, 4);
}
}
+
+ tcg_temp_free(incr);
+ tcg_temp_free(addr);
}
DISAS_INSN(bitop_im)
@@ -4029,7 +4111,9 @@ void register_m68k_insns (CPUM68KState *env)
BASE(pea, 4840, ffc0);
BASE(swap, 4840, fff8);
INSN(bkpt, 4848, fff8, BKPT);
- BASE(movem, 48c0, fbc0);
+ INSN(movem, 48d0, fbf8, CF_ISA_A);
+ INSN(movem, 48e8, fbf8, CF_ISA_A);
+ INSN(movem, 4880, fb80, M68000);
BASE(ext, 4880, fff8);
BASE(ext, 48c0, fff8);
BASE(ext, 49c0, fff8);
--
2.7.4
^ permalink raw reply related
* [PATCH v9 3/4] x86/cpufeature: add RING3MWAIT to CPU features
From: Grzegorz Andrejczuk @ 2016-11-09 13:46 UTC (permalink / raw)
To: tglx, mingo, hpa, x86
Cc: bp, dave.hansen, lukasz.daniluk, james.h.cownie, jacob.jun.pan,
Piotr.Luc, linux-kernel, Grzegorz Andrejczuk
In-Reply-To: <1478699194-30946-1-git-send-email-grzegorz.andrejczuk@intel.com>
Add Intel Xeon Phi x200 (KnightsLanding) CPU feature - ring 3 MONITOR/MWAIT.
Signed-off-by: Grzegorz Andrejczuk <grzegorz.andrejczuk@intel.com>
---
arch/x86/include/asm/cpufeatures.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 92a8308..5b7f701 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -100,7 +100,7 @@
#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */
#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */
-/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
+#define X86_FEATURE_RING3MWAIT ( 3*32+25) /* ring 3 MONITOR/MWAIT */
#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */
#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
--
2.5.1
^ permalink raw reply related
* [Qemu-devel] [PATCH v2 3/5] target-m68k: Inline shifts
From: Richard Henderson @ 2016-11-09 13:46 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent
In-Reply-To: <1478699171-10637-1-git-send-email-rth@twiddle.net>
Also manage word and byte operands and fix the computation of
overflow in the case of M68000 arithmetic shifts.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-m68k/helper.c | 52 ------------
target-m68k/helper.h | 3 -
target-m68k/translate.c | 214 ++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 189 insertions(+), 80 deletions(-)
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 60fe997..25d5dc1 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -320,58 +320,6 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
m68k_switch_sp(env);
}
-uint32_t HELPER(shl_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
- uint64_t result;
-
- shift &= 63;
- result = (uint64_t)val << shift;
-
- env->cc_c = (result >> 32) & 1;
- env->cc_n = result;
- env->cc_z = result;
- env->cc_v = 0;
- env->cc_x = shift ? env->cc_c : env->cc_x;
-
- return result;
-}
-
-uint32_t HELPER(shr_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
- uint64_t temp;
- uint32_t result;
-
- shift &= 63;
- temp = (uint64_t)val << 32 >> shift;
- result = temp >> 32;
-
- env->cc_c = (temp >> 31) & 1;
- env->cc_n = result;
- env->cc_z = result;
- env->cc_v = 0;
- env->cc_x = shift ? env->cc_c : env->cc_x;
-
- return result;
-}
-
-uint32_t HELPER(sar_cc)(CPUM68KState *env, uint32_t val, uint32_t shift)
-{
- uint64_t temp;
- uint32_t result;
-
- shift &= 63;
- temp = (int64_t)val << 32 >> shift;
- result = temp >> 32;
-
- env->cc_c = (temp >> 31) & 1;
- env->cc_n = result;
- env->cc_z = result;
- env->cc_v = result ^ val;
- env->cc_x = shift ? env->cc_c : env->cc_x;
-
- return result;
-}
-
/* MAC unit. */
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
take values, others take register numbers and manipulate the contents
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index 226ef5f..cae5bcb 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -7,9 +7,6 @@ DEF_HELPER_4(divul, void, env, int, int, i32)
DEF_HELPER_4(divsl, void, env, int, int, s32)
DEF_HELPER_4(divull, void, env, int, int, i32)
DEF_HELPER_4(divsll, void, env, int, int, s32)
-DEF_HELPER_3(shl_cc, i32, env, i32, i32)
-DEF_HELPER_3(shr_cc, i32, env, i32, i32)
-DEF_HELPER_3(sar_cc, i32, env, i32, i32)
DEF_HELPER_2(set_sr, void, env, i32)
DEF_HELPER_3(movec, void, env, i32, i32)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 4f224d7..1b3765f 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2883,48 +2883,205 @@ DISAS_INSN(addx_mem)
gen_store(s, opsize, addr_dest, QREG_CC_N);
}
-/* TODO: This could be implemented without helper functions. */
-DISAS_INSN(shift_im)
+static inline void shift_im(DisasContext *s, uint16_t insn, int opsize)
{
- TCGv reg;
- int tmp;
- TCGv shift;
+ int count = (insn >> 9) & 7;
+ int logical = insn & 8;
+ int left = insn & 0x100;
+ int bits = opsize_bytes(opsize) * 8;
+ TCGv reg = gen_extend(DREG(insn, 0), opsize, !logical);
+
+ if (count == 0) {
+ count = 8;
+ }
+
+ tcg_gen_movi_i32(QREG_CC_V, 0);
+ if (left) {
+ tcg_gen_shri_i32(QREG_CC_C, reg, bits - count);
+ tcg_gen_shli_i32(QREG_CC_N, reg, count);
+
+ /* Note that ColdFire always clears V (done above),
+ while M68000 sets if the most significant bit is changed at
+ any time during the shift operation */
+ if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+ /* if shift count >= bits, V is (reg != 0) */
+ if (count >= bits) {
+ tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V);
+ } else {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_sari_i32(QREG_CC_V, reg, bits - 1);
+ tcg_gen_sari_i32(t0, t0, bits - count);
+ tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, QREG_CC_V, t0);
+ tcg_temp_free(t0);
+ }
+ tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
+ }
+ } else {
+ tcg_gen_shri_i32(QREG_CC_C, reg, count - 1);
+ if (logical) {
+ tcg_gen_shri_i32(QREG_CC_N, reg, count);
+ } else {
+ tcg_gen_sari_i32(QREG_CC_N, reg, count);
+ }
+ }
+
+ gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
+ tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
+ tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+ tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
+ gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
set_cc_op(s, CC_OP_FLAGS);
+}
- reg = DREG(insn, 0);
- tmp = (insn >> 9) & 7;
- if (tmp == 0)
- tmp = 8;
- shift = tcg_const_i32(tmp);
- /* No need to flush flags becuse we know we will set C flag. */
- if (insn & 0x100) {
- gen_helper_shl_cc(reg, cpu_env, reg, shift);
+static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize)
+{
+ int logical = insn & 8;
+ int left = insn & 0x100;
+ int bits = opsize_bytes(opsize) * 8;
+ TCGv reg = gen_extend(DREG(insn, 0), opsize, !logical);
+ TCGv s32;
+ TCGv_i64 t64, s64;
+
+ t64 = tcg_temp_new_i64();
+ s64 = tcg_temp_new_i64();
+ s32 = tcg_temp_new();
+
+ /* Note that m68k truncates the shift count modulo 64, not 32.
+ In addition, a 64-bit shift makes it easy to find "the last
+ bit shifted out", for the carry flag. */
+ tcg_gen_andi_i32(s32, DREG(insn, 9), 63);
+ tcg_gen_extu_i32_i64(s64, s32);
+ tcg_gen_extu_i32_i64(t64, reg);
+
+ /* Optimistically set V=0. Also used as a zero source below. */
+ tcg_gen_movi_i32(QREG_CC_V, 0);
+ if (left) {
+ tcg_gen_shl_i64(t64, t64, s64);
+
+ tcg_gen_extr_i64_i32(QREG_CC_N, QREG_CC_C, t64);
+
+ /* Note that C=0 if shift count is 0, and we get that for free. */
+ tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
+
+ /* X = C, but only if the shift count was non-zero. */
+ tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
+ QREG_CC_C, QREG_CC_X);
+
+ /* M68000 sets V if the most significant bit is changed at
+ * any time during the shift operation. Do this via creating
+ * an extension of the sign bit, comparing, and discarding
+ * the bits below the sign bit. I.e.
+ * int64_t s = (intN_t)reg;
+ * int64_t t = (int64_t)(intN_t)reg << count;
+ * V = ((s ^ t) & (-1 << (bits - 1))) != 0
+ */
+ if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+ /* Sign extend the input to 64 bits; re-do the shift. */
+ tcg_gen_ext_i32_i64(t64, reg);
+ tcg_gen_shl_i64(s64, t64, s64);
+ /* Clear all bits that are unchanged. */
+ tcg_gen_xor_i64(t64, t64, s64);
+ /* Ignore the bits below the sign bit. */
+ tcg_gen_andi_i64(t64, t64, -1ULL << (bits - 1));
+ /* If any bits remain set, we have overflow. */
+ tcg_gen_setcondi_i64(TCG_COND_NE, t64, t64, 0);
+ tcg_gen_extrl_i64_i32(QREG_CC_V, t64);
+ tcg_gen_neg_i32(QREG_CC_V, QREG_CC_V);
+ }
} else {
- if (insn & 8) {
- gen_helper_shr_cc(reg, cpu_env, reg, shift);
+ tcg_gen_shli_i64(t64, t64, 32);
+ if (logical) {
+ tcg_gen_shr_i64(t64, t64, s64);
} else {
- gen_helper_sar_cc(reg, cpu_env, reg, shift);
+ tcg_gen_sar_i64(t64, t64, s64);
}
+ tcg_gen_extr_i64_i32(QREG_CC_C, QREG_CC_N, t64);
+
+ /* Note that C=0 if shift count is 0, and we get that for free. */
+ tcg_gen_shri_i32(QREG_CC_C, QREG_CC_C, 31);
+
+ /* X = C, but only if the shift count was non-zero. */
+ tcg_gen_movcond_i32(TCG_COND_NE, QREG_CC_X, s32, QREG_CC_V,
+ QREG_CC_C, QREG_CC_X);
}
+ gen_ext(QREG_CC_N, QREG_CC_N, opsize, 1);
+ tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+
+ tcg_temp_free(s32);
+ tcg_temp_free_i64(s64);
+ tcg_temp_free_i64(t64);
+
+ /* Write back the result. */
+ gen_partset_reg(opsize, DREG(insn, 0), QREG_CC_N);
+ set_cc_op(s, CC_OP_FLAGS);
+}
+
+DISAS_INSN(shift8_im)
+{
+ shift_im(s, insn, OS_BYTE);
+}
+
+DISAS_INSN(shift16_im)
+{
+ shift_im(s, insn, OS_WORD);
+}
+
+DISAS_INSN(shift_im)
+{
+ shift_im(s, insn, OS_LONG);
+}
+
+DISAS_INSN(shift8_reg)
+{
+ shift_reg(s, insn, OS_BYTE);
+}
+
+DISAS_INSN(shift16_reg)
+{
+ shift_reg(s, insn, OS_WORD);
}
DISAS_INSN(shift_reg)
{
- TCGv reg;
- TCGv shift;
+ shift_reg(s, insn, OS_LONG);
+}
- reg = DREG(insn, 0);
- shift = DREG(insn, 9);
- if (insn & 0x100) {
- gen_helper_shl_cc(reg, cpu_env, reg, shift);
+DISAS_INSN(shift_mem)
+{
+ int logical = insn & 8;
+ int left = insn & 0x100;
+ TCGv src;
+ TCGv addr;
+
+ SRC_EA(env, src, OS_WORD, !logical, &addr);
+ tcg_gen_movi_i32(QREG_CC_V, 0);
+ if (left) {
+ tcg_gen_shri_i32(QREG_CC_C, src, 15);
+ tcg_gen_shli_i32(QREG_CC_N, src, 1);
+
+ /* Note that ColdFire always clears V,
+ while M68000 sets if the most significant bit is changed at
+ any time during the shift operation */
+ if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) {
+ src = gen_extend(src, OS_WORD, 1);
+ tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src);
+ }
} else {
- if (insn & 8) {
- gen_helper_shr_cc(reg, cpu_env, reg, shift);
+ tcg_gen_mov_i32(QREG_CC_C, src);
+ if (logical) {
+ tcg_gen_shri_i32(QREG_CC_N, src, 1);
} else {
- gen_helper_sar_cc(reg, cpu_env, reg, shift);
+ tcg_gen_sari_i32(QREG_CC_N, src, 1);
}
}
+
+ gen_ext(QREG_CC_N, QREG_CC_N, OS_WORD, 1);
+ tcg_gen_andi_i32(QREG_CC_C, QREG_CC_C, 1);
+ tcg_gen_mov_i32(QREG_CC_Z, QREG_CC_N);
+ tcg_gen_mov_i32(QREG_CC_X, QREG_CC_C);
+
+ DEST_EA(env, insn, OS_WORD, QREG_CC_N, &addr);
set_cc_op(s, CC_OP_FLAGS);
}
@@ -4208,6 +4365,13 @@ void register_m68k_insns (CPUM68KState *env)
INSN(adda, d0c0, f0c0, M68000);
INSN(shift_im, e080, f0f0, CF_ISA_A);
INSN(shift_reg, e0a0, f0f0, CF_ISA_A);
+ INSN(shift8_im, e000, f0f0, M68000);
+ INSN(shift16_im, e040, f0f0, M68000);
+ INSN(shift_im, e080, f0f0, M68000);
+ INSN(shift8_reg, e020, f0f0, M68000);
+ INSN(shift16_reg, e060, f0f0, M68000);
+ INSN(shift_reg, e0a0, f0f0, M68000);
+ INSN(shift_mem, e0c0, fcc0, M68000);
INSN(undef_fpu, f000, f000, CF_ISA_A);
INSN(fpu, f200, ffc0, CF_FPU);
INSN(fbcc, f280, ff80, CF_FPU);
--
2.7.4
^ permalink raw reply related
* [Qemu-devel] [PATCH v2 4/5] target-m68k: Implement bitfield ops for registers
From: Richard Henderson @ 2016-11-09 13:46 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent
In-Reply-To: <1478699171-10637-1-git-send-email-rth@twiddle.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-m68k/translate.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 210 insertions(+)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 1b3765f..be59c37 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3085,6 +3085,210 @@ DISAS_INSN(shift_mem)
set_cc_op(s, CC_OP_FLAGS);
}
+DISAS_INSN(bfext_reg)
+{
+ int ext = read_im16(env, s);
+ int is_sign = insn & 0x200;
+ TCGv src = DREG(insn, 0);
+ TCGv dst = DREG(ext, 12);
+ int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
+ int ofs = extract32(ext, 6, 5); /* big bit-endian */
+ int pos = 32 - ofs - len; /* little bit-endian */
+ TCGv tmp = tcg_temp_new();
+ TCGv shift;
+
+ /* In general, we're going to rotate the field so that it's at the
+ top of the word and then right-shift by the compliment of the
+ width to extend the field. */
+ if (ext & 0x20) {
+ /* Variable width. */
+ if (ext & 0x800) {
+ /* Variable offset. */
+ tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
+ tcg_gen_rotl_i32(tmp, src, tmp);
+ } else {
+ tcg_gen_rotli_i32(tmp, src, ofs);
+ }
+
+ shift = tcg_temp_new();
+ tcg_gen_neg_i32(shift, DREG(ext, 0));
+ tcg_gen_andi_i32(shift, shift, 31);
+ tcg_gen_sar_i32(QREG_CC_N, tmp, shift);
+ if (is_sign) {
+ tcg_gen_mov_i32(dst, QREG_CC_N);
+ } else {
+ tcg_gen_shr_i32(dst, tmp, shift);
+ }
+ tcg_temp_free(shift);
+ } else {
+ /* Immediate width. */
+ if (ext & 0x800) {
+ /* Variable offset */
+ tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
+ tcg_gen_rotl_i32(tmp, src, tmp);
+ src = tmp;
+ pos = 32 - len;
+ } else {
+ /* Immediate offset. If the field doesn't wrap around the
+ end of the word, rely on (s)extract completely. */
+ if (pos < 0) {
+ tcg_gen_rotli_i32(tmp, src, ofs);
+ src = tmp;
+ pos = 32 - len;
+ }
+ }
+
+ tcg_gen_sextract_i32(QREG_CC_N, src, pos, len);
+ if (is_sign) {
+ tcg_gen_mov_i32(dst, QREG_CC_N);
+ } else {
+ tcg_gen_extract_i32(dst, src, pos, len);
+ }
+ }
+
+ tcg_temp_free(tmp);
+ set_cc_op(s, CC_OP_LOGIC);
+}
+
+DISAS_INSN(bfop_reg)
+{
+ int ext = read_im16(env, s);
+ TCGv src = DREG(insn, 0);
+ int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
+ int ofs = extract32(ext, 6, 5); /* big bit-endian */
+ TCGv mask;
+
+ if ((ext & 0x820) == 0) {
+ /* Immediate width and offset. */
+ uint32_t maski = 0x7fffffffu >> (len - 1);
+ if (ofs + len <= 32) {
+ tcg_gen_shli_i32(QREG_CC_N, src, ofs);
+ } else {
+ tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
+ }
+ tcg_gen_andi_i32(QREG_CC_N, QREG_CC_N, ~maski);
+ mask = tcg_const_i32(ror32(maski, ofs));
+ } else {
+ TCGv tmp = tcg_temp_new();
+ if (ext & 0x20) {
+ /* Variable width */
+ tcg_gen_subi_i32(tmp, DREG(ext, 0), 1);
+ tcg_gen_andi_i32(tmp, tmp, 31);
+ mask = tcg_const_i32(0x7fffffffu);
+ tcg_gen_shr_i32(mask, mask, tmp);
+ } else {
+ /* Immediate width */
+ mask = tcg_const_i32(0x7fffffffu >> (len - 1));
+ }
+ if (ext & 0x800) {
+ /* Variable offset */
+ tcg_gen_andi_i32(tmp, DREG(ext, 6), 31);
+ tcg_gen_rotl_i32(QREG_CC_N, src, tmp);
+ tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
+ tcg_gen_rotr_i32(mask, mask, tmp);
+ } else {
+ /* Immediate offset (and variable width) */
+ tcg_gen_rotli_i32(QREG_CC_N, src, ofs);
+ tcg_gen_andc_i32(QREG_CC_N, QREG_CC_N, mask);
+ tcg_gen_rotri_i32(mask, mask, ofs);
+ }
+ tcg_temp_free(tmp);
+ }
+ set_cc_op(s, CC_OP_LOGIC);
+
+ switch (insn & 0x0f00) {
+ case 0x0a00: /* bfchg */
+ tcg_gen_eqv_i32(src, src, mask);
+ break;
+ case 0x0c00: /* bfclr */
+ tcg_gen_and_i32(src, src, mask);
+ break;
+ case 0x0e00: /* bfset */
+ tcg_gen_orc_i32(src, src, mask);
+ break;
+ case 0x0800: /* bftst */
+ /* flags already set; no other work to do. */
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ tcg_temp_free(mask);
+}
+
+DISAS_INSN(bfins_reg)
+{
+ int ext = read_im16(env, s);
+ TCGv dst = DREG(insn, 0);
+ TCGv src = DREG(ext, 12);
+ int len = ((extract32(ext, 0, 5) - 1) & 31) + 1;
+ int ofs = extract32(ext, 6, 5); /* big bit-endian */
+ int pos = 32 - ofs - len; /* little bit-endian */
+ TCGv tmp;
+
+ tmp = tcg_temp_new();
+
+ if (ext & 0x20) {
+ /* Variable width */
+ tcg_gen_neg_i32(tmp, DREG(ext, 0));
+ tcg_gen_andi_i32(tmp, tmp, 31);
+ tcg_gen_shl_i32(QREG_CC_N, src, tmp);
+ } else {
+ /* Immediate width */
+ tcg_gen_shli_i32(QREG_CC_N, src, 32 - len);
+ }
+ set_cc_op(s, CC_OP_LOGIC);
+
+ /* Immediate width and offset */
+ if ((ext & 0x820) == 0) {
+ /* Check for suitability for deposit. */
+ if (pos >= 0) {
+ tcg_gen_deposit_i32(dst, dst, src, pos, len);
+ } else {
+ uint32_t maski = -2U << (len - 1);
+ uint32_t roti = (ofs + len) & 31;
+ tcg_gen_andi_i32(tmp, src, maski);
+ tcg_gen_rotri_i32(tmp, tmp, roti);
+ tcg_gen_andi_i32(dst, dst, ror32(maski, roti));
+ tcg_gen_or_i32(dst, dst, tmp);
+ }
+ } else {
+ TCGv mask = tcg_temp_new();
+ TCGv rot = tcg_temp_new();
+
+ if (ext & 0x20) {
+ /* Variable width */
+ tcg_gen_subi_i32(rot, DREG(ext, 0), 1);
+ tcg_gen_andi_i32(rot, rot, 31);
+ tcg_gen_movi_i32(mask, -2);
+ tcg_gen_shl_i32(mask, mask, rot);
+ tcg_gen_mov_i32(rot, DREG(ext, 0));
+ tcg_gen_andc_i32(tmp, src, mask);
+ } else {
+ /* Immediate width (variable offset) */
+ uint32_t maski = -2U << (len - 1);
+ tcg_gen_andi_i32(tmp, src, ~maski);
+ tcg_gen_movi_i32(mask, maski);
+ tcg_gen_movi_i32(rot, len & 31);
+ }
+ if (ext & 0x800) {
+ /* Variable offset */
+ tcg_gen_add_i32(rot, rot, DREG(ext, 6));
+ } else {
+ /* Immediate offset (variable width) */
+ tcg_gen_addi_i32(rot, rot, ofs);
+ }
+ tcg_gen_andi_i32(rot, rot, 31);
+ tcg_gen_rotr_i32(mask, mask, rot);
+ tcg_gen_rotr_i32(tmp, tmp, rot);
+ tcg_gen_and_i32(dst, dst, mask);
+ tcg_gen_or_i32(dst, dst, tmp);
+
+ tcg_temp_free(rot);
+ tcg_temp_free(mask);
+ }
+ tcg_temp_free(tmp);
+}
+
DISAS_INSN(ff1)
{
TCGv reg;
@@ -4372,6 +4576,12 @@ void register_m68k_insns (CPUM68KState *env)
INSN(shift16_reg, e060, f0f0, M68000);
INSN(shift_reg, e0a0, f0f0, M68000);
INSN(shift_mem, e0c0, fcc0, M68000);
+ INSN(bfext_reg, e9c0, fdf8, BITFIELD); /* bfextu & bfexts */
+ INSN(bfins_reg, efc0, fff8, BITFIELD);
+ INSN(bfop_reg, eac0, fff8, BITFIELD); /* bfchg */
+ INSN(bfop_reg, ecc0, fff8, BITFIELD); /* bfclr */
+ INSN(bfop_reg, eec0, fff8, BITFIELD); /* bfset */
+ INSN(bfop_reg, e8c0, fff8, BITFIELD); /* bftst */
INSN(undef_fpu, f000, f000, CF_ISA_A);
INSN(fpu, f200, ffc0, CF_FPU);
INSN(fbcc, f280, ff80, CF_FPU);
--
2.7.4
^ permalink raw reply related
* [Qemu-devel] [PATCH v2 5/5] target-m68k: Implement bitfield ops for memory
From: Richard Henderson @ 2016-11-09 13:46 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent
In-Reply-To: <1478699171-10637-1-git-send-email-rth@twiddle.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-m68k/cpu.h | 1 +
target-m68k/helper.h | 7 ++
target-m68k/op_helper.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++
target-m68k/translate.c | 142 ++++++++++++++++++++++++++++++++++++-
4 files changed, 333 insertions(+), 2 deletions(-)
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 7c119ba..0b63c0a 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -37,6 +37,7 @@
#define OS_DOUBLE 4
#define OS_EXTENDED 5
#define OS_PACKED 6
+#define OS_UNSIZED 7
#define MAX_QREGS 32
diff --git a/target-m68k/helper.h b/target-m68k/helper.h
index cae5bcb..301b7d1 100644
--- a/target-m68k/helper.h
+++ b/target-m68k/helper.h
@@ -77,3 +77,10 @@ DEF_HELPER_2(flush_flags, void, env, i32)
DEF_HELPER_2(set_ccr, void, env, i32)
DEF_HELPER_FLAGS_1(get_ccr, TCG_CALL_NO_WG_SE, i32, env)
DEF_HELPER_2(raise_exception, void, env, i32)
+
+DEF_HELPER_FLAGS_4(bfexts_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
+DEF_HELPER_FLAGS_4(bfextu_mem, TCG_CALL_NO_WG, i64, env, i32, s32, i32)
+DEF_HELPER_FLAGS_5(bfins_mem, TCG_CALL_NO_WG, i32, env, i32, i32, s32, i32)
+DEF_HELPER_FLAGS_4(bfchg_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
+DEF_HELPER_FLAGS_4(bfclr_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
+DEF_HELPER_FLAGS_4(bfset_mem, TCG_CALL_NO_WG, i32, env, i32, s32, i32)
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index a4bfa4e..77d1f58 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -359,3 +359,188 @@ void HELPER(divsll)(CPUM68KState *env, int numr, int regr, int32_t den)
env->dregs[regr] = rem;
env->dregs[numr] = quot;
}
+
+struct bf_data {
+ uint32_t addr;
+ uint32_t bofs;
+ uint32_t blen;
+ uint32_t len;
+};
+
+static struct bf_data bf_prep(uint32_t addr, int32_t ofs, uint32_t len)
+{
+ int bofs, blen;
+
+ /* Bound length; map 0 to 32. */
+ len = ((len - 1) & 31) + 1;
+
+ /* Note that ofs is signed. */
+ addr += ofs / 8;
+ bofs = ofs % 8;
+ if (bofs < 0) {
+ bofs += 8;
+ addr -= 1;
+ }
+
+ /* Compute the number of bytes required (minus one) to
+ satisfy the bitfield. */
+ blen = (bofs + len - 1) / 8;
+
+ /* Canonicalize the bit offset for data loaded into a 64-bit big-endian
+ word. For the cases where BLEN is not a power of 2, adjust ADDR so
+ that we can use the next power of two sized load without crossing a
+ page boundary, unless the field itself crosses the boundary. */
+ switch (blen) {
+ case 0:
+ bofs += 56;
+ break;
+ case 1:
+ bofs += 48;
+ break;
+ case 2:
+ if (addr & 1) {
+ bofs += 8;
+ addr -= 1;
+ }
+ /* fallthru */
+ case 3:
+ bofs += 32;
+ break;
+ case 4:
+ if (addr & 3) {
+ bofs += 8 * (addr & 3);
+ addr &= -4;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return (struct bf_data){
+ .addr = addr,
+ .bofs = bofs,
+ .blen = blen,
+ .len = len,
+ };
+}
+
+static uint64_t bf_load(CPUM68KState *env, uint32_t addr, int blen,
+ uintptr_t ra)
+{
+ switch (blen) {
+ case 0:
+ return cpu_ldub_data_ra(env, addr, ra);
+ case 1:
+ return cpu_lduw_data_ra(env, addr, ra);
+ case 2:
+ case 3:
+ return cpu_ldl_data_ra(env, addr, ra);
+ case 4:
+ return cpu_ldq_data_ra(env, addr, ra);
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void bf_store(CPUM68KState *env, uint32_t addr, int blen,
+ uint64_t data, uintptr_t ra)
+{
+ switch (blen) {
+ case 0:
+ cpu_stb_data_ra(env, addr, data, ra);
+ break;
+ case 1:
+ cpu_stw_data_ra(env, addr, data, ra);
+ break;
+ case 2:
+ case 3:
+ cpu_stl_data_ra(env, addr, data, ra);
+ break;
+ case 4:
+ cpu_stq_data_ra(env, addr, data, ra);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+uint32_t HELPER(bfexts_mem)(CPUM68KState *env, uint32_t addr,
+ int32_t ofs, uint32_t len)
+{
+ uintptr_t ra = GETPC();
+ struct bf_data d = bf_prep(addr, ofs, len);
+ uint64_t data = bf_load(env, d.addr, d.blen, ra);
+
+ return (int64_t)(data << d.bofs) >> (64 - len);
+}
+
+uint64_t HELPER(bfextu_mem)(CPUM68KState *env, uint32_t addr,
+ int32_t ofs, uint32_t len)
+{
+ uintptr_t ra = GETPC();
+ struct bf_data d = bf_prep(addr, ofs, len);
+ uint64_t data = bf_load(env, d.addr, d.blen, ra);
+
+ /* Put CC_N at the top of the high word; put the zero-extended value
+ at the bottom of the low word. */
+ data <<= d.bofs;
+ data >>= 64 - d.len;
+ data |= data << (64 - d.len);
+
+ return data;
+}
+
+uint32_t HELPER(bfins_mem)(CPUM68KState *env, uint32_t addr, uint32_t val,
+ int32_t ofs, uint32_t len)
+{
+ uintptr_t ra = GETPC();
+ struct bf_data d = bf_prep(addr, ofs, len);
+ uint64_t data = bf_load(env, d.addr, d.blen, ra);
+ uint64_t mask = -1ull << (64 - d.len) >> d.bofs;
+
+ data = (data & ~mask) | (((uint64_t)val << (64 - d.len)) >> d.bofs);
+
+ bf_store(env, d.addr, d.blen, data, ra);
+
+ /* The field at the top of the word is also CC_N for CC_OP_LOGIC. */
+ return val << (32 - d.len);
+}
+
+uint32_t HELPER(bfchg_mem)(CPUM68KState *env, uint32_t addr,
+ int32_t ofs, uint32_t len)
+{
+ uintptr_t ra = GETPC();
+ struct bf_data d = bf_prep(addr, ofs, len);
+ uint64_t data = bf_load(env, d.addr, d.blen, ra);
+ uint64_t mask = -1ull << (64 - d.len) >> d.bofs;
+
+ bf_store(env, d.addr, d.blen, data ^ mask, ra);
+
+ return ((data & mask) << d.bofs) >> 32;
+}
+
+uint32_t HELPER(bfclr_mem)(CPUM68KState *env, uint32_t addr,
+ int32_t ofs, uint32_t len)
+{
+ uintptr_t ra = GETPC();
+ struct bf_data d = bf_prep(addr, ofs, len);
+ uint64_t data = bf_load(env, d.addr, d.blen, ra);
+ uint64_t mask = -1ull << (64 - d.len) >> d.bofs;
+
+ bf_store(env, d.addr, d.blen, data & ~mask, ra);
+
+ return ((data & mask) << d.bofs) >> 32;
+}
+
+uint32_t HELPER(bfset_mem)(CPUM68KState *env, uint32_t addr,
+ int32_t ofs, uint32_t len)
+{
+ uintptr_t ra = GETPC();
+ struct bf_data d = bf_prep(addr, ofs, len);
+ uint64_t data = bf_load(env, d.addr, d.blen, ra);
+ uint64_t mask = -1ull << (64 - d.len) >> d.bofs;
+
+ bf_store(env, d.addr, d.blen, data | mask, ra);
+
+ return ((data & mask) << d.bofs) >> 32;
+}
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index be59c37..61d9681 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -752,10 +752,17 @@ static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
case 0: /* Data register direct. */
case 1: /* Address register direct. */
return NULL_QREG;
- case 2: /* Indirect register */
case 3: /* Indirect postincrement. */
+ if (opsize == OS_UNSIZED) {
+ return NULL_QREG;
+ }
+ /* fallthru */
+ case 2: /* Indirect register */
return get_areg(s, reg0);
case 4: /* Indirect predecrememnt. */
+ if (opsize == OS_UNSIZED) {
+ return NULL_QREG;
+ }
reg = get_areg(s, reg0);
tmp = tcg_temp_new();
tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize));
@@ -3150,6 +3157,49 @@ DISAS_INSN(bfext_reg)
set_cc_op(s, CC_OP_LOGIC);
}
+DISAS_INSN(bfext_mem)
+{
+ int ext = read_im16(env, s);
+ int is_sign = insn & 0x200;
+ TCGv dest = DREG(ext, 12);
+ TCGv addr, len, ofs;
+
+ addr = gen_lea(env, s, insn, OS_UNSIZED);
+ if (IS_NULL_QREG(addr)) {
+ gen_addr_fault(s);
+ return;
+ }
+
+ if (ext & 0x20) {
+ len = DREG(ext, 0);
+ } else {
+ len = tcg_const_i32(extract32(ext, 0, 5));
+ }
+ if (ext & 0x800) {
+ ofs = DREG(ext, 6);
+ } else {
+ ofs = tcg_const_i32(extract32(ext, 6, 5));
+ }
+
+ if (is_sign) {
+ gen_helper_bfexts_mem(dest, cpu_env, addr, ofs, len);
+ tcg_gen_mov_i32(QREG_CC_N, dest);
+ } else {
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ gen_helper_bfextu_mem(tmp, cpu_env, addr, ofs, len);
+ tcg_gen_extr_i64_i32(dest, QREG_CC_N, tmp);
+ tcg_temp_free_i64(tmp);
+ }
+ set_cc_op(s, CC_OP_LOGIC);
+
+ if (!(ext & 0x20)) {
+ tcg_temp_free(len);
+ }
+ if (!(ext & 0x800)) {
+ tcg_temp_free(ofs);
+ }
+}
+
DISAS_INSN(bfop_reg)
{
int ext = read_im16(env, s);
@@ -3215,6 +3265,54 @@ DISAS_INSN(bfop_reg)
tcg_temp_free(mask);
}
+DISAS_INSN(bfop_mem)
+{
+ int ext = read_im16(env, s);
+ TCGv addr, len, ofs;
+
+ addr = gen_lea(env, s, insn, OS_UNSIZED);
+ if (IS_NULL_QREG(addr)) {
+ gen_addr_fault(s);
+ return;
+ }
+
+ if (ext & 0x20) {
+ len = DREG(ext, 0);
+ } else {
+ len = tcg_const_i32(extract32(ext, 0, 5));
+ }
+ if (ext & 0x800) {
+ ofs = DREG(ext, 6);
+ } else {
+ ofs = tcg_const_i32(extract32(ext, 6, 5));
+ }
+
+ switch (insn & 0x0f00) {
+ case 0x0a00: /* bfchg */
+ gen_helper_bfchg_mem(QREG_CC_N, cpu_env, addr, ofs, len);
+ break;
+ case 0x0c00: /* bfclr */
+ gen_helper_bfclr_mem(QREG_CC_N, cpu_env, addr, ofs, len);
+ break;
+ case 0x0e00: /* bfset */
+ gen_helper_bfset_mem(QREG_CC_N, cpu_env, addr, ofs, len);
+ break;
+ case 0x0800: /* bftst */
+ gen_helper_bfexts_mem(QREG_CC_N, cpu_env, addr, ofs, len);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ set_cc_op(s, CC_OP_LOGIC);
+
+ if (!(ext & 0x20)) {
+ tcg_temp_free(len);
+ }
+ if (!(ext & 0x800)) {
+ tcg_temp_free(ofs);
+ }
+}
+
DISAS_INSN(bfins_reg)
{
int ext = read_im16(env, s);
@@ -3289,6 +3387,40 @@ DISAS_INSN(bfins_reg)
tcg_temp_free(tmp);
}
+DISAS_INSN(bfins_mem)
+{
+ int ext = read_im16(env, s);
+ TCGv src = DREG(ext, 12);
+ TCGv addr, len, ofs;
+
+ addr = gen_lea(env, s, insn, OS_UNSIZED);
+ if (IS_NULL_QREG(addr)) {
+ gen_addr_fault(s);
+ return;
+ }
+
+ if (ext & 0x20) {
+ len = DREG(ext, 0);
+ } else {
+ len = tcg_const_i32(extract32(ext, 0, 5));
+ }
+ if (ext & 0x800) {
+ ofs = DREG(ext, 6);
+ } else {
+ ofs = tcg_const_i32(extract32(ext, 6, 5));
+ }
+
+ gen_helper_bfins_mem(QREG_CC_N, cpu_env, addr, src, ofs, len);
+ set_cc_op(s, CC_OP_LOGIC);
+
+ if (!(ext & 0x20)) {
+ tcg_temp_free(len);
+ }
+ if (!(ext & 0x800)) {
+ tcg_temp_free(ofs);
+ }
+}
+
DISAS_INSN(ff1)
{
TCGv reg;
@@ -4576,11 +4708,17 @@ void register_m68k_insns (CPUM68KState *env)
INSN(shift16_reg, e060, f0f0, M68000);
INSN(shift_reg, e0a0, f0f0, M68000);
INSN(shift_mem, e0c0, fcc0, M68000);
- INSN(bfext_reg, e9c0, fdf8, BITFIELD); /* bfextu & bfexts */
+ INSN(bfext_mem, e9c0, fdc0, BITFIELD); /* bfextu & bfexts */
+ INSN(bfext_reg, e9c0, fdf8, BITFIELD);
+ INSN(bfins_mem, efc0, ffc0, BITFIELD);
INSN(bfins_reg, efc0, fff8, BITFIELD);
+ INSN(bfop_mem, eac0, ffc0, BITFIELD); /* bfchg */
INSN(bfop_reg, eac0, fff8, BITFIELD); /* bfchg */
+ INSN(bfop_mem, ecc0, ffc0, BITFIELD); /* bfclr */
INSN(bfop_reg, ecc0, fff8, BITFIELD); /* bfclr */
+ INSN(bfop_mem, eec0, ffc0, BITFIELD); /* bfset */
INSN(bfop_reg, eec0, fff8, BITFIELD); /* bfset */
+ INSN(bfop_mem, e8c0, ffc0, BITFIELD); /* bftst */
INSN(bfop_reg, e8c0, fff8, BITFIELD); /* bftst */
INSN(undef_fpu, f000, f000, CF_ISA_A);
INSN(fpu, f200, ffc0, CF_FPU);
--
2.7.4
^ permalink raw reply related
* [PATCH v9 4/4] x86/cpufeatures: handle RING3MWAIT on Xeon Phi models
From: Grzegorz Andrejczuk @ 2016-11-09 13:46 UTC (permalink / raw)
To: tglx, mingo, hpa, x86
Cc: bp, dave.hansen, lukasz.daniluk, james.h.cownie, jacob.jun.pan,
Piotr.Luc, linux-kernel, Grzegorz Andrejczuk
In-Reply-To: <1478699194-30946-1-git-send-email-grzegorz.andrejczuk@intel.com>
Unfortunately presence of this feature cannot be detected
automatically (by reading some other MSR) therefore it is required
to do explicit check for the family and model of the cpu.
If processor is Intel Xeon Phi x200 RING 3 MONITOR/MWAIT feature is enabled
by setting cpu cap X86_FEATURE_RING3MWAIT and elf HWCAP2_RING3MWAIT.
Signed-off-by: Grzegorz Andrejczuk <grzegorz.andrejczuk@intel.com>
---
Documentation/kernel-parameters.txt | 6 +++++
Documentation/x86/x86_64/boot-options.txt | 5 ++++
arch/x86/kernel/cpu/intel.c | 39 +++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index a4f4d69..4683cc1 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3120,6 +3120,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
pg. [PARIDE]
See Documentation/blockdev/paride.txt.
+ phir3mwait= [X86-64] Disable ring 3 MONITOR/MWAIT on Intel Xeon Phi
+ codenamed Knight Landing cpus.
+ It has no effect on cpus other than Intel Xeon Phi.
+ Format: { disable }
+ See Documentation/x86/x86_64/boot-options.txt
+
pirq= [SMP,APIC] Manual mp-table setup
See Documentation/x86/i386/IO-APIC.txt.
diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt
index 0965a71..1a515e8 100644
--- a/Documentation/x86/x86_64/boot-options.txt
+++ b/Documentation/x86/x86_64/boot-options.txt
@@ -281,6 +281,11 @@ Debugging
kstack=N Print N words from the kernel stack in oops dumps.
+ phir3mwait=disable
+ Disables unconditional setting bit 1 of the MSR_MISC_FEATURE_ENABLES
+ for Intel Xeon Phi, this way administrator can switch off ring 3 mwait
+ feature.
+
Miscellaneous
nogbpages
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index fcd484d..3bfc8e5 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -14,6 +14,8 @@
#include <asm/bugs.h>
#include <asm/cpu.h>
#include <asm/intel-family.h>
+#include <asm/hwcap2.h>
+#include <asm/elf.h>
#ifdef CONFIG_X86_64
#include <linux/topology.h>
@@ -61,6 +63,41 @@ void check_mpx_erratum(struct cpuinfo_x86 *c)
}
}
+#ifdef CONFIG_X86_64
+static int phi_r3mwait_disabled __read_mostly;
+
+static int __init phir3mwait_disable(char *__unused)
+{
+ phi_r3mwait_disabled = 1;
+ return 1;
+}
+__setup("phir3mwait=disable", phir3mwait_disable);
+
+static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c)
+{
+ /*
+ * Ring 3 MONITOR/MWAIT feature cannot be detected without
+ * cpu model and family comparison.
+ */
+ if (c->x86 != 6 || c->x86_model != INTEL_FAM6_XEON_PHI_KNL)
+ return;
+
+ if (phi_r3mwait_disabled) {
+ msr_clear_bit(MSR_MISC_FEATURE_ENABLES,
+ MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT);
+ return;
+ }
+
+ msr_set_bit(MSR_MISC_FEATURE_ENABLES,
+ MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT);
+ set_cpu_cap(c, X86_FEATURE_RING3MWAIT);
+ ELF_HWCAP2 |= HWCAP2_RING3MWAIT;
+}
+
+#else
+static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *__unused) {}
+#endif
+
static void early_init_intel(struct cpuinfo_x86 *c)
{
u64 misc_enable;
@@ -565,6 +602,8 @@ static void init_intel(struct cpuinfo_x86 *c)
detect_vmx_virtcap(c);
init_intel_energy_perf(c);
+
+ probe_xeon_phi_r3mwait(c);
}
#ifdef CONFIG_X86_32
--
2.5.1
^ permalink raw reply related
* Re: [PATCH] t6026-merge-attr: don't fail if sleep exits early
From: Johannes Schindelin @ 2016-11-09 13:47 UTC (permalink / raw)
To: Jeff King; +Cc: Andreas Schwab, Johannes Sixt, git
In-Reply-To: <20161108200543.7ivo3xoafdl4uw6h@sigill.intra.peff.net>
Hi
On Tue, 8 Nov 2016, Jeff King wrote:
> On Tue, Nov 08, 2016 at 06:03:04PM +0100, Andreas Schwab wrote:
>
> > Commit 5babb5bdb3 ("t6026-merge-attr: clean up background process at end
> > of test case") added a kill command to clean up after the test, but this
> > can fail if the sleep command exits before the cleanup is executed.
> > Ignore the error from the kill command.
> >
> > Signed-off-by: Andreas Schwab <schwab@suse.de>
> > ---
> > The failure can be simulated by adding a sleep after the last command to
> > delay the cleanup.
>
> Thanks for the reproduction hint. I sometimes run the test suite through
> a "stress" script that sees if a test script racily fails under load,
> but I wasn't able to trigger it here (I guess a full second is just too
> long even under high load). But the extra sleep makes it obvious.
>
> Looks like the original is in v2.10.1, so this should probably go to
> maint, as well as the upcoming v2.11-rc1.
The reason why we do not ignore kill errors is that we want to make sure
that the script *actually ran*. Otherwise, the thing we need to test here
does not necessarily get tested.
So I would rather go with the patch Hannes hinted at when he said that he
did not want to change the file name (as it would have made the diff less
obvious): increase the number of seconds.
Will send out a superseding patch in a minute,
Dscho
^ permalink raw reply
* RE: [PATCH xf86-video-ati] Reindent code in radeon_dri2_create_buffer2
From: Deucher, Alexander @ 2016-11-09 13:48 UTC (permalink / raw)
To: 'Michel Dänzer',
amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
In-Reply-To: <20161109070454.23007-1-michel-otUistvHUpPR7s880joybQ@public.gmane.org>
> -----Original Message-----
> From: amd-gfx [mailto:amd-gfx-bounces@lists.freedesktop.org] On Behalf
> Of Michel Dänzer
> Sent: Wednesday, November 09, 2016 2:05 AM
> To: amd-gfx@lists.freedesktop.org
> Subject: [PATCH xf86-video-ati] Reindent code in
> radeon_dri2_create_buffer2
>
> From: Michel Dänzer <michel.daenzer@amd.com>
>
> Fixes warning about misleading indentation from recent versions of gcc:
>
> ../../src/radeon_dri2.c: In function ‘radeon_dri2_create_buffer2’:
> ../../src/radeon_dri2.c:224:2: warning: this ‘if’ clause does not guard... [-
> Wmisleading-indentation]
> if (flags & RADEON_CREATE_PIXMAP_TILING_MACRO)
> ^~
> ../../src/radeon_dri2.c:227:6: note: ...this statement, but the latter is
> misleadingly indented as if it is guarded by the ‘if’
> if (aligned_width == front_width)
> ^~
>
> No functional change intended.
>
> Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
> ---
> src/radeon_dri2.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
> index 1206b2a..8112670 100644
> --- a/src/radeon_dri2.c
> +++ b/src/radeon_dri2.c
> @@ -224,14 +224,14 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
> if (flags & RADEON_CREATE_PIXMAP_TILING_MACRO)
> tiling |= RADEON_TILING_MACRO;
>
> - if (aligned_width == front_width)
> - aligned_width = pScrn->virtualX;
> -
> - pixmap = (*pScreen->CreatePixmap)(pScreen,
> - aligned_width,
> - height,
> - depth,
> - flags |
> RADEON_CREATE_PIXMAP_DRI2);
> + if (aligned_width == front_width)
> + aligned_width = pScrn->virtualX;
> +
> + pixmap = (*pScreen->CreatePixmap)(pScreen,
> + aligned_width,
> + height,
> + depth,
> + flags |
> RADEON_CREATE_PIXMAP_DRI2);
> }
>
> buffers = calloc(1, sizeof *buffers);
> --
> 2.10.2
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
^ permalink raw reply
* Re: [Qemu-devel] [PATCH] hw/input/hid: support alternative sysrq/break scancodes for gtk-vnc
From: Gerd Hoffmann @ 2016-11-09 13:49 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: berrange, qemu-devel
In-Reply-To: <20161028145132.1702-1-peter@korsgaard.com>
Hi,
> Now, it isn't obvious to me which sequence is really "right", but as the
> 0x54/0xc6 keycodes are currently unused in hid.c, supporting both seems like
> the pragmatic solution to me. The USB HID keyboard boot protocol used by
> hid.c doesn't have any other mapping applicable to these keys.
>
> The other guest keyboard interfaces (ps/2, virtio, ..) are not affected,
> because they handle these keys differently.
A better fix would be to switch hid.c to use Q_KEY_CODE_* too.
Patches doing that are welcome. It's a big change though and not
reasonable to do during the freeze, so I'll go pick up this two-line fix
for 2.8 nevertheless.
thanks,
Gerd
^ permalink raw reply
* Re: [PATCH 0/5] wic: bugfixes & --fixed-size support
From: Maciej Borzęcki @ 2016-11-09 13:49 UTC (permalink / raw)
To: Burton, Ross; +Cc: Maciej Borzecki, OE-core
In-Reply-To: <CAJTo0LaARkjM1C1D=k_NdoCRy5ivQdnbT+C_X-7WnnpnuQN0Ew@mail.gmail.com>
On Wed, Nov 9, 2016 at 2:17 PM, Burton, Ross <ross.burton@intel.com> wrote:
> I pulled this series into a test run on the autobuilder and it is throwing
> quite a lot of exceptions, such as:
>
> Traceback (most recent call last):
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/wic",
> line 319, in <module>
> sys.exit(main(sys.argv[1:]))
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/wic",
> line 314, in main
> return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage,
> subcommands)
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/lib/wic/help.py",
> line 95, in invoke_subcommand
> subcommands.get(args[0], subcommand_error)[0](args[1:], usage)
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/wic",
> line 247, in wic_create_subcommand
> options.compressor, options.bmap, options.debug)
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/lib/wic/engine.py",
> line 195, in wic_create
> crobj.main(cmdline)
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/lib/wic/creator.py",
> line 125, in main
> return self._subcmds[pname](options, *args[1:])
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/lib/wic/plugins/imager/direct_plugin.py",
> line 93, in do_create
> creator.create()
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/lib/wic/imager/baseimager.py",
> line 159, in create
> self._create()
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/lib/wic/imager/direct.py",
> line 305, in _create
> system_id=part.system_id)
> File
> "/home/pokybuild/yocto-autobuilder/yocto-worker/nightly-x86-64-lsb/build/scripts/lib/wic/utils/partitionedfs.py",
> line 101, in add_partition
> size = size * 1024 // self.sector_size
> TypeError: unsupported operand type(s) for //: 'str' and 'int'
> WARNING:
> TOPDIR/tmp/work/genericx86_64-poky-linux/core-image-lsb/1.0-r0/temp/run.do_image_wic.15783:1
> exit 1 from 'BUILDDIR="TOPDIR" wic create "$wks" --vars
> "TOPDIR/tmp/sysroots/genericx86-64/imgdata/" -e "core-image-lsb" -o "$out/"'
>
> See
> http://errors.yoctoproject.org/Errors/Latest/Autobuilder/?filter=a44a6a635c9ed02edb2a3dee0a13b0067becc425&type=commit
> for more examples and context.
Thanks. I see now that bootimg-efi and rawcopy plugins do not convert partition
size to int as they should be.
>
> Ross
>
> On 8 November 2016 at 15:56, Maciej Borzecki <maciej.borzecki@rndity.com>
> wrote:
>>
>> The patch series is a follow-up after a previous attempt of adding
>> --reserved-size option to wic[1].
>>
>> The series introduces a number of fixes in patches 1 - 4.
>>
>> The last patch in the series introduces --fixed-size option as discussed
>> in [1].
>> The patch also introduces minor refactoring to code responsible for
>> computing
>> partition size.
>>
>> Aside from new option, another user-visible change is how the size rootfs
>> partitions with vfat is calculated. In previous code, vfat rootfs
>> partition size
>> did not account for --extra-space nor --overhead-factor. Now, all rootfs
>> partitions (except for squashfs) are subject to the same rules of
>> partition
>> sizing.
>>
>>
>> http://lists.openembedded.org/pipermail/openembedded-core/2016-October/127634.html
>>
>> Maciej Borzecki (5):
>> wic: make sure that partition size is always an integer in internal
>> processing
>> wic: use partition size when creating empty partition files
>> wic: check that filesystem is specified for a rootfs partition
>> wic: fix function comment typos
>> wic: add --fixed-size wks option
>>
>> scripts/lib/wic/help.py | 14 +++--
>> scripts/lib/wic/imager/direct.py | 2 +-
>> scripts/lib/wic/ksparser.py | 41 +++++++++++++--
>> scripts/lib/wic/partition.py | 93
>> +++++++++++++++++++++-------------
>> scripts/lib/wic/utils/partitionedfs.py | 6 +--
>> 5 files changed, 109 insertions(+), 47 deletions(-)
>>
>> --
>> 2.5.0
>>
>> --
>> _______________________________________________
>> Openembedded-core mailing list
>> Openembedded-core@lists.openembedded.org
>> http://lists.openembedded.org/mailman/listinfo/openembedded-core
>
>
--
Maciej Borzecki
RnDity
^ permalink raw reply
* Re: [Qemu-devel] [Qemu-block] [PATCH for-2.8] block: Let write zeroes fallback work even with small max_transfer
From: Stefan Hajnoczi @ 2016-11-09 13:49 UTC (permalink / raw)
To: Eric Blake
Cc: qemu-devel, Kevin Wolf, Fam Zheng, qemu-block, qemu-stable,
Max Reitz, Ed Swierk, Stefan Hajnoczi, Denis V . Lunev
In-Reply-To: <1478645535-21236-1-git-send-email-eblake@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1137 bytes --]
On Tue, Nov 08, 2016 at 04:52:15PM -0600, Eric Blake wrote:
> Commit 443668ca rewrote the write_zeroes logic to guarantee that
> an unaligned request never crosses a cluster boundary. But
> in the rewrite, the new code assumed that at most one iteration
> would be needed to get to an alignment boundary.
>
> However, it is easy to trigger an assertion failure: the Linux
> kernel limits loopback devices to advertise a max_transfer of
> only 64k. Any operation that requires falling back to writes
> rather than more efficient zeroing must obey max_transfer during
> that fallback, which means an unaligned head may require multiple
> iterations of the write fallbacks before reaching the aligned
> boundaries, when layering a format with clusters larger than 64k
> atop the protocol of file access to a loopback device.
>
> Test case:
>
> $ qemu-img create -f qcow2 -o cluster_size=1M file 10M
> $ losetup /dev/loop2 /path/to/file
> $ qemu-io -f qcow2 /dev/loop2
> qemu-io> w 7m 1k
> qemu-io> w -z 8003584 2093056
Please include a qemu-iotests test case to protect against regressions.
Thanks,
Stefan
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* [Qemu-devel] [PULL for-2.8 0/2] usb: two memory leak fixes.
From: Gerd Hoffmann @ 2016-11-09 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Gerd Hoffmann
Hi,
Here is the usb patch queue, fixing two memory leaks.
please pull,
Gerd
The following changes since commit 207faf24c58859f5240f66bf6decc33b87a1776e:
Merge remote-tracking branch 'pm215/tags/pull-target-arm-20161107' into staging (2016-11-07 14:02:15 +0000)
are available in the git repository at:
git://git.kraxel.org/qemu tags/pull-usb-20161109-1
for you to fetch changes up to f0bf4999eae156142a86290fda45de4094e3e8b4:
usbredir: free vm_change_state_handler in usbredir destroy dispatch (2016-11-08 15:01:23 +0100)
----------------------------------------------------------------
usb: two memory leak fixes.
----------------------------------------------------------------
Li Qiang (2):
usb: ehci: fix memory leak in ehci_init_transfer
usbredir: free vm_change_state_handler in usbredir destroy dispatch
hw/usb/hcd-ehci.c | 1 +
hw/usb/redirect.c | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)
^ permalink raw reply
* [Qemu-devel] [PULL 1/2] usb: ehci: fix memory leak in ehci_init_transfer
From: Gerd Hoffmann @ 2016-11-09 13:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Li Qiang, Gerd Hoffmann
In-Reply-To: <1478698412-4865-1-git-send-email-kraxel@redhat.com>
From: Li Qiang <liqiang6-s@360.cn>
In ehci_init_transfer function, if the 'cpage' is bigger than 4,
it doesn't free the 'p->sgl' once allocated previously thus leading
a memory leak issue. This patch avoid this.
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Message-id: 5821c0f4.091c6b0a.e0c92.e811@mx.google.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/usb/hcd-ehci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f4ece9a..7622a3a 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1190,6 +1190,7 @@ static int ehci_init_transfer(EHCIPacket *p)
while (bytes > 0) {
if (cpage > 4) {
fprintf(stderr, "cpage out of range (%d)\n", cpage);
+ qemu_sglist_destroy(&p->sgl);
return -1;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH] t6026: ensure that long-running script really is
From: Johannes Schindelin @ 2016-11-09 13:51 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Johannes Sixt, Jeff King, Andreas Schwab
When making sure that background tasks are cleaned up in 5babb5b
(t6026-merge-attr: clean up background process at end of test case,
2016-09-07), we considered to let the background task sleep longer, just
to be certain that it will still be running when we want to kill it
after the test.
Sadly, the assumption appears not to hold true that the test case passes
quickly enough to kill the background task within a second.
Simply increase it to an hour. No system can be possibly slow enough to
make above-mentioned assumption incorrect.
Reported by Andreas Schwab.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Published-As: https://github.com/dscho/git/releases/tag/t6026-sleep-v1
Fetch-It-Via: git fetch https://github.com/dscho/git t6026-sleep-v1
t/t6026-merge-attr.sh | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh
index 7a6e33e..348d78b 100755
--- a/t/t6026-merge-attr.sh
+++ b/t/t6026-merge-attr.sh
@@ -183,16 +183,16 @@ test_expect_success 'up-to-date merge without common ancestor' '
test_expect_success 'custom merge does not lock index' '
git reset --hard anchor &&
- write_script sleep-one-second.sh <<-\EOF &&
- sleep 1 &
+ write_script sleep-an-hour.sh <<-\EOF &&
+ sleep 3600 &
echo $! >sleep.pid
EOF
test_when_finished "kill \$(cat sleep.pid)" &&
test_write_lines >.gitattributes \
- "* merge=ours" "text merge=sleep-one-second" &&
+ "* merge=ours" "text merge=sleep-an-hour" &&
test_config merge.ours.driver true &&
- test_config merge.sleep-one-second.driver ./sleep-one-second.sh &&
+ test_config merge.sleep-an-hour.driver ./sleep-an-hour.sh &&
git merge master
'
base-commit: be5a750939c212bc0781ffa04fabcfd2b2bd744e
--
2.10.1.583.g721a9e0
^ permalink raw reply related
* Re: [PATCH v4 1/3] spi-nor: Add support for Intel SPI serial flash controller
From: Cyrille Pitchen @ 2016-11-09 13:51 UTC (permalink / raw)
To: Mika Westerberg, linux-mtd
Cc: mkraemer, David Woodhouse, key.seong.lim, linux-kernel,
Peter Tyser, Brian Norris, Lee Jones, Marek Vasut
In-Reply-To: <20161017145858.143771-2-mika.westerberg@linux.intel.com>
Hi Mika,
Le 17/10/2016 à 16:58, Mika Westerberg a écrit :
> Add support for the SPI serial flash host controller found on many Intel
> CPUs including Baytrail and Braswell. The SPI serial flash controller is
> used to access BIOS and other platform specific information. By default the
> driver exposes a single read-only MTD device but with a module parameter
> "writeable=1" the MTD device can be made read-write which makes it possible
> to upgrade BIOS directly from Linux.
>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
> Documentation/mtd/intel-spi.txt | 88 ++++
> drivers/mtd/spi-nor/Kconfig | 20 +
> drivers/mtd/spi-nor/Makefile | 2 +
> drivers/mtd/spi-nor/intel-spi-platform.c | 57 +++
> drivers/mtd/spi-nor/intel-spi.c | 780 +++++++++++++++++++++++++++++++
> drivers/mtd/spi-nor/intel-spi.h | 24 +
> include/linux/platform_data/intel-spi.h | 31 ++
> 7 files changed, 1002 insertions(+)
> create mode 100644 Documentation/mtd/intel-spi.txt
> create mode 100644 drivers/mtd/spi-nor/intel-spi-platform.c
> create mode 100644 drivers/mtd/spi-nor/intel-spi.c
> create mode 100644 drivers/mtd/spi-nor/intel-spi.h
> create mode 100644 include/linux/platform_data/intel-spi.h
>
> diff --git a/Documentation/mtd/intel-spi.txt b/Documentation/mtd/intel-spi.txt
> new file mode 100644
> index 000000000000..bc357729c2cb
> --- /dev/null
> +++ b/Documentation/mtd/intel-spi.txt
> @@ -0,0 +1,88 @@
> +Upgrading BIOS using intel-spi
> +------------------------------
> +
> +Many Intel CPUs like Baytrail and Braswell include SPI serial flash host
> +controller which is used to hold BIOS and other platform specific data.
> +Since contents of the SPI serial flash is crucial for machine to function,
> +it is typically protected by different hardware protection mechanisms to
> +avoid accidental (or on purpose) overwrite of the content.
> +
> +Not all manufacturers protect the SPI serial flash, mainly because it
> +allows upgrading the BIOS image directly from an OS.
> +
> +The intel-spi driver makes it possible to read and write the SPI serial
> +flash, if certain protection bits are not set and locked. If it finds
> +any of them set, the whole MTD device is made read-only to prevent
> +partial overwrites. By default the driver exposes SPI serial flash
> +contents as read-only but it can be changed from kernel command line,
> +passing "intel-spi.writeable=1".
> +
> +Please keep in mind that overwriting the BIOS image on SPI serial flash
> +might render the machine unbootable and requires special equipment like
> +Dediprog to revive. You have been warned!
> +
> +Below are the steps how to upgrade MinnowBoard MAX BIOS directly from
> +Linux.
> +
> + 1) Download and extract the latest Minnowboard MAX BIOS SPI image
> + [1]. At the time writing this the latest image is v92.
> +
> + 2) Install mtd-utils package [2]. We need this in order to erase the SPI
> + serial flash. Distros like Debian and Fedora have this prepackaged with
> + name "mtd-utils".
> +
> + 3) Add "intel-spi.writeable=1" to the kernel command line and reboot
> + the board (you can also reload the driver passing "writeable=1" as
> + module parameter to modprobe).
> +
> + 4) Once the board is up and running again, find the right MTD partition
> + (it is named as "BIOS"):
> +
> + # cat /proc/mtd
> + dev: size erasesize name
> + mtd0: 00800000 00001000 "BIOS"
> +
> + So here it will be /dev/mtd0 but it may vary.
> +
> + 5) Make backup of the existing image first:
> +
> + # dd if=/dev/mtd0ro of=bios.bak
> + 16384+0 records in
> + 16384+0 records out
> + 8388608 bytes (8.4 MB) copied, 10.0269 s, 837 kB/s
> +
> + 6) Verify the backup
> +
> + # sha1sum /dev/mtd0ro bios.bak
> + fdbb011920572ca6c991377c4b418a0502668b73 /dev/mtd0ro
> + fdbb011920572ca6c991377c4b418a0502668b73 bios.bak
> +
> + The SHA1 sums must match. Otherwise do not continue any further!
> +
> + 7) Erase the SPI serial flash. After this step, do not reboot the
> + board! Otherwise it will not start anymore.
> +
> + # flash_erase /dev/mtd0 0 0
> + Erasing 4 Kibyte @ 7ff000 -- 100 % complete
> +
> + 8) Once completed without errors you can write the new BIOS image:
> +
> + # dd if=MNW2MAX1.X64.0092.R01.1605221712.bin of=/dev/mtd0
> +
> + 9) Verify that the new content of the SPI serial flash matches the new
> + BIOS image:
> +
> + # sha1sum /dev/mtd0ro MNW2MAX1.X64.0092.R01.1605221712.bin
> + 9b4df9e4be2057fceec3a5529ec3d950836c87a2 /dev/mtd0ro
> + 9b4df9e4be2057fceec3a5529ec3d950836c87a2 MNW2MAX1.X64.0092.R01.1605221712.bin
> +
> + The SHA1 sums should match.
> +
> + 10) Now you can reboot your board and observe the new BIOS starting up
> + properly.
> +
> +References
> +----------
> +
> +[1] https://firmware.intel.com/sites/default/files/MinnowBoard.MAX_.X64.92.R01.zip
> +[2] http://www.linux-mtd.infradead.org/
> diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
> index 4a682ee0f632..02013ffa5231 100644
> --- a/drivers/mtd/spi-nor/Kconfig
> +++ b/drivers/mtd/spi-nor/Kconfig
> @@ -76,4 +76,24 @@ config SPI_NXP_SPIFI
> Flash. Enable this option if you have a device with a SPIFI
> controller and want to access the Flash as a mtd device.
>
> +config SPI_INTEL_SPI
> + tristate
> +
> +config SPI_INTEL_SPI_PLATFORM
> + tristate "Intel PCH/PCU SPI flash platform driver" if EXPERT
> + depends on X86
> + select SPI_INTEL_SPI
> + help
> + This enables platform support for the Intel PCH/PCU SPI
> + controller in master mode. This controller is present in modern
> + Intel hardware and is used to hold BIOS and other persistent
> + settings. Using this driver it is possible to upgrade BIOS
> + directly from Linux.
> +
> + Say N here unless you know what you are doing. Overwriting the
> + SPI flash may render the system unbootable.
> +
> + To compile this driver as a module, choose M here: the module
> + will be called intel-spi-platform.
> +
> endif # MTD_SPI_NOR
> diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
> index 121695e83542..1796e8cd6e1a 100644
> --- a/drivers/mtd/spi-nor/Makefile
> +++ b/drivers/mtd/spi-nor/Makefile
> @@ -5,3 +5,5 @@ obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
> obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
> obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
> obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
> +obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
> +obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o
> diff --git a/drivers/mtd/spi-nor/intel-spi-platform.c b/drivers/mtd/spi-nor/intel-spi-platform.c
> new file mode 100644
> index 000000000000..5c943df9398f
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/intel-spi-platform.c
> @@ -0,0 +1,57 @@
> +/*
> + * Intel PCH/PCU SPI flash platform driver.
> + *
> + * Copyright (C) 2016, Intel Corporation
> + * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/ioport.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include "intel-spi.h"
> +
> +static int intel_spi_platform_probe(struct platform_device *pdev)
> +{
> + struct intel_spi_boardinfo *info;
> + struct intel_spi *ispi;
> + struct resource *mem;
> +
> + info = dev_get_platdata(&pdev->dev);
> + if (!info)
> + return -EINVAL;
> +
> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + ispi = intel_spi_probe(&pdev->dev, mem, info);
> + if (IS_ERR(ispi))
> + return PTR_ERR(ispi);
> +
> + platform_set_drvdata(pdev, ispi);
> + return 0;
> +}
> +
> +static int intel_spi_platform_remove(struct platform_device *pdev)
> +{
> + struct intel_spi *ispi = platform_get_drvdata(pdev);
> +
> + return intel_spi_remove(ispi);
> +}
> +
> +static struct platform_driver intel_spi_platform_driver = {
> + .probe = intel_spi_platform_probe,
> + .remove = intel_spi_platform_remove,
> + .driver = {
> + .name = "intel-spi",
> + },
> +};
> +
> +module_platform_driver(intel_spi_platform_driver);
> +
> +MODULE_DESCRIPTION("Intel PCH/PCU SPI flash platform driver");
> +MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:intel-spi");
> diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c
> new file mode 100644
> index 000000000000..ded613bff1ab
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/intel-spi.c
> @@ -0,0 +1,780 @@
> +/*
> + * Intel PCH/PCU SPI flash driver.
> + *
> + * Copyright (C) 2016, Intel Corporation
> + * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/sizes.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/mtd/spi-nor.h>
> +#include <linux/platform_data/intel-spi.h>
> +
> +#include "intel-spi.h"
> +
> +/* Offsets are from @ispi->base */
> +#define BFPREG 0x00
> +
> +#define HSFSTS_CTL 0x04
> +#define HSFSTS_CTL_FSMIE BIT(31)
> +#define HSFSTS_CTL_FDBC_SHIFT 24
> +#define HSFSTS_CTL_FDBC_MASK (0x3f << HSFSTS_CTL_FDBC_SHIFT)
> +
> +#define HSFSTS_CTL_FCYCLE_SHIFT 17
> +#define HSFSTS_CTL_FCYCLE_MASK (0x0f << HSFSTS_CTL_FCYCLE_SHIFT)
> +/* HW sequencer opcodes */
> +#define HSFSTS_CTL_FCYCLE_READ (0x00 << HSFSTS_CTL_FCYCLE_SHIFT)
> +#define HSFSTS_CTL_FCYCLE_WRITE (0x02 << HSFSTS_CTL_FCYCLE_SHIFT)
> +#define HSFSTS_CTL_FCYCLE_ERASE (0x03 << HSFSTS_CTL_FCYCLE_SHIFT)
> +#define HSFSTS_CTL_FCYCLE_ERASE_64K (0x04 << HSFSTS_CTL_FCYCLE_SHIFT)
> +#define HSFSTS_CTL_FCYCLE_RDID (0x06 << HSFSTS_CTL_FCYCLE_SHIFT)
> +#define HSFSTS_CTL_FCYCLE_WRSR (0x07 << HSFSTS_CTL_FCYCLE_SHIFT)
> +#define HSFSTS_CTL_FCYCLE_RDSR (0x08 << HSFSTS_CTL_FCYCLE_SHIFT)
> +
> +#define HSFSTS_CTL_FGO BIT(16)
> +#define HSFSTS_CTL_FLOCKDN BIT(15)
> +#define HSFSTS_CTL_FDV BIT(14)
> +#define HSFSTS_CTL_SCIP BIT(5)
> +#define HSFSTS_CTL_AEL BIT(2)
> +#define HSFSTS_CTL_FCERR BIT(1)
> +#define HSFSTS_CTL_FDONE BIT(0)
> +
> +#define FADDR 0x08
> +#define DLOCK 0x0c
> +#define FDATA(n) (0x10 + ((n) * 4))
> +
> +#define FRACC 0x50
> +
> +#define FREG(n) (0x54 + ((n) * 4))
> +#define FREG_BASE_MASK 0x3fff
> +#define FREG_LIMIT_SHIFT 16
> +#define FREG_LIMIT_MASK (0x03fff << FREG_LIMIT_SHIFT)
> +
> +/* Offset is from @ispi->pregs */
> +#define PR(n) ((n) * 4)
> +#define PR_WPE BIT(31)
> +#define PR_LIMIT_SHIFT 16
> +#define PR_LIMIT_MASK (0x3fff << PR_LIMIT_SHIFT)
> +#define PR_RPE BIT(15)
> +#define PR_BASE_MASK 0x3fff
> +/* Last PR is GPR0 */
> +#define PR_NUM (5 + 1)
> +
> +/* Offsets are from @ispi->sregs */
> +#define SSFSTS_CTL 0x00
> +#define SSFSTS_CTL_FSMIE BIT(23)
> +#define SSFSTS_CTL_DS BIT(22)
> +#define SSFSTS_CTL_DBC_SHIFT 16
> +#define SSFSTS_CTL_SPOP BIT(11)
> +#define SSFSTS_CTL_ACS BIT(10)
> +#define SSFSTS_CTL_SCGO BIT(9)
> +#define SSFSTS_CTL_COP_SHIFT 12
> +#define SSFSTS_CTL_FRS BIT(7)
> +#define SSFSTS_CTL_DOFRS BIT(6)
> +#define SSFSTS_CTL_AEL BIT(4)
> +#define SSFSTS_CTL_FCERR BIT(3)
> +#define SSFSTS_CTL_FDONE BIT(2)
> +#define SSFSTS_CTL_SCIP BIT(0)
> +
> +#define PREOP_OPTYPE 0x04
> +#define OPMENU0 0x08
> +#define OPMENU1 0x0c
> +
> +/* CPU specifics */
> +#define BYT_PR 0x74
> +#define BYT_SSFSTS_CTL 0x90
> +#define BYT_BCR 0xfc
> +#define BYT_BCR_WPD BIT(0)
> +#define BYT_FREG_NUM 5
> +
> +#define LPT_PR 0x74
> +#define LPT_SSFSTS_CTL 0x90
> +#define LPT_FREG_NUM 5
> +
> +#define BXT_PR 0x84
> +#define BXT_SSFSTS_CTL 0xa0
> +#define BXT_FREG_NUM 12
> +
> +#define INTEL_SPI_TIMEOUT 5000 /* ms */
> +
> +/**
> + * struct intel_spi - Driver private data
> + * @dev: Device pointer
> + * @info: Pointer to board specific info
> + * @nor: SPI NOR layer structure
> + * @base: Beginning of MMIO space
> + * @pregs: Start of protection registers
> + * @sregs: Start of software sequencer registers
> + * @nregions: Maximum number of regions
> + * @writeable: Is the chip writeable
> + * @swseq: Use SW sequencer in register reads/writes
> + * @erase_64k: 64k erase supported
> + * @opcodes: Opcodes which are supported. This are programmed by BIOS
> + * before it locks down the controller.
> + * @preopcodes: Preopcodes which are supported.
> + */
> +struct intel_spi {
> + struct device *dev;
> + const struct intel_spi_boardinfo *info;
> + struct spi_nor nor;
> + void __iomem *base;
> + void __iomem *pregs;
> + void __iomem *sregs;
> + size_t nregions;
> + bool writeable;
> + bool swseq;
> + bool erase_64k;
> + u8 opcodes[8];
> + u8 preopcodes[2];
> +};
> +
> +static bool writeable;
> +module_param(writeable, bool, 0);
> +MODULE_PARM_DESC(writeable, "Enable write access to SPI flash chip (default=0)");
> +
> +static void intel_spi_dump_regs(struct intel_spi *ispi)
> +{
> + u32 value;
> + int i;
> +
> + dev_dbg(ispi->dev, "BFPREG=0x%08x\n", readl(ispi->base + BFPREG));
> +
> + value = readl(ispi->base + HSFSTS_CTL);
> + dev_dbg(ispi->dev, "HSFSTS_CTL=0x%08x\n", value);
> + if (value & HSFSTS_CTL_FLOCKDN)
> + dev_dbg(ispi->dev, "-> Locked\n");
> +
> + dev_dbg(ispi->dev, "FADDR=0x%08x\n", readl(ispi->base + FADDR));
> + dev_dbg(ispi->dev, "DLOCK=0x%08x\n", readl(ispi->base + DLOCK));
> +
> + for (i = 0; i < 16; i++)
> + dev_dbg(ispi->dev, "FDATA(%d)=0x%08x\n",
> + i, readl(ispi->base + FDATA(i)));
> +
> + dev_dbg(ispi->dev, "FRACC=0x%08x\n", readl(ispi->base + FRACC));
> +
> + for (i = 0; i < ispi->nregions; i++)
> + dev_dbg(ispi->dev, "FREG(%d)=0x%08x\n", i,
> + readl(ispi->base + FREG(i)));
> + for (i = 0; i < PR_NUM; i++)
> + dev_dbg(ispi->dev, "PR(%d)=0x%08x\n", i,
> + readl(ispi->pregs + PR(i)));
> +
> + value = readl(ispi->sregs + SSFSTS_CTL);
> + dev_dbg(ispi->dev, "SSFSTS_CTL=0x%08x\n", value);
> + dev_dbg(ispi->dev, "PREOP_OPTYPE=0x%08x\n",
> + readl(ispi->sregs + PREOP_OPTYPE));
> + dev_dbg(ispi->dev, "OPMENU0=0x%08x\n", readl(ispi->sregs + OPMENU0));
> + dev_dbg(ispi->dev, "OPMENU1=0x%08x\n", readl(ispi->sregs + OPMENU1));
> +
> + if (ispi->info->type == INTEL_SPI_BYT)
> + dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR));
> +
> + dev_dbg(ispi->dev, "Protected regions:\n");
> + for (i = 0; i < PR_NUM; i++) {
> + u32 base, limit;
> +
> + value = readl(ispi->pregs + PR(i));
> + if (!(value & (PR_WPE | PR_RPE)))
> + continue;
> +
> + limit = (value & PR_LIMIT_MASK) >> PR_LIMIT_SHIFT;
> + base = value & PR_BASE_MASK;
> +
> + dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x [%c%c]\n",
> + i, base << 12, (limit << 12) | 0xfff,
> + value & PR_WPE ? 'W' : '.',
> + value & PR_RPE ? 'R' : '.');
> + }
> +
> + dev_dbg(ispi->dev, "Flash regions:\n");
> + for (i = 0; i < ispi->nregions; i++) {
> + u32 region, base, limit;
> +
> + region = readl(ispi->base + FREG(i));
> + base = region & FREG_BASE_MASK;
> + limit = (region & FREG_LIMIT_MASK) >> FREG_LIMIT_SHIFT;
> +
> + if (base > limit || (i > 0 && limit == 0))
> + dev_dbg(ispi->dev, " %02d disabled\n", i);
> + else
> + dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x\n",
> + i, base << 12, (limit << 12) | 0xfff);
> + }
> +
> + dev_dbg(ispi->dev, "Using %cW sequencer for register access\n",
> + ispi->swseq ? 'S' : 'H');
> +}
> +
> +/* Reads max 64 bytes from the device fifo */
> +static int intel_spi_read_block(struct intel_spi *ispi, void *buf, size_t size)
> +{
> + size_t bytes;
> + int i = 0;
> +
> + if (size > 64)
This is not a blocking point but just a recommendation: you should define
and use a macro for this 64 byte FIFO size instead of using this hardcoded
64 value here and in intel_spi_write_block(), intel_spi_write(),
intel_spi_read().
> + return -EINVAL;
> +
> + while (size > 0) {
> + bytes = min_t(size_t, size, 4);
> + memcpy_fromio(buf, ispi->base + FDATA(i++), bytes);
Here again another general recommendation: be careful about using
operators like ++ on macro parameters. In the case of this FDATA() macro
it will work as expected but unwanted side effect might occur depending on
the actual macro definition:
int i = 1;
#define DOUBLE(n) ((n) + (n))
DOUBLE(i++); /* here i is incremented twice, not just once. */
> + size -= bytes;
> + buf += bytes;
> + }
> +
> + return 0;
> +}
> +
> +/* Writes max 64 bytes to the device fifo */
> +static int intel_spi_write_block(struct intel_spi *ispi, const void *buf,
> + size_t size)
> +{
> + size_t bytes;
> + int i = 0;
> +
> + if (size > 64)
> + return -EINVAL;
> +
> + while (size > 0) {
> + bytes = min_t(size_t, size, 4);
> + memcpy_toio(ispi->base + FDATA(i++), buf, bytes);
> + size -= bytes;
> + buf += bytes;
> + }
> +
> + return 0;
> +}
> +
> +static int intel_spi_wait_hw_busy(struct intel_spi *ispi)
> +{
> + unsigned long timeout = jiffies + msecs_to_jiffies(INTEL_SPI_TIMEOUT);
> + u32 hwstat;
> +
> + while (!time_after(jiffies, timeout)) {
> + hwstat = readl(ispi->base + HSFSTS_CTL);
> + if (!(hwstat & HSFSTS_CTL_SCIP))
> + return 0;
> + cond_resched();
> + }
> +
> + return -ETIMEDOUT;
> +}
> +
> +static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
> +{
> + unsigned long timeout = jiffies + msecs_to_jiffies(INTEL_SPI_TIMEOUT);
> + u32 swstat;
> +
> + while (!time_after(jiffies, timeout)) {
> + swstat = readl(ispi->sregs + SSFSTS_CTL);
> + if (!(swstat & SSFSTS_CTL_SCIP))
> + return 0;
> + cond_resched();
> + }
> +
> + return -ETIMEDOUT;
> +}
> +
> +static int intel_spi_init(struct intel_spi *ispi)
> +{
> + u32 opmenu0, opmenu1, val;
> + int i;
> +
> + switch (ispi->info->type) {
> + case INTEL_SPI_BYT:
> + ispi->sregs = ispi->base + BYT_SSFSTS_CTL;
> + ispi->pregs = ispi->base + BYT_PR;
> + ispi->nregions = BYT_FREG_NUM;
> +
> + if (writeable) {
> + /* Disable write protection */
> + val = readl(ispi->base + BYT_BCR);
> + if (!(val & BYT_BCR_WPD)) {
> + val |= BYT_BCR_WPD;
> + writel(val, ispi->base + BYT_BCR);
> + val = readl(ispi->base + BYT_BCR);
> + }
> +
> + ispi->writeable = !!(val & BYT_BCR_WPD);
> + }
> +
> + break;
> +
> + case INTEL_SPI_LPT:
> + ispi->sregs = ispi->base + LPT_SSFSTS_CTL;
> + ispi->pregs = ispi->base + LPT_PR;
> + ispi->nregions = LPT_FREG_NUM;
> + break;
> +
> + case INTEL_SPI_BXT:
> + ispi->sregs = ispi->base + BXT_SSFSTS_CTL;
> + ispi->pregs = ispi->base + BXT_PR;
> + ispi->nregions = BXT_FREG_NUM;
> + ispi->erase_64k = true;
> + break;
> +
> + default:
> + return -EINVAL;
> + }
> +
> + /* Disable #SMI generation */
> + val = readl(ispi->base + HSFSTS_CTL);
> + val &= ~HSFSTS_CTL_FSMIE;
> + writel(val, ispi->base + HSFSTS_CTL);
> +
> + /*
> + * BIOS programs allowed opcodes and then locks down the register.
> + * So read back what opcodes it decided to support. That's the set
> + * we are going to support as well.
> + */
> + opmenu0 = readl(ispi->sregs + OPMENU0);
> + opmenu1 = readl(ispi->sregs + OPMENU1);
> +
> + /*
> + * Some controllers can only do basic operations using hardware
> + * sequencer. All other operations are supposed to be carried out
> + * using software sequencer. If we find that BIOS has programmed
> + * opcodes for the software sequencer we use that over the hardware
> + * sequencer.
> + */
> + if (opmenu0 && opmenu1) {
> + for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) {
> + ispi->opcodes[i] = opmenu0 >> i * 8;
> + ispi->opcodes[i + 4] = opmenu1 >> i * 8;
> + }
> +
> + val = readl(ispi->sregs + PREOP_OPTYPE);
> + ispi->preopcodes[0] = val;
> + ispi->preopcodes[1] = val >> 8;
> +
> + /* Disable #SMI generation from SW sequencer */
> + val = readl(ispi->sregs + SSFSTS_CTL);
> + val &= ~SSFSTS_CTL_FSMIE;
> + writel(val, ispi->sregs + SSFSTS_CTL);
> +
> + ispi->swseq = true;
> + }
> +
> + intel_spi_dump_regs(ispi);
> +
> + return 0;
> +}
> +
> +static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++)
> + if (ispi->opcodes[i] == opcode)
> + return i;
> + return -EINVAL;
> +}
> +
> +static int intel_spi_hw_cycle(struct intel_spi *ispi, u8 opcode, u8 *buf,
> + int len)
> +{
> + u32 val, status;
> + int ret;
> +
> + val = readl(ispi->base + HSFSTS_CTL);
> + val &= ~(HSFSTS_CTL_FCYCLE_MASK | HSFSTS_CTL_FDBC_MASK);
> +
> + switch (opcode) {
> + case SPINOR_OP_RDID:
> + val |= HSFSTS_CTL_FCYCLE_RDID;
> + break;
> + case SPINOR_OP_WRSR:
> + val |= HSFSTS_CTL_FCYCLE_WRSR;
> + break;
> + case SPINOR_OP_RDSR:
> + val |= HSFSTS_CTL_FCYCLE_RDSR;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + val |= (len - 1) << HSFSTS_CTL_FDBC_SHIFT;
> + val |= HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> + val |= HSFSTS_CTL_FGO;
> + writel(val, ispi->base + HSFSTS_CTL);
> +
> + ret = intel_spi_wait_hw_busy(ispi);
> + if (ret)
> + return ret;
> +
> + status = readl(ispi->base + HSFSTS_CTL);
> + if (status & HSFSTS_CTL_FCERR)
> + return -EIO;
> + else if (status & HSFSTS_CTL_AEL)
> + return -EACCES;
> +
> + return 0;
> +}
> +
> +static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, u8 *buf,
> + int len)
> +{
> + u32 val, status;
> + int ret;
> +
> + ret = intel_spi_opcode_index(ispi, opcode);
> + if (ret < 0)
> + return ret;
> +
> + val = (len << SSFSTS_CTL_DBC_SHIFT) | SSFSTS_CTL_DS;
> + val |= ret << SSFSTS_CTL_COP_SHIFT;
> + val |= SSFSTS_CTL_FCERR | SSFSTS_CTL_FDONE;
> + val |= SSFSTS_CTL_SCGO;
> + writel(val, ispi->sregs + SSFSTS_CTL);
> +
> + ret = intel_spi_wait_sw_busy(ispi);
> + if (ret)
> + return ret;
> +
> + status = readl(ispi->base + SSFSTS_CTL);
> + if (status & SSFSTS_CTL_FCERR)
> + return -EIO;
> + else if (status & SSFSTS_CTL_AEL)
> + return -EACCES;
> +
> + return 0;
> +}
> +
> +static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
> +{
> + struct intel_spi *ispi = nor->priv;
> + int ret;
> +
> + /* Address of the first chip */
> + writel(0, ispi->base + FADDR);
> +
> + if (ispi->swseq)
> + ret = intel_spi_sw_cycle(ispi, opcode, buf, len);
> + else
> + ret = intel_spi_hw_cycle(ispi, opcode, buf, len);
> +
> + if (ret)
> + return ret;
> +
> + return intel_spi_read_block(ispi, buf, len);
> +}
> +
> +static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
> +{
> + struct intel_spi *ispi = nor->priv;
> + int ret;
> +
> + /*
> + * This is handled with atomic operation and preop code in Intel
> + * controller so skip it here now.
> + */
> + if (opcode == SPINOR_OP_WREN)
> + return 0;
> +
> + writel(0, ispi->base + FADDR);
> +
> + /* Write the value beforehand */
> + ret = intel_spi_write_block(ispi, buf, len);
> + if (ret)
> + return ret;
> +
> + if (ispi->swseq)
> + return intel_spi_sw_cycle(ispi, opcode, buf, len);
> + return intel_spi_hw_cycle(ispi, opcode, buf, len);
> +}
> +
> +static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
> + u_char *read_buf)
> +{
> + struct intel_spi *ispi = nor->priv;
> + size_t block_size, retlen = 0;
> + u32 val, status;
> + ssize_t ret;
> +
As I understand some Intel SPI controllers can only use op codes in a fixed
instruction set, so here you should check the nor->read_opcode.
Indeed when the support of SFDP tables will be integrated, the
nor->read_opcode might change between calls of the nor->read() handler.
spi_nor_read_sfdp() make use of this nor->read() handler but set
nor->read_opcode to SPINOR_OP_RDSFDP (5Ah) before calling the handler.
Then, if intel_spi_read() is called with an unsupported nor->read_opcode,
it should fail returning -EINVAL. The spi-nor framework will handle this
failure correctly.
You can find the SFDP patch here:
http://patchwork.ozlabs.org/patch/685984/
> + while (len > 0) {
> + block_size = min_t(size_t, len, 64);
> +
> + writel(from, ispi->base + FADDR);
> +
> + val = readl(ispi->base + HSFSTS_CTL);
> + val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> + val &= ~HSFSTS_CTL_FDBC_MASK;
> + val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT;
> + val &= ~HSFSTS_CTL_FCYCLE_MASK;
> + val |= HSFSTS_CTL_FCYCLE_READ;
> + val |= HSFSTS_CTL_FGO;
> + writel(val, ispi->base + HSFSTS_CTL);
> +
> + ret = intel_spi_wait_hw_busy(ispi);
> + if (ret)
> + return ret;
> +
> + status = readl(ispi->base + HSFSTS_CTL);
> + if (status & HSFSTS_CTL_FCERR)
> + ret = -EIO;
> + else if (status & HSFSTS_CTL_AEL)
> + ret = -EACCES;
> +
> + if (ret < 0) {
> + dev_err(ispi->dev, "read error: %llx: %#x\n", from,
> + status);
> + return ret;
> + }
> +
> + ret = intel_spi_read_block(ispi, read_buf, block_size);
> + if (ret)
> + return ret;
> +
> + len -= block_size;
> + from += block_size;
> + retlen += block_size;
> + read_buf += block_size;
> + }
> +
> + return retlen;
> +}
> +
> +static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
> + const u_char *write_buf)
> +{
> + struct intel_spi *ispi = nor->priv;
> + size_t block_size, retlen = 0;
> + u32 val, status;
> + ssize_t ret;
> +
> + while (len > 0) {
> + block_size = min_t(size_t, len, 64);
> +
> + writel(to, ispi->base + FADDR);
> +
> + val = readl(ispi->base + HSFSTS_CTL);
> + val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> + val &= ~HSFSTS_CTL_FDBC_MASK;
> + val |= (block_size - 1) << HSFSTS_CTL_FDBC_SHIFT;
> + val &= ~HSFSTS_CTL_FCYCLE_MASK;
> + val |= HSFSTS_CTL_FCYCLE_WRITE;
> +
> + /* Write enable */
> + if (ispi->preopcodes[1] == SPINOR_OP_WREN)
> + val |= SSFSTS_CTL_SPOP;
> + val |= SSFSTS_CTL_ACS;
> + writel(val, ispi->base + HSFSTS_CTL);
> +
> + ret = intel_spi_write_block(ispi, write_buf, block_size);
> + if (ret) {
> + dev_err(ispi->dev, "failed to write block\n");
> + return ret;
> + }
> +
> + /* Start the write now */
> + val = readl(ispi->base + HSFSTS_CTL);
> + writel(val | HSFSTS_CTL_FGO, ispi->base + HSFSTS_CTL);
> +
> + ret = intel_spi_wait_hw_busy(ispi);
> + if (ret) {
> + dev_err(ispi->dev, "timeout\n");
> + return ret;
> + }
> +
> + status = readl(ispi->base + HSFSTS_CTL);
> + if (status & HSFSTS_CTL_FCERR)
> + ret = -EIO;
> + else if (status & HSFSTS_CTL_AEL)
> + ret = -EACCES;
> +
> + if (ret < 0) {
> + dev_err(ispi->dev, "write error: %llx: %#x\n", to,
> + status);
> + return ret;
> + }
> +
> + len -= block_size;
> + to += block_size;
> + retlen += block_size;
> + write_buf += block_size;
> + }
> +
> + return retlen;
> +}
> +
> +static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
> +{
> + size_t erase_size, len = nor->mtd.erasesize;
> + struct intel_spi *ispi = nor->priv;
> + u32 val, status, cmd;
> + int ret;
> +
> + /* If the hardware can do 64k erase use that when possible */
> + if (len >= SZ_64K && ispi->erase_64k) {
> + cmd = HSFSTS_CTL_FCYCLE_ERASE_64K;
> + erase_size = SZ_64K;
> + } else {
> + cmd = HSFSTS_CTL_FCYCLE_ERASE;
> + erase_size = SZ_4K;
> + }
> +
> + while (len > 0) {
> + writel(offs, ispi->base + FADDR);
> +
> + val = readl(ispi->base + HSFSTS_CTL);
> + val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> + val &= ~HSFSTS_CTL_FDBC_MASK;
> + val &= ~HSFSTS_CTL_FCYCLE_MASK;
> + val |= cmd;
> + val |= HSFSTS_CTL_FGO;
> + writel(val, ispi->base + HSFSTS_CTL);
> +
> + ret = intel_spi_wait_hw_busy(ispi);
> + if (ret)
> + return ret;
> +
> + status = readl(ispi->base + HSFSTS_CTL);
> + if (status & HSFSTS_CTL_FCERR)
> + return -EIO;
> + else if (status & HSFSTS_CTL_AEL)
> + return -EACCES;
> +
> + offs += erase_size;
> + len -= erase_size;
> + }
> +
> + return 0;
> +}
> +
> +static bool intel_spi_is_protected(const struct intel_spi *ispi,
> + unsigned int base, unsigned int limit)
> +{
> + int i;
> +
> + for (i = 0; i < PR_NUM; i++) {
> + u32 pr_base, pr_limit, pr_value;
> +
> + pr_value = readl(ispi->pregs + PR(i));
> + if (!(pr_value & (PR_WPE | PR_RPE)))
> + continue;
> +
> + pr_limit = (pr_value & PR_LIMIT_MASK) >> PR_LIMIT_SHIFT;
> + pr_base = pr_value & PR_BASE_MASK;
> +
> + if (pr_base >= base && pr_limit <= limit)
> + return true;
> + }
> +
> + return false;
> +}
> +
> +/*
> + * There will be a single partition holding all enabled flash regions. We
> + * call this "BIOS".
> + */
> +static void intel_spi_fill_partition(struct intel_spi *ispi,
> + struct mtd_partition *part)
> +{
> + u64 end;
> + int i;
> +
> + memset(part, 0, sizeof(*part));
> +
> + /* Start from the mandatory descriptor region */
> + part->size = 4096;
> + part->name = "BIOS";
> +
> + /*
> + * Now try to find where this partition ends based on the flash
> + * region registers.
> + */
> + for (i = 1; i < ispi->nregions; i++) {
> + u32 region, base, limit;
> +
> + region = readl(ispi->base + FREG(i));
> + base = region & FREG_BASE_MASK;
> + limit = (region & FREG_LIMIT_MASK) >> FREG_LIMIT_SHIFT;
> +
> + if (base > limit || limit == 0)
> + continue;
> +
> + /*
> + * If any of the regions have protection bits set, make the
> + * whole partition read-only to be on the safe side.
> + */
> + if (intel_spi_is_protected(ispi, base, limit))
> + ispi->writeable = 0;
> +
> + end = (limit << 12) + 4096;
> + if (end > part->size)
> + part->size = end;
> + }
> +}
> +
> +struct intel_spi *intel_spi_probe(struct device *dev,
> + struct resource *mem, const struct intel_spi_boardinfo *info)
> +{
> + struct mtd_partition part;
> + struct intel_spi *ispi;
> + int ret;
> +
> + if (!info || !mem)
> + return ERR_PTR(-EINVAL);
> +
> + ispi = devm_kzalloc(dev, sizeof(*ispi), GFP_KERNEL);
> + if (!ispi)
> + return ERR_PTR(-ENOMEM);
> +
> + ispi->base = devm_ioremap_resource(dev, mem);
> + if (IS_ERR(ispi->base))
> + return ispi->base;
> +
> + ispi->dev = dev;
> + ispi->info = info;
> + ispi->writeable = info->writeable;
> +
> + ret = intel_spi_init(ispi);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + ispi->nor.dev = ispi->dev;
> + ispi->nor.priv = ispi;
> + ispi->nor.read_reg = intel_spi_read_reg;
> + ispi->nor.write_reg = intel_spi_write_reg;
> + ispi->nor.read = intel_spi_read;
> + ispi->nor.write = intel_spi_write;
> + ispi->nor.erase = intel_spi_erase;
> +
> + ret = spi_nor_scan(&ispi->nor, NULL, SPI_NOR_NORMAL);
> + if (ret) {
> + dev_info(dev, "failed to locate the chip\n");
> + return ERR_PTR(ret);
> + }
> +
> + intel_spi_fill_partition(ispi, &part);
> +
> + /* Prevent writes if not explicitly enabled */
> + if (!ispi->writeable || !writeable)
> + ispi->nor.mtd.flags &= ~MTD_WRITEABLE;
> +
> + ret = mtd_device_parse_register(&ispi->nor.mtd, NULL, NULL, &part, 1);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + return ispi;
> +}
> +EXPORT_SYMBOL_GPL(intel_spi_probe);
> +
> +int intel_spi_remove(struct intel_spi *ispi)
> +{
> + return mtd_device_unregister(&ispi->nor.mtd);
> +}
> +EXPORT_SYMBOL_GPL(intel_spi_remove);
> +
> +MODULE_DESCRIPTION("Intel PCH/PCU SPI flash core driver");
> +MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/mtd/spi-nor/intel-spi.h b/drivers/mtd/spi-nor/intel-spi.h
> new file mode 100644
> index 000000000000..5ab7dc250050
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/intel-spi.h
> @@ -0,0 +1,24 @@
> +/*
> + * Intel PCH/PCU SPI flash driver.
> + *
> + * Copyright (C) 2016, Intel Corporation
> + * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef INTEL_SPI_H
> +#define INTEL_SPI_H
> +
> +#include <linux/platform_data/intel-spi.h>
> +
> +struct intel_spi;
> +struct resource;
> +
> +struct intel_spi *intel_spi_probe(struct device *dev,
> + struct resource *mem, const struct intel_spi_boardinfo *info);
> +int intel_spi_remove(struct intel_spi *ispi);
> +
> +#endif /* INTEL_SPI_H */
> diff --git a/include/linux/platform_data/intel-spi.h b/include/linux/platform_data/intel-spi.h
> new file mode 100644
> index 000000000000..942b0c3f8f08
> --- /dev/null
> +++ b/include/linux/platform_data/intel-spi.h
> @@ -0,0 +1,31 @@
> +/*
> + * Intel PCH/PCU SPI flash driver.
> + *
> + * Copyright (C) 2016, Intel Corporation
> + * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef INTEL_SPI_PDATA_H
> +#define INTEL_SPI_PDATA_H
> +
> +enum intel_spi_type {
> + INTEL_SPI_BYT = 1,
> + INTEL_SPI_LPT,
> + INTEL_SPI_BXT,
> +};
> +
> +/**
> + * struct intel_spi_boardinfo - Board specific data for Intel SPI driver
> + * @type: Type which this controller is compatible with
> + * @writeable: The chip is writeable
> + */
> +struct intel_spi_boardinfo {
> + enum intel_spi_type type;
> + bool writeable;
> +};
> +
> +#endif /* INTEL_SPI_PDATA_H */
>
Best regards,
Cyrille
^ permalink raw reply
* Re: Bug: git config does not respect read-only .gitconfig file
From: Jonathan Word @ 2016-11-09 13:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Markus Hitter, git, jword
In-Reply-To: <xmqqk2cdbg5v.fsf@gitster.mtv.corp.google.com>
> It is unreasonable to drop the write-enable bit of
> a file in a writable directory and expect it to stay unmodified. The
> W-bit on the file is not usable as a security measure, and we do not
> use it as such.
The point here is not a matter of security - it is of expectations.
When a user drops write access on the global ~/.gitconfig I think
a reasonable user would expect future `git config --global` calls to
fail by default. The possibility of an override is a different matter,
and my initial proposal included the details of enabling direct
override. I don't think there is any presumption that this is a
security related discussion.
> I do not offhand know how much a new feature "this repository can be
> modified by pushing into and fetching from, but its configuration
> cannot be modified" is a sensible thing to have.
I agree that per-repository files almost never run into an issue with
this. Our problem is strictly with the global ~/.gitconfig which in our
use case is owned by a shared system account and used implicitly
by many developers. Thus any one of those devs can call
`git config` without any signal that they are changing something
that ought not to be changed and should think carefully.
This would be equivalent to dropping write access to a file that
your account owns so that vi / emacs / etc.. will warn that the
file is read-only before modifying it (useful for any number of
sensitive files). Obviously from a security perspective you have
a number of means of potential override, however all require additional
steps that surface the initial intention that the file should not
change - or should only change rarely after additional confirmation.
> perhaps the lock_file()
> function can have access(path, W_OK) check before it returns a
> tempfile that has been successfully opened?
That sounds ideal
On Tue, Nov 8, 2016 at 8:22 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>
>> Probably converting "rename(from, to)" to first check "access(to,
>> W_OK)". That's racy, but it's the best we could do.
>
> Hmph, if these (possibly problematic) callers are all following the
> usual "lock, write to temp, rename" pattern, perhaps the lock_file()
> function can have access(path, W_OK) check before it returns a
> tempfile that has been successfully opened?
>
> Having said that, I share your assessment that this is not a code or
> design problem. It is unreasonable to drop the write-enable bit of
> a file in a writable directory and expect it to stay unmodified. The
> W-bit on the file is not usable as a security measure, and we do not
> use it as such.
>
> I do not offhand know how much a new feature "this repository can be
> modified by pushing into and fetching from, but its configuration
> cannot be modified" is a sensible thing to have. But it is quite
> clear that even if we were to implement such feature, we wouldn't be
> using W-bit on .git/config to signal that.
>
^ permalink raw reply
* Re: bump librados' soversion
From: Jason Dillaman @ 2016-11-09 13:52 UTC (permalink / raw)
To: kefu chai; +Cc: ceph-devel@vger.kernel.org, Sage Weil
In-Reply-To: <CAJE9aOMoOJSccnXA=gCxuO3KN+0fziF3mRhMxBcF3dy4tmwy9A@mail.gmail.com>
Am I correct in assuming the original issue that forced this change
was because a >2GB message was sent over the wire and that bug has
been fixed?
If so, can we just revert the API change and do a soversion bump when
we really clean up the librados API, which has been talked about for a
while now? There is some cleanup work needed in the librbd API that
would break the API, so it would be nice to do it all at once instead
of library-by-library, release-by-release.
There only seems to be a few places within the codebase that even use
"advance", and they could be switched over to a new a "advance2" /
"advance64" method in the interim if required.
If we do bump the soversion for this, obviously the current failing
client upgrade test would just need to be removed.
On Wed, Nov 9, 2016 at 1:16 AM, kefu chai <tchaikov@gmail.com> wrote:
> hi cephers,
>
> i am proposing bumping the soversion of librados2 to librados3. as in
> 053bfa6[0], we changed the function signature of
> ceph::buffer::list::advance(), which is incompatible with the prior
> version of librados. that's partially why we have
> http://tracker.ceph.com/issues/17809, in which, the old librbd client
> fails to start, due to unresolved symbols.
>
> and if user has some (homebrew) packages depending on librados2. those
> packages will be broken as well. the same applies to executables
> linked against librados2 shared library. so we need to bump the
> soversion. but to minimize the impact, i think we will not introduce
> incompatible changes between major releases, in other words, the
> soversion won't change from jewel to kraken, for example. if i
> understand sage's comment correctly.
>
> yes, i knew this issue was raised before from time to time. but maybe
> this is a good chance to do the soversion change in kraken.
>
> a PR is posted to address this problem. see
> https://github.com/ceph/ceph/pull/11843.
>
> --
> [0] https://github.com/ceph/ceph/pull/9395/commits/053bfa650ba1d656dfb20e389ef25afc4c383bb3
> [1] https://github.com/ceph/ceph/pull/9395#issuecomment-224278945
>
> --
> Regards
> Kefu Chai
--
Jason
^ permalink raw reply
* Re: [PATCH] x86/vm_event: Added support for VM_EVENT_REASON_INTERRUPT
From: Razvan Cojocaru @ 2016-11-09 13:53 UTC (permalink / raw)
To: Jan Beulich
Cc: kevin.tian, sstabellini, suravee.suthikulpanit, andrew.cooper3,
xen-devel, julien.grall, tamas, jun.nakajima, boris.ostrovsky
In-Reply-To: <582313E5020000780011D518@prv-mh.provo.novell.com>
On 11/09/2016 01:17 PM, Jan Beulich wrote:
>> @@ -259,6 +266,13 @@ struct vm_event_cpuid {
>> > uint32_t _pad;
>> > };
>> >
>> > +struct vm_event_interrupt {
>> > + uint32_t vector;
>> > + uint32_t type;
>> > + uint32_t error_code;
>> > + uint64_t cr2;
>> > +};
> This being x86-specific, I think it should be named or union-ized
> accordingly.
I think I should also pad this to be a multiple of 64 bits as the others
are (with a uint32_t _pad; member).
Thanks,
Razvan
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply
* Re: amd756 driver error introduced with kernel-4.9.0-0.rc1.git0.2.fc26
From: Jean Delvare @ 2016-11-09 13:54 UTC (permalink / raw)
To: Johnny Bieren; +Cc: linux-i2c
In-Reply-To: <58221469.50005@redhat.com>
On Tue, 8 Nov 2016 13:07:37 -0500, Johnny Bieren wrote:
> No, that option is not enabled.
>
> cat /boot/config-4.9.0-0.rc1.git0.2.fc26.x86_64 | grep DEBUG_TEST
> # CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
Then I don't know. I can't see how the only recent change to the
i2c-amd756 driver (ea734404f3daf1f6b5103171d848c9d4641fd96b) could
cause this. The warning comes from:
WARN_ON(!list_empty(&dev->devres_head));
which was added a decade ago so nothing new here.
I'm out of ideas. The only way to move forward is to bisect it to find
out the exact commit which triggered the warning.
--
Jean Delvare
SUSE L3 Support
^ permalink raw reply
* [PATCH V5 2/3] ARM64 LPC: Add missing range exception for special ISA
From: One Thousand Gnomes @ 2016-11-09 13:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2368890.jTbyGqYR0M@wuerfel>
> I think it is a relatively safe assumption that there is only one
> ISA bridge. A lot of old drivers hardcode PIO or memory addresses
It's not a safe assumption for x86 at least. There are a few systems with
multiple ISA busses particularly older laptops with a docking station.
> when talking to an ISA device, so having multiple instances is
> already problematic.
PCMCIA devices handle it themselves so are ok. I'm not clear how the dual
PIIX4 configuration used in the older IBM laptop docks actually worked so
I assume the transaction went out of both bridges and providing one of
them responded the other kept silent as you simply stuffed the card into
the dock and it worked.
Alan
^ permalink raw reply
* Re: [PATCH] sequencer: silence -Wtautological-constant-out-of-range-compare
From: Johannes Schindelin @ 2016-11-09 13:54 UTC (permalink / raw)
To: Jeff King; +Cc: git, Lars Schneider
In-Reply-To: <20161109035728.v2mqvtj4ep4dj74j@sigill.intra.peff.net>
Hi Peff,
On Tue, 8 Nov 2016, Jeff King wrote:
> diff --git a/sequencer.c b/sequencer.c
> index 5fd75f30d..6f0ff9e41 100644
> --- a/sequencer.c
> +++ b/sequencer.c
> @@ -629,7 +629,7 @@ static const char *todo_command_strings[] = {
>
> static const char *command_to_string(const enum todo_command command)
> {
> - if (command < ARRAY_SIZE(todo_command_strings))
> + if ((size_t)command < ARRAY_SIZE(todo_command_strings))
> return todo_command_strings[command];
> die("Unknown command: %d", command);
I have come to prefer a slightly different approach. Will send it out in a
moment.
Ciao,
Dscho
^ permalink raw reply
* [Buildroot] [PATCH] qt5webkit: Get sources from Qt-5-unofficial-builds
From: Алексей Бродкин @ 2016-11-09 13:55 UTC (permalink / raw)
To: buildroot
In-Reply-To: <6163885.zDEeHnFoFK@sagittea>
Hi J?r?me,
2016-11-09 16:31 GMT+03:00 J?r?me Pouiller <jezz@sysmic.org>:
>
> Hello Alexey,
>
> On Wednesday 09 November 2016 15:38:05 Alexey Brodkin wrote:
> [...]
> > --- a/package/qt5/qt5.mk
> > +++ b/package/qt5/qt5.mk
> > @@ -1,6 +1,7 @@
> > QT5_VERSION_MAJOR = 5.6
> > QT5_VERSION = $(QT5_VERSION_MAJOR).2
> > QT5_SITE = http://download.qt.io/official_releases/qt/$(QT5_VERSION_MAJOR)/$(QT5_VERSION)/submodules
> > +QT5_SNAPSHOTS_SITE = http://download.qt.io/snapshots/qt/$(QT5_VERSION_MAJOR)/$(QT5_VERSION)/latest_src/submodules
>
> Is it possible to also use snapshots site for official modules?
I think it's possible, see
http://download.qt.io/snapshots/qt/5.6/5.6.2/latest_src/submodules/
But I'd prefer to stick to official release paths for officially
supported submodules.
Just in case "snapshots" stuff gets purged at some point in time.
> [...]
> > --- a/package/qt5/qt5webkit/qt5webkit.mk
> > +++ b/package/qt5/qt5webkit/qt5webkit.mk
> > @@ -4,10 +4,9 @@
> > #
> > ################################################################################
> >
> > -QT5WEBKIT_VERSION = b35917bcb44d7f200af0f4ac68a126fa0aa8d93d
> > -# Using GitHub since it supports downloading tarballs from random commits.
> > -# The http://code.qt.io/cgit/qt/qtwebkit.git/ repo doesn't allow to do so.
> > -QT5WEBKIT_SITE = $(call github,qtproject,qtwebkit,$(QT5WEBKIT_VERSION))
> > +QT5WEBKIT_VERSION = $(QT5_VERSION)
> > +QT5WEBKIT_SITE = $(QT5_SNAPSHOTS_SITE)
> > +QT5WEBKIT_SOURCE = qtwebkit-opensource-src-$(QT5WEBKIT_EXAMPLES_VERSION).tar.xz
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> You mean QT5WEBKIT_VERSION?
Did I send it? Oh boy... I was daydreaming most probably.
That's how people and companies leak their secrets :)
I was trying to bring WebkitExamples back in BR and this one was a prerequisite
that simplifies recovery of WebkitExamples sources. That said the
patch was build-tested
but with another patch on top of it and so I didn't catch this copy-pasta.
Will do a respin now.
-Alexey
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.