* [RFC PATCH 1/1] BPF JIT for PPC64
From: Matt Evans @ 2011-06-24 6:02 UTC (permalink / raw)
To: netdev, linuxppc-dev
arch/powerpc/Kconfig | 1 +
arch/powerpc/Makefile | 3 +-
arch/powerpc/include/asm/ppc-opcode.h | 40 ++
arch/powerpc/net/Makefile | 4 +
arch/powerpc/net/bpf_jit.S | 138 +++++++
arch/powerpc/net/bpf_jit.h | 226 +++++++++++
arch/powerpc/net/bpf_jit_comp.c | 697 +++++++++++++++++++++++++++++++++
7 files changed, 1108 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2729c66..39860fc 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -134,6 +134,7 @@ config PPC
select GENERIC_IRQ_SHOW_LEVEL
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_SYSCALL_TRACEPOINTS
+ select HAVE_BPF_JIT if PPC64
config EARLY_PRINTK
bool
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index b7212b6..b94740f 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -154,7 +154,8 @@ core-y += arch/powerpc/kernel/ \
arch/powerpc/lib/ \
arch/powerpc/sysdev/ \
arch/powerpc/platforms/ \
- arch/powerpc/math-emu/
+ arch/powerpc/math-emu/ \
+ arch/powerpc/net/
core-$(CONFIG_XMON) += arch/powerpc/xmon/
core-$(CONFIG_KVM) += arch/powerpc/kvm/
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index e472659..e980faa 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -71,6 +71,42 @@
#define PPC_INST_ERATSX 0x7c000126
#define PPC_INST_ERATSX_DOT 0x7c000127
+/* Misc instructions for BPF compiler */
+#define PPC_INST_LD 0xe8000000
+#define PPC_INST_LHZ 0xa0000000
+#define PPC_INST_LWZ 0x80000000
+#define PPC_INST_STD 0xf8000000
+#define PPC_INST_STDU 0xf8000001
+#define PPC_INST_MFLR 0x7c0802a6
+#define PPC_INST_MTLR 0x7c0803a6
+#define PPC_INST_CMPWI 0x2c000000
+#define PPC_INST_CMPDI 0x2c200000
+#define PPC_INST_CMPLW 0x7c000040
+#define PPC_INST_CMPLWI 0x28000000
+#define PPC_INST_ADDI 0x38000000
+#define PPC_INST_ADDIS 0x3c000000
+#define PPC_INST_ADD 0x7c000214
+#define PPC_INST_SUB 0x7c000050
+#define PPC_INST_BLR 0x4e800020
+#define PPC_INST_BLRL 0x4e800021
+#define PPC_INST_MULLW 0x7c0001d6
+#define PPC_INST_MULHWU 0x7c000016
+#define PPC_INST_MULLI 0x1c000000
+#define PPC_INST_DIVWU 0x7c0003d6
+#define PPC_INST_RLWINM 0x54000000
+#define PPC_INST_RLDICR 0x78000004
+#define PPC_INST_SLW 0x7c000030
+#define PPC_INST_SRW 0x7c000430
+#define PPC_INST_AND 0x7c000038
+#define PPC_INST_ANDDOT 0x7c000039
+#define PPC_INST_OR 0x7c000378
+#define PPC_INST_ANDI 0x70000000
+#define PPC_INST_ORI 0x60000000
+#define PPC_INST_ORIS 0x64000000
+#define PPC_INST_NEG 0x7c0000d0
+#define PPC_INST_BRANCH 0x48000000
+#define PPC_INST_BRANCH_COND 0x40800000
+
/* macros to insert fields into opcodes */
#define __PPC_RA(a) (((a) & 0x1f) << 16)
#define __PPC_RB(b) (((b) & 0x1f) << 11)
@@ -83,6 +119,10 @@
#define __PPC_T_TLB(t) (((t) & 0x3) << 21)
#define __PPC_WC(w) (((w) & 0x3) << 21)
#define __PPC_WS(w) (((w) & 0x1f) << 11)
+#define __PPC_SH(s) __PPC_WS(s)
+#define __PPC_MB(s) (((s) & 0x1f) << 6)
+#define __PPC_ME(s) (((s) & 0x1f) << 1)
+#define __PPC_BI(s) (((s) & 0x1f) << 16)
/*
* Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a
diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile
new file mode 100644
index 0000000..90568c3
--- /dev/null
+++ b/arch/powerpc/net/Makefile
@@ -0,0 +1,4 @@
+#
+# Arch-specific network modules
+#
+obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o
diff --git a/arch/powerpc/net/bpf_jit.S b/arch/powerpc/net/bpf_jit.S
new file mode 100644
index 0000000..ce2225e
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit.S
@@ -0,0 +1,138 @@
+/* bpf_jit.S: Packet/header access helper functions
+ * for PPC64 BPF compiler.
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <asm/ppc_asm.h>
+#include "bpf_jit.h"
+
+/*
+ * All of these routines are called directly from generated code,
+ * whose register usage is:
+ *
+ * r3 skb
+ * r4,r5 A,X
+ * r6 *** address parameter to helper ***
+ * r7-r10 scratch
+ * r14 skb->data
+ * r15 skb headlen
+ * r16-31 M[]
+ */
+
+/*
+ * To consider: These helpers are so small it may be better to just
+ * generate them inline. They're out here for debug at the moment,
+ * but inline code can do the simple headlen check then branch
+ * directly to slow_path_XXX if required. (In fact, could load a spare
+ * GPR with slow_path_generic and pass size as an argument.)
+ *
+ * Technically, the "is addr < 0" check is unnecessary & slowing down
+ * the ABS path, as it's statically checked on generation.
+ */
+ .globl sk_load_word
+sk_load_word:
+ cmpdi r_addr, 0
+ blt bpf_error
+ /* Are we accessing past headlen? */
+ subi r_scratch1, r_HL, 4
+ cmpd r_scratch1, r_addr
+ blt bpf_slow_path_word
+ /* Nope, just hitting the header. cr0 here is eq or gt! */
+ lwzx r_A, r_D, r_addr
+ /* When big endian we don't need to byteswap. */
+ blr /* Return success, cr0 != LT */
+
+ .globl sk_load_half
+sk_load_half:
+ cmpdi r_addr, 0
+ blt bpf_error
+ subi r_scratch1, r_HL, 2
+ cmpd r_scratch1, r_addr
+ blt bpf_slow_path_half
+ lhzx r_A, r_D, r_addr
+ blr
+
+ .globl sk_load_byte
+sk_load_byte:
+ cmpdi r_addr, 0
+ blt bpf_error
+ cmpd r_HL, r_addr
+ ble bpf_slow_path_byte
+ lbzx r_A, r_D, r_addr
+ blr
+
+/*
+ * BPF_S_LDX_B_MSH: ldxb 4*([offset]&0xf)
+ * r_addr is the offset value, already known positive
+ */
+ .globl sk_load_byte_msh
+sk_load_byte_msh:
+ cmpd r_HL, r_addr
+ ble bpf_slow_path_byte_msh
+ lbzx r_X, r_D, r_addr
+ rlwinm r_X, r_X, 2, 32-4-2, 31-2
+ blr
+
+bpf_error:
+ /* Entered with cr0 = lt */
+ li r3, 0
+ /* Generated code will 'blt epilogue', returning 0. */
+ blr
+
+/* Call out to skb_copy_bits:
+ * We'll need to back up our volatile regs first; we have
+ * local variable space at r1+(BPF_PPC_STACK_BASIC).
+ * Allocate a new stack frame here to remain ABI-compliant in
+ * stashing LR.
+ */
+#define bpf_slow_path_common(SIZE) \
+ mflr r0; \
+ std r0, 16(r1); \
+ /* R3 goes in parameter space of caller's frame */ \
+ std r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
+ std r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
+ std r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
+ stdu r1, -128(r1); \
+ /* R3 = r_skb, as passed */ \
+ mr r4, r_addr; \
+ addi r5, r1, 128+BPF_PPC_STACK_BASIC+(2*8); \
+ li r6, SIZE; \
+ bl skb_copy_bits; \
+ /* R3 = 0 on success */ \
+ addi r1, r1, 128; \
+ ld r0, 16(r1); \
+ ld r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
+ ld r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
+ mtlr r0; \
+ cmpdi r3, 0; \
+ blt bpf_error; /* cr0 = LT */ \
+ ld r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
+ /* Great success! */
+
+bpf_slow_path_word:
+ bpf_slow_path_common(4)
+ /* Data value is on stack, and cr0 != LT */
+ lwz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ blr
+
+bpf_slow_path_half:
+ bpf_slow_path_common(2)
+ lhz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ blr
+
+bpf_slow_path_byte:
+ bpf_slow_path_common(1)
+ lbz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ blr
+
+bpf_slow_path_byte_msh:
+ bpf_slow_path_common(1)
+ lbz r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
+ rlwinm r_X, r_X, 2, 32-4-2, 31-2
+ blr
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
new file mode 100644
index 0000000..1fe54b9
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit.h
@@ -0,0 +1,226 @@
+/* bpf_jit.h: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _BPF_JIT_H
+#define _BPF_JIT_H
+
+#define BPF_PPC_STACK_LOCALS 32
+#define BPF_PPC_STACK_BASIC 112
+#define BPF_PPC_STACK_SAVE 128
+#define BPF_PPC_STACKFRAME (BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \
+ BPF_PPC_STACK_SAVE)
+
+/*
+ * Generated code register usage:
+ *
+ * As normal PPC C ABI (e.g. r1=sp, r2=TOC), with:
+ *
+ * skb r3 (Entry parameter)
+ * A register r4
+ * X register r5
+ * addr param r6
+ * r7-r10 scratch
+ * skb->data r14
+ * skb headlen r15 (skb->len - skb->data_len)
+ * m[0] r16
+ * m[...] ...
+ * m[15] r31
+ */
+#define r_skb 3
+#define r_ret 3
+#define r_A 4
+#define r_X 5
+#define r_addr 6
+#define r_scratch1 7
+#define r_D 14
+#define r_HL 15
+#define r_M 16
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Assembly helpers from arch/powerpc/net/bpf_jit.S:
+ */
+extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
+
+#define FUNCTION_DESCR_SIZE 24
+
+/*
+ * 16-bit immediate helper macros: HA() is for use with sign-extending instrs
+ * (e.g. LD, ADDI). If the bottom 16 bits is "-ve", add another bit into the
+ * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000).
+ */
+#define IMM_H(i) ((uintptr_t)(i)>>16)
+#define IMM_HA(i) (((uintptr_t)(i)>>16) + \
+ (((uintptr_t)(i) & 0x8000) >> 15))
+#define IMM_L(i) ((uintptr_t)(i) & 0xffff)
+
+#define PLANT_INSTR(d, idx, instr) \
+ do { if (d) { (d)[idx] = instr; } idx++; } while (0)
+#define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr)
+
+#define PPC_NOP() EMIT(PPC_INST_NOP)
+#define PPC_BLR() EMIT(PPC_INST_BLR)
+#define PPC_BLRL() EMIT(PPC_INST_BLRL)
+#define PPC_MTLR(r) EMIT(PPC_INST_MTLR | __PPC_RT(r))
+#define PPC_ADDI(d, a, i) EMIT(PPC_INST_ADDI | __PPC_RT(d) | \
+ __PPC_RA(a) | IMM_L(i))
+#define PPC_MR(d, a) PPC_OR(d, a, a)
+#define PPC_LI(r, i) PPC_ADDI(r, 0, i)
+#define PPC_ADDIS(d, a, i) EMIT(PPC_INST_ADDIS | \
+ __PPC_RS(d) | __PPC_RA(a) | IMM_L(i))
+#define PPC_LIS(r, i) PPC_ADDIS(r, 0, i)
+#define PPC_STD(r, base, i) EMIT(PPC_INST_STD | __PPC_RS(r) | \
+ __PPC_RA(base) | ((i) & 0xfffc))
+
+#define PPC_LD(r, base, i) EMIT(PPC_INST_LD | __PPC_RT(r) | \
+ __PPC_RA(base) | IMM_L(i))
+#define PPC_LWZ(r, base, i) EMIT(PPC_INST_LWZ | __PPC_RT(r) | \
+ __PPC_RA(base) | IMM_L(i))
+#define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | __PPC_RT(r) | \
+ __PPC_RA(base) | IMM_L(i))
+/* Convenience helpers for the above with 'far' offsets: */
+#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \
+ else { PPC_ADDIS(r, base, IMM_HA(i)); \
+ PPC_LD(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LWZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LWZ(r, base, i); \
+ else { PPC_ADDIS(r, base, IMM_HA(i)); \
+ PPC_LWZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LHZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LHZ(r, base, i); \
+ else { PPC_ADDIS(r, base, IMM_HA(i)); \
+ PPC_LHZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_CMPWI(a, i) EMIT(PPC_INST_CMPWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPDI(a, i) EMIT(PPC_INST_CMPDI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLWI(a, i) EMIT(PPC_INST_CMPLWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLW(a, b) EMIT(PPC_INST_CMPLW | __PPC_RA(a) | __PPC_RB(b))
+
+#define PPC_SUB(d, a, b) EMIT(PPC_INST_SUB | __PPC_RT(d) | \
+ __PPC_RB(a) | __PPC_RA(b))
+#define PPC_ADD(d, a, b) EMIT(PPC_INST_ADD | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MUL(d, a, b) EMIT(PPC_INST_MULLW | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULHWU(d, a, b) EMIT(PPC_INST_MULHWU | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULI(d, a, i) EMIT(PPC_INST_MULLI | __PPC_RT(d) | \
+ __PPC_RA(a) | IMM_L(i))
+#define PPC_DIVWU(d, a, b) EMIT(PPC_INST_DIVWU | __PPC_RT(d) | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_AND(d, a, b) EMIT(PPC_INST_AND | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ANDI(d, a, i) EMIT(PPC_INST_ANDI | __PPC_RA(d) | \
+ __PPC_RS(a) | IMM_L(i))
+#define PPC_AND_DOT(d, a, b) EMIT(PPC_INST_ANDDOT | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(b))
+#define PPC_OR(d, a, b) EMIT(PPC_INST_OR | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ORI(d, a, i) EMIT(PPC_INST_ORI | __PPC_RA(d) | \
+ __PPC_RS(a) | IMM_L(i))
+#define PPC_ORIS(d, a, i) EMIT(PPC_INST_ORIS | __PPC_RA(d) | \
+ __PPC_RS(a) | IMM_L(i))
+#define PPC_SLW(d, a, s) EMIT(PPC_INST_SLW | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(s))
+#define PPC_SRW(d, a, s) EMIT(PPC_INST_SRW | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_RB(s))
+/* slwi = rlwinm Rx, Ry, n, 0, 31-n */
+#define PPC_SLWI(d, a, i) EMIT(PPC_INST_RLWINM | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_SH(i) | \
+ __PPC_MB(0) | __PPC_ME(31-(i)))
+/* srwi = rlwinm Rx, Ry, 32-n, n, 31 */
+#define PPC_SRWI(d, a, i) EMIT(PPC_INST_RLWINM | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_SH(32-(i)) | \
+ __PPC_MB(i) | __PPC_ME(31))
+/* sldi = rldicr Rx, Ry, n, 63-n */
+#define PPC_SLDI(d, a, i) EMIT(PPC_INST_RLDICR | __PPC_RA(d) | \
+ __PPC_RS(a) | __PPC_SH(i) | \
+ __PPC_MB(63-(i)) | (((i) & 0x20) >> 4))
+#define PPC_NEG(d, a) EMIT(PPC_INST_NEG | __PPC_RT(d) | __PPC_RA(a))
+
+/* Long jump; (unconditional 'branch') */
+#define PPC_JMP(dest) EMIT(PPC_INST_BRANCH | \
+ (((dest) - (ctx->idx * 4)) & 0x03fffffc))
+/* "cond" here covers BO:BI fields. */
+#define PPC_BCC_SHORT(cond, dest) EMIT(PPC_INST_BRANCH_COND | \
+ (((cond) & 0x3ff) << 16) | \
+ (((dest) - (ctx->idx * 4)) & \
+ 0xfffc))
+#define PPC_LI32(d, i) do { PPC_LI(d, IMM_L(i)); \
+ if ((u32)(uintptr_t)(i) >= 32768) { \
+ PPC_ADDIS(d, d, IMM_HA(i)); \
+ } } while(0)
+#define PPC_LI64(d, i) do { \
+ if (!((uintptr_t)(i) & 0xffffffff00000000ULL)) \
+ PPC_LI32(d, i); \
+ else { \
+ PPC_LIS(d, ((uintptr_t)(i) >> 48)); \
+ if ((uintptr_t)(i) & 0x0000ffff00000000ULL) \
+ PPC_ORI(d, d, \
+ ((uintptr_t)(i) >> 32) & 0xffff); \
+ PPC_SLDI(d, d, 32); \
+ if ((uintptr_t)(i) & 0x00000000ffff0000ULL) \
+ PPC_ORIS(d, d, \
+ ((uintptr_t)(i) >> 16) & 0xffff); \
+ if ((uintptr_t)(i) & 0x000000000000ffffULL) \
+ PPC_ORI(d, d, (uintptr_t)(i) & 0xffff); \
+ } } while (0);
+
+static inline bool is_nearbranch(int offset)
+{
+ return (offset < 32768) && (offset >= -32768);
+}
+
+/*
+ * The fly in the ointment of code size changing from pass to pass is
+ * avoided by padding the short branch case with a NOP. If code size differs
+ * with different branch reaches we will have the issue of code moving from
+ * one pass to the next and will need a few passes to converge on a stable
+ * state.
+ */
+#define PPC_BCC(cond, dest) do { \
+ if (is_nearbranch((dest) - (ctx->idx * 4))) { \
+ PPC_BCC_SHORT(cond, dest); \
+ PPC_NOP(); \
+ } else { \
+ /* Flip the 'T or F' bit to invert comparison */ \
+ PPC_BCC_SHORT(cond ^ COND_CMP_TRUE, (ctx->idx+2)*4); \
+ PPC_JMP(dest); \
+ } } while(0)
+
+/* To create a branch condition, select a bit of cr0... */
+#define CR0_LT 0
+#define CR0_GT 1
+#define CR0_EQ 2
+/* ...and modify BO[3] */
+#define COND_CMP_TRUE 0x100
+#define COND_CMP_FALSE 0x000
+/* Together, they make all required comparisons: */
+#define COND_GT (CR0_GT | COND_CMP_TRUE)
+#define COND_GE (CR0_LT | COND_CMP_FALSE)
+#define COND_EQ (CR0_EQ | COND_CMP_TRUE)
+#define COND_NE (CR0_EQ | COND_CMP_FALSE)
+#define COND_LT (CR0_LT | COND_CMP_TRUE)
+
+#define SEEN_DATAREF 0x10000 /* might call external helpers */
+#define SEEN_XREG 0x20000 /* X reg is used */
+#define SEEN_MEM 0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary
+ * storage */
+#define SEEN_MEM_MSK 0x0ffff
+
+struct codegen_context {
+ unsigned int seen;
+ unsigned int idx;
+ int pc_ret0; /* bpf index of first RET #0 instruction (if any) */
+};
+
+#endif
+
+#endif
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
new file mode 100644
index 0000000..8a76350
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -0,0 +1,697 @@
+/* bpf_jit_comp.c: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * Based on the x86 BPF compiler, by Eric Dumazet (eric.dumazet@gmail.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#include <linux/moduleloader.h>
+#include <asm/cacheflush.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include "bpf_jit.h"
+
+#ifndef __BIG_ENDIAN
+/* There are endianness assumptions herein. */
+#error "Little-endian PPC not supported in BPF compiler"
+#endif
+
+int bpf_jit_enable __read_mostly;
+
+
+static inline void bpf_flush_icache(void *start, void *end)
+{
+ smp_wmb();
+ flush_icache_range((unsigned long)start, (unsigned long)end);
+}
+
+static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
+ struct codegen_context *ctx)
+{
+ int i;
+ const struct sock_filter *filter = fp->insns;
+
+ if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+ /* Make stackframe */
+ if (ctx->seen & SEEN_DATAREF) {
+ /* If we call any helpers (for loads), save LR */
+ EMIT(PPC_INST_MFLR | __PPC_RT(0));
+ PPC_STD(0, 1, 16);
+
+ /* Back up non-volatile regs. */
+ PPC_STD(r_D, 1, -(8*(32-r_D)));
+ PPC_STD(r_HL, 1, -(8*(32-r_HL)));
+ }
+ if (ctx->seen & SEEN_MEM) {
+ /*
+ * Conditionally save regs r15-r31 as some will be used
+ * for M[] data.
+ */
+ for (i = 0; i < 16; i++) {
+ if (ctx->seen & (1 << i))
+ PPC_STD(r_M + i, 1, -128 + (8*i));
+ }
+ }
+ EMIT(PPC_INST_STDU | __PPC_RS(1) | __PPC_RA(1) |
+ (-BPF_PPC_STACKFRAME & 0xfffc));
+ }
+
+ if (ctx->seen & SEEN_DATAREF) {
+ /*
+ * If this filter needs to access skb data,
+ * prepare r_D and r_HL:
+ * r_HL = skb->len - skb->data_len
+ * r_D = skb->data
+ */
+ PPC_LWZ_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+ data_len));
+ PPC_LWZ_OFFS(r_HL, r_skb, offsetof(struct sk_buff, len));
+ PPC_SUB(r_HL, r_HL, r_scratch1);
+ PPC_LD_OFFS(r_D, r_skb, offsetof(struct sk_buff, data));
+ }
+
+ if (ctx->seen & SEEN_XREG) {
+ /*
+ * TODO: Could also detect whether first instr. sets X and
+ * avoid this (as below, with A).
+ */
+ PPC_LI(r_X, 0);
+ }
+
+ switch (filter[0].code) {
+ case BPF_S_RET_K:
+ case BPF_S_LD_W_LEN:
+ case BPF_S_ANC_PROTOCOL:
+ case BPF_S_ANC_IFINDEX:
+ case BPF_S_ANC_MARK:
+ case BPF_S_ANC_RXHASH:
+ case BPF_S_ANC_CPU:
+ case BPF_S_ANC_QUEUE:
+ case BPF_S_LD_W_ABS:
+ case BPF_S_LD_H_ABS:
+ case BPF_S_LD_B_ABS:
+ /* first instruction sets A register (or is RET 'constant') */
+ break;
+ default:
+ /* make sure we dont leak kernel information to user */
+ PPC_LI(r_A, 0);
+ }
+}
+
+static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
+{
+ int i;
+
+ if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+ PPC_ADDI(1, 1, BPF_PPC_STACKFRAME);
+ if (ctx->seen & SEEN_DATAREF) {
+ PPC_LD(0, 1, 16);
+ PPC_MTLR(0);
+ PPC_LD(r_D, 1, -(8*(32-r_D)));
+ PPC_LD(r_HL, 1, -(8*(32-r_HL)));
+ }
+ if (ctx->seen & SEEN_MEM) {
+ /* Restore any saved non-vol registers */
+ for (i = 0; i < 16; i++) {
+ if (ctx->seen & (1 << i))
+ PPC_LD(r_M + i, 1, -128 + (8*i));
+ }
+ }
+ }
+ /* The RETs have left a return value in R3. */
+
+ PPC_BLR();
+}
+
+/* Assemble the body code between the prologue & epilogue. */
+static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
+ struct codegen_context *ctx,
+ unsigned int *addrs)
+{
+ const struct sock_filter *filter = fp->insns;
+ int flen = fp->len;
+ u8 *func;
+ unsigned int true_cond;
+ int i;
+
+ /* Start of epilogue code */
+ unsigned int exit_addr = addrs[flen];
+
+ for (i = 0; i < flen; i++) {
+ unsigned int K = filter[i].k;
+
+ /*
+ * addrs[] maps a BPF bytecode address into a real offset from
+ * the start of the body code.
+ */
+ addrs[i] = ctx->idx * 4;
+
+ switch (filter[i].code) {
+ /*** ALU ops ***/
+ case BPF_S_ALU_ADD_X: /* A += X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_ADD(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_ADD_K: /* A += K; */
+ if (!K)
+ break;
+ if (K < 32768)
+ PPC_ADDI(r_A, r_A, K);
+ else
+ PPC_ADDI(r_A, r_A, IMM_L(K));
+ PPC_ADDIS(r_A, r_A, IMM_HA(K));
+ break;
+ case BPF_S_ALU_SUB_X: /* A -= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_SUB(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_SUB_K: /* A -= K */
+ if (!K)
+ break;
+ if (K < 32768)
+ PPC_ADDI(r_A, r_A, -K);
+ else
+ PPC_ADDI(r_A, r_A, IMM_L(-K));
+ PPC_ADDIS(r_A, r_A, IMM_HA(-K));
+ break;
+ case BPF_S_ALU_MUL_X: /* A *= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_MUL(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_MUL_K: /* A *= K */
+ if (K < 32768)
+ PPC_MULI(r_A, r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_MUL(r_A, r_A, r_scratch1);
+ }
+ break;
+ case BPF_S_ALU_DIV_X: /* A /= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_CMPWI(r_X, 0);
+ if (ctx->pc_ret0 != -1) {
+ PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+ } else {
+ /*
+ * Exit, returning 0; first pass hits here
+ * (longer worst-case code size).
+ */
+ PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+ PPC_LI(r_ret, 0);
+ PPC_JMP(exit_addr);
+ }
+ PPC_DIVWU(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+ PPC_LI32(r_scratch1, K);
+ /* Top 32 bits of 64bit result -> A */
+ PPC_MULHWU(r_A, r_A, r_scratch1);
+ break;
+ case BPF_S_ALU_AND_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_AND(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_AND_K:
+ if (!IMM_H(K))
+ PPC_ANDI(r_A, r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_AND(r_A, r_A, r_scratch1);
+ }
+ break;
+ case BPF_S_ALU_OR_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_OR(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_OR_K:
+ if (IMM_L(K))
+ PPC_ORI(r_A, r_A, IMM_L(K));
+ if (K >= 65536)
+ PPC_ORIS(r_A, r_A, IMM_H(K));
+ break;
+ case BPF_S_ALU_LSH_X: /* A <<= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_SLW(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_LSH_K:
+ if (K == 0)
+ break;
+ else
+ PPC_SLWI(r_A, r_A, K);
+ break;
+ case BPF_S_ALU_RSH_X: /* A >>= X; */
+ ctx->seen |= SEEN_XREG;
+ PPC_SRW(r_A, r_A, r_X);
+ break;
+ case BPF_S_ALU_RSH_K: /* A >>= K; */
+ if (K == 0)
+ break;
+ else
+ PPC_SRWI(r_A, r_A, K);
+ break;
+ case BPF_S_ALU_NEG:
+ PPC_NEG(r_A, r_A);
+ break;
+ case BPF_S_RET_K:
+ PPC_LI32(r_ret, K);
+ if (!K) {
+ if (ctx->pc_ret0 == -1)
+ ctx->pc_ret0 = i;
+ }
+ /*
+ * If this isn't the very last instruction, branch to
+ * the epilogue if we've stuff to clean up. Otherwise,
+ * if there's nothing to tidy, just return. If we /are/
+ * the last instruction, we're about to fall through to
+ * the epilogue to return.
+ */
+ if (i != flen - 1) {
+ /*
+ * Note: 'seen' is properly valid only on pass
+ * #2. Both parts of this conditional are the
+ * same instruction size though, meaning the
+ * first pass will still correctly determine the
+ * code size/addresses.
+ */
+ if (ctx->seen)
+ PPC_JMP(exit_addr);
+ else
+ PPC_BLR();
+ }
+ break;
+ case BPF_S_RET_A:
+ PPC_MR(r_ret, r_A);
+ if (i != flen - 1) {
+ if (ctx->seen)
+ PPC_JMP(exit_addr);
+ else
+ PPC_BLR();
+ }
+ break;
+ case BPF_S_MISC_TAX: /* X = A */
+ ctx->seen |= SEEN_XREG;
+ PPC_MR(r_X, r_A);
+ break;
+ case BPF_S_MISC_TXA: /* A = X */
+ ctx->seen |= SEEN_XREG;
+ PPC_MR(r_A, r_X);
+ break;
+
+ /*** Constant loads/M[] access ***/
+ case BPF_S_LD_IMM: /* A = K */
+ PPC_LI32(r_A, K);
+ break;
+ case BPF_S_LDX_IMM: /* X = K */
+ ctx->seen |= SEEN_XREG;
+ PPC_LI32(r_X, K);
+ break;
+ case BPF_S_LD_MEM: /* A = mem[K] */
+ PPC_MR(r_A, r_M + (K & 0xf));
+ ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_LDX_MEM: /* X = mem[K] */
+ PPC_MR(r_X, r_M + (K & 0xf));
+ ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_ST: /* mem[K] = A */
+ PPC_MR(r_M + (K & 0xf), r_A);
+ ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_STX: /* mem[K] = X */
+ PPC_MR(r_M + (K & 0xf), r_X);
+ ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
+ break;
+ case BPF_S_LD_W_LEN: /* A = skb->len; */
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+ PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, len));
+ break;
+ case BPF_S_LDX_W_LEN: /* X = skb->len; */
+ ctx->seen |= SEEN_XREG;
+ PPC_LWZ_OFFS(r_X, r_skb, offsetof(struct sk_buff, len));
+ break;
+
+ /*** Ancillary info loads ***/
+
+ /* None of the BPF_S_ANC* codes appear to be passed by
+ * sk_chk_filter(). The interpreter and the x86 BPF
+ * compiler implement them so we do too -- they may be
+ * planted in future.
+ */
+ case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ protocol) != 2);
+ PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ protocol));
+ /* ntohs is a NOP with BE loads. */
+ break;
+ case BPF_S_ANC_IFINDEX:
+ PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+ dev));
+ PPC_CMPDI(r_scratch1, 0);
+ if (ctx->pc_ret0 != -1) {
+ PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+ } else {
+ /* Exit, returning 0; first pass hits here. */
+ PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+ PPC_LI(r_ret, 0);
+ PPC_JMP(exit_addr);
+ }
+ BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+ ifindex) != 4);
+ PPC_LWZ_OFFS(r_A, r_scratch1,
+ offsetof(struct net_device, ifindex));
+ break;
+ case BPF_S_ANC_MARK:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+ PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ mark));
+ break;
+ case BPF_S_ANC_RXHASH:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+ PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ rxhash));
+ break;
+ case BPF_S_ANC_QUEUE:
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+ queue_mapping) != 2);
+ PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+ queue_mapping));
+ break;
+ case BPF_S_ANC_CPU:
+#ifdef CONFIG_SMP
+ /*
+ * PACA ptr is r13:
+ * raw_smp_processor_id() = local_paca->paca_index
+ */
+ PPC_LHZ_OFFS(r_A, 13,
+ offsetof(struct paca_struct, paca_index));
+#else
+ PPC_LI(r_A, 0);
+#endif
+ break;
+
+ /*** Absolute loads from packet header/data ***/
+ case BPF_S_LD_W_ABS:
+ func = sk_load_word;
+ goto common_load;
+ case BPF_S_LD_H_ABS:
+ func = sk_load_half;
+ goto common_load;
+ case BPF_S_LD_B_ABS:
+ func = sk_load_byte;
+ common_load:
+ /*
+ * Load from [K]. Reference with the (negative)
+ * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported.
+ */
+ ctx->seen |= SEEN_DATAREF;
+ if ((int)K < 0)
+ return -ENOTSUPP;
+ PPC_LI64(r_scratch1, func);
+ PPC_MTLR(r_scratch1);
+ PPC_LI32(r_addr, K);
+ PPC_BLRL();
+ /*
+ * Helper returns 'lt' condition on error, and an
+ * appropriate return value in r3
+ */
+ PPC_BCC(COND_LT, exit_addr);
+ break;
+
+ /*** Indirect loads from packet header/data ***/
+ case BPF_S_LD_W_IND:
+ func = sk_load_word;
+ goto common_load_ind;
+ case BPF_S_LD_H_IND:
+ func = sk_load_half;
+ goto common_load_ind;
+ case BPF_S_LD_B_IND:
+ func = sk_load_byte;
+ common_load_ind:
+ /*
+ * Load from [X + K]. Negative offsets are tested for
+ * in the helper functions, and result in a 'ret 0'.
+ */
+ ctx->seen |= SEEN_DATAREF | SEEN_XREG;
+ PPC_LI64(r_scratch1, func);
+ PPC_MTLR(r_scratch1);
+ PPC_ADDI(r_addr, r_X, IMM_L(K));
+ if (K >= 32768)
+ PPC_ADDIS(r_addr, r_addr, IMM_HA(K));
+ PPC_BLRL();
+ /* If error, cr0.LT set */
+ PPC_BCC(COND_LT, exit_addr);
+ break;
+
+ case BPF_S_LDX_B_MSH:
+ /*
+ * x86 version drops packet (RET 0) when K<0, whereas
+ * interpreter does allow K<0 (__load_pointer, special
+ * ancillary data).
+ */
+ ctx->seen |= SEEN_XREG;
+ func = sk_load_byte_msh;
+ goto common_load;
+ break;
+
+ /*** Jump and branches ***/
+ case BPF_S_JMP_JA:
+ PPC_JMP(addrs[i + K]);
+ break;
+
+ case BPF_S_JMP_JGT_K:
+ case BPF_S_JMP_JGT_X:
+ true_cond = COND_GT;
+ goto cond_branch;
+ case BPF_S_JMP_JGE_K:
+ case BPF_S_JMP_JGE_X:
+ true_cond = COND_GE;
+ goto cond_branch;
+ case BPF_S_JMP_JEQ_K:
+ case BPF_S_JMP_JEQ_X:
+ true_cond = COND_EQ;
+ goto cond_branch;
+ case BPF_S_JMP_JSET_K:
+ case BPF_S_JMP_JSET_X:
+ true_cond = COND_NE;
+ /* Fall through */
+ cond_branch:
+ /* same targets, can avoid doing the test :) */
+ if (filter[i].jt == filter[i].jf) {
+ if (filter[i].jt > 0)
+ PPC_JMP(addrs[i + 1 + filter[i].jt]);
+ break;
+ }
+
+ switch (filter[i].code) {
+ case BPF_S_JMP_JGT_X:
+ case BPF_S_JMP_JGE_X:
+ case BPF_S_JMP_JEQ_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_CMPLW(r_A, r_X);
+ break;
+ case BPF_S_JMP_JSET_X:
+ ctx->seen |= SEEN_XREG;
+ PPC_AND_DOT(r_scratch1, r_A, r_X);
+ break;
+ case BPF_S_JMP_JEQ_K:
+ case BPF_S_JMP_JGT_K:
+ case BPF_S_JMP_JGE_K:
+ if (K < 32768)
+ PPC_CMPLWI(r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_CMPLW(r_A, r_scratch1);
+ }
+ break;
+ case BPF_S_JMP_JSET_K:
+ if (K < 32768)
+ /* PPC_ANDI is /only/ dot-form */
+ PPC_ANDI(r_scratch1, r_A, K);
+ else {
+ PPC_LI32(r_scratch1, K);
+ PPC_AND_DOT(r_scratch1, r_A,
+ r_scratch1);
+ }
+ break;
+ }
+ /* Sometimes branches are constructed "backward", with
+ * the false path being the branch and true path being
+ * a fallthrough to the next instruction.
+ */
+ if (filter[i].jt == 0)
+ /* Swap the sense of the branch */
+ PPC_BCC(true_cond ^ COND_CMP_TRUE,
+ addrs[i + 1 + filter[i].jf]);
+ else {
+ PPC_BCC(true_cond, addrs[i + 1 + filter[i].jt]);
+ if (filter[i].jf != 0)
+ PPC_JMP(addrs[i + 1 + filter[i].jf]);
+ }
+ break;
+ default:
+ /* The filter contains something cruel & unusual.
+ * We don't handle it, but also there shouldn't be
+ * anything missing from our list.
+ */
+ pr_err("BPF filter opcode %04x (@%d) unsupported\n",
+ filter[i].code, i);
+ return -ENOTSUPP;
+ }
+
+ }
+ /* Set end-of-body-code address for exit. */
+ addrs[i] = ctx->idx * 4;
+
+ return 0;
+}
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+ unsigned int proglen;
+ unsigned int alloclen;
+ u32 *image = NULL;
+ u32 *code_base;
+ unsigned int *addrs;
+ struct codegen_context cgctx;
+ int pass;
+ int flen = fp->len;
+
+ if (!bpf_jit_enable)
+ return;
+
+ addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL);
+ if (addrs == NULL)
+ return;
+
+ /*
+ * There are multiple assembly passes as the generated code will change
+ * size as it settles down, figuring out the max branch offsets/exit
+ * paths required.
+ *
+ * The range of standard conditional branches is +/- 32Kbytes. Since
+ * BPF_MAXINSNS = 4096, we can only jump from (worst case) start to
+ * finish with 8 bytes/instruction. Not feasible, so long jumps are
+ * used, distinct from short branches.
+ *
+ * Current:
+ *
+ * For now, both branch types assemble to 2 words (short branches padded
+ * with a NOP); this is inefficient, but assembly will always complete
+ * after exactly 3 passes:
+ *
+ * First pass: No code buffer; Program is "faux-generated" -- no code
+ * emitted but maximum size of output determined (and addrs[] filled
+ * in). Also, we note whether we use M[], whether we use skb data, etc.
+ * All generation choices assumed to be 'worst-case', e.g. branches all
+ * far (2 instructions), return path code reduction not available, etc.
+ *
+ * Second pass: Code buffer allocated with size determined previously.
+ * Prologue generated to support features we have seen used. Exit paths
+ * determined and addrs[] is filled in again, as code may be slightly
+ * smaller as a result.
+ *
+ * Third pass: Code generated 'for real', and branch destinations
+ * determined from now-accurate addrs[] map.
+ *
+ * Ideal:
+ *
+ * If we optimise this, near branches will be shorter. On the
+ * first assembly pass, we should err on the side of caution and
+ * generate the biggest code. On subsequent passes, branches will be
+ * generated short or long and code size will reduce. With smaller
+ * code, more branches may fall into the short category, and code will
+ * reduce more.
+ *
+ * Finally, if we see one pass generate code the same size as the
+ * previous pass we have converged and should now generate code for
+ * real. Allocating at the end will also save the memory that would
+ * otherwise be wasted by the (small) current code shrinkage.
+ * Preferably, we should do a small number of passes (e.g. 5) and if we
+ * haven't converged by then, get impatient and force code to generate
+ * as-is, even if the odd branch would be left long. The chances of a
+ * long jump are tiny with all but the most enormous of BPF filter
+ * inputs, so we should usually converge on the third pass.
+ */
+
+ cgctx.idx = 0;
+ cgctx.seen = 0;
+ cgctx.pc_ret0 = -1;
+ /* Scouting faux-generate pass 0 */
+ if (bpf_jit_build_body(fp, 0, &cgctx, addrs))
+ /* We hit something illegal or unsupported. */
+ goto out;
+
+ /*
+ * Pretend to build prologue, given the features we've seen. This will
+ * update ctgtx.idx as it pretends to output instructions, then we can
+ * calculate total size from idx.
+ */
+ bpf_jit_build_prologue(fp, 0, &cgctx);
+ bpf_jit_build_epilogue(0, &cgctx);
+
+ proglen = cgctx.idx * 4;
+ alloclen = proglen + FUNCTION_DESCR_SIZE;
+ image = module_alloc(max_t(unsigned int, alloclen,
+ sizeof(struct work_struct)));
+ if (!image)
+ goto out;
+
+ code_base = image + (FUNCTION_DESCR_SIZE/4);
+
+ /* Code generation passes 1-2 */
+ for (pass = 1; pass < 3; pass++) {
+ /* Now build the prologue, body code & epilogue for real. */
+ cgctx.idx = 0;
+ bpf_jit_build_prologue(fp, code_base, &cgctx);
+ bpf_jit_build_body(fp, code_base, &cgctx, addrs);
+ bpf_jit_build_epilogue(code_base, &cgctx);
+
+ if (bpf_jit_enable > 1)
+ pr_info("Pass %d: shrink = %d, seen = 0x%x\n", pass,
+ proglen - (cgctx.idx * 4), cgctx.seen);
+ }
+
+ if (bpf_jit_enable > 1)
+ pr_info("flen=%d proglen=%u pass=%d image=%p\n",
+ flen, proglen, pass, image);
+
+ if (image) {
+ if (bpf_jit_enable > 1)
+ print_hex_dump(KERN_ERR, "JIT code: ",
+ DUMP_PREFIX_ADDRESS,
+ 16, 1, code_base,
+ proglen, false);
+
+ bpf_flush_icache(code_base, code_base + (proglen/4));
+ /* Function descriptor nastiness: Address + TOC */
+ ((u64 *)image)[0] = (u64)code_base;
+ ((u64 *)image)[1] = local_paca->kernel_toc;
+ fp->bpf_func = (void *)image;
+ }
+out:
+ kfree(addrs);
+ return;
+}
+
+static void jit_free_defer(struct work_struct *arg)
+{
+ module_free(NULL, arg);
+}
+
+/* run from softirq, we must use a work_struct to call
+ * module_free() from process context
+ */
+void bpf_jit_free(struct sk_filter *fp)
+{
+ if (fp->bpf_func != sk_run_filter) {
+ struct work_struct *work = (struct work_struct *)fp->bpf_func;
+
+ INIT_WORK(work, jit_free_defer);
+ schedule_work(work);
+ }
+}
^ permalink raw reply related
* [RFC PATCH 0/1] BPF JIT for PPC64
From: Matt Evans @ 2011-06-24 6:02 UTC (permalink / raw)
To: netdev, linuxppc-dev
Hi,
Inspired by Eric Dumazet's x86-64 compiler for Berkeley Packet Filter programs,
I've written a BPF compiler for 64-bit PowerPC. Although it hasn't finished its
strenuous testing regime, I'll have intermittent net access for a couple of
weeks so thought I'd post it for feedback now and submit a 'proper' version when
I'm back.
It's a fairly simple code generator, following a similar structure to the x86
version. The filter programs are an array of opcode/constant/branch destination
structs, and can perform arithmetic/logical/comparison operations on two virtual
registers A and X, loads from packet headers/data and accesses to local
variables, M[]. Branching is also supported, but only forwards and only within
the extent of the program.
I would probably describe this as more of a "static template binary translator"
than a "JIT" but have kept naming consistent :)
Features include:
- Filter code is generated as an ABI-compliant function, stackframe &
prologue/epilogue if necessary.
- Simple filters (e.g. RET nn) need no stackframe or save/restore code so
generate into only an li/blr.
- Local variables, M[], live in registers
- I believe this supports all BPF opcodes, although "complicated" loads from
negative packet offsets (e.g. SKF_LL_OFF) are not yet supported.
Caveats include: :)
- Packet data loads call out to simple helper functions (bpf_jit.S) which
themselves may fall back to a trampoline to skb_copy_bits. I haven't decided
whether (as per comments there) it would be better to generate the simple
loads inline and only call out in the slow case.
- Branches currently generate to "bcc 1f; b <far dest>; 1:" or
"bcc <near dest> ; nop" so either case is the same size. Multiple passes of
assembly are used (the first gets an idea of how big everything is and what
features are required), the next generates everything at accurate size, the
third generates everything with accurate branch destination addresses); I
intend not to nop-pad the short branch case but changing code size may
result in more passes and a 'settling-down period'. Kept simple for now.
- Anyone running PPC64 little-endian is doing something both interesting and
unsupported for this work :-) (There are some trivial endian assumptions.)
Tested in-situ (tcpdump with varying complexity filters) and with a random BPF
generator; I haven't verified loads from the fall back skb_copy_bits path. Bug
reports/testing would be very welcome.
Cheers,
Matt
^ permalink raw reply
* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Segher Boessenkool @ 2011-06-24 3:50 UTC (permalink / raw)
To: Tabi Timur-B04825
Cc: McClintock Matthew-B29882, Wood Scott-B07421, Gala Kumar-B11780,
paulus@samba.org, linuxppc-dev@ozlabs.org
In-Reply-To: <4E03F8C1.60706@freescale.com>
(context put back:)
>> But does that mean that a guest should never be allowed to modify a
>> virtualized
>> timebase register, even if the hypervisor can support it?
>
> The book3e mtspr writeup doesn't appear to specify the behavior when
> writing to a read-only SPR, so perhaps you could argue that something
> other
> than a no-op is implementation-specific behavior.
>> v2.06 III-E 9.2.1:
>> "Writing the Time Base is hypervisor privileged."
>>
>> v2.06 III-E 2.1:
>> "If a hypervisor-privileged register is accessed in the guest
>> supervisor
>> state (MSR[GS PR] = 0b10), an Embedded Hypervisor Privilege exception
>> occurs."
>>
>> (v2.06 III-E 5.4.1, the big SPR table, also shows the TB regs (for
>> writing,
>> i.e. 284 and 285) to be hypervisor privileged. Consistency, hurray
>> :-) )
>
> To me, all this means that a guest cannot write to the actual timebase
> register.
It also means that the hypervisor gets a trap when a guest tries to do
this.
> I'm not interpreting this to mean that a hypervisor can't
> virtualize the timebase and allow a guest to read/write a virtual
> timebase
> register, so that it thinks it's writing to the real hardware timebase
> register.
Yes, a hypervisor can do this. The behaviour of the hardware is not
implementation-specific (modulo bugs ;-) ); when a guest tries to write
to the timebase, the hypervisor gets a trap. The hypervisor can then
do whatever it wants with it.
Segher
^ permalink raw reply
* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Tabi Timur-B04825 @ 2011-06-24 2:38 UTC (permalink / raw)
To: Segher Boessenkool
Cc: McClintock Matthew-B29882, Wood Scott-B07421, Gala Kumar-B11780,
paulus@samba.org, linuxppc-dev@ozlabs.org
In-Reply-To: <59f786bfaced051a14e2bb75d3d1ce77@kernel.crashing.org>
Segher Boessenkool wrote:
>
> v2.06 III-E 9.2.1:
> "Writing the Time Base is hypervisor privileged."
>
> v2.06 III-E 2.1:
> "If a hypervisor-privileged register is accessed in the guest supervisor
> state (MSR[GS PR] =3D 0b10), an Embedded Hypervisor Privilege exception
> occurs."
>
> (v2.06 III-E 5.4.1, the big SPR table, also shows the TB regs (for writin=
g,
> i.e. 284 and 285) to be hypervisor privileged. Consistency, hurray :-) )
To me, all this means that a guest cannot write to the actual timebase=20
register. I'm not interpreting this to mean that a hypervisor can't=20
virtualize the timebase and allow a guest to read/write a virtual timebase=
=20
register, so that it thinks it's writing to the real hardware timebase regi=
ster.
--=20
Timur Tabi
Linux kernel developer at Freescale=
^ permalink raw reply
* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Segher Boessenkool @ 2011-06-24 2:36 UTC (permalink / raw)
To: Scott Wood
Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
McClintock Matthew-B29882, Gala Kumar-B11780, Timur Tabi
In-Reply-To: <20110623124802.7aeb6b66@schlenkerla.am.freescale.net>
>> But does that mean that a guest should never be allowed to modify a
>> virtualized
>> timebase register, even if the hypervisor can support it?
>
> The book3e mtspr writeup doesn't appear to specify the behavior when
> writing to a read-only SPR, so perhaps you could argue that something
> other
> than a no-op is implementation-specific behavior.
v2.06 III-E 9.2.1:
"Writing the Time Base is hypervisor privileged."
v2.06 III-E 2.1:
"If a hypervisor-privileged register is accessed in the guest supervisor
state (MSR[GS PR] = 0b10), an Embedded Hypervisor Privilege exception
occurs."
(v2.06 III-E 5.4.1, the big SPR table, also shows the TB regs (for
writing,
i.e. 284 and 285) to be hypervisor privileged. Consistency, hurray :-)
)
Segher
^ permalink raw reply
* Re: [PATCH] powerpc, 460gt: Add 460gt as compatible in the check for 460ex-compatible crypto
From: Segher Boessenkool @ 2011-06-24 2:14 UTC (permalink / raw)
To: Mike Williams; +Cc: linuxppc-dev
In-Reply-To: <BANLkTinisHPrEN8Xc_KoqFwxknMooE=H4w@mail.gmail.com>
>>> - =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL,=20
>>> "amcc,ppc460ex-crypto")) {
>>> + =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL,=20
>>> "amcc,ppc460ex-crypto") ||
>>> + =A0 =A0 =A0 =A0 =A0 of_find_compatible_node(NULL, NULL,=20
>>> "amcc,ppc460gt-crypto")) {
>>
>> If the device is actually compatible, the device tree node should=20
>> claim
>> it is, and you do not need this code change.
>
> That was actually my first instinct, however I tried to follow the
> current convention in the glacier and canyonlands DTS files, which is
> to set every device compatible to 460gt or 460ex, depending on the
> processor. Many of the devices are identical between the two, since
> they are variations of the same SoC, so which is the preferred method?
> Follow the device tree convention and add the compatibility check in
> the driver,
That is not the convention.
> or alter the device trees? I'll send another patch if it's
> the latter.
You say
compatible =3D "amcc,ppc460gt-crypto", "amcc,ppc460ex-crypto";
So, a unique name for the actual device first, followed by the name of
what it is compatible to. The driver for 460ex-crypto will then work
without any changes, but it can also do some 460gt-specific workarounds
or enhancements; or you could even have a totally separate driver for
the 460gt-crypto (you'll have to arrange for it to be used preferably
then).
You should document this 460gt-crypto binding, btw (a single line in
the 460ex-crypto binding doc will do).
Segher
^ permalink raw reply
* [PATCH v9 11/13] powerpc: select HAVE_SECCOMP_FILTER and provide seccomp_execve
From: Will Drewry @ 2011-06-24 0:36 UTC (permalink / raw)
To: linux-kernel
Cc: linuxppc-dev, Will Drewry, fweisbec, scarybeasts, djm, jmorris,
rostedt, tglx, mingo, Paul Mackerras, kees.cook, torvalds, segoon
In-Reply-To: <1308875813-20122-1-git-send-email-wad@chromium.org>
Facilitate the use of CONFIG_SECCOMP_FILTER by wrapping compatibility
system call numbering for execve and selecting HAVE_SECCOMP_FILTER.
v9: rebase on to bccaeafd7c117acee36e90d37c7e05c19be9e7bf
Signed-off-by: Will Drewry <wad@chromium.org>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/seccomp.h | 2 ++
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2729c66..030d392 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -129,6 +129,7 @@ config PPC
select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
select HAVE_GENERIC_HARDIRQS
select HAVE_SPARSE_IRQ
+ select HAVE_SECCOMP_FILTER
select IRQ_PER_CPU
select GENERIC_IRQ_SHOW
select GENERIC_IRQ_SHOW_LEVEL
diff --git a/arch/powerpc/include/asm/seccomp.h b/arch/powerpc/include/asm/seccomp.h
index 00c1d91..3cb9cc1 100644
--- a/arch/powerpc/include/asm/seccomp.h
+++ b/arch/powerpc/include/asm/seccomp.h
@@ -7,10 +7,12 @@
#define __NR_seccomp_write __NR_write
#define __NR_seccomp_exit __NR_exit
#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+#define __NR_seccomp_execve __NR_execve
#define __NR_seccomp_read_32 __NR_read
#define __NR_seccomp_write_32 __NR_write
#define __NR_seccomp_exit_32 __NR_exit
#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+#define __NR_seccomp_execve_32 __NR_execve
#endif /* _ASM_POWERPC_SECCOMP_H */
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Benjamin Herrenschmidt @ 2011-06-23 22:01 UTC (permalink / raw)
To: Ralf Baechle
Cc: devel, David Howells, linux-m32r, Paul Mundt, linux-sh,
Greg Kroah-Hartman, linux-kernel, Chris Metcalf, Martyn Welch,
linux-am33-list, Paul Mackerras, linux-m32r-ja, H. Peter Anvin,
Thomas Gleixner, linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <20110623120234.GA22524@linux-mips.org>
On Thu, 2011-06-23 at 13:02 +0100, Ralf Baechle wrote:
> On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:
>
> > On 23/06/11 12:45, Ralf Baechle wrote:
> > > On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi driver turns
> > > into tragedy:
> > >
> > > CC [M] drivers/staging/comedi/drivers.o
> > > drivers/staging/comedi/drivers.c: In function ‘comedi_buf_alloc’:
> > > drivers/staging/comedi/drivers.c:505:41: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function)
> > > drivers/staging/comedi/drivers.c:505:41: note: each undeclared identifier is rep orted only once for each function it appears in
> > > make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
> > >
> > > Restrict the driver to only those architectures that define PAGE_KERNEL_NOCACHE.
> > >
> > > PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as SGI IP27
> > > are even uable to offer uncached operation - at least in the way an unwitting
> > > driver might assume. I haven't looked in details how the driver is using
> > > the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it XFS-style using
> > > cached memory and the flush_kernel_vmap_range / invalidate_kernel_vmap_range
> > > APIs in conjunction with the DMA API is a practical alternative.
> > >
> > > Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
> > >
> > > drivers/staging/comedi/Kconfig | 1 +
> > > 1 files changed, 1 insertions(+), 0 deletions(-)
> > >
> > > diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
> > > index 1502d80..bccdc12 100644
> > > --- a/drivers/staging/comedi/Kconfig
> > > +++ b/drivers/staging/comedi/Kconfig
> > > @@ -2,6 +2,7 @@ config COMEDI
> > > tristate "Data acquisition support (comedi)"
> > > default N
> > > depends on m
> > > + depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
> >
> > I'm sure I got comedi to compile on a 32-bit PPC board not that long ago. Has
> > something changed, or is this just not an exhaustive list?
It went away. There's a proper API (pgprot_noncached), but it depends
what this is used for and it's likely to be broken anyways... what is
that driver trying to map non-cached ?
Cheers,
Ben.
> (Adding the PPC folks to cc.)
>
> A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find anything so
> I don't think the driver will build there. I don't have a PPC toolchain
> to verify that.
>
> Ralf
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] libata/sas: only set FROZEN flag if new EH is supported
From: Benjamin Herrenschmidt @ 2011-06-23 21:43 UTC (permalink / raw)
To: Brian King
Cc: jgarzik, wayneb, linux-kernel, linux-ide, mbizon, Tejun Heo,
Nishanth Aravamudan, linuxppc-dev
In-Reply-To: <4E039C95.3070907@linux.vnet.ibm.com>
On Thu, 2011-06-23 at 15:05 -0500, Brian King wrote:
>
> Same here.
>
> When did this last work on this system? It seems like this is
> completely
> separate from the libata issue.
It's separate. See my other internal message. This is a BML system and
it's broken as far as 2.6.36 but the BML "patched" kernel works,
anyways, moving that off list for now.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 3/5] drivers/amba: create devices from device tree
From: Grant Likely @ 2011-06-23 20:55 UTC (permalink / raw)
To: Rob Herring
Cc: Nicolas Pitre, Russell King, Arnd Bergmann, devicetree-discuss,
linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <4E00F9ED.1020500@gmail.com>
On Tue, Jun 21, 2011 at 2:07 PM, Rob Herring <robherring2@gmail.com> wrote:
> Grant,
>
> On 06/21/2011 01:45 PM, Grant Likely wrote:
>> Add a function to create amba_devices (i.e. primecell peripherals)
>> from device tree nodes. The device tree scanning is done by the
>> of_platform_populate() function which can call of_amba_device_create
>> based on a match table entry.
>>
>> Nodes with a "arm,primecell-periphid" property can override the h/w
>> peripheral id value.
>>
>> Based on the original work by Jeremy Kerr.
>>
>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Acked-by: Linus Walleij <linus.walleij@linaro.org>
>> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>> [grant.likely: add Jeremy's original s-o-b line, changes from review
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0comments, and moved all code to drivers/o=
f/platform.c]
>> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
>> ---
>> =A0.../devicetree/bindings/arm/primecell.txt =A0 =A0 =A0 =A0 =A0| =A0 21=
++++++
>> =A0drivers/of/platform.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
=A0 =A0 =A0| =A0 71 ++++++++++++++++++++
>> =A02 files changed, 92 insertions(+), 0 deletions(-)
>> =A0create mode 100644 Documentation/devicetree/bindings/arm/primecell.tx=
t
>>
>> diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Docum=
entation/devicetree/bindings/arm/primecell.txt
>> new file mode 100644
>> index 0000000..1d5d7a8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/primecell.txt
>> @@ -0,0 +1,21 @@
>> +* ARM Primecell Peripherals
>> +
>> +ARM, Ltd. Primecell peripherals have a standard id register that can be=
used to
>> +identify the peripheral type, vendor, and revision. This value can be u=
sed for
>> +driver matching.
>> +
>> +Required properties:
>> +
>> +- compatible : should be a specific value for peripheral and "arm,prime=
cell"
>
> Can I review what I wrote... Perhaps we should put strings in for all
> existing drivers in the kernel. This should be a complete list:
>
> arm,pl010
> arm,pl011
> st,pl011
> arm,pl022
> st,pl022
> st,pl023
> arm,pl030
> arm,pl031
> st,pl031
> arm,pl061
> arm,pl050
> arm,pl080
> arm,pl081
> st,pl080
> arm,pl110
> arm,pl180
> arm,pl330
> arm,sp804
> arm,sp805
Yes, this whole list should be added.
g.
^ permalink raw reply
* Re: Connecting SGMII PHY to eTSEC1 on P1022
From: Felix Radensky @ 2011-06-23 20:43 UTC (permalink / raw)
To: Timur Tabi; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <4E02229B.50707@embedded-sol.com>
Hi,
On 06/22/2011 08:12 PM, Felix Radensky wrote:
> Hi Timur,
>
> On 06/22/2011 07:18 PM, Timur Tabi wrote:
>> Felix Radensky wrote:
>>> What am I doing wrong ?
>> Can you debug the PHY driver to see if it's getting called and
>> trying to talk to
>> the PHY itself?
>>
> I'll do that tomorrow and report back.
I've found the problem by looking at the code. My SGMII PHY is Marvell
88E1112.
Marvell PHY driver claims it supports that PHY, but in reality it
doesn't. It uses
routines initially written for 88E1111 to configure 88E1112,
essentially writing
to registers that do not exist on that PHY. After disabling Marvell
PHY driver my
PHY started working.
Felix.
^ permalink raw reply
* [PATCH] fsl-diu-fb: remove check for pixel clock ranges
From: Timur Tabi @ 2011-06-23 20:20 UTC (permalink / raw)
To: lethal, linux-fbdev, agust, yorksun, linuxppc-dev
The Freescale DIU framebuffer driver defines two constants, MIN_PIX_CLK and
MAX_PIX_CLK, that are supposed to represent the lower and upper limits of
the pixel clock. These values, however, are true only for one platform
clock rate (533MHz) and only for the MPC8610. So the actual range for
the pixel clock is chip-specific, which means the current values are almost
always wrong. The chance of an out-of-range pixel clock being used are also
remote.
Rather than try to detect an out-of-range clock in the DIU driver, we depend
on the board-specific pixel clock function (e.g. p1022ds_set_pixel_clock)
to clamp the pixel clock to a supported value.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
drivers/video/fsl-diu-fb.c | 16 ----------------
include/linux/fsl-diu-fb.h | 6 ------
2 files changed, 0 insertions(+), 22 deletions(-)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index bedf5be..0acc7d6 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -555,8 +555,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
static int fsl_diu_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- unsigned long htotal, vtotal;
-
pr_debug("check_var xres: %d\n", var->xres);
pr_debug("check_var yres: %d\n", var->yres);
@@ -635,20 +633,6 @@ static int fsl_diu_check_var(struct fb_var_screeninfo *var,
break;
}
- /* If the pixclock is below the minimum spec'd value then set to
- * refresh rate for 60Hz since this is supported by most monitors.
- * Refer to Documentation/fb/ for calculations.
- */
- if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) {
- htotal = var->xres + var->right_margin + var->hsync_len +
- var->left_margin;
- vtotal = var->yres + var->lower_margin + var->vsync_len +
- var->upper_margin;
- var->pixclock = (vtotal * htotal * 6UL) / 100UL;
- var->pixclock = KHZ2PICOS(var->pixclock);
- pr_debug("pixclock set for 60Hz refresh = %u ps\n",
- var->pixclock);
- }
var->height = -1;
var->width = -1;
diff --git a/include/linux/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h
index 781d467..daa9952 100644
--- a/include/linux/fsl-diu-fb.h
+++ b/include/linux/fsl-diu-fb.h
@@ -24,12 +24,6 @@
* See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory()
*/
#define MEM_ALLOC_THRESHOLD (1024*768*4+32)
-/* Minimum value that the pixel clock can be set to in pico seconds
- * This is determined by platform clock/3 where the minimum platform
- * clock is 533MHz. This gives 5629 pico seconds.
- */
-#define MIN_PIX_CLK 5629
-#define MAX_PIX_CLK 96096
#include <linux/types.h>
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH] libata/sas: only set FROZEN flag if new EH is supported
From: Brian King @ 2011-06-23 20:05 UTC (permalink / raw)
To: Nishanth Aravamudan
Cc: Wayne Boyer, linux-kernel, linux-ide, jgarzik, Tejun Heo, mbizon,
linuxppc-dev
In-Reply-To: <20110623171502.GA11855@us.ibm.com>
On 06/23/2011 12:15 PM, Nishanth Aravamudan wrote:
> On 23.06.2011 [14:42:00 +1000], Benjamin Herrenschmidt wrote:
>> On Thu, 2011-06-23 at 14:31 +1000, Benjamin Herrenschmidt wrote:
>>> On Tue, 2011-06-21 at 15:30 -0500, Brian King wrote:
>>>> Looks good to me. Jeff/Tejun - any issues with merging this?
>>>
>>> BTW. Current upstream with that patch applied on a machine here leads to
>>> several oddities, I don't know at this point whether any of that is
>>> actually a regression :
>>
>> Ooops... pressed "send" too quickly. Here's a log excerpt with some
>> comments:
>
> Hrm, I didn't see any of this on my box, which I thought was the same as
> yours :)
>
>> ipr: IBM Power RAID SCSI Device Driver version: 2.5.2 (April 27, 2011)
>> ipr 0000:04:00.0: Found IOA with IRQ: 129
>> ipr 0000:04:00.0: Initializing IOA.
>> ipr 0000:04:00.0: Starting IOA initialization sequence.
>> ipr 0000:04:00.0: Adapter firmware version: 04220029
>> ipr 0000:04:00.0: IOA initialized.
>> scsi0 : IBM 2B4C Storage Adapter
>> scsi 0:0:4:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
>> scsi scan: INQUIRY result too short (5), using 36
>>
>> -> Are these odd INQUIRY results expected ?
Looking at the log, my guess is that we are dealing with a zero buffer. If we were
to get an all zero buffer on the Inquiry, we would think it was a Direct-Access
device with an inquiry response buffer of 5 bytes in length.
>> scsi 0:0:5:0: Direct-Access PQ: 0 ANSI: 0
>> scsi 0:0:6:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
>> scsi 0:0:7:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 0:0:18:0: Direct-Access PQ: 0 ANSI: 0
I'm guessing this should really be an Enclosure device here rather than a disk,
which would be symptomatic of the all zero inquiry buffer.
>> scsi 0:2:18:0: Enclosure IBM PSBPD6E4A 3GSAS 0109 PQ: 0 ANSI: 4
>> scsi: unknown device type 31
>> scsi 0:255:255:255: No Device IBM 2B4C001SISIOA 0150 PQ: 0 ANSI: 0
>>
>> -> The above looks odd, not sure what it means
>
> The "unknown device type"? I see it all the time on lots of different
> machines.
That is normal and expected on an ipr adapter. The unknown device seen on every ipr
adapter at SCSI bus/target/lun 255:255:255 is the adapter itself. It is used by
the RAID management tools in Linux to do things like RAID configuration via SG_IO.
>
>> ipr 0000:05:00.0: Found IOA with IRQ: 130
>> ipr 0000:05:00.0: Initializing IOA.
>> scsi 0:254:0:0: Processor IBM 57CB001SISIOA 0150 PQ: 0 ANSI: 0
>> ipr 0000:05:00.0: Starting IOA initialization sequence.
>> ipr 0000:05:00.0: Adapter firmware version: 04220029
>> ipr 0000:05:00.0: IOA initialized.
>> scsi1 : IBM 57CB Storage Adapter
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 1:0:4:0: Direct-Access PQ: 0 ANSI: 0
>> scsi 1:0:5:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 1:0:6:0: Direct-Access PQ: 0 ANSI: 0
>> scsi 1:0:7:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
>> scsi 1:0:18:0: Enclosure IBM PSBPD6E4A 3GSAS 0109 PQ: 0 ANSI: 4
>> scsi: On host 1 channel 0 id 18 only 511 (max_scsi_report_luns) of 402653184 luns reported, try increasing max_scsi_report_luns.
>> scsi: host 1 channel 0 id 18 lun 0xc0000007f01e810f has a LUN larger than currently supported.
>>
>> -> Now that looks horribly wrong... that LUN number looks like a kernel pointer
>
> Yeah, that's weird.
>
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 1:2:18:0: Direct-Access PQ: 0 ANSI: 0
>> ata1.00: ATAPI: IBM RMBO0040532, SA61, max UDMA/100
>> ata1.00: failed to IDENTIFY (device reports invalid type, err_mask=0x0)
>> ata1.00: revalidation failed (errno=-22)
>> ata1.00: disabled
>>
>> -> So SATA works "better" with the patch but doesn't actually work properly :-)
>>
>> scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured
>>
>> -> That error could give us more info... not sure what it means, we do have plenty of
>> memory...
>
> That message is sort of strange. It's not necessarily referring to
> memory allocation failing, but the port allocation failing in the SCSI
> code. And that just means an error, like the failed to IDENTIFY above,
> is occurring in the allocation path. It *can* also mean memory
> allocation failure, I think, just not in this case.
>
> I don't know much about the following errors, though, sorry.
>
> -Nish
>
>> scsi 1:8:0:0: Enclosure IBM VSBPD6E4B 3GSAS 01 PQ: 0 ANSI: 2
>> scsi: unknown device type 31
>> scsi 1:255:255:255: No Device IBM 57CB001SISIOA 0150 PQ: 0 ANSI: 0
>> work_for_cpu used greatest stack depth: 9520 bytes left
>> st: Version 20101219, fixed bufsize 32768, s/g segs 256
>> sd 0:0:4:0: [sda] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:5:0: [sdb] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:6:0: [sdc] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:7:0: [sdd] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:18:0: [sde] READ CAPACITY failed
>> sd 0:0:18:0: [sde] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
>> sd 0:0:18:0: [sde] Sense Key : Illegal Request [current]
>> sd 0:0:18:0: [sde] Add. Sense: Invalid command operation code
>>
>> -> Any idea what's up with that guy ?
If this guy is really an enclosure, this is the response you would get
on a Read Capacity.
>>
>> sd 0:0:4:0: Attached scsi generic sg0 type 0
>> sd 0:0:5:0: [sdb] Write Protect is off
>> sd 0:0:5:0: Attached scsi generic sg1 type 0
>> sd 0:0:18:0: [sde] Test WP failed, assume Write Enabled
>> sd 0:0:6:0: Attached scsi generic sg2 type 0
>> sd 0:0:18:0: [sde] Asking for cache data failed
>> sd 0:0:7:0: Attached scsi generic sg3 type 0
>> sd 0:0:18:0: [sde] Assuming drive cache: write through
>> sd 1:2:18:0: [sdj] READ CAPACITY failed
>> sd 1:2:18:0: [sdj] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
>> sd 1:2:18:0: [sdj] Sense Key : Illegal Request [current]
>> sd 1:2:18:0: [sdj] Add. Sense: Invalid command operation code
>>
>> -> And this one ?
Same here.
When did this last work on this system? It seems like this is completely
separate from the libata issue.
-Brian
--
Brian King
Linux on Power Virtualization
IBM Linux Technology Center
^ permalink raw reply
* [PATCH] powerpc/85xx: clamp the P1022DS DIU pixel clock to allowed values
From: Timur Tabi @ 2011-06-23 19:48 UTC (permalink / raw)
To: kumar.gala, linuxppc-dev
To ensure that the DIU pixel clock will not be set to an invalid value,
clamp the PXCLK divider to the allowed range (2-255). This also acts as
a limiter for the pixel clock.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
arch/powerpc/platforms/85xx/p1022_ds.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index e083e1f..266b3aa 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -195,8 +195,13 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
do_div(temp, pixclock);
freq = temp;
- /* pixclk is the ratio of the platform clock to the pixel clock */
+ /*
+ * 'pxclk' is the ratio of the platform clock to the pixel clock.
+ * This number is programmed into the CLKDVDR register, and the valid
+ * range of values is 2-255.
+ */
pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+ pxclk = clamp_t(u32, pxclk, 2, 255);
/* Disable the pixel clock, and set it to non-inverted and no delay */
clrbits32(&guts->clkdvdr,
--
1.7.3.4
^ permalink raw reply related
* [PATCH] powerpc/85xx: enable the framebuffer console for the defconfigs
From: Timur Tabi @ 2011-06-23 19:48 UTC (permalink / raw)
To: kumar.gala, linuxppc-dev
In-Reply-To: <1308858535-17396-1-git-send-email-timur@freescale.com>
Enable framebuffer console support by default in the defconfigs for the
Freescale 85xx-based reference board. This allows the boot messages to
be shown on the video display on the P1022DS.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
arch/powerpc/configs/mpc85xx_defconfig | 4 ++++
arch/powerpc/configs/mpc85xx_smp_defconfig | 4 ++++
2 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 96b89df..b212e3d 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -128,6 +128,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
CONFIG_FB_FSL_DIU=y
# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
CONFIG_SOUND=y
CONFIG_SND=y
# CONFIG_SND_SUPPORT_OLD_API is not set
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index de65841..87fbb2e 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -130,6 +130,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
CONFIG_FB_FSL_DIU=y
# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
CONFIG_SOUND=y
CONFIG_SND=y
# CONFIG_SND_SUPPORT_OLD_API is not set
--
1.7.3.4
^ permalink raw reply related
* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Scott Wood @ 2011-06-23 17:48 UTC (permalink / raw)
To: Timur Tabi
Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
McClintock Matthew-B29882, Gala Kumar-B11780
In-Reply-To: <4E0378F4.5010501@freescale.com>
On Thu, 23 Jun 2011 12:33:40 -0500
Timur Tabi <timur@freescale.com> wrote:
> Scott Wood wrote:
> > From Power ISA 2.06B, book III-E, section 9.2.1:
> >
> > Virtualized Implementation Note:
> >
> > In virtualized implementations, TBU and TBL are
> > read-only.
>
> But does that mean that a guest should never be allowed to modify a virtualized
> timebase register, even if the hypervisor can support it?
The book3e mtspr writeup doesn't appear to specify the behavior when
writing to a read-only SPR, so perhaps you could argue that something other
than a no-op is implementation-specific behavior.
For a guest, the safe thing is to not write to those registers unless you
specifically know it's going to do what you want under a particular
implementation. It's not specifically a Topaz limitation.
> >> > So a generic HV mode bit is not going to help me, unless there's also a bit
> >> > that's specific to our hypervisor. And even then, we would need some way to
> >> > differentiate among different versions of our hypervisor, in case some future
> >> > version adds timebase support.
>
> > That's very unlikely to happen.
>
> I know. I was just being architecturally pedantic.
It's not as if it would hurt anything to ignore such a capability.
> > Ideally we would avoid doing this sync even when not running under a
> > hypervisor, as long as firmware has done the sync, and kexec hasn't messed
> > it up. Besides being a waste of boot time, the firmware's sync is
> > probably tighter since it can use a platform-specific mechanism to start all
> > the timebases at once.
>
> I agree with that, but for now, I need to work around that kexec "limitation".
Is there any way we can detect whether we booted via kexec (as opposed to
just having kexec support enabled), and only do the sync in that case?
-Scott
^ permalink raw reply
* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Timur Tabi @ 2011-06-23 17:33 UTC (permalink / raw)
To: Scott Wood
Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
McClintock Matthew-B29882, Gala Kumar-B11780
In-Reply-To: <20110623122210.06ee9f55@schlenkerla.am.freescale.net>
Scott Wood wrote:
> From Power ISA 2.06B, book III-E, section 9.2.1:
>
> Virtualized Implementation Note:
>
> In virtualized implementations, TBU and TBL are
> read-only.
But does that mean that a guest should never be allowed to modify a virtualized
timebase register, even if the hypervisor can support it?
>> > So a generic HV mode bit is not going to help me, unless there's also a bit
>> > that's specific to our hypervisor. And even then, we would need some way to
>> > differentiate among different versions of our hypervisor, in case some future
>> > version adds timebase support.
> That's very unlikely to happen.
I know. I was just being architecturally pedantic.
> Ideally we would avoid doing this sync even when not running under a
> hypervisor, as long as firmware has done the sync, and kexec hasn't messed
> it up. Besides being a waste of boot time, the firmware's sync is
> probably tighter since it can use a platform-specific mechanism to start all
> the timebases at once.
I agree with that, but for now, I need to work around that kexec "limitation".
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Scott Wood @ 2011-06-23 17:22 UTC (permalink / raw)
To: Timur Tabi
Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
McClintock Matthew-B29882, Gala Kumar-B11780
In-Reply-To: <4E020268.2020809@freescale.com>
On Wed, 22 Jun 2011 09:55:36 -0500
Timur Tabi <timur@freescale.com> wrote:
> Kumar Gala wrote:
> >> >=20
> >> > Well, not exactly. Paul wants to break that up since we're adding so=
me
> >> > primitive support for 201 HV mode too (for 970's). Last we discussed,
> >> > the plan was to go for a generic HV mode bit and a separate bit for =
the
> >> > version.
> >> >=20
> >> > Cheers,
> >> > Ben.
>=20
> > Any ETA on Paul's intro of the FTR bit? If not I'll pull this into my =
'next' tree and we can clean up later.
>=20
> Just FYI, this particular patch is because of a limitation in the Freesca=
le
> hypervisor. It's not because we're running in guest mode. If the hyperv=
isor
> provided full emulation of the timebase register, then we wouldn't need t=
his
> patch. The same can be said of KVM or any other hypervisor.
=46rom Power ISA 2.06B, book III-E, section 9.2.1:
Virtualized Implementation Note:
In virtualized implementations, TBU and TBL are
read-only.
> So a generic HV mode bit is not going to help me, unless there's also a b=
it
> that's specific to our hypervisor. And even then, we would need some way=
to
> differentiate among different versions of our hypervisor, in case some fu=
ture
> version adds timebase support.=20
That's very unlikely to happen.
Ideally we would avoid doing this sync even when not running under a
hypervisor, as long as firmware has done the sync, and kexec hasn't messed
it up. Besides being a waste of boot time, the firmware's sync is
probably tighter since it can use a platform-specific mechanism to start all
the timebases at once.
-Scott
^ permalink raw reply
* Re: [PATCH] libata/sas: only set FROZEN flag if new EH is supported
From: Nishanth Aravamudan @ 2011-06-23 17:15 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-ide, jgarzik, wayneb, linux-kernel, Tejun Heo, Brian King,
mbizon, linuxppc-dev
In-Reply-To: <1308804120.32158.202.camel@pasglop>
On 23.06.2011 [14:42:00 +1000], Benjamin Herrenschmidt wrote:
> On Thu, 2011-06-23 at 14:31 +1000, Benjamin Herrenschmidt wrote:
> > On Tue, 2011-06-21 at 15:30 -0500, Brian King wrote:
> > > Looks good to me. Jeff/Tejun - any issues with merging this?
> >
> > BTW. Current upstream with that patch applied on a machine here leads to
> > several oddities, I don't know at this point whether any of that is
> > actually a regression :
>
> Ooops... pressed "send" too quickly. Here's a log excerpt with some
> comments:
Hrm, I didn't see any of this on my box, which I thought was the same as
yours :)
> ipr: IBM Power RAID SCSI Device Driver version: 2.5.2 (April 27, 2011)
> ipr 0000:04:00.0: Found IOA with IRQ: 129
> ipr 0000:04:00.0: Initializing IOA.
> ipr 0000:04:00.0: Starting IOA initialization sequence.
> ipr 0000:04:00.0: Adapter firmware version: 04220029
> ipr 0000:04:00.0: IOA initialized.
> scsi0 : IBM 2B4C Storage Adapter
> scsi 0:0:4:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
> scsi scan: INQUIRY result too short (5), using 36
>
> -> Are these odd INQUIRY results expected ?
>
> scsi 0:0:5:0: Direct-Access PQ: 0 ANSI: 0
> scsi 0:0:6:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
> scsi 0:0:7:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
> scsi scan: INQUIRY result too short (5), using 36
> scsi 0:0:18:0: Direct-Access PQ: 0 ANSI: 0
> scsi 0:2:18:0: Enclosure IBM PSBPD6E4A 3GSAS 0109 PQ: 0 ANSI: 4
> scsi: unknown device type 31
> scsi 0:255:255:255: No Device IBM 2B4C001SISIOA 0150 PQ: 0 ANSI: 0
>
> -> The above looks odd, not sure what it means
The "unknown device type"? I see it all the time on lots of different
machines.
> ipr 0000:05:00.0: Found IOA with IRQ: 130
> ipr 0000:05:00.0: Initializing IOA.
> scsi 0:254:0:0: Processor IBM 57CB001SISIOA 0150 PQ: 0 ANSI: 0
> ipr 0000:05:00.0: Starting IOA initialization sequence.
> ipr 0000:05:00.0: Adapter firmware version: 04220029
> ipr 0000:05:00.0: IOA initialized.
> scsi1 : IBM 57CB Storage Adapter
> scsi scan: INQUIRY result too short (5), using 36
> scsi 1:0:4:0: Direct-Access PQ: 0 ANSI: 0
> scsi 1:0:5:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
> scsi scan: INQUIRY result too short (5), using 36
> scsi 1:0:6:0: Direct-Access PQ: 0 ANSI: 0
> scsi 1:0:7:0: Direct-Access IBM ST9300603SS BB09 PQ: 0 ANSI: 6
> scsi 1:0:18:0: Enclosure IBM PSBPD6E4A 3GSAS 0109 PQ: 0 ANSI: 4
> scsi: On host 1 channel 0 id 18 only 511 (max_scsi_report_luns) of 402653184 luns reported, try increasing max_scsi_report_luns.
> scsi: host 1 channel 0 id 18 lun 0xc0000007f01e810f has a LUN larger than currently supported.
>
> -> Now that looks horribly wrong... that LUN number looks like a kernel pointer
Yeah, that's weird.
> scsi scan: INQUIRY result too short (5), using 36
> scsi 1:2:18:0: Direct-Access PQ: 0 ANSI: 0
> ata1.00: ATAPI: IBM RMBO0040532, SA61, max UDMA/100
> ata1.00: failed to IDENTIFY (device reports invalid type, err_mask=0x0)
> ata1.00: revalidation failed (errno=-22)
> ata1.00: disabled
>
> -> So SATA works "better" with the patch but doesn't actually work properly :-)
>
> scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured
>
> -> That error could give us more info... not sure what it means, we do have plenty of
> memory...
That message is sort of strange. It's not necessarily referring to
memory allocation failing, but the port allocation failing in the SCSI
code. And that just means an error, like the failed to IDENTIFY above,
is occurring in the allocation path. It *can* also mean memory
allocation failure, I think, just not in this case.
I don't know much about the following errors, though, sorry.
-Nish
> scsi 1:8:0:0: Enclosure IBM VSBPD6E4B 3GSAS 01 PQ: 0 ANSI: 2
> scsi: unknown device type 31
> scsi 1:255:255:255: No Device IBM 57CB001SISIOA 0150 PQ: 0 ANSI: 0
> work_for_cpu used greatest stack depth: 9520 bytes left
> st: Version 20101219, fixed bufsize 32768, s/g segs 256
> sd 0:0:4:0: [sda] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:5:0: [sdb] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:6:0: [sdc] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:7:0: [sdd] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:18:0: [sde] READ CAPACITY failed
> sd 0:0:18:0: [sde] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 0:0:18:0: [sde] Sense Key : Illegal Request [current]
> sd 0:0:18:0: [sde] Add. Sense: Invalid command operation code
>
> -> Any idea what's up with that guy ?
>
> sd 0:0:4:0: Attached scsi generic sg0 type 0
> sd 0:0:5:0: [sdb] Write Protect is off
> sd 0:0:5:0: Attached scsi generic sg1 type 0
> sd 0:0:18:0: [sde] Test WP failed, assume Write Enabled
> sd 0:0:6:0: Attached scsi generic sg2 type 0
> sd 0:0:18:0: [sde] Asking for cache data failed
> sd 0:0:7:0: Attached scsi generic sg3 type 0
> sd 0:0:18:0: [sde] Assuming drive cache: write through
> sd 1:2:18:0: [sdj] READ CAPACITY failed
> sd 1:2:18:0: [sdj] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 1:2:18:0: [sdj] Sense Key : Illegal Request [current]
> sd 1:2:18:0: [sdj] Add. Sense: Invalid command operation code
>
> -> And this one ?
>
> There's more below ...
>
> sd 0:0:18:0: Attached scsi generic sg4 type 0
> sd 1:0:4:0: [sdf] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> scsi 0:2:18:0: Attached scsi generic sg5 type 13
> sd 1:0:6:0: [sdh] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> scsi 0:255:255:255: Attached scsi generic sg6 type 31
> scsi 0:254:0:0: Attached scsi generic sg7 type 3
> sd 1:0:4:0: Attached scsi generic sg8 type 0
> sd 1:2:18:0: [sdj] Test WP failed, assume Write Enabled
> sd 1:0:5:0: Attached scsi generic sg9 type 0
> sd 1:0:6:0: Attached scsi generic sg10 type 0
> sd 1:0:7:0: [sdi] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 1:2:18:0: [sdj] Asking for cache data failed
> sd 1:2:18:0: [sdj] Assuming drive cache: write through
> sd 1:0:7:0: Attached scsi generic sg11 type 0
> scsi 1:0:18:0: Attached scsi generic sg12 type 13
> sd 0:0:4:0: [sda] Write Protect is off
> sd 1:2:18:0: Attached scsi generic sg13 type 0
> sd 0:0:18:0: [sde] READ CAPACITY failed
> sd 0:0:18:0: [sde] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 0:0:18:0: [sde] Sense Key : Illegal Request [current]
> sd 0:0:18:0: [sde] Add. Sense: Invalid command operation code
> scsi 1:8:0:0: Attached scsi generic sg14 type 13
> scsi 1:255:255:255: Attached scsi generic sg15 type 31
> e1000: Intel(R) PRO/1000 Network Driver - version 7.3.21-k8-NAPI
> e1000: Copyright (c) 1999-2006 Intel Corporation.
> e1000e: Intel(R) PRO/1000 Network Driver - 1.3.10-k2
> e1000e: Copyright(c) 1999 - 2011 Intel Corporation.
> sd 1:0:6:0: [sdh] Write Protect is off
> sd 0:0:5:0: [sdb] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 0:0:18:0: [sde] Test WP failed, assume Write Enabled
> sd 0:0:7:0: [sdd] Write Protect is off
> sd 1:2:18:0: [sdj] READ CAPACITY failed
> sd 1:2:18:0: [sdj] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 1:2:18:0: [sdj] Sense Key : Illegal Request [current]
> sd 1:2:18:0: [sdj] Add. Sense: Invalid command operation code
> sd 0:0:18:0: [sde] Asking for cache data failed
> sd 0:0:18:0: [sde] Assuming drive cache: write through
> sd 0:0:18:0: [sde] Attached SCSI disk
> sd 1:0:5:0: [sdg] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 1:0:4:0: [sdf] Write Protect is off
> sd 1:2:18:0: [sdj] Test WP failed, assume Write Enabled
> sd 0:0:6:0: [sdc] Write Protect is off
> sd 1:2:18:0: [sdj] Asking for cache data failed
> sd 1:2:18:0: [sdj] Assuming drive cache: write through
> sd 1:2:18:0: [sdj] Attached SCSI disk
> sd 0:0:7:0: [sdd] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 0:0:4:0: [sda] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:6:0: [sdh] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:4:0: [sdf] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:5:0: [sdg] Write Protect is off
> sd 1:0:7:0: [sdi] Write Protect is off
> sd 0:0:6:0: [sdc] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:7:0: [sdi] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:5:0: [sdg] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sdb: unknown partition table
> sdd: unknown partition table
> sdh: unknown partition table
> sdi: unknown partition table
> sdf: [AIX] unknown partition table
> sdg: unknown partition table
> e1000e 0002:03:00.0: Disabling ASPM L1
> sdc: unknown partition table
> e1000e 0002:03:00.0: (unregistered net_device): Failed to initialize MSI interrupts. Falling back to legacy interrupts.
> scsi 1:254:0:0: Processor IBM 2B4C001SISIOA 0150 PQ: 0 ANSI: 0
> sda: [AIX] unknown partition table
> sd 0:0:5:0: [sdb] Attached SCSI disk
> sd 1:0:6:0: [sdh] Attached SCSI disk
> sd 1:0:7:0: [sdi] Attached SCSI disk
> sd 0:0:6:0: [sdc] Attached SCSI disk
> sd 1:0:5:0: [sdg] Attached SCSI disk
> sd 0:0:7:0: [sdd] Attached SCSI disk
> scsi 1:254:0:0: Attached scsi generic sg16 type 3
> sd 1:0:4:0: [sdf] Attached SCSI disk
> sd 0:0:4:0: [sda] Attached SCSI disk
>
> Cheers,
> Ben.
> >
> >
> > > Thanks,
> > >
> > > Brian
> > >
> > > On 06/21/2011 11:07 AM, Nishanth Aravamudan wrote:
> > > > Ping on this -- Tejun, Brian, Jeff, this is a pretty annoying 2.6.39
> > > > regression which it would be good to have fixed in 3.0.
> > > >
> > > > Thanks,
> > > > Nish
> > > >
> > > > On 16.06.2011 [08:28:36 -0700], Nishanth Aravamudan wrote:
> > > >> On 16.06.2011 [08:28:39 -0500], Brian King wrote:
> > > >>> On 06/16/2011 02:51 AM, Tejun Heo wrote:
> > > >>>> On Wed, Jun 15, 2011 at 04:34:17PM -0700, Nishanth Aravamudan wrote:
> > > >>>>>> That looks like the right thing to do. For ipr's usage of
> > > >>>>>> libata, we don't have the concept of a port frozen state, so this flag
> > > >>>>>> should really never get set. The alternate way to fix this would be to
> > > >>>>>> only set ATA_PFLAG_FROZEN in ata_port_alloc if ap->ops->error_handler
> > > >>>>>> is not NULL.
> > > >>>>>
> > > >>>>> It seemed like ipr is as you say, but I wasn't sure if it was
> > > >>>>> appropriate to make the change above in the common libata-scis code or
> > > >>>>> not. I don't want to break some other device on accident.
> > > >>>>>
> > > >>>>> Also, I tried your suggestion, but I don't think that can happen in
> > > >>>>> ata_port_alloc? ata_port_alloc is allocated ap itself, and it seems like
> > > >>>>> ap->ops typically gets set only after ata_port_alloc returns?
> > > >>>>
> > > >>>> Maybe we can test error_handler in ata_sas_port_start()?
> > > >>>
> > > >>> Good point. Since libsas is converted to the new eh now, we would need to have
> > > >>> this test.
> > > >>
> > > >> Commit 7b3a24c57d2eeda8dba9c205342b12689c4679f9 ("ahci: don't enable
> > > >> port irq before handler is registered") caused a regression for CD-ROMs
> > > >> attached to the IPR SATA bus on Power machines:
> > > >>
> > > >> ata_port_alloc: ENTER
> > > >> ata_port_probe: ata1: bus probe begin
> > > >> ata1.00: ata_dev_read_id: ENTER
> > > >> ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40)
> > > >> ata1.00: ata_dev_read_id: ENTER
> > > >> ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40)
> > > >> ata1.00: limiting speed to UDMA7:PIO5
> > > >> ata1.00: ata_dev_read_id: ENTER
> > > >> ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40)
> > > >> ata1.00: disabled
> > > >> ata_port_probe: ata1: bus probe end
> > > >> scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured
> > > >>
> > > >> The FROZEN flag added in that commit is only cleared by the new EH code,
> > > >> which is not used by ipr. Clear this flag in the SAS code if we don't
> > > >> support new EH.
> > > >>
> > > >> Reported-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > > >> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> > > >>
> > > >> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> > > >> index d51f979..ebe1685 100644
> > > >> --- a/drivers/ata/libata-scsi.c
> > > >> +++ b/drivers/ata/libata-scsi.c
> > > >> @@ -3797,6 +3797,12 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
> > > >> */
> > > >> int ata_sas_port_start(struct ata_port *ap)
> > > >> {
> > > >> + /*
> > > >> + * the port is marked as frozen at allocation time, but if we don't
> > > >> + * have new eh, we won't thaw it
> > > >> + */
> > > >> + if (!ap->ops->error_handler)
> > > >> + ap->pflags &= ~ATA_PFLAG_FROZEN;
> > > >> return 0;
> > > >> }
> > > >> EXPORT_SYMBOL_GPL(ata_sas_port_start);
> > > >>
> > > >>
> > > >> --
> > > >> Nishanth Aravamudan <nacc@us.ibm.com>
> > > >> IBM Linux Technology Center
> > > >
> > >
> > >
> >
>
>
--
Nishanth Aravamudan <nacc@us.ibm.com>
IBM Linux Technology Center
^ permalink raw reply
* [PATCH 1/2] powerpc/86xx: enable the framebuffer console on the MPC8610 HPCD
From: Timur Tabi @ 2011-06-23 16:16 UTC (permalink / raw)
To: kumar.gala, linuxppc-dev
Enable framebuffer console support by default in the defconfig on the
Freescale MPC8610 HPCD reference board. This allows the boot messages to
be shown on the video display.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index 036bfb2..0db9ba0 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -89,6 +89,11 @@ CONFIG_I2C_MPC=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
CONFIG_FB_FSL_DIU=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_MIXER_OSS=y
--
1.7.3.4
^ permalink raw reply related
* [PATCH 2/2] powerpc/86xx: improve calculation of DIU pixel clock on the MPC8610 HPCD
From: Timur Tabi @ 2011-06-23 16:16 UTC (permalink / raw)
To: kumar.gala, linuxppc-dev
In-Reply-To: <1308845808-11392-1-git-send-email-timur@freescale.com>
mpc8610hpcd_set_pixel_clock() calculates the correct value of the PXCLK
bits in the CLKDVDR register for a given pixel clock rate. The code which
performs this calculation is overly complicated and includes an error
estimation routine that doesn't work most of the time anyway. Replace the
code with the simpler routine that's currently used on the P1022DS.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 107 ++++++++++++---------------
1 files changed, 48 insertions(+), 59 deletions(-)
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index a896511..74e018e 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -39,12 +39,19 @@
#include <sysdev/fsl_pci.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/simple_gpio.h>
+#include <asm/fsl_guts.h>
#include "mpc86xx.h"
static struct device_node *pixis_node;
static unsigned char *pixis_bdcfg0, *pixis_arch;
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN 0x80000000
+#define CLKDVDR_PXCKINV 0x10000000
+#define CLKDVDR_PXCKDLY 0x06000000
+#define CLKDVDR_PXCLK_MASK 0x001F0000
+
#ifdef CONFIG_SUSPEND
static irqreturn_t mpc8610_sw9_irq(int irq, void *data)
{
@@ -205,72 +212,54 @@ void mpc8610hpcd_set_monitor_port(int monitor_port)
bdcfg[monitor_port]);
}
+/**
+ * mpc8610hpcd_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
{
- u32 __iomem *clkdvdr;
- u32 temp;
- /* variables for pixel clock calcs */
- ulong bestval, bestfreq, speed_ccb, minpixclock, maxpixclock;
- ulong pixval;
- long err;
- int i;
-
- clkdvdr = ioremap(get_immrbase() + 0xe0800, sizeof(u32));
- if (!clkdvdr) {
- printk(KERN_ERR "Err: can't map clock divider register!\n");
+ struct device_node *guts_np = NULL;
+ struct ccsr_guts_86xx __iomem *guts;
+ unsigned long freq;
+ u64 temp;
+ u32 pxclk;
+
+ /* Map the global utilities registers. */
+ guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
+ if (!guts_np) {
+ pr_err("mpc8610hpcd: missing global utilties device node\n");
return;
}
- /* Pixel Clock configuration */
- speed_ccb = fsl_get_sys_freq();
-
- /* Calculate the pixel clock with the smallest error */
- /* calculate the following in steps to avoid overflow */
- pr_debug("DIU pixclock in ps - %d\n", pixclock);
- temp = 1000000000/pixclock;
- temp *= 1000;
- pixclock = temp;
- pr_debug("DIU pixclock freq - %u\n", pixclock);
-
- temp = pixclock * 5 / 100;
- pr_debug("deviation = %d\n", temp);
- minpixclock = pixclock - temp;
- maxpixclock = pixclock + temp;
- pr_debug("DIU minpixclock - %lu\n", minpixclock);
- pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
- pixval = speed_ccb/pixclock;
- pr_debug("DIU pixval = %lu\n", pixval);
-
- err = 100000000;
- bestval = pixval;
- pr_debug("DIU bestval = %lu\n", bestval);
-
- bestfreq = 0;
- for (i = -1; i <= 1; i++) {
- temp = speed_ccb / ((pixval+i) + 1);
- pr_debug("DIU test pixval i= %d, pixval=%lu, temp freq. = %u\n",
- i, pixval, temp);
- if ((temp < minpixclock) || (temp > maxpixclock))
- pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
- minpixclock, maxpixclock);
- else if (abs(temp - pixclock) < err) {
- pr_debug("Entered the else if block %d\n", i);
- err = abs(temp - pixclock);
- bestval = pixval+i;
- bestfreq = temp;
- }
+ guts = of_iomap(guts_np, 0);
+ of_node_put(guts_np);
+ if (!guts) {
+ pr_err("mpc8610hpcd: could not map global utilties device\n");
+ return;
}
- pr_debug("DIU chose = %lx\n", bestval);
- pr_debug("DIU error = %ld\n NomPixClk ", err);
- pr_debug("DIU: Best Freq = %lx\n", bestfreq);
- /* Modify PXCLK in GUTS CLKDVDR */
- pr_debug("DIU: Current value of CLKDVDR = 0x%08x\n", (*clkdvdr));
- temp = (*clkdvdr) & 0x2000FFFF;
- *clkdvdr = temp; /* turn off clock */
- *clkdvdr = temp | 0x80000000 | (((bestval) & 0x1F) << 16);
- pr_debug("DIU: Modified value of CLKDVDR = 0x%08x\n", (*clkdvdr));
- iounmap(clkdvdr);
+ /* Convert pixclock from a wavelength to a frequency */
+ temp = 1000000000000ULL;
+ do_div(temp, pixclock);
+ freq = temp;
+
+ /*
+ * 'pxclk' is the ratio of the platform clock to the pixel clock.
+ * On the MPC8610, the value programmed into CLKDVDR is the ratio
+ * minus one. The valid range of values is 2-31.
+ */
+ pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq) - 1;
+ pxclk = clamp_t(u32, pxclk, 2, 31);
+
+ /* Disable the pixel clock, and set it to non-inverted and no delay */
+ clrbits32(&guts->clkdvdr,
+ CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+ /* Enable the clock and set the pxclk */
+ setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+ iounmap(guts);
}
ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
--
1.7.3.4
^ permalink raw reply related
* Fwd: [PATCH] powerpc, 460gt: Add 460gt as compatible in the check for 460ex-compatible crypto
From: Mike Williams @ 2011-06-23 14:21 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <BANLkTikKNqEoQxGA642h14eOUjZ3hGZaQw@mail.gmail.com>
On Wed, Jun 22, 2011 at 7:24 PM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
>> - =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-cry=
pto")) {
>> + =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-cry=
pto") ||
>> + =A0 =A0 =A0 =A0 =A0 of_find_compatible_node(NULL, NULL, "amcc,ppc460gt=
-crypto")) {
>
> If the device is actually compatible, the device tree node should claim
> it is, and you do not need this code change.
That was actually my first instinct, however I tried to follow the
current convention in the glacier and canyonlands DTS files, which is
to set every device compatible to 460gt or 460ex, depending on the
processor. Many of the devices are identical between the two, since
they are variations of the same SoC, so which is the preferred method?
Follow the device tree convention and add the compatibility check in
the driver, or alter the device trees? I'll send another patch if it's
the latter.
Thanks,
Mike
>
>
> Segher
>
>
^ permalink raw reply
* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Kumar Gala @ 2011-06-23 12:10 UTC (permalink / raw)
To: Ralf Baechle
Cc: devel, David Howells, linux-m32r, Paul Mundt, linux-sh,
Greg Kroah-Hartman, linux-kernel, Chris Metcalf, Martyn Welch,
linux-am33-list, Paul Mackerras, linux-m32r-ja, H. Peter Anvin,
Thomas Gleixner, linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <20110623120234.GA22524@linux-mips.org>
On Jun 23, 2011, at 7:02 AM, Ralf Baechle wrote:
> On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:
>=20
>> On 23/06/11 12:45, Ralf Baechle wrote:
>>> On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi =
driver turns
>>> into tragedy:
>>>=20
>>> CC [M] drivers/staging/comedi/drivers.o
>>> drivers/staging/comedi/drivers.c: In function =91comedi_buf_alloc=92:
>>> drivers/staging/comedi/drivers.c:505:41: error: =
=91PAGE_KERNEL_NOCACHE=92 undeclared (first use in this function)
>>> drivers/staging/comedi/drivers.c:505:41: note: each undeclared =
identifier is rep orted only once for each function it appears in
>>> make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
>>>=20
>>> Restrict the driver to only those architectures that define =
PAGE_KERNEL_NOCACHE.
>>>=20
>>> PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as =
SGI IP27
>>> are even uable to offer uncached operation - at least in the way an =
unwitting
>>> driver might assume. I haven't looked in details how the driver is =
using
>>> the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it =
XFS-style using
>>> cached memory and the flush_kernel_vmap_range / =
invalidate_kernel_vmap_range
>>> APIs in conjunction with the DMA API is a practical alternative.
>>>=20
>>> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
>>>=20
>>> drivers/staging/comedi/Kconfig | 1 +
>>> 1 files changed, 1 insertions(+), 0 deletions(-)
>>>=20
>>> diff --git a/drivers/staging/comedi/Kconfig =
b/drivers/staging/comedi/Kconfig
>>> index 1502d80..bccdc12 100644
>>> --- a/drivers/staging/comedi/Kconfig
>>> +++ b/drivers/staging/comedi/Kconfig
>>> @@ -2,6 +2,7 @@ config COMEDI
>>> tristate "Data acquisition support (comedi)"
>>> default N
>>> depends on m
>>> + depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || =
X86
>>=20
>> I'm sure I got comedi to compile on a 32-bit PPC board not that long =
ago. Has
>> something changed, or is this just not an exhaustive list?
>=20
> (Adding the PPC folks to cc.)
>=20
> A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find =
anything so
> I don't think the driver will build there. I don't have a PPC =
toolchain
> to verify that.
I can verify it fails on PPC as well:
drivers/staging/comedi/drivers.c: In function 'comedi_buf_alloc':
drivers/staging/comedi/drivers.c:505:37: error: 'PAGE_KERNEL_NOCACHE' =
undeclared (first use in this function)
drivers/staging/comedi/drivers.c:505:37: note: each undeclared =
identifier is reported only once for each function it appears in
However, we do have a #define for PAGE_KERNEL_NC.
- k=
^ permalink raw reply
* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Ralf Baechle @ 2011-06-23 12:02 UTC (permalink / raw)
To: Martyn Welch
Cc: devel, linux-m32r-ja, linux-m32r, Paul Mundt, linux-sh,
Greg Kroah-Hartman, linux-kernel, Chris Metcalf, David Howells,
linux-am33-list, Paul Mackerras, H. Peter Anvin, Thomas Gleixner,
linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <4E032940.5010205@ge.com>
On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:
> On 23/06/11 12:45, Ralf Baechle wrote:
> > On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi driver turns
> > into tragedy:
> >
> > CC [M] drivers/staging/comedi/drivers.o
> > drivers/staging/comedi/drivers.c: In function ‘comedi_buf_alloc’:
> > drivers/staging/comedi/drivers.c:505:41: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function)
> > drivers/staging/comedi/drivers.c:505:41: note: each undeclared identifier is rep orted only once for each function it appears in
> > make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
> >
> > Restrict the driver to only those architectures that define PAGE_KERNEL_NOCACHE.
> >
> > PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as SGI IP27
> > are even uable to offer uncached operation - at least in the way an unwitting
> > driver might assume. I haven't looked in details how the driver is using
> > the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it XFS-style using
> > cached memory and the flush_kernel_vmap_range / invalidate_kernel_vmap_range
> > APIs in conjunction with the DMA API is a practical alternative.
> >
> > Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
> >
> > drivers/staging/comedi/Kconfig | 1 +
> > 1 files changed, 1 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
> > index 1502d80..bccdc12 100644
> > --- a/drivers/staging/comedi/Kconfig
> > +++ b/drivers/staging/comedi/Kconfig
> > @@ -2,6 +2,7 @@ config COMEDI
> > tristate "Data acquisition support (comedi)"
> > default N
> > depends on m
> > + depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
>
> I'm sure I got comedi to compile on a 32-bit PPC board not that long ago. Has
> something changed, or is this just not an exhaustive list?
(Adding the PPC folks to cc.)
A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find anything so
I don't think the driver will build there. I don't have a PPC toolchain
to verify that.
Ralf
^ permalink raw reply
* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Martyn Welch @ 2011-06-23 12:13 UTC (permalink / raw)
To: Ralf Baechle
Cc: devel, linux-m32r-ja, linux-m32r, Paul Mundt, linux-sh,
Greg Kroah-Hartman, linux-kernel, Chris Metcalf, David Howells,
linux-am33-list, Paul Mackerras, H. Peter Anvin, Thomas Gleixner,
linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <20110623120234.GA22524@linux-mips.org>
On 23/06/11 13:02, Ralf Baechle wrote:
> On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:
>
>> On 23/06/11 12:45, Ralf Baechle wrote:
>>> On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi driver turns
>>> into tragedy:
>>>
>>> CC [M] drivers/staging/comedi/drivers.o
>>> drivers/staging/comedi/drivers.c: In function ‘comedi_buf_alloc’:
>>> drivers/staging/comedi/drivers.c:505:41: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function)
>>> drivers/staging/comedi/drivers.c:505:41: note: each undeclared identifier is rep orted only once for each function it appears in
>>> make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
>>>
>>> Restrict the driver to only those architectures that define PAGE_KERNEL_NOCACHE.
>>>
>>> PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as SGI IP27
>>> are even uable to offer uncached operation - at least in the way an unwitting
>>> driver might assume. I haven't looked in details how the driver is using
>>> the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it XFS-style using
>>> cached memory and the flush_kernel_vmap_range / invalidate_kernel_vmap_range
>>> APIs in conjunction with the DMA API is a practical alternative.
>>>
>>> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
>>>
>>> drivers/staging/comedi/Kconfig | 1 +
>>> 1 files changed, 1 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
>>> index 1502d80..bccdc12 100644
>>> --- a/drivers/staging/comedi/Kconfig
>>> +++ b/drivers/staging/comedi/Kconfig
>>> @@ -2,6 +2,7 @@ config COMEDI
>>> tristate "Data acquisition support (comedi)"
>>> default N
>>> depends on m
>>> + depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
>>
>> I'm sure I got comedi to compile on a 32-bit PPC board not that long ago. Has
>> something changed, or is this just not an exhaustive list?
>
> (Adding the PPC folks to cc.)
>
> A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find anything so
> I don't think the driver will build there. I don't have a PPC toolchain
> to verify that.
Ah, just found the tree looks like I had a little patch to make it seemingly
work, though it will make it "not work" for most other archs at a guess (it
may not even be right on PPC):
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 44d6b62..263ad3d 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -505,7 +505,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct
comedi_subdevice *s,
}
if (i == n_pages) {
async->prealloc_buf =
- vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NOCACHE);
+ vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NC);
}
vfree(pages);
(Sorry for the wrapping)
--
Martyn Welch (Principal Software Engineer) | Registered in England and
GE Intelligent Platforms | Wales (3828642) at 100
T +44(0)127322748 | Barbirolli Square, Manchester,
E martyn.welch@ge.com | M2 3AB VAT:GB 927559189
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox