* [PATCH 3/3] powerpc: Implement PR_[GS]ET_UNALIGN prctls for powerpc
From: Paul Mackerras @ 2006-06-07 6:15 UTC (permalink / raw)
To: akpm, linuxppc-dev
This gives the ability to control whether alignment exceptions get
fixed up or reported to the process as a SIGBUS, using the existing
PR_SET_UNALIGN and PR_GET_UNALIGN prctls. We do not implement the
option of logging a message on alignment exceptions.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -805,9 +805,11 @@ #endif /* CONFIG_MATH_EMULATION */
void alignment_exception(struct pt_regs *regs)
{
- int fixed;
+ int fixed = 0;
- fixed = fix_alignment(regs);
+ /* we don't implement logging of alignment exceptions */
+ if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+ fixed = fix_alignment(regs);
if (fixed == 1) {
regs->nip += 4; /* skip over emulated instruction */
diff a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -752,6 +752,17 @@
return put_user(val, (unsigned int __user *)adr);
}
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+ tsk->thread.align_ctl = val;
+ return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+ return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
+}
+
#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
int sys_clone(unsigned long clone_flags, unsigned long usp,
diff a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -149,6 +149,7 @@ #endif
unsigned int val; /* Floating point status */
} fpscr;
int fpexc_mode; /* floating-point exception mode */
+ unsigned int align_ctl; /* alignment handling control */
#ifdef CONFIG_PPC64
unsigned long start_tb; /* Start purr when proc switched in */
unsigned long accum_tb; /* Total accumilated purr for process */
@@ -218,6 +219,12 @@ #define SET_FPEXC_CTL(tsk, val) set_fpex
extern int get_endian(struct task_struct *tsk, unsigned long adr);
extern int set_endian(struct task_struct *tsk, unsigned int val);
+#define GET_UNALIGN_CTL(tsk, adr) get_unalign_ctl((tsk), (adr))
+#define SET_UNALIGN_CTL(tsk, val) set_unalign_ctl((tsk), (val))
+
+extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
+extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
+
static inline unsigned int __unpack_fe01(unsigned long msr_bits)
{
return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
^ permalink raw reply
* [PATCH 2/3] powerpc: Implement support for setting little-endian mode via prctl
From: Paul Mackerras @ 2006-06-07 6:14 UTC (permalink / raw)
To: akpm, linuxppc-dev
This adds the PowerPC part of the code to allow processes to change
their endian mode via prctl.
This also extends the alignment exception handler to be able to fix up
alignment exceptions that occur in little-endian mode, both for
"PowerPC" little-endian and true little-endian.
We always enter signal handlers in big-endian mode -- the support for
little-endian mode does not amount to the creation of a little-endian
user/kernel ABI. If the signal handler returns, the endian mode is
restored to what it was when the signal was delivered.
We have two new kernel CPU feature bits, one for PPC little-endian and
one for true little-endian. Most of the classic 32-bit processors
support PPC little-endian, and this is reflected in the CPU feature
table. There are two corresponding feature bits reported to userland
in the AT_HWCAP aux vector entry.
This is based on an earlier patch by Anton Blanchard.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index faaec9c..4734b5d 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -35,17 +35,19 @@ #define IS_DSFORM(inst) (((inst) >> 26)
#define INVALID { 0, 0 }
-#define LD 1 /* load */
-#define ST 2 /* store */
-#define SE 4 /* sign-extend value */
-#define F 8 /* to/from fp regs */
-#define U 0x10 /* update index register */
-#define M 0x20 /* multiple load/store */
-#define SW 0x40 /* byte swap int or ... */
-#define S 0x40 /* ... single-precision fp */
-#define SX 0x40 /* byte count in XER */
+/* Bits in the flags field */
+#define LD 0 /* load */
+#define ST 1 /* store */
+#define SE 2 /* sign-extend value */
+#define F 4 /* to/from fp regs */
+#define U 8 /* update index register */
+#define M 0x10 /* multiple load/store */
+#define SW 0x20 /* byte swap */
+#define S 0x40 /* single-precision fp or... */
+#define SX 0x40 /* ... byte count in XER */
#define HARD 0x80 /* string, stwcx. */
+/* DSISR bits reported for a DCBZ instruction: */
#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
#define SWAP(a, b) (t = (a), (a) = (b), (b) = t)
@@ -256,12 +258,16 @@ #else
#define REG_BYTE(rp, i) *((u8 *)(rp) + (i))
#endif
+#define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz))
+
static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
unsigned int reg, unsigned int nb,
- unsigned int flags, unsigned int instr)
+ unsigned int flags, unsigned int instr,
+ unsigned long swiz)
{
unsigned long *rptr;
- unsigned int nb0, i;
+ unsigned int nb0, i, bswiz;
+ unsigned long p;
/*
* We do not try to emulate 8 bytes multiple as they aren't really
@@ -280,9 +286,12 @@ static int emulate_multiple(struct pt_re
if (nb == 0)
return 1;
} else {
- if (__get_user(instr,
- (unsigned int __user *)regs->nip))
+ unsigned long pc = regs->nip ^ (swiz & 4);
+
+ if (__get_user(instr, (unsigned int __user *)pc))
return -EFAULT;
+ if (swiz == 0 && (flags & SW))
+ instr = cpu_to_le32(instr);
nb = (instr >> 11) & 0x1f;
if (nb == 0)
nb = 32;
@@ -300,7 +309,10 @@ static int emulate_multiple(struct pt_re
return -EFAULT; /* bad address */
rptr = ®s->gpr[reg];
- if (flags & LD) {
+ p = (unsigned long) addr;
+ bswiz = (flags & SW)? 3: 0;
+
+ if (!(flags & ST)) {
/*
* This zeroes the top 4 bytes of the affected registers
* in 64-bit mode, and also zeroes out any remaining
@@ -311,26 +323,28 @@ static int emulate_multiple(struct pt_re
memset(®s->gpr[0], 0,
((nb0 + 3) / 4) * sizeof(unsigned long));
- for (i = 0; i < nb; ++i)
- if (__get_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb; ++i, ++p)
+ if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = ®s->gpr[0];
addr += nb;
- for (i = 0; i < nb0; ++i)
- if (__get_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb0; ++i, ++p)
+ if (__get_user(REG_BYTE(rptr, i ^ bswiz),
+ SWIZ_PTR(p)))
return -EFAULT;
}
} else {
- for (i = 0; i < nb; ++i)
- if (__put_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb; ++i, ++p)
+ if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = ®s->gpr[0];
addr += nb;
- for (i = 0; i < nb0; ++i)
- if (__put_user(REG_BYTE(rptr, i), addr + i))
+ for (i = 0; i < nb0; ++i, ++p)
+ if (__put_user(REG_BYTE(rptr, i ^ bswiz),
+ SWIZ_PTR(p)))
return -EFAULT;
}
}
@@ -352,7 +366,7 @@ int fix_alignment(struct pt_regs *regs)
unsigned int reg, areg;
unsigned int dsisr;
unsigned char __user *addr;
- unsigned char __user *p;
+ unsigned long p, swiz;
int ret, t;
union {
u64 ll;
@@ -380,11 +394,15 @@ int fix_alignment(struct pt_regs *regs)
* let's make one up from the instruction
*/
if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {
- unsigned int real_instr;
- if (unlikely(__get_user(real_instr,
- (unsigned int __user *)regs->nip)))
+ unsigned long pc = regs->nip;
+
+ if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE))
+ pc ^= 4;
+ if (unlikely(__get_user(instr, (unsigned int __user *)pc)))
return -EFAULT;
- dsisr = make_dsisr(real_instr);
+ if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))
+ instr = cpu_to_le32(instr);
+ dsisr = make_dsisr(instr);
}
/* extract the operation and registers from the dsisr */
@@ -397,6 +415,24 @@ int fix_alignment(struct pt_regs *regs)
nb = aligninfo[instr].len;
flags = aligninfo[instr].flags;
+ /* Byteswap little endian loads and stores */
+ swiz = 0;
+ if (regs->msr & MSR_LE) {
+ flags ^= SW;
+ /*
+ * So-called "PowerPC little endian" mode works by
+ * swizzling addresses rather than by actually doing
+ * any byte-swapping. To emulate this, we XOR each
+ * byte address with 7. We also byte-swap, because
+ * the processor's address swizzling depends on the
+ * operand size (it xors the address with 7 for bytes,
+ * 6 for halfwords, 4 for words, 0 for doublewords) but
+ * we will xor with 7 and load/store each byte separately.
+ */
+ if (cpu_has_feature(CPU_FTR_PPC_LE))
+ swiz = 7;
+ }
+
/* DAR has the operand effective address */
addr = (unsigned char __user *)regs->dar;
@@ -412,7 +448,8 @@ int fix_alignment(struct pt_regs *regs)
* function
*/
if (flags & M)
- return emulate_multiple(regs, addr, reg, nb, flags, instr);
+ return emulate_multiple(regs, addr, reg, nb,
+ flags, instr, swiz);
/* Verify the address of the operand */
if (unlikely(user_mode(regs) &&
@@ -431,51 +468,71 @@ int fix_alignment(struct pt_regs *regs)
/* If we are loading, get the data from user space, else
* get it from register values
*/
- if (flags & LD) {
+ if (!(flags & ST)) {
data.ll = 0;
ret = 0;
- p = addr;
+ p = (unsigned long) addr;
switch (nb) {
case 8:
- ret |= __get_user(data.v[0], p++);
- ret |= __get_user(data.v[1], p++);
- ret |= __get_user(data.v[2], p++);
- ret |= __get_user(data.v[3], p++);
+ ret |= __get_user(data.v[0], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[1], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[2], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[3], SWIZ_PTR(p++));
case 4:
- ret |= __get_user(data.v[4], p++);
- ret |= __get_user(data.v[5], p++);
+ ret |= __get_user(data.v[4], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[5], SWIZ_PTR(p++));
case 2:
- ret |= __get_user(data.v[6], p++);
- ret |= __get_user(data.v[7], p++);
+ ret |= __get_user(data.v[6], SWIZ_PTR(p++));
+ ret |= __get_user(data.v[7], SWIZ_PTR(p++));
if (unlikely(ret))
return -EFAULT;
}
- } else if (flags & F)
+ } else if (flags & F) {
data.dd = current->thread.fpr[reg];
- else
+ if (flags & S) {
+ /* Single-precision FP store requires conversion... */
+#ifdef CONFIG_PPC_FPU
+ preempt_disable();
+ enable_kernel_fp();
+ cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread);
+ preempt_enable();
+#else
+ return 0;
+#endif
+ }
+ } else
data.ll = regs->gpr[reg];
- /* Perform other misc operations like sign extension, byteswap,
+ if (flags & SW) {
+ switch (nb) {
+ case 8:
+ SWAP(data.v[0], data.v[7]);
+ SWAP(data.v[1], data.v[6]);
+ SWAP(data.v[2], data.v[5]);
+ SWAP(data.v[3], data.v[4]);
+ break;
+ case 4:
+ SWAP(data.v[4], data.v[7]);
+ SWAP(data.v[5], data.v[6]);
+ break;
+ case 2:
+ SWAP(data.v[6], data.v[7]);
+ break;
+ }
+ }
+
+ /* Perform other misc operations like sign extension
* or floating point single precision conversion
*/
- switch (flags & ~U) {
+ switch (flags & ~(U|SW)) {
case LD+SE: /* sign extend */
if ( nb == 2 )
data.ll = data.x16.low16;
else /* nb must be 4 */
data.ll = data.x32.low32;
break;
- case LD+S: /* byte-swap */
- case ST+S:
- if (nb == 2) {
- SWAP(data.v[6], data.v[7]);
- } else {
- SWAP(data.v[4], data.v[7]);
- SWAP(data.v[5], data.v[6]);
- }
- break;
- /* Single-precision FP load and store require conversions... */
+ /* Single-precision FP load requires conversion... */
case LD+F+S:
#ifdef CONFIG_PPC_FPU
preempt_disable();
@@ -486,34 +543,24 @@ #else
return 0;
#endif
break;
- case ST+F+S:
-#ifdef CONFIG_PPC_FPU
- preempt_disable();
- enable_kernel_fp();
- cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread);
- preempt_enable();
-#else
- return 0;
-#endif
- break;
}
/* Store result to memory or update registers */
if (flags & ST) {
ret = 0;
- p = addr;
+ p = (unsigned long) addr;
switch (nb) {
case 8:
- ret |= __put_user(data.v[0], p++);
- ret |= __put_user(data.v[1], p++);
- ret |= __put_user(data.v[2], p++);
- ret |= __put_user(data.v[3], p++);
+ ret |= __put_user(data.v[0], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[1], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[2], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[3], SWIZ_PTR(p++));
case 4:
- ret |= __put_user(data.v[4], p++);
- ret |= __put_user(data.v[5], p++);
+ ret |= __put_user(data.v[4], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[5], SWIZ_PTR(p++));
case 2:
- ret |= __put_user(data.v[6], p++);
- ret |= __put_user(data.v[7], p++);
+ ret |= __put_user(data.v[6], SWIZ_PTR(p++));
+ ret |= __put_user(data.v[7], SWIZ_PTR(p++));
}
if (unlikely(ret))
return -EFAULT;
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 0c487ee..2a62d99 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -54,7 +54,8 @@ #define COMMON_USER_POWER5 (COMMON_USER_
#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
- PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
+ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
+ PPC_FEATURE_TRUE_LE)
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
@@ -74,7 +75,7 @@ #ifdef CONFIG_PPC64
.pvr_value = 0x00400000,
.cpu_name = "POWER3 (630)",
.cpu_features = CPU_FTRS_POWER3,
- .cpu_user_features = COMMON_USER_PPC64,
+ .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
@@ -87,7 +88,7 @@ #ifdef CONFIG_PPC64
.pvr_value = 0x00410000,
.cpu_name = "POWER3 (630+)",
.cpu_features = CPU_FTRS_POWER3,
- .cpu_user_features = COMMON_USER_PPC64,
+ .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 8,
@@ -306,7 +307,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00030000,
.cpu_name = "603",
.cpu_features = CPU_FTRS_603,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
@@ -317,7 +318,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00060000,
.cpu_name = "603e",
.cpu_features = CPU_FTRS_603,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
@@ -328,7 +329,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00070000,
.cpu_name = "603ev",
.cpu_features = CPU_FTRS_603,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
@@ -339,7 +340,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00040000,
.cpu_name = "604",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 2,
@@ -351,7 +352,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00090000,
.cpu_name = "604e",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -363,7 +364,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00090000,
.cpu_name = "604r",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -375,7 +376,7 @@ #if CLASSIC_PPC
.pvr_value = 0x000a0000,
.cpu_name = "604ev",
.cpu_features = CPU_FTRS_604,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -387,7 +388,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00084202,
.cpu_name = "740/750",
.cpu_features = CPU_FTRS_740_NOTAU,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -399,7 +400,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00080100,
.cpu_name = "750CX",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -411,7 +412,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00082200,
.cpu_name = "750CX",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -423,7 +424,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00082210,
.cpu_name = "750CXe",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -435,7 +436,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00083214,
.cpu_name = "750CXe",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -447,7 +448,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00083000,
.cpu_name = "745/755",
.cpu_features = CPU_FTRS_750,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -459,7 +460,7 @@ #if CLASSIC_PPC
.pvr_value = 0x70000100,
.cpu_name = "750FX",
.cpu_features = CPU_FTRS_750FX1,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -471,7 +472,7 @@ #if CLASSIC_PPC
.pvr_value = 0x70000200,
.cpu_name = "750FX",
.cpu_features = CPU_FTRS_750FX2,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -483,7 +484,7 @@ #if CLASSIC_PPC
.pvr_value = 0x70000000,
.cpu_name = "750FX",
.cpu_features = CPU_FTRS_750FX,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -495,7 +496,7 @@ #if CLASSIC_PPC
.pvr_value = 0x70020000,
.cpu_name = "750GX",
.cpu_features = CPU_FTRS_750GX,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -507,7 +508,7 @@ #if CLASSIC_PPC
.pvr_value = 0x00080000,
.cpu_name = "740/750",
.cpu_features = CPU_FTRS_740,
- .cpu_user_features = COMMON_USER,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -519,7 +520,8 @@ #if CLASSIC_PPC
.pvr_value = 0x000c1101,
.cpu_name = "7400 (1.1)",
.cpu_features = CPU_FTRS_7400_NOTAU,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -531,7 +533,8 @@ #if CLASSIC_PPC
.pvr_value = 0x000c0000,
.cpu_name = "7400",
.cpu_features = CPU_FTRS_7400,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -543,7 +546,8 @@ #if CLASSIC_PPC
.pvr_value = 0x800c0000,
.cpu_name = "7410",
.cpu_features = CPU_FTRS_7400,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
@@ -555,7 +559,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80000200,
.cpu_name = "7450",
.cpu_features = CPU_FTRS_7450_20,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -569,7 +574,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80000201,
.cpu_name = "7450",
.cpu_features = CPU_FTRS_7450_21,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -583,7 +589,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80000000,
.cpu_name = "7450",
.cpu_features = CPU_FTRS_7450_23,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -597,7 +604,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80010100,
.cpu_name = "7455",
.cpu_features = CPU_FTRS_7455_1,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -611,7 +619,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80010200,
.cpu_name = "7455",
.cpu_features = CPU_FTRS_7455_20,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -625,7 +634,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80010000,
.cpu_name = "7455",
.cpu_features = CPU_FTRS_7455,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -639,7 +649,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80020100,
.cpu_name = "7447/7457",
.cpu_features = CPU_FTRS_7447_10,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -653,7 +664,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80020101,
.cpu_name = "7447/7457",
.cpu_features = CPU_FTRS_7447_10,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -667,7 +679,7 @@ #if CLASSIC_PPC
.pvr_value = 0x80020000,
.cpu_name = "7447/7457",
.cpu_features = CPU_FTRS_7447,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -681,7 +693,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80030000,
.cpu_name = "7447A",
.cpu_features = CPU_FTRS_7447A,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
@@ -695,7 +708,8 @@ #if CLASSIC_PPC
.pvr_value = 0x80040000,
.cpu_name = "7448",
.cpu_features = CPU_FTRS_7447A,
- .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ .cpu_user_features = COMMON_USER |
+ PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 2dd47d2..e473245 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -708,6 +708,50 @@ #endif
return put_user(val, (unsigned int __user *) adr);
}
+int set_endian(struct task_struct *tsk, unsigned int val)
+{
+ struct pt_regs *regs = tsk->thread.regs;
+
+ if ((val == PR_ENDIAN_LITTLE && !cpu_has_feature(CPU_FTR_REAL_LE)) ||
+ (val == PR_ENDIAN_PPC_LITTLE && !cpu_has_feature(CPU_FTR_PPC_LE)))
+ return -EINVAL;
+
+ if (regs == NULL)
+ return -EINVAL;
+
+ if (val == PR_ENDIAN_BIG)
+ regs->msr &= ~MSR_LE;
+ else if (val == PR_ENDIAN_LITTLE || val == PR_ENDIAN_PPC_LITTLE)
+ regs->msr |= MSR_LE;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+int get_endian(struct task_struct *tsk, unsigned long adr)
+{
+ struct pt_regs *regs = tsk->thread.regs;
+ unsigned int val;
+
+ if (!cpu_has_feature(CPU_FTR_PPC_LE) &&
+ !cpu_has_feature(CPU_FTR_REAL_LE))
+ return -EINVAL;
+
+ if (regs == NULL)
+ return -EINVAL;
+
+ if (regs->msr & MSR_LE) {
+ if (cpu_has_feature(CPU_FTR_REAL_LE))
+ val = PR_ENDIAN_LITTLE;
+ else
+ val = PR_ENDIAN_PPC_LITTLE;
+ } else
+ val = PR_ENDIAN_BIG;
+
+ return put_user(val, (unsigned int __user *)adr);
+}
+
#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))
int sys_clone(unsigned long clone_flags, unsigned long usp,
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 01e3c08..a885e25 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -419,9 +419,7 @@ static long restore_user_regs(struct pt_
{
long err;
unsigned int save_r2 = 0;
-#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
unsigned long msr;
-#endif
/*
* restore general registers but not including MSR or SOFTE. Also
@@ -430,11 +428,16 @@ #endif
if (!sig)
save_r2 = (unsigned int)regs->gpr[2];
err = restore_general_regs(regs, sr);
+ err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
if (!sig)
regs->gpr[2] = (unsigned long) save_r2;
if (err)
return 1;
+ /* if doing signal return, restore the previous little-endian mode */
+ if (sig)
+ regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
/*
* Do this before updating the thread state in
* current->thread.fpr/vr/evr. That way, if we get preempted
@@ -455,7 +458,7 @@ #ifdef CONFIG_ALTIVEC
/* force the process to reload the altivec registers from
current->thread when it next does altivec instructions */
regs->msr &= ~MSR_VEC;
- if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
+ if (msr & MSR_VEC) {
/* restore altivec registers from the stack */
if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
sizeof(sr->mc_vregs)))
@@ -472,7 +475,7 @@ #ifdef CONFIG_SPE
/* force the process to reload the spe registers from
current->thread when it next does spe instructions */
regs->msr &= ~MSR_SPE;
- if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
+ if (msr & MSR_SPE) {
/* restore spe registers from the stack */
if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
ELF_NEVRREG * sizeof(u32)))
@@ -777,6 +780,8 @@ static int handle_rt_signal(unsigned lon
regs->gpr[5] = (unsigned long) &rt_sf->uc;
regs->gpr[6] = (unsigned long) rt_sf;
regs->nip = (unsigned long) ka->sa.sa_handler;
+ /* enter the signal handler in big-endian mode */
+ regs->msr &= ~MSR_LE;
regs->trap = 0;
return 1;
@@ -1047,6 +1052,8 @@ #endif
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) sc;
regs->nip = (unsigned long) ka->sa.sa_handler;
+ /* enter the signal handler in big-endian mode */
+ regs->msr &= ~MSR_LE;
regs->trap = 0;
return 1;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 27f65b9..6801b19 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -141,9 +141,7 @@ #endif
unsigned long err = 0;
unsigned long save_r13 = 0;
elf_greg_t *gregs = (elf_greg_t *)regs;
-#ifdef CONFIG_ALTIVEC
unsigned long msr;
-#endif
int i;
/* If this is not a signal return, we preserve the TLS in r13 */
@@ -154,7 +152,12 @@ #endif
err |= __copy_from_user(regs, &sc->gp_regs,
PT_MSR*sizeof(unsigned long));
- /* skip MSR and SOFTE */
+ /* get MSR separately, transfer the LE bit if doing signal return */
+ err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
+ if (sig)
+ regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
+ /* skip SOFTE */
for (i = PT_MSR+1; i <= PT_RESULT; i++) {
if (i == PT_SOFTE)
continue;
@@ -179,7 +182,6 @@ #endif
#ifdef CONFIG_ALTIVEC
err |= __get_user(v_regs, &sc->v_regs);
- err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
if (err)
return err;
/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
@@ -410,6 +412,8 @@ static int setup_rt_frame(int signr, str
/* Set up "regs" so we "return" to the signal handler. */
err |= get_user(regs->nip, &funct_desc_ptr->entry);
+ /* enter the signal handler in big-endian mode */
+ regs->msr &= ~MSR_LE;
regs->gpr[1] = newsp;
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
regs->gpr[3] = signr;
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 064a525..91a6e04 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -658,7 +658,7 @@ static int emulate_instruction(struct pt
u32 instword;
u32 rd;
- if (!user_mode(regs))
+ if (!user_mode(regs) || (regs->msr & MSR_LE))
return -EINVAL;
CHECK_FULL_REGS(regs);
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 9fcf016..72ded03 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -24,6 +24,9 @@ #define PPC_FEATURE_SMT 0x00004000
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
#define PPC_FEATURE_ARCH_2_05 0x00001000
+#define PPC_FEATURE_TRUE_LE 0x00000002
+#define PPC_FEATURE_PPC_LE 0x00000001
+
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@@ -104,6 +107,8 @@ #define CPU_FTR_NEED_COHERENT ASM_CONST
#define CPU_FTR_NO_BTIC ASM_CONST(0x0000000000040000)
#define CPU_FTR_BIG_PHYS ASM_CONST(0x0000000000080000)
#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000000000100000)
+#define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000)
+#define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000)
#ifdef __powerpc64__
/* Add the 64b processor unique features in the top half of the word */
@@ -136,6 +141,7 @@ #define CPU_FTR_COHERENT_ICACHE ASM_CON
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0)
#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0)
+#define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0)
#define CPU_FTR_PURR ASM_CONST(0x0)
#endif
@@ -192,92 +198,95 @@ #define CLASSIC_PPC (!defined(CONFIG_8xx
#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
#define CPU_FTRS_603 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
- CPU_FTR_MAYBE_CAN_NAP)
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
#define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
- CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE)
+ CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
+ CPU_FTR_PPC_LE)
#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
#define CPU_FTRS_740 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+ CPU_FTR_PPC_LE)
#define CPU_FTRS_750 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
- CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+ CPU_FTR_PPC_LE)
#define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
#define CPU_FTRS_750FX2 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_NO_DPM)
+ CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
#define CPU_FTRS_750FX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
#define CPU_FTRS_750GX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \
CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
- CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
#define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
- CPU_FTR_MAYBE_CAN_NAP)
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
#define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
- CPU_FTR_MAYBE_CAN_NAP)
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
- CPU_FTR_NEED_COHERENT)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
- CPU_FTR_NEED_COHERENT)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
- CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT)
+ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
#define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
#define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_USE_TB | \
CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
- CPU_FTR_NEED_COHERENT)
+ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
#define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
@@ -307,7 +316,7 @@ #define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_I
#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
#ifdef __powerpc64__
#define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
- CPU_FTR_HPTE_TABLE | CPU_FTR_IABR)
+ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
#define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
CPU_FTR_MMCRA | CPU_FTR_CTRL)
@@ -325,7 +334,7 @@ #define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_I
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
- CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE)
+ CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE)
#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 93f83ef..02b56f2 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -212,6 +212,12 @@ #define SET_FPEXC_CTL(tsk, val) set_fpex
extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr);
extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val);
+#define GET_ENDIAN(tsk, adr) get_endian((tsk), (adr))
+#define SET_ENDIAN(tsk, val) set_endian((tsk), (val))
+
+extern int get_endian(struct task_struct *tsk, unsigned long adr);
+extern int set_endian(struct task_struct *tsk, unsigned int val);
+
static inline unsigned int __unpack_fe01(unsigned long msr_bits)
{
return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
^ permalink raw reply related
* [PATCH 1/3] Add a prctl to change the endianness of a process.
From: Paul Mackerras @ 2006-06-07 6:10 UTC (permalink / raw)
To: akpm, linux-kernel, linuxppc-dev
From: Anton Blanchard <anton@samba.org>
This new prctl is intended for changing the execution mode of the
processor, on processors that support both a little-endian mode and a
big-endian mode. It is intended for use by programs such as
instruction set emulators (for example an x86 emulator on PowerPC),
which may find it convenient to use the processor in an alternate
endianness mode when executing translated instructions.
Note that this does not imply the existence of a fully-fledged ABI for
both endiannesses, or of compatibility code for converting system
calls done in the non-native endianness mode. The program is expected
to arrange for all of its system call arguments to be presented in the
native endianness.
Switching between big and little-endian mode will require some care in
constructing the instruction sequence for the switch. Generally the
instructions up to the instruction that invokes the prctl system call
will have to be in the old endianness, and subsequent instructions
will have to be in the new endianness.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
Andrew: if you are OK with this patch, I will put it in the
powerpc.git tree along with the next 2 patches in this series, and
merge them to Linus after 2.6.17 is released.
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index bf022c4..52a9be4 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -52,4 +52,11 @@ # define PR_TIMING_TIMESTAMP 1
#define PR_SET_NAME 15 /* Set process name */
#define PR_GET_NAME 16 /* Get process name */
+/* Get/set process endian */
+#define PR_GET_ENDIAN 19
+#define PR_SET_ENDIAN 20
+# define PR_ENDIAN_BIG 0
+# define PR_ENDIAN_LITTLE 1 /* True little endian mode */
+# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */
+
#endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index 0b6ec0e..12d2d75 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -57,6 +57,12 @@ #endif
#ifndef GET_FPEXC_CTL
# define GET_FPEXC_CTL(a,b) (-EINVAL)
#endif
+#ifndef GET_ENDIAN
+# define GET_ENDIAN(a,b) (-EINVAL)
+#endif
+#ifndef SET_ENDIAN
+# define SET_ENDIAN(a,b) (-EINVAL)
+#endif
/*
* this is where the system-wide overflow UID and GID are defined, for
@@ -2057,6 +2063,13 @@ asmlinkage long sys_prctl(int option, un
return -EFAULT;
return 0;
}
+ case PR_GET_ENDIAN:
+ error = GET_ENDIAN(current, arg2);
+ break;
+ case PR_SET_ENDIAN:
+ error = SET_ENDIAN(current, arg2);
+ break;
+
default:
error = -EINVAL;
break;
^ permalink raw reply related
* Problem in PCI with MPC5200B
From: Ram Prasad H L @ 2006-06-07 5:35 UTC (permalink / raw)
To: linuxppc-embedded
hi all,
We are using a customised board which is based on
the reference design of lite5200B. But our board is customised by adding
a PCI-PCI Bridge on the primary bus. On the secondary bus we have added
a DSP(DM642) along with 2 PCI slots, which are routed through
bridge (PCI2250) to MPC5200B.
As far as software is concerned we are using "mpc5200_lite_K26-BSP-b30"
BSP downloaded from freescale's website for lite5200B. This BSP has a
u-boot-1.1.3 and linux kernel-2.6.11.7. As far as u-boot is concerned
the PCI devices are allocated and assigned with proper resources (BAR's)
which come under the range for Mem region(40000000 - 4fffffff) and I/O
region (50000000 - 50ffffff). But during the boot process of linux we
are getting the following errors:
****************************************************************************
***
PCI: Probing PCI hardware
PCI: Cannot allocate resource region 1 of PCI bridge 1
PCI: bridge 1 resource 1 moved to 4ff00000..4fffffff
PCI: Cannot allocate resource region 2 of PCI bridge 1
PCI: bridge 1 resource 2 moved to 4fe00000..4fefffff
PCI: Failed to allocate mem resource #0: 400000 @ 50000000 for 0000:01:08.0
PCI: Failed to allocate mem resource #1: 800000 @ 50000000 for 0000:01:08.0
PCI: Failed to allocate I/O resource #2: 10 @ 1000 for 0000:01:08.0
****************************************************************************
****
where 0000:01:08.0 is the dev function address for DM642(DSP).
I'm stuck up with this problem since long time. Plz help me in giving some
pointers
for overcoming this problem as i'm a newbie to linux-pci. Any patches for
the kernel
2.6.11.7 which can resolve the above problem would be of great help.
Thanks and regards,
Ramprasad
The information contained in this electronic message and any attachments to this message are intended for the exclusive use of the addressee(s)and may contain confidential or privileged information. If you are not the intended recipient, please notify the sender or administrator@tataelxsi.co.in
^ permalink raw reply
* Re: [PATCH] powerpc: Add udbg-immortal kernel option
From: Benjamin Herrenschmidt @ 2006-06-07 4:19 UTC (permalink / raw)
To: Olof Johansson; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <20060607022412.GA5661@pb15.lixom.net>
On Tue, 2006-06-06 at 19:24 -0700, Olof Johansson wrote:
> On Wed, Jun 07, 2006 at 12:06:20PM +1000, Benjamin Herrenschmidt wrote:
> > return;
> > + if (strstr(saved_command_line, "udbg-immortal")) {
> > + printk(KERN_INFO "early console immortal !\n");
> > + return;
> > + }
>
> So it's YOU who add spaces before punctuation all over arch/powerpc!
> Please fix. ;-)
No way :) Besides, that's how it should be done in french :)
Ben.
^ permalink raw reply
* Re: [PATCH] powerpc: Add udbg-immortal kernel option
From: Olof Johansson @ 2006-06-07 2:24 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <1149645981.27572.96.camel@localhost.localdomain>
On Wed, Jun 07, 2006 at 12:06:20PM +1000, Benjamin Herrenschmidt wrote:
> return;
> + if (strstr(saved_command_line, "udbg-immortal")) {
> + printk(KERN_INFO "early console immortal !\n");
> + return;
> + }
So it's YOU who add spaces before punctuation all over arch/powerpc!
Please fix. ;-)
-Olof
^ permalink raw reply
* [PATCH] powerpc: Add udbg-immortal kernel option
From: Benjamin Herrenschmidt @ 2006-06-07 2:06 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev list
When debugging early kernel crashes that happen after console_init() and
before a proper console driver takes over, we often have to go hack into
udbg.c to prevent it from unregistering so we can "see" what is
happening. This patch adds a kernel command line option "udbg-immortal"
instead to avoid having to modify the kernel.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Paul: this is not 2.6.17 material
Index: linux-work/arch/powerpc/kernel/udbg.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/udbg.c 2006-05-31 14:13:59.000000000 +1000
+++ linux-work/arch/powerpc/kernel/udbg.c 2006-05-31 14:48:07.000000000 +1000
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/console.h>
+#include <linux/init.h>
#include <asm/processor.h>
#include <asm/udbg.h>
@@ -141,12 +142,14 @@ static int early_console_initialized;
void __init disable_early_printk(void)
{
-#if 1
if (!early_console_initialized)
return;
+ if (strstr(saved_command_line, "udbg-immortal")) {
+ printk(KERN_INFO "early console immortal !\n");
+ return;
+ }
unregister_console(&udbg_console);
early_console_initialized = 0;
-#endif
}
/* called by setup_system */
^ permalink raw reply
* [PATCH] powerpc: Fix cell blade detection
From: Benjamin Herrenschmidt @ 2006-06-07 2:04 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev list
From: Arnd Bergmann <arnd@arndb.de>
The IBM Cell blade firmware might confuse the kernel to think it's a
pSeries machine. This fixes it for now. With a bit of luck, the firmware
will be updated to avoid that in the future but currently that patch is
needed.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Index: linux-work/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/prom_init.c 2006-06-06 11:59:20.000000000 +1000
+++ linux-work/arch/powerpc/kernel/prom_init.c 2006-06-06 12:04:42.000000000 +1000
@@ -1623,6 +1623,15 @@ static int __init prom_find_machine_type
if (strstr(p, RELOC("Power Macintosh")) ||
strstr(p, RELOC("MacRISC")))
return PLATFORM_POWERMAC;
+#ifdef CONFIG_PPC64
+ /* We must make sure we don't detect the IBM Cell
+ * blades as pSeries due to some firmware issues,
+ * so we do it here.
+ */
+ if (strstr(p, RELOC("IBM,CBEA")) ||
+ strstr(p, RELOC("IBM,CPBW-1.0")))
+ return PLATFORM_GENERIC;
+#endif /* CONFIG_PPC64 */
i += sl + 1;
}
}
Index: linux-work/arch/powerpc/platforms/cell/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/cell/setup.c 2006-05-11 11:45:08.000000000 +1000
+++ linux-work/arch/powerpc/platforms/cell/setup.c 2006-06-06 12:03:03.000000000 +1000
@@ -125,14 +125,13 @@ static void __init cell_init_early(void)
static int __init cell_probe(void)
{
- /* XXX This is temporary, the Cell maintainer will come up with
- * more appropriate detection logic
- */
unsigned long root = of_get_flat_dt_root();
- if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
- return 0;
- return 1;
+ if (of_flat_dt_is_compatible(root, "IBM,CBEA") ||
+ of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+ return 1;
+
+ return 0;
}
/*
Index: linux-work/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/pseries/setup.c 2006-06-05 17:55:31.000000000 +1000
+++ linux-work/arch/powerpc/platforms/pseries/setup.c 2006-06-06 13:05:21.000000000 +1000
@@ -399,6 +399,7 @@ static int __init pSeries_probe_hypertas
static int __init pSeries_probe(void)
{
+ unsigned long root = of_get_flat_dt_root();
char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
"device_type", NULL);
if (dtype == NULL)
@@ -406,6 +407,13 @@ static int __init pSeries_probe(void)
if (strcmp(dtype, "chrp"))
return 0;
+ /* Cell blades firmware claims to be chrp while it's not. Until this
+ * is fixed, we need to avoid those here.
+ */
+ if (of_flat_dt_is_compatible(root, "IBM,CPBW-1.0") ||
+ of_flat_dt_is_compatible(root, "IBM,CBEA"))
+ return 0;
+
DBG("pSeries detected, looking for LPAR capability...\n");
/* Now try to figure out if we are running on LPAR */
^ permalink raw reply
* [PATCH] powerpc: Fix call to ibm,client-architecture-support
From: Benjamin Herrenschmidt @ 2006-06-07 2:01 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev list
The code in prom_init.c calling the firmware
ibm,client-architecture-support on pSeries has a bug where it fails to
properly pass the instance handle of the firmware object when trying to
call a method. Result ranges from the call doing nothing to the firmware
crashing. (Found by Segher, thanks !)
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Index: linux-work/arch/powerpc/kernel/prom_init.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/prom_init.c 2006-05-30 13:00:51.000000000 +1000
+++ linux-work/arch/powerpc/kernel/prom_init.c 2006-06-06 11:59:20.000000000 +1000
@@ -822,6 +822,7 @@ static void __init prom_send_capabilitie
/* try calling the ibm,client-architecture-support method */
if (call_prom_ret("call-method", 3, 2, &ret,
ADDR("ibm,client-architecture-support"),
+ root,
ADDR(ibm_architecture_vec)) == 0) {
/* the call exists... */
if (ret)
^ permalink raw reply
* [PATCH] powerpc: oprofile support for POWER6
From: Michael Neuling @ 2006-06-07 1:23 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
POWER6 moves some of the MMCRA bits and also requires some bits to be
cleared each PMU interrupt.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Acked-by: Anton Blanchard <anton@samba.org>
---
Paul: for your post 2.6.17 queue
arch/powerpc/kernel/cputable.c | 10 +++++++-
arch/powerpc/oprofile/op_model_power4.c | 37 ++++++++++++--------------------
include/asm-powerpc/cputable.h | 11 ++++++---
include/asm-powerpc/reg.h | 4 +++
4 files changed, 36 insertions(+), 26 deletions(-)
Index: linux-2.6-powerpc/arch/powerpc/kernel/cputable.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/kernel/cputable.c
+++ linux-2.6-powerpc/arch/powerpc/kernel/cputable.c
@@ -236,6 +236,8 @@ struct cpu_spec cpu_specs[] = {
.num_pmcs = 6,
.oprofile_cpu_type = "ppc64/power5",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_mmcra_sihv = MMCRA_SIHV,
+ .oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5",
},
{ /* Power5 GS */
@@ -249,6 +251,8 @@ struct cpu_spec cpu_specs[] = {
.num_pmcs = 6,
.oprofile_cpu_type = "ppc64/power5+",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_mmcra_sihv = MMCRA_SIHV,
+ .oprofile_mmcra_sipr = MMCRA_SIPR,
.platform = "power5+",
},
{ /* Power6 */
@@ -259,9 +263,13 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_POWER6,
.icache_bsize = 128,
.dcache_bsize = 128,
- .num_pmcs = 6,
+ .num_pmcs = 8,
.oprofile_cpu_type = "ppc64/power6",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
+ .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
+ .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
+ POWER6_MMCRA_OTHER,
.platform = "power6",
},
{ /* Cell Broadband Engine */
Index: linux-2.6-powerpc/arch/powerpc/oprofile/op_model_power4.c
===================================================================
--- linux-2.6-powerpc.orig/arch/powerpc/oprofile/op_model_power4.c
+++ linux-2.6-powerpc/arch/powerpc/oprofile/op_model_power4.c
@@ -24,10 +24,6 @@
static unsigned long reset_value[OP_MAX_COUNTER];
static int oprofile_running;
-static int mmcra_has_sihv;
-/* Unfortunately these bits vary between CPUs */
-static unsigned long mmcra_sihv = MMCRA_SIHV;
-static unsigned long mmcra_sipr = MMCRA_SIPR;
/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
static u32 mmcr0_val;
@@ -41,16 +37,6 @@ static void power4_reg_setup(struct op_c
int i;
/*
- * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above.
- * However we disable it on all POWER4 until we verify it works
- * (I was seeing some strange behaviour last time I tried).
- *
- * It has been verified to work on POWER5 so we enable it there.
- */
- if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
- mmcra_has_sihv = 1;
-
- /*
* The performance counter event settings are given in the mmcr0,
* mmcr1 and mmcra values passed from the user in the
* op_system_config structure (sys variable).
@@ -202,18 +188,19 @@ static unsigned long get_pc(struct pt_re
unsigned long mmcra;
/* Cant do much about it */
- if (!mmcra_has_sihv)
+ if (!cur_cpu_spec->oprofile_mmcra_sihv)
return pc;
mmcra = mfspr(SPRN_MMCRA);
/* Were we in the hypervisor? */
- if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
+ if (firmware_has_feature(FW_FEATURE_LPAR) &&
+ (mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
/* function descriptor madness */
return *((unsigned long *)hypervisor_bucket);
/* We were in userspace, nothing to do */
- if (mmcra & mmcra_sipr)
+ if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr)
return pc;
#ifdef CONFIG_PPC_RTAS
@@ -235,15 +222,14 @@ static unsigned long get_pc(struct pt_re
return pc;
}
-static int get_kernel(unsigned long pc)
+static int get_kernel(unsigned long pc, unsigned long mmcra)
{
int is_kernel;
- if (!mmcra_has_sihv) {
+ if (!cur_cpu_spec->oprofile_mmcra_sihv) {
is_kernel = is_kernel_addr(pc);
} else {
- unsigned long mmcra = mfspr(SPRN_MMCRA);
- is_kernel = ((mmcra & mmcra_sipr) == 0);
+ is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0);
}
return is_kernel;
@@ -257,9 +243,12 @@ static void power4_handle_interrupt(stru
int val;
int i;
unsigned int mmcr0;
+ unsigned long mmcra;
+
+ mmcra = mfspr(SPRN_MMCRA);
pc = get_pc(regs);
- is_kernel = get_kernel(pc);
+ is_kernel = get_kernel(pc, mmcra);
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);
@@ -287,6 +276,10 @@ static void power4_handle_interrupt(stru
*/
mmcr0 &= ~MMCR0_PMAO;
+ /* Clear the appropriate bits in the MMCRA */
+ mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear;
+ mtspr(SPRN_MMCRA, mmcra);
+
/*
* now clear the freeze bit, counting will not start until we
* rfid from this exception, because only at that point will
Index: linux-2.6-powerpc/include/asm-powerpc/cputable.h
===================================================================
--- linux-2.6-powerpc.orig/include/asm-powerpc/cputable.h
+++ linux-2.6-powerpc/include/asm-powerpc/cputable.h
@@ -69,6 +69,13 @@ struct cpu_spec {
/* Processor specific oprofile operations */
enum powerpc_oprofile_type oprofile_type;
+ /* Bit locations inside the mmcra change */
+ unsigned long oprofile_mmcra_sihv;
+ unsigned long oprofile_mmcra_sipr;
+
+ /* Bits to clear during an oprofile exception */
+ unsigned long oprofile_mmcra_clear;
+
/* Name of processor class, for the ELF AT_PLATFORM entry */
char *platform;
};
@@ -117,7 +124,6 @@ extern void do_cpu_ftr_fixups(unsigned l
#define CPU_FTR_SMT ASM_CONST(0x0000010000000000)
#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000)
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
-#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000)
#define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000)
#define CPU_FTR_PURR ASM_CONST(0x0000400000000000)
@@ -134,7 +140,6 @@ extern void do_cpu_ftr_fixups(unsigned l
#define CPU_FTR_SMT ASM_CONST(0x0)
#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0)
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0)
-#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0)
#define CPU_FTR_PURR ASM_CONST(0x0)
#endif
@@ -320,7 +325,7 @@ extern void do_cpu_ftr_fixups(unsigned l
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
- CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR)
+ CPU_FTR_PURR)
#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_MMCRA | CPU_FTR_SMT | \
Index: linux-2.6-powerpc/include/asm-powerpc/reg.h
===================================================================
--- linux-2.6-powerpc.orig/include/asm-powerpc/reg.h
+++ linux-2.6-powerpc/include/asm-powerpc/reg.h
@@ -443,6 +443,10 @@
#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */
#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */
#define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
+#define POWER6_MMCRA_SIHV 0x0000040000000000ULL
+#define POWER6_MMCRA_SIPR 0x0000020000000000ULL
+#define POWER6_MMCRA_THRM 0x00000020UL
+#define POWER6_MMCRA_OTHER 0x0000000EUL
#define SPRN_PMC1 787
#define SPRN_PMC2 788
#define SPRN_PMC3 789
^ permalink raw reply
* Re: Collecting hypervisor call stats
From: Christopher Yeoh @ 2006-06-07 1:08 UTC (permalink / raw)
To: Mike Kravetz; +Cc: Chris Yeoh, Bryan Rosenburg, linuxppc-dev
In-Reply-To: <20060606164646.GA3161@w-mikek2.ibm.com>
At 2006/6/6 09:46-0700 Mike Kravetz writes:
> On Thu, Jun 01, 2006 at 03:12:15PM +1000, Christopher Yeoh wrote:
> > Here's a patch we've used for collecting hcall counts and times.
>
> Thanks for the patch/code Chris! I'm using this as a basis for something
> that we may want to merge into the tree. Just a couple of questions.
>
> Your 'wrappers' have the following general form:
>
>
> Can you explain the need for barrier(s) before and after the call to the
> real routine? It usually takes me a couple days of thought to figure out
> exactly where these are needed. :)
Ah oops, it turns out I was wrong and they're not necessary after all.
> The use of get_cpu_var/put_cpu_var result in disabling/enabling preemption.
> I can understand why this would be desirable to assure the accuracy of the
> statistics. But, I was wondering if the desired accuracy is worth the added
> overhead. My thought was to make these as lightweight as possible and
> sacrifice some accuracy if necessary. After all, no 'internal decisions' are
> being made because of this data. It is simply exposed to user land.
> Thoughts?
For what we were using them for at the time we weren't really
concerned about a small degradation in performance and were more
interested in accuracy. I guess I'd recommend doing some benchmarking
to see what difference they really make.
Chris
--
cyeoh@au.ibm.com
IBM OzLabs Linux Development Group
Canberra, Australia
^ permalink raw reply
* Re: [PATCH 0/5] Sizing zones and holes in an architecture independent manner V7
From: Andrew Morton @ 2006-06-06 23:43 UTC (permalink / raw)
To: Mel Gorman
Cc: davej, tony.luck, linux-mm, mel, ak, bob.picco, linux-kernel,
linuxppc-dev
In-Reply-To: <20060606134710.21419.48239.sendpatchset@skynet.skynet.ie>
On Tue, 6 Jun 2006 14:47:10 +0100 (IST)
Mel Gorman <mel@csn.ul.ie> wrote:
> This is V7 of the patchset to size zones and memory holes in an
> architecture-independent manner.
I hope this won't deprive me of my 4 kbyte highmem zone.
I won't merge these patches for rc6-mm1 - we already have a few problems in
this area which I don't think anyone understands yet.
^ permalink raw reply
* RE: [PATCH/2.6.17-rc4 4/10]Powerpc: Add tsi108 pic support
From: Benjamin Herrenschmidt @ 2006-06-06 23:08 UTC (permalink / raw)
To: Alexandre Bounine; +Cc: linuxppc-dev list, Paul Mackerras, Yang Xin-Xin-r48390
In-Reply-To: <8A1F97E8A7ACE847B1DB69DFDCBC6E807D634E@caribou.pc.tundra.com>
On Tue, 2006-06-06 at 10:45 -0400, Alexandre Bounine wrote:
> We have a level-signalled irq from the cascaded PCI interrupt controller. If I do EOI at
> this time, level request will not have chance to be cleared (unless all PCI interrupts have
> an SA_INTERRUPT flag) and result in recurring interrupts.
Hrm... Ok, when the cascade is a 8259 or an MPIC, we don't have that
problem despite the output also being level... I think that's because
the cascade handler itself will mask the cascade interrupt (on MPIC,
reading the irq does an ack which will mask that priority level). If
your cascaded controller doesn't act this way, you may need something a
bit different in your cascade handler rather than changing mpic.
However, I wouldn't bother too much. As I said, this is all changing a
lot at the moment as I'm porting powerpc to Ingo Molnar and Thomas
Gleixner's new "genirq" layer. Cascade handling will be different and
taken out of MPIC, so you'll be able to implement it the way your want
(with much greater control on what happens) without changing the MPIC
driver.
I'll have patches posted on the list in a few days hopefully.
> I chose to have an individual flag instead of checking model ID to avoid multiple checks within ISR
> (in case if we have more that one mpic version requiring this option). I also expect that it may be
> useful for any external level-signalling cascades connected to MPIC.
As I said above, I think it can just go away with the port to genirq.
> Motivation is the same as above - I just do not want to have multiple ID checks here. I agree that it is
> driven by mpic type (model ID) only. I can remove this one if you do not expect any
> new "broken" MPICs on horizon.
Well, I do expect broken ones but not with that specific issue :)
Cheers,
Ben.
^ permalink raw reply
* 82xx CPM commands
From: Rune Torgersen @ 2006-06-06 22:13 UTC (permalink / raw)
To: linuxppc-embedded
Hi.
Besause of some weird system hangs we have seen, I am wondering if the
CPM command register may need a lock around it.
In one of our drivers we can end up writing a CPM command every
millisecond on worst case during an error condition.
Sometimes during that error condition the whole CPU locks up. (or rather
it spins in an interrupt somewhere).
After looking at all the other places in the kernel the CPM command
register gets written, I am convinced that there does exists conditions
where we might accidentally write to the command register while some
other thread/irq is writing/waiting for command completion.
The code in all paces looks like:
cp->cp_cpcr =3D mk_cr_cmd(SOME COMMAND);
while (cp->cp_cpcr & CPM_CR_FLG);
I think we might need a lock around it.
local_irq_save() woild work, but would lock the whole CPU while the CPM
command completes (which can take 200 CPM clock cycles, avg 40 according
to maual)
Easiest way would probaby be to have a (inline) function that does the
lock/write/wait/unlock.
There is a couple of places that does a udelay between the write and the
wait.
^ permalink raw reply
* Re: ppc85xx DMA
From: Naru Sundar @ 2006-06-06 21:38 UTC (permalink / raw)
To: Liu Dave-r63238; +Cc: linuxppc-embedded
In-Reply-To: <20060606211610.GD27078@fulcrummicro.com>
Ah hah. I got it working.
Turns out using the ioremapped address was bad, I had to use the actual
nonremapped physical address.
Thanks for the info!
-naru
On Tue, Jun 06, 2006 at 02:16:10PM -0700, Naru Sundar wrote:
> To clarify, I am definitely using the physical addresses. virt_to_bus and
> virt_to_phys result in the same value. My transfer completes and I see
> BCR go back to 0, but I can't manage to actually see any data difference
> at the destination side.
>
> The destination address is an ioremapped region that I pass through
> virt_to_phys. The src is kmalloc'd memory that has GFP_DMA set.
>
> On Tue, Jun 06, 2006 at 11:55:48AM -0700, Naru Sundar wrote:
> > On Tue, Jun 06, 2006 at 09:39:29AM +0800, Liu Dave-r63238 wrote:
> > > What is the DMA transfer mode? Is direct or chaining mode?
> >
> > Direct mode. I fixed an error with my bit ordering for the configuration
> > registers, and now the transfer seems to complete, but I don't see any
> > actual data showing up in the destination register that I am writing to.
> >
> > > Did you ioremap the DMA register space?
> >
> > Yes, I can write the destination address manually. So I am thinking my addresses
> > are wrong.
> >
> > For the source and dest address I used:
> >
> > dma_map_single(NULL, ptr, len, DMA_TO_DEVICE)
> >
> > (which effectively does a virt_to_bus on ppc and so should just return to me
> > the bus address used by the dma).
> >
> > -naru
> > _______________________________________________
> > Linuxppc-embedded mailing list
> > Linuxppc-embedded@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply
* Re: Base address of executables - weirdness?
From: H. Peter Anvin @ 2006-06-06 21:21 UTC (permalink / raw)
To: Andreas Schwab; +Cc: linuxppc-dev
In-Reply-To: <jeirne56kn.fsf@sykes.suse.de>
Andreas Schwab wrote:
> "H. Peter Anvin" <hpa@zytor.com> writes:
>
>> Until recently, binaries linked with ld defaulted to a base address of
>> 0x10000000+SIZEOF_HEADERS. However, recently I've gotten a couple of
>> reports -- and I've been able to confirm this on my FC5 system -- that
>> some versions of ld links at 0x01800000+SIZEOF_HEADERS.
>
> You are probably using the wrong linker emulation. There are three
> emulations enabled when building binutils for ppc-linux, but only the
> elf32ppclinux emulation it the right one that uses 0x10000000 for the base
> address.
>
Hm. Well, it's using the default one, but perhaps I should try to specify an explicit -m
option. Sure enough, that did the trick.
THANKS!
-hpa
^ permalink raw reply
* Re: ppc85xx DMA
From: Naru Sundar @ 2006-06-06 21:16 UTC (permalink / raw)
To: Liu Dave-r63238; +Cc: linuxppc-embedded
In-Reply-To: <20060606185548.GB27078@fulcrummicro.com>
To clarify, I am definitely using the physical addresses. virt_to_bus and
virt_to_phys result in the same value. My transfer completes and I see
BCR go back to 0, but I can't manage to actually see any data difference
at the destination side.
The destination address is an ioremapped region that I pass through
virt_to_phys. The src is kmalloc'd memory that has GFP_DMA set.
On Tue, Jun 06, 2006 at 11:55:48AM -0700, Naru Sundar wrote:
> On Tue, Jun 06, 2006 at 09:39:29AM +0800, Liu Dave-r63238 wrote:
> > What is the DMA transfer mode? Is direct or chaining mode?
>
> Direct mode. I fixed an error with my bit ordering for the configuration
> registers, and now the transfer seems to complete, but I don't see any
> actual data showing up in the destination register that I am writing to.
>
> > Did you ioremap the DMA register space?
>
> Yes, I can write the destination address manually. So I am thinking my addresses
> are wrong.
>
> For the source and dest address I used:
>
> dma_map_single(NULL, ptr, len, DMA_TO_DEVICE)
>
> (which effectively does a virt_to_bus on ppc and so should just return to me
> the bus address used by the dma).
>
> -naru
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
^ permalink raw reply
* Re: Base address of executables - weirdness?
From: Andreas Schwab @ 2006-06-06 21:15 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: linuxppc-dev
In-Reply-To: <4485A279.4050403@zytor.com>
"H. Peter Anvin" <hpa@zytor.com> writes:
> Until recently, binaries linked with ld defaulted to a base address of
> 0x10000000+SIZEOF_HEADERS. However, recently I've gotten a couple of
> reports -- and I've been able to confirm this on my FC5 system -- that
> some versions of ld links at 0x01800000+SIZEOF_HEADERS.
You are probably using the wrong linker emulation. There are three
emulations enabled when building binutils for ppc-linux, but only the
elf32ppclinux emulation it the right one that uses 0x10000000 for the base
address.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply
* Re: eth0: tx queue full
From: Wolfgang Denk @ 2006-06-06 20:53 UTC (permalink / raw)
To: salvatore cusenza; +Cc: linuxppc-embedded
In-Reply-To: <9252a64b0606060113v696adbb7ib43ad95836c0724b@mail.gmail.com>
In message <9252a64b0606060113v696adbb7ib43ad95836c0724b@mail.gmail.com> you wrote:
>
> At runtime during the usual life of my board (MPC852 and linux-2.4.20 Denk's
> distribution)
> I have experienced the following crash:
2.4.20 is at least 3.5 years old. Please use recent code.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Brain fried - Core dumped
^ permalink raw reply
* 2.4 kernel scheduling (?) problems
From: Tobias Netzel @ 2006-06-06 18:29 UTC (permalink / raw)
To: linuxppc-dev
Hello all,
I'm new to this list - hoping you will help me with the 2.4 kernel,
although it's old now.
I'm improving hardware support for the NuBus PMacs. The NuBus Pmacs are
68k Macs with a PPC CPU and a different bus bridge/memory controller.
The NuBus PMac port is something like a hack to the PPC architecture
using some things from the PMac platform.
An open firmware device tree is emulated as far as needed. We use the
same PMU driver (although I hacked it a bit because we directly route
the PMU interrupts), ADB and RTC driver and the same functions to
calibrate the decrementer using the VIA timer.
The problem I got is that for example during SCSI transfers (I'm using
an old scanner) neither the X screen gets updated nor does the system
respond to any interrupts but the NMI.
Debugging messages through the serial port are still sent. So I have to
wait until the whole transfer is done. The kernel only receives
interrupts after a SCSI command has finished and before a new one is
sent. The data from the scanner is transfered in blocks of 32 kB.
The behaviour is similar when I do an performance test using "dd" or
"hdparm" on the IDE CD-ROM drive. Burning CDs using that IDE drive
works but causes the same problem as when scanning with the SCSI
scanner.
With the IDE hard disk I don't get this problem.
When I run "top" during those problem transfers the CPU utilization by
the system is higher than 95% ("top" hardly gets updated) - I doubt
that this is necessary as on the NuBus PMacs the PPC CPUs (and
especially the 217 MHz G3 with 512 kB L2 cache I'm using) should be
idle most of the time waiting for the slow 33 MHz system bus.
The strange thing is that the CPU misses all interrupts (except the
NMI) although interrupts aren't turned off in the CPU (otherwise the
PMU would shut us down and the NMI wouldn't work). I also tried to use
a timer to poll the interrupt controllers but the interrupt handling
routines also only find one pending interrupt in 10 seconds even when I
constantly move the mouse and hit keys.
At first I thought this was something caused by the hardware but in
MacOS 9 the SCSI driver doesn't block anything.
But is it possible that this is because of something like scheduling
problems of the kernel?
And if so might updating to the 2.6 kernel fix that issue?
Tobias
^ permalink raw reply
* Re: Base address of executables - weirdness?
From: Linas Vepstas @ 2006-06-06 17:33 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: linuxppc-dev
In-Reply-To: <4485A279.4050403@zytor.com>
On Tue, Jun 06, 2006 at 08:42:49AM -0700, H. Peter Anvin wrote:
> I'm trying to track down an odd issue with klibc on ppc32.
>
> Until recently, binaries linked with ld defaulted to a base address of
> 0x10000000+SIZEOF_HEADERS. However, recently I've gotten a couple of
> reports -- and I've been able to confirm this on my FC5 system -- that
> some versions of ld links at 0x01800000+SIZEOF_HEADERS. Needless to
> say, this is more than a bit confusing, *especially* since "ld -verbose"
> still reports:
>
> PROVIDE (__executable_start = 0x10000000); . = 0x10000000 +
> SIZEOF_HEADERS;
>
> ... at the top of the linker script.
>
> I'm rather baffled. Has anyone else seen this, and/or have any other
> explanation?
Googling "0x01800000 linux ppc" brings up some interesting but old hits.
However, I swear I saw someone suggest a patch last week that changed
0x10000000 to 0x01800000 somewhere, (vmlinux.lds ??) as a proposed cure
for a bug. Sorry, I deleted it.
--linas
^ permalink raw reply
* RE: [PATCH/2.6.17-rc4 4/10]Powerpc: Add tsi108 pic support
From: Alexandre Bounine @ 2006-06-06 18:58 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Zang Roy-r61911
Cc: linuxppc-dev list, Paul Mackerras, Yang Xin-Xin-r48390
I forgot to mention another argument in favor of adding separate =
MPIC_SPV_EOI and MPIC_CASC_NOEOI flags:
If we have MPIC with "broken" logic but standard register map we can use =
model ID =3D 0 for
the standard MPIC without creating additional data structure.
Regards,
Alex.
-----Original Message-----
From: Alexandre Bounine=20
Sent: Tuesday, June 06, 2006 10:46 AM
To: 'Benjamin Herrenschmidt'; Zang Roy-r61911
Cc: Kumar Gala; linuxppc-dev list; Yang Xin-Xin-r48390; Paul Mackerras
Subject: RE: [PATCH/2.6.17-rc4 4/10]Powerpc: Add tsi108 pic support
> -----Original Message-----
> From: Benjamin Herrenschmidt [mailto:benh@kernel.crashing.org]
> Sent: Tuesday, June 06, 2006 6:17 AM
> To: Zang Roy-r61911
> Cc: Alexandre Bounine; Kumar Gala; linuxppc-dev list; Yang
> Xin-Xin-r48390; Paul Mackerras
> Subject: RE: [PATCH/2.6.17-rc4 4/10]Powerpc: Add tsi108 pic support
>=20
>=20
> On Tue, 2006-06-06 at 17:43 +0800, Zang Roy-r61911 wrote:
>=20
> > Update Tsi108 implementation of MPIC.
> > Any comment?=20
> >=20
> > Integrate Tundra Semiconductor tsi108 host bridge interrupt=20
> controller=20
> > to mpic arch.
>=20
> Looks much better :) Still a few things...=20
>
Sounds good. We are moving in right direction :)
=20
> > + mpic =3D mpic_alloc(mpic_paddr,
> > + MPIC_PRIMARY | MPIC_BIG_ENDIAN |=20
> MPIC_WANTS_RESET |
> > + MPIC_SPV_EOI | MPIC_CASC_NOEOI |=20
> > + MPIC_MOD_ID(MPIC_ID_TSI108),
> > + 0, /* num_sources used */
> > + TSI108_IRQ_BASE,
> > + 0, /* num_sources used */
> > + NR_IRQS - 4 /* XXXX */,
> > + mpc7448_hpc2_pic_initsenses,
> > + sizeof(mpc7448_hpc2_pic_initsenses),=20
> "Tsi108_PIC");
>=20
> That's a hell lot of new flags... I'm not sure we need that many or a
> single TSI108 one that encloses all the new ones. Also, I'm=20
> not sure we
> need that model ID encoding thing. Let's do things simple, besides, I
> don't want to encourage HW folks into doing the same kind of=20
> contraption
> in the future
More details in comments below.
>(btw, tell the TSI folks for me that they had a BAD BAD
> BAD idea to muck around with the base design that way, especially
> changing the register map in incompatible ways for no good reason).
>=20
Done!
> > + /* Configure MPIC outputs to CPU0 */
> > + tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
> > }
>=20
> It doesn't use the standard multiple processor outputs mecanism of
> MPIC ?
> =20
> > +static struct mpic_info mpic_infos[] =3D {
> > + [0] =3D { /* Original OpenPIC compatible MPIC */
> > + .greg_base =3D MPIC_GREG_BASE,
> > + .greg_frr0 =3D MPIC_GREG_FEATURE_0,
> > + .greg_config0 =3D MPIC_GREG_GLOBAL_CONF_0,
> > + .greg_vendor_id =3D MPIC_GREG_VENDOR_ID,
> > + .greg_ipi_vp0 =3D MPIC_GREG_IPI_VECTOR_PRI_0,
> > + .greg_ipi_stride =3D MPIC_GREG_IPI_STRIDE,
> > + .greg_spurious =3D MPIC_GREG_SPURIOUS,
> > + .greg_tfrr =3D MPIC_GREG_TIMER_FREQ,
> > +
>=20
> .../...
>=20
> It's a bit sad to have to go all the way to doing such tables, but I
> suspect it's probably the best way to handle it at this=20
> point.
> Send more
> nastygrams to the HW folks for me.
>=20
Done:)
> > mpic->num_sources =3D 0; /* so far */
> > mpic->senses =3D senses;
> > mpic->senses_count =3D senses_count;
> > + mpic->hw_set =3D &mpic_infos[MPIC_GET_MOD_ID(flags)];
>=20
> Well... the model ID thing might not be that a bad idea in=20
> the end :) I
> need to think about it. I might have to deal with yet another=20
> MPIC that
> has another regiser map (yeah yeah, TSI aren't the only ones=20
> to not get
> it)...=20
>
I'll tell this to HW guys as well :)=20
> .../...
>=20
> > @@ -963,7 +1043,7 @@ int mpic_get_one_irq(struct mpic *mpic,=20
> > {
> > u32 irq;
> > =20
> > - irq =3D mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
> > + irq =3D mpic_cpu_read(mpic->hw_set->cpu_intack) &=20
> mpic->hw_set->irq_vpr_vector;
> > #ifdef DEBUG_LOW
> > DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
> > #endif
> > @@ -972,11 +1052,18 @@ #ifdef DEBUG_LOW
> > DBG("%s: cascading ...\n", mpic->name);
> > #endif
> > irq =3D mpic->cascade(regs, mpic->cascade_data);
> > - mpic_eoi(mpic);
> > +#ifdef DEBUG_LOW
> > + DBG("%s: cascaded irq: %d\n", mpic->name, irq);
> > +#endif
> > + if (!(mpic->flags & MPIC_CASC_NOEOI))
> > + mpic_eoi(mpic);
> > return irq;
> > }
>=20
> Can you tell me why you need the above ? (Why you aren't EOI'ing the
> cascade ?) Note that the cascade handling is going away from=20
> mpic anyway
> with the port to genirq that I'll publish later this week for=20
> 2.6.18 and
> it will almost be handled as a normal interrupt...
>=20
We have a level-signalled irq from the cascaded PCI interrupt =
controller. If I do EOI at=20
this time, level request will not have chance to be cleared (unless all =
PCI interrupts have
an SA_INTERRUPT flag) and result in recurring interrupts.=20
I chose to have an individual flag instead of checking model ID to avoid =
multiple checks within ISR (in case if we have more that one mpic =
version requiring this option). I also expect that it may be useful for =
any external level-signalling cascades connected to MPIC. =20
> > - if (unlikely(irq =3D=3D MPIC_VEC_SPURRIOUS))
> > + if (unlikely(irq =3D=3D MPIC_VEC_SPURRIOUS)) {
> > + if (mpic->flags & MPIC_SPV_EOI)
> > + mpic_eoi(mpic);
> > return -1;
> > + }
>=20
> I think the above thing could just test the model ID. It's=20
> unlikely that
> another implementation need the same "feature", so just test the model
> ID rather than adding a flag and if we ever have another=20
> model with the
> same "feature", then we'll go back to adding a flag :)
>=20
Motivation is the same as above - I just do not want to have multiple ID =
checks here. I agree that it is driven by mpic type (model ID) only. I =
can remove this one if you do not expect any
new "broken" MPICs on horizon. =20
> Cheers,
> Ben.
>=20
Thanks for your feedback,
Alex.
>=20
>=20
^ permalink raw reply
* Re: ppc85xx DMA
From: Naru Sundar @ 2006-06-06 18:55 UTC (permalink / raw)
To: Liu Dave-r63238; +Cc: linuxppc-embedded
In-Reply-To: <9FCDBA58F226D911B202000BDBAD4673026FD940@zch01exm40.ap.freescale.net>
On Tue, Jun 06, 2006 at 09:39:29AM +0800, Liu Dave-r63238 wrote:
> What is the DMA transfer mode? Is direct or chaining mode?
Direct mode. I fixed an error with my bit ordering for the configuration
registers, and now the transfer seems to complete, but I don't see any
actual data showing up in the destination register that I am writing to.
> Did you ioremap the DMA register space?
Yes, I can write the destination address manually. So I am thinking my addresses
are wrong.
For the source and dest address I used:
dma_map_single(NULL, ptr, len, DMA_TO_DEVICE)
(which effectively does a virt_to_bus on ppc and so should just return to me
the bus address used by the dma).
-naru
^ permalink raw reply
* Re: Base address of executables - weirdness?
From: H. Peter Anvin @ 2006-06-06 18:21 UTC (permalink / raw)
To: Linas Vepstas; +Cc: linuxppc-dev
In-Reply-To: <20060606173343.GE9294@austin.ibm.com>
Linas Vepstas wrote:
> On Tue, Jun 06, 2006 at 08:42:49AM -0700, H. Peter Anvin wrote:
>> I'm trying to track down an odd issue with klibc on ppc32.
>>
>> Until recently, binaries linked with ld defaulted to a base address of
>> 0x10000000+SIZEOF_HEADERS. However, recently I've gotten a couple of
>> reports -- and I've been able to confirm this on my FC5 system -- that
>> some versions of ld links at 0x01800000+SIZEOF_HEADERS. Needless to
>> say, this is more than a bit confusing, *especially* since "ld -verbose"
>> still reports:
>>
>> PROVIDE (__executable_start = 0x10000000); . = 0x10000000 +
>> SIZEOF_HEADERS;
>>
>> ... at the top of the linker script.
>>
>> I'm rather baffled. Has anyone else seen this, and/or have any other
>> explanation?
>
> Googling "0x01800000 linux ppc" brings up some interesting but old hits.
>
> However, I swear I saw someone suggest a patch last week that changed
> 0x10000000 to 0x01800000 somewhere, (vmlinux.lds ??) as a proposed cure
> for a bug. Sorry, I deleted it.
>
Well, it's worse than I previously surmised. I can't seem to find any combination of
options which work on both affected and unaffected binutils. This is a real mess.
-hpa
^ permalink raw reply
* RE: Intercept System call using Kernel module is 2.6 kernel
From: Jenkins, Clive @ 2006-06-06 17:14 UTC (permalink / raw)
To: Meswani, Mitesh, linuxppc-dev
> x=3Dmitesh_func();=20
> printf("mitesh_func returned %d\n",x);
The first thing would be to change your user-space program
to print the error number from errno after your "system call".
x=3Dmitesh_func();=20
printf("mitesh_func returned %d, errno=3D%d\n",x,errno);
Or you can use perror() -- look it up.
Clive
=20
4) I verify from the system logs that when I insmod the kernel module I
get all the print statements. I verified from the logs that the address
of the sys_call_table is correctly passed and from /proc/kallsysms I can
see that my function mitesh_func has been defined and has the address as
indicated in the logs.=20
The problem is that when I execute my user app I expect to see two
things:=20
a) I should see a message in the log "Executing mitesh_func..." and=20
b) A return value of 2=20
However I get an error value -1 returned.=20
Any help and ideas are highly appreciated. =20
Thank you in advance,=20
Mitesh=20
^ permalink raw reply
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