[POWERPC] Add support for FP emulation for the e300c2 core
authorKim Phillips <kim.phillips@freescale.com>
Fri, 8 Dec 2006 08:43:30 +0000 (02:43 -0600)
committerKumar Gala <galak@kernel.crashing.org>
Fri, 8 Dec 2006 08:43:30 +0000 (02:43 -0600)
The e300c2 has no FPU.  Its MSR[FP] is grounded to zero.  If an attempt
is made to execute a floating point instruction (including floating-point
load, store, or move instructions), the e300c2 takes a floating-point
unavailable interrupt.

This patch adds support for FP emulation on the e300c2 by declaring a
new CPU_FTR_FP_TAKES_FPUNAVAIL, where FP unavail interrupts are
intercepted and redirected to the ProgramCheck exception path for
correct emulation handling.

(If we run out of CPU_FTR bits we could look to reclaim this bit by adding
support to test the cpu_user_features for PPC_FEATURE_HAS_FPU instead)

It adds a nop to the exception path for 32-bit processors with a FPU.

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/Kconfig
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/traps.c
include/asm-powerpc/cputable.h

index 291c95ac4b313d4f791367f583ead200a4b11788..0b2d05da89d7dfdd9aef89bd79f3bc4fbbc307c2 100644 (file)
@@ -706,7 +706,7 @@ config FORCE_MAX_ZONEORDER
 
 config MATH_EMULATION
        bool "Math emulation"
-       depends on 4xx || 8xx || E200 || E500
+       depends on 4xx || 8xx || E200 || PPC_83xx || E500
        ---help---
          Some PowerPC chips designed for embedded applications do not have
          a floating-point unit and therefore do not implement the
index 9d1614c3ce67d047adf9573dcb40704602783a5a..11bfbaf655b59277bc9c51ab30fe30dac5ce0b5e 100644 (file)
@@ -833,7 +833,7 @@ static struct cpu_spec cpu_specs[] = {
                .pvr_mask               = 0x7fff0000,
                .pvr_value              = 0x00840000,
                .cpu_name               = "e300c2",
-               .cpu_features           = CPU_FTRS_E300,
+               .cpu_features           = CPU_FTRS_E300C2,
                .cpu_user_features      = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
index d88e182e40b3849ba085ec3f83265adac690e538..9417cf5b4b7e7af4b361b0075a3b3c4d96dd2416 100644 (file)
@@ -437,6 +437,13 @@ Alignment:
 /* Floating-point unavailable */
        . = 0x800
 FPUnavailable:
+BEGIN_FTR_SECTION
+/*
+ * Certain Freescale cores don't have a FPU and treat fp instructions
+ * as a FP Unavailable exception.  Redirect to illegal/emulation handling.
+ */
+       b       ProgramCheck
+END_FTR_SECTION_IFSET(CPU_FTR_FPU_UNAVAILABLE)
        EXCEPTION_PROLOG
        bne     load_up_fpu             /* if from user, just load it up */
        addi    r3,r1,STACK_FRAME_OVERHEAD
index 0d4e203fa7a05d90751ff0e7e60cb891f413d6af..fde820e52d0387d796e69ce8de031c4ce09d27c1 100644 (file)
@@ -782,6 +782,8 @@ void __kprobes program_check_exception(struct pt_regs *regs)
        unsigned int reason = get_reason(regs);
        extern int do_mathemu(struct pt_regs *regs);
 
+       /* We can now get here via a FP Unavailable exception if the core
+        * has no FPU, in that case no reason flags will be set */
 #ifdef CONFIG_MATH_EMULATION
        /* (reason & REASON_ILLEGAL) would be the obvious thing here,
         * but there seems to be a hardware bug on the 405GP (RevD)
index 6fe5c9d4ca3b946e2ad5f348070851b6e039d086..aca72f90849ee48b41ee49a76afab1ebfbf3fdc4 100644 (file)
@@ -126,6 +126,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTR_NODSISRALIGN           ASM_CONST(0x0000000000100000)
 #define CPU_FTR_PPC_LE                 ASM_CONST(0x0000000000200000)
 #define CPU_FTR_REAL_LE                        ASM_CONST(0x0000000000400000)
+#define CPU_FTR_FPU_UNAVAILABLE                ASM_CONST(0x0000000000800000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -295,6 +296,9 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
 #define CPU_FTRS_E300  (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
            CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
            CPU_FTR_COMMON)
+#define CPU_FTRS_E300C2        (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
+           CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \
+           CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE)
 #define CPU_FTRS_CLASSIC32     (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
            CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
 #define CPU_FTRS_8XX   (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
@@ -364,7 +368,8 @@ enum {
            CPU_FTRS_7450_21 | CPU_FTRS_7450_23 | CPU_FTRS_7455_1 |
            CPU_FTRS_7455_20 | CPU_FTRS_7455 | CPU_FTRS_7447_10 |
            CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX |
-           CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_CLASSIC32 |
+           CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 |
+           CPU_FTRS_CLASSIC32 |
 #else
            CPU_FTRS_GENERIC_32 |
 #endif
@@ -403,7 +408,8 @@ enum {
            CPU_FTRS_7450_21 & CPU_FTRS_7450_23 & CPU_FTRS_7455_1 &
            CPU_FTRS_7455_20 & CPU_FTRS_7455 & CPU_FTRS_7447_10 &
            CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX &
-           CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_CLASSIC32 &
+           CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 &
+           CPU_FTRS_CLASSIC32 &
 #else
            CPU_FTRS_GENERIC_32 &
 #endif