From b1d4c6cac02808b1d4e84d0187dc6014bffd2446 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 4 Mar 2014 10:11:39 +0000 Subject: MIPS: PM: Add CPU PM callbacks for general CPU context Add a CPU power management notifier callback for preserving general CPU context. The CPU PM callbacks will be triggered by the powering down of CPU cores, for example by cpuidle drivers & in the future by suspend to RAM implementations. The current state preserved is mostly related to the process context: - FPU - DSP - ASID - UserLocal - Watch registers Signed-off-by: James Hogan Signed-off-by: Paul Burton diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5cd695f..322bbe1 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -50,6 +50,7 @@ config MIPS select CLONE_BACKWARDS select HAVE_DEBUG_STACKOVERFLOW select HAVE_CC_STACKPROTECTOR + select CPU_PM if CPU_IDLE menu "Machine selection" diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 277dab3..97540a8 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -107,6 +107,8 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_MIPS_CM) += mips-cm.o obj-$(CONFIG_MIPS_CPC) += mips-cpc.o +obj-$(CONFIG_CPU_PM) += pm.o + # # DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not # safe to unconditionnaly use the assembler -mdsp / -mdspr2 switches diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c new file mode 100644 index 0000000..112903f --- /dev/null +++ b/arch/mips/kernel/pm.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2014 Imagination Technologies Ltd. + * + * 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; either version 2 of the License, or (at your + * option) any later version. + * + * CPU PM notifiers for saving/restoring general CPU state. + */ + +#include +#include + +#include +#include +#include +#include + +/** + * mips_cpu_save() - Save general CPU state. + * Ensures that general CPU context is saved, notably FPU and DSP. + */ +static int mips_cpu_save(void) +{ + /* Save FPU state */ + lose_fpu(1); + + /* Save DSP state */ + save_dsp(current); + + return 0; +} + +/** + * mips_cpu_restore() - Restore general CPU state. + * Restores important CPU context. + */ +static void mips_cpu_restore(void) +{ + unsigned int cpu = smp_processor_id(); + + /* Restore ASID */ + if (current->mm) + write_c0_entryhi(cpu_asid(cpu, current->mm)); + + /* Restore DSP state */ + restore_dsp(current); + + /* Restore UserLocal */ + if (cpu_has_userlocal) + write_c0_userlocal(current_thread_info()->tp_value); + + /* Restore watch registers */ + __restore_watch(); +} + +/** + * mips_pm_notifier() - Notifier for preserving general CPU context. + * @self: Notifier block. + * @cmd: CPU PM event. + * @v: Private data (unused). + * + * This is called when a CPU power management event occurs, and is used to + * ensure that important CPU context is preserved across a CPU power down. + */ +static int mips_pm_notifier(struct notifier_block *self, unsigned long cmd, + void *v) +{ + int ret; + + switch (cmd) { + case CPU_PM_ENTER: + ret = mips_cpu_save(); + if (ret) + return NOTIFY_STOP; + break; + case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + mips_cpu_restore(); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block mips_pm_notifier_block = { + .notifier_call = mips_pm_notifier, +}; + +static int __init mips_pm_init(void) +{ + return cpu_pm_register_notifier(&mips_pm_notifier_block); +} +arch_initcall(mips_pm_init); -- cgit v0.10.2 From ae4ce45419f908cf884d3fdc37f5706972068d34 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 4 Mar 2014 10:20:43 +0000 Subject: MIPS: traps: Add CPU PM callback for trap configuration Implement a CPU power management callback for restoring trap related CPU configuration after CPU power up from a low power state. The following state is restored: - Status register - HWREna register - Exception vector configuration registers - Context/XContext register Signed-off-by: James Hogan Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h index e277bba..ecae1dc 100644 --- a/arch/mips/include/asm/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -31,11 +31,15 @@ do { \ } while (0) #ifdef CONFIG_MIPS_PGD_C0_CONTEXT + +#define TLBMISS_HANDLER_RESTORE() \ + write_c0_xcontext((unsigned long) smp_processor_id() << \ + SMP_CPUID_REGSHIFT) + #define TLBMISS_HANDLER_SETUP() \ do { \ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir); \ - write_c0_xcontext((unsigned long) smp_processor_id() << \ - SMP_CPUID_REGSHIFT); \ + TLBMISS_HANDLER_RESTORE(); \ } while (0) #else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/ @@ -47,9 +51,12 @@ do { \ */ extern unsigned long pgd_current[]; -#define TLBMISS_HANDLER_SETUP() \ +#define TLBMISS_HANDLER_RESTORE() \ write_c0_context((unsigned long) smp_processor_id() << \ - SMP_CPUID_REGSHIFT); \ + SMP_CPUID_REGSHIFT) + +#define TLBMISS_HANDLER_SETUP() \ + TLBMISS_HANDLER_RESTORE(); \ back_to_back_c0_hazard(); \ TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir) #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/ diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 074e857..9651f68 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1865,32 +1866,16 @@ static int __init ulri_disable(char *s) } __setup("noulri", ulri_disable); -void per_cpu_trap_init(bool is_boot_cpu) +/* configure STATUS register */ +static void configure_status(void) { - unsigned int cpu = smp_processor_id(); - unsigned int status_set = ST0_CU0; - unsigned int hwrena = cpu_hwrena_impl_bits; -#ifdef CONFIG_MIPS_MT_SMTC - int secondaryTC = 0; - int bootTC = (cpu == 0); - - /* - * Only do per_cpu_trap_init() for first TC of Each VPE. - * Note that this hack assumes that the SMTC init code - * assigns TCs consecutively and in ascending order. - */ - - if (((read_c0_tcbind() & TCBIND_CURTC) != 0) && - ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id)) - secondaryTC = 1; -#endif /* CONFIG_MIPS_MT_SMTC */ - /* * Disable coprocessors and select 32-bit or 64-bit addressing * and the 16/32 or 32/32 FPR register model. Reset the BEV * flag that some firmware may have left set and the TS bit (for * IP27). Set XX for ISA IV code to work. */ + unsigned int status_set = ST0_CU0; #ifdef CONFIG_64BIT status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX; #endif @@ -1901,6 +1886,12 @@ void per_cpu_trap_init(bool is_boot_cpu) change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX, status_set); +} + +/* configure HWRENA register */ +static void configure_hwrena(void) +{ + unsigned int hwrena = cpu_hwrena_impl_bits; if (cpu_has_mips_r2) hwrena |= 0x0000000f; @@ -1910,11 +1901,10 @@ void per_cpu_trap_init(bool is_boot_cpu) if (hwrena) write_c0_hwrena(hwrena); +} -#ifdef CONFIG_MIPS_MT_SMTC - if (!secondaryTC) { -#endif /* CONFIG_MIPS_MT_SMTC */ - +static void configure_exception_vector(void) +{ if (cpu_has_veic || cpu_has_vint) { unsigned long sr = set_c0_status(ST0_BEV); write_c0_ebase(ebase); @@ -1930,6 +1920,34 @@ void per_cpu_trap_init(bool is_boot_cpu) } else set_c0_cause(CAUSEF_IV); } +} + +void per_cpu_trap_init(bool is_boot_cpu) +{ + unsigned int cpu = smp_processor_id(); +#ifdef CONFIG_MIPS_MT_SMTC + int secondaryTC = 0; + int bootTC = (cpu == 0); + + /* + * Only do per_cpu_trap_init() for first TC of Each VPE. + * Note that this hack assumes that the SMTC init code + * assigns TCs consecutively and in ascending order. + */ + + if (((read_c0_tcbind() & TCBIND_CURTC) != 0) && + ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id)) + secondaryTC = 1; +#endif /* CONFIG_MIPS_MT_SMTC */ + + configure_status(); + configure_hwrena(); + +#ifdef CONFIG_MIPS_MT_SMTC + if (!secondaryTC) { +#endif /* CONFIG_MIPS_MT_SMTC */ + + configure_exception_vector(); /* * Before R2 both interrupt numbers were fixed to 7, so on R2 only: @@ -2185,3 +2203,32 @@ void __init trap_init(void) cu2_notifier(default_cu2_call, 0x80000000); /* Run last */ } + +static int trap_pm_notifier(struct notifier_block *self, unsigned long cmd, + void *v) +{ + switch (cmd) { + case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + configure_status(); + configure_hwrena(); + configure_exception_vector(); + + /* Restore register with CPU number for TLB handlers */ + TLBMISS_HANDLER_RESTORE(); + + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block trap_pm_notifier_block = { + .notifier_call = trap_pm_notifier, +}; + +static int __init trap_pm_init(void) +{ + return cpu_pm_register_notifier(&trap_pm_notifier_block); +} +arch_initcall(trap_pm_init); -- cgit v0.10.2 From 61d73044fe4cb8b9b50fa2a612cb4492b9db43cd Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 4 Mar 2014 10:23:57 +0000 Subject: MIPS: c-r4k: Add CPU PM callback for coherency Implement a CPU power management callback for the r4k cache, to set up coherency again after leaving a powered down state. Signed-off-by: James Hogan Signed-off-by: Paul Burton diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 1c74a6a..a2a71c5 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -7,6 +7,7 @@ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include #include #include #include @@ -1644,3 +1645,26 @@ void r4k_cache_init(void) coherency_setup(); board_cache_error_setup = r4k_cache_error_setup; } + +static int r4k_cache_pm_notifier(struct notifier_block *self, unsigned long cmd, + void *v) +{ + switch (cmd) { + case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + coherency_setup(); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block r4k_cache_pm_notifier_block = { + .notifier_call = r4k_cache_pm_notifier, +}; + +int __init r4k_cache_init_pm(void) +{ + return cpu_pm_register_notifier(&r4k_cache_pm_notifier_block); +} +arch_initcall(r4k_cache_init_pm); -- cgit v0.10.2 From eaa38d6343adbb5070c27af29aeeb3df126f47f2 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 28 Feb 2014 17:09:20 +0000 Subject: MIPS: tlb-r4k: Add CPU PM callback to reconfigure TLB Add a CPU power management callback for the r4k TLB which reconfigures it after the CPU leaves a powered down state. Signed-off-by: James Hogan Signed-off-by: Paul Burton diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index eeaf50f..89e3fab 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -8,6 +8,7 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. */ +#include #include #include #include @@ -421,7 +422,10 @@ static int __init set_ntlb(char *str) __setup("ntlb=", set_ntlb); -void tlb_init(void) +/* + * Configure TLB (for init or after a CPU has been powered off). + */ +static void r4k_tlb_configure(void) { /* * You should never change this register: @@ -453,6 +457,11 @@ void tlb_init(void) local_flush_tlb_all(); /* Did I tell you that ARC SUCKS? */ +} + +void tlb_init(void) +{ + r4k_tlb_configure(); if (ntlb) { if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) { @@ -466,3 +475,26 @@ void tlb_init(void) build_tlb_refill_handler(); } + +static int r4k_tlb_pm_notifier(struct notifier_block *self, unsigned long cmd, + void *v) +{ + switch (cmd) { + case CPU_PM_ENTER_FAILED: + case CPU_PM_EXIT: + r4k_tlb_configure(); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block r4k_tlb_pm_notifier_block = { + .notifier_call = r4k_tlb_pm_notifier, +}; + +static int __init r4k_tlb_init_pm(void) +{ + return cpu_pm_register_notifier(&r4k_tlb_pm_notifier_block); +} +arch_initcall(r4k_tlb_init_pm); -- cgit v0.10.2 From 74e91335190c628b870c69cff8360d23707b1f53 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 4 Mar 2014 10:25:45 +0000 Subject: MIPS: PM: Implement PM helper macros Implement assembler helper macros in asm/pm.h for platform code to use for saving context across low power states - for example suspend to RAM or powered down cpuidle states. Macros are provided for saving and restoring the main CPU context used by C code and doing important configuration which must be done very early during resume. Notably EVA needs segmentation control registers to be restored before the stack or dynamically allocated memory is accessed, so that state is saved in global data. Signed-off-by: James Hogan Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/pm.h b/arch/mips/include/asm/pm.h new file mode 100644 index 0000000..268546f --- /dev/null +++ b/arch/mips/include/asm/pm.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2014 Imagination Technologies Ltd + * + * 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; either version 2 of the License, or (at your + * option) any later version. + * + * PM helper macros for CPU power off (e.g. Suspend-to-RAM). + */ + +#ifndef __ASM_PM_H +#define __ASM_PM_H + +#ifdef __ASSEMBLY__ + +#include +#include +#include +#include + +/* Save CPU state to stack for suspend to RAM */ +.macro SUSPEND_SAVE_REGS + subu sp, PT_SIZE + /* Call preserved GPRs */ + LONG_S $16, PT_R16(sp) + LONG_S $17, PT_R17(sp) + LONG_S $18, PT_R18(sp) + LONG_S $19, PT_R19(sp) + LONG_S $20, PT_R20(sp) + LONG_S $21, PT_R21(sp) + LONG_S $22, PT_R22(sp) + LONG_S $23, PT_R23(sp) + LONG_S $28, PT_R28(sp) + LONG_S $30, PT_R30(sp) + LONG_S $31, PT_R31(sp) + /* A couple of CP0 registers with space in pt_regs */ + mfc0 k0, CP0_STATUS + LONG_S k0, PT_STATUS(sp) +#ifdef CONFIG_MIPS_MT_SMTC + mfc0 k0, CP0_TCSTATUS + LONG_S k0, PT_TCSTATUS(sp) +#endif +.endm + +/* Restore CPU state from stack after resume from RAM */ +.macro RESUME_RESTORE_REGS_RETURN + .set push + .set noreorder + /* A couple of CP0 registers with space in pt_regs */ + LONG_L k0, PT_STATUS(sp) + mtc0 k0, CP0_STATUS +#ifdef CONFIG_MIPS_MT_SMTC + LONG_L k0, PT_TCSTATUS(sp) + mtc0 k0, CP0_TCSTATUS +#endif + /* Call preserved GPRs */ + LONG_L $16, PT_R16(sp) + LONG_L $17, PT_R17(sp) + LONG_L $18, PT_R18(sp) + LONG_L $19, PT_R19(sp) + LONG_L $20, PT_R20(sp) + LONG_L $21, PT_R21(sp) + LONG_L $22, PT_R22(sp) + LONG_L $23, PT_R23(sp) + LONG_L $28, PT_R28(sp) + LONG_L $30, PT_R30(sp) + LONG_L $31, PT_R31(sp) + /* Pop and return */ + jr ra + addiu sp, PT_SIZE + .set pop +.endm + +/* Get address of static suspend state into t1 */ +.macro LA_STATIC_SUSPEND + la t1, mips_static_suspend_state +.endm + +/* Save important CPU state for early restoration to global data */ +.macro SUSPEND_SAVE_STATIC +#ifdef CONFIG_EVA + /* + * Segment configuration is saved in global data where it can be easily + * reloaded without depending on the segment configuration. + */ + mfc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */ + LONG_S k0, SSS_SEGCTL0(t1) + mfc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */ + LONG_S k0, SSS_SEGCTL1(t1) + mfc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */ + LONG_S k0, SSS_SEGCTL2(t1) +#endif + /* save stack pointer (pointing to GPRs) */ + LONG_S sp, SSS_SP(t1) +.endm + +/* Restore important CPU state early from global data */ +.macro RESUME_RESTORE_STATIC +#ifdef CONFIG_EVA + /* + * Segment configuration must be restored prior to any access to + * allocated memory, as it may reside outside of the legacy kernel + * segments. + */ + LONG_L k0, SSS_SEGCTL0(t1) + mtc0 k0, CP0_PAGEMASK, 2 /* SegCtl0 */ + LONG_L k0, SSS_SEGCTL1(t1) + mtc0 k0, CP0_PAGEMASK, 3 /* SegCtl1 */ + LONG_L k0, SSS_SEGCTL2(t1) + mtc0 k0, CP0_PAGEMASK, 4 /* SegCtl2 */ + tlbw_use_hazard +#endif + /* restore stack pointer (pointing to GPRs) */ + LONG_L sp, SSS_SP(t1) +.endm + +/* flush caches to make sure context has reached memory */ +.macro SUSPEND_CACHE_FLUSH + .extern __wback_cache_all + .set push + .set noreorder + la t1, __wback_cache_all + LONG_L t0, 0(t1) + jalr t0 + nop + .set pop + .endm + +/* Save suspend state and flush data caches to RAM */ +.macro SUSPEND_SAVE + SUSPEND_SAVE_REGS + LA_STATIC_SUSPEND + SUSPEND_SAVE_STATIC + SUSPEND_CACHE_FLUSH +.endm + +/* Restore saved state after resume from RAM and return */ +.macro RESUME_RESTORE_RETURN + LA_STATIC_SUSPEND + RESUME_RESTORE_STATIC + RESUME_RESTORE_REGS_RETURN +.endm + +#else /* __ASSEMBLY__ */ + +/** + * struct mips_static_suspend_state - Core saved CPU state across S2R. + * @segctl: CP0 Segment control registers. + * @sp: Stack frame where GP register context is saved. + * + * This structure contains minimal CPU state that must be saved in static kernel + * data in order to be able to restore the rest of the state. This includes + * segmentation configuration in the case of EVA being enabled, as they must be + * restored prior to any kmalloc'd memory being referenced (even the stack + * pointer). + */ +struct mips_static_suspend_state { +#ifdef CONFIG_EVA + unsigned long segctl[3]; +#endif + unsigned long sp; +}; + +#endif /* !__ASSEMBLY__ */ + +#endif /* __ASM_PM_HELPERS_H */ diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 0ea75c2..e085cde 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -404,6 +405,20 @@ void output_pbe_defines(void) } #endif +#ifdef CONFIG_CPU_PM +void output_pm_defines(void) +{ + COMMENT(" PM offsets. "); +#ifdef CONFIG_EVA + OFFSET(SSS_SEGCTL0, mips_static_suspend_state, segctl[0]); + OFFSET(SSS_SEGCTL1, mips_static_suspend_state, segctl[1]); + OFFSET(SSS_SEGCTL2, mips_static_suspend_state, segctl[2]); +#endif + OFFSET(SSS_SP, mips_static_suspend_state, sp); + BLANK(); +} +#endif + void output_kvm_defines(void) { COMMENT(" KVM/MIPS Specfic offsets. "); diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c index 112903f..fefdf39 100644 --- a/arch/mips/kernel/pm.c +++ b/arch/mips/kernel/pm.c @@ -15,8 +15,12 @@ #include #include #include +#include #include +/* Used by PM helper macros in asm/pm.h */ +struct mips_static_suspend_state mips_static_suspend_state; + /** * mips_cpu_save() - Save general CPU state. * Ensures that general CPU context is saved, notably FPU and DSP. -- cgit v0.10.2 From 0467811e9bdb22c7a1595db4c230efd99265e3c7 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 14 Feb 2014 09:21:30 +0000 Subject: MIPS: mark GIC clockevent device with CLOCK_EVT_FEAT_C3STOP Although the GIC counter will continue when a core is in a low power state and it will still trigger interrupts, the core will be incapable of servicing those interrupts rendering them useless. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c index 594cbbf..925bae5 100644 --- a/arch/mips/kernel/cevt-gic.c +++ b/arch/mips/kernel/cevt-gic.c @@ -73,7 +73,8 @@ int gic_clockevent_init(void) cd = &per_cpu(gic_clockevent_device, cpu); cd->name = "MIPS GIC"; - cd->features = CLOCK_EVT_FEAT_ONESHOT; + cd->features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_C3STOP; clockevent_set_clock(cd, gic_frequency); -- cgit v0.10.2 From 414408d0eedd782a397ba89fd8f732ffbd3acde8 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 5 Mar 2014 11:35:53 +0000 Subject: MIPS: allow GIC clockevent device config from other CPUs This patch allows the GIC clockevent device for a CPU to be configured by another CPU. This makes GIC clockevent devices suitable for use as the tick broadcast device, where formerly the GIC timer local to the configuring CPU would have been configured incorrectly. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 0827166..10f6a99 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -380,6 +380,7 @@ extern unsigned int gic_compare_int (void); extern cycle_t gic_read_count(void); extern cycle_t gic_read_compare(void); extern void gic_write_compare(cycle_t cnt); +extern void gic_write_cpu_compare(cycle_t cnt, int cpu); extern void gic_send_ipi(unsigned int intr); extern unsigned int plat_ipi_call_int_xlate(unsigned int); extern unsigned int plat_ipi_resched_int_xlate(unsigned int); diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c index 925bae5..6093716 100644 --- a/arch/mips/kernel/cevt-gic.c +++ b/arch/mips/kernel/cevt-gic.c @@ -26,7 +26,7 @@ static int gic_next_event(unsigned long delta, struct clock_event_device *evt) cnt = gic_read_count(); cnt += (u64)delta; - gic_write_compare(cnt); + gic_write_cpu_compare(cnt, cpumask_first(evt->cpumask)); res = ((int)(gic_read_count() - cnt) >= 0) ? -ETIME : 0; return res; } diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c index 8520dad..88e4c32 100644 --- a/arch/mips/kernel/irq-gic.c +++ b/arch/mips/kernel/irq-gic.c @@ -54,6 +54,21 @@ void gic_write_compare(cycle_t cnt) (int)(cnt & 0xffffffff)); } +void gic_write_cpu_compare(cycle_t cnt, int cpu) +{ + unsigned long flags; + + local_irq_save(flags); + + GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu); + GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI), + (int)(cnt >> 32)); + GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO), + (int)(cnt & 0xffffffff)); + + local_irq_restore(flags); +} + cycle_t gic_read_compare(void) { unsigned int hi, lo; -- cgit v0.10.2 From 5977d682d21cc65a9e0e402e94709e210af04459 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 14 Feb 2014 09:20:15 +0000 Subject: MIPS: mark R4K clockevent device with CLOCK_EVT_FEAT_C3STOP When a core enters a clock off or power down state its CP0 counter will be stopped along with it. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 50d3f5a..7820d5d 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -195,7 +195,8 @@ int r4k_clockevent_init(void) cd = &per_cpu(mips_clockevent_device, cpu); cd->name = "MIPS"; - cd->features = CLOCK_EVT_FEAT_ONESHOT; + cd->features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_C3STOP; clockevent_set_clock(cd, mips_hpt_frequency); -- cgit v0.10.2 From d8107efd8a3c15ec5885dbe1d3168e26c6b3e2e4 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 15 Apr 2014 12:05:24 +0100 Subject: MIPS: mark R4K clockevent device with CLOCK_EVT_FEAT_PERCPU The CLOCK_EVT_FEAT_PERCPU flag indicates that a clockevent device is only configurable by the CPU for which it is registered, and thus cannot be used as the tick broadcast device. That property is true of the R4K timer, which is inaccessible from other cores. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 7820d5d..f3c549c 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -196,7 +196,8 @@ int r4k_clockevent_init(void) cd->name = "MIPS"; cd->features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_C3STOP; + CLOCK_EVT_FEAT_C3STOP | + CLOCK_EVT_FEAT_PERCPU; clockevent_set_clock(cd, mips_hpt_frequency); -- cgit v0.10.2 From 60bdb9c7bd9ab5b63ad68e9391056f8757b810f1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 5 Mar 2014 11:41:47 +0000 Subject: MIPS: allow R4K clockevent device to function regardless of GIC Having the GIC clockevent driver compiled should not prevent the R4K timer clockevent driver from functioning. One will be selected as the CPU local timer based upon their priorities and the other may simply be unused or in the case of the GIC timer may be used as the tick broadcast device. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index f3c549c..4dcd1fb 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -72,9 +72,6 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id) /* Clear Count/Compare Interrupt */ write_c0_compare(read_c0_compare()); cd = &per_cpu(mips_clockevent_device, cpu); -#ifdef CONFIG_CEVT_GIC - if (!gic_present) -#endif cd->event_handler(cd); } @@ -212,9 +209,6 @@ int r4k_clockevent_init(void) cd->set_mode = mips_set_clock_mode; cd->event_handler = mips_event_handler; -#ifdef CONFIG_CEVT_GIC - if (!gic_present) -#endif clockevents_register_device(cd); if (cp0_timer_irq_installed) -- cgit v0.10.2 From cc7964af8f997a20240d3ec5bf90c4fd20d3c48a Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 14 Feb 2014 09:24:58 +0000 Subject: MIPS: support for generic clockevents broadcast This patch adds support for generic clockevents broadcast using the a dummy clockevent device and the tick_broadcast function introduced by commit 12ad10004645 "clockevents: Add generic timer broadcast function". Signed-off-by: Paul Burton diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 322bbe1..5cdc53b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -51,6 +51,7 @@ config MIPS select HAVE_DEBUG_STACKOVERFLOW select HAVE_CC_STACKPROTECTOR select CPU_PM if CPU_IDLE + select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST menu "Machine selection" diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 0a022ee..9a52264 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -404,3 +404,46 @@ void dump_send_ipi(void (*dump_ipi_callback)(void *)) } EXPORT_SYMBOL(dump_send_ipi); #endif + +#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST + +static DEFINE_PER_CPU(atomic_t, tick_broadcast_count); +static DEFINE_PER_CPU(struct call_single_data, tick_broadcast_csd); + +void tick_broadcast(const struct cpumask *mask) +{ + atomic_t *count; + struct call_single_data *csd; + int cpu; + + for_each_cpu(cpu, mask) { + count = &per_cpu(tick_broadcast_count, cpu); + csd = &per_cpu(tick_broadcast_csd, cpu); + + if (atomic_inc_return(count) == 1) + smp_call_function_single_async(cpu, csd); + } +} + +static void tick_broadcast_callee(void *info) +{ + int cpu = smp_processor_id(); + tick_receive_broadcast(); + atomic_set(&per_cpu(tick_broadcast_count, cpu), 0); +} + +static int __init tick_broadcast_init(void) +{ + struct call_single_data *csd; + int cpu; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + csd = &per_cpu(tick_broadcast_csd, cpu); + csd->func = tick_broadcast_callee; + } + + return 0; +} +early_initcall(tick_broadcast_init); + +#endif /* CONFIG_GENERIC_CLOCKEVENTS_BROADCAST */ -- cgit v0.10.2 From 76306f4272e036e600254a98bc291df50cedd949 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 14 Feb 2014 16:30:52 +0000 Subject: MIPS: introduce cpu_coherent_mask Add a mask of CPUs which are currently known to be operating coherently. This is setup initially to be all present CPUs, but in a subsequent patch CPUs in a MIPS Coherent Processing System will be cleared in this mask as they enter non-coherent idle states. This will be used in order to determine when a CPU within a CPS system may need to be powered back up, but may also be used in future to optimise away wakeups for cache operations or TLB invalidations. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index efa02ac..b037334 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h @@ -46,6 +46,9 @@ extern int __cpu_logical_map[NR_CPUS]; extern volatile cpumask_t cpu_callin_map; +/* Mask of CPUs which are currently definitely operating coherently */ +extern cpumask_t cpu_coherent_mask; + extern void asmlinkage smp_bootstrap(void); /* diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 9a52264..991ae96 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -66,6 +66,8 @@ EXPORT_SYMBOL(cpu_sibling_map); /* representing cpus for which sibling maps can be computed */ static cpumask_t cpu_sibling_setup_map; +cpumask_t cpu_coherent_mask; + static inline void set_cpu_sibling_map(int cpu) { int i; @@ -124,6 +126,7 @@ asmlinkage void start_secondary(void) cpu = smp_processor_id(); cpu_data[cpu].udelay_val = loops_per_jiffy; + cpu_set(cpu, cpu_coherent_mask); notify_cpu_starting(cpu); set_cpu_online(cpu, true); @@ -186,6 +189,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) #ifndef CONFIG_HOTPLUG_CPU init_cpu_present(cpu_possible_mask); #endif + cpumask_copy(&cpu_coherent_mask, cpu_possible_mask); } /* preload SMP state for boot cpu */ -- cgit v0.10.2 From 2ba60250b01bfbab6b2293f8c1492312eb6a4131 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 14 Feb 2014 09:27:15 +0000 Subject: MIPS: CPC: provide functions to retrieve register addresses This patch introduces addr_ functions in addition to the existing read_ & write_ functions. The new functions simply return the address of the appropriate CPC register rather than performing a memory access. This will be used in a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h index 988507e..c5bb609 100644 --- a/arch/mips/include/asm/mips-cpc.h +++ b/arch/mips/include/asm/mips-cpc.h @@ -72,7 +72,12 @@ static inline bool mips_cpc_present(void) #define MIPS_CPC_COCB_OFS 0x4000 /* Macros to ease the creation of register access functions */ -#define BUILD_CPC_R_(name, off) \ +#define BUILD_CPC_R_(name, off) \ +static inline u32 *addr_cpc_##name(void) \ +{ \ + return (u32 *)(mips_cpc_base + (off)); \ +} \ + \ static inline u32 read_cpc_##name(void) \ { \ return __raw_readl(mips_cpc_base + (off)); \ -- cgit v0.10.2 From 76ae658465c2319a63f3814b1e1e6e0664a1f542 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 14 Feb 2014 09:28:06 +0000 Subject: MIPS: CPC: provide locking functions This patch provides functions to lock & unlock access to the "core-other" register region of the CPC. Without performing appropriate locking it is possible for code using this region to be preempted or to race with code on another VPE within the same core, with one changing the core which the "core-other" region is acting upon at an inopportune time for the other. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/mips-cpc.h b/arch/mips/include/asm/mips-cpc.h index c5bb609..e139a53 100644 --- a/arch/mips/include/asm/mips-cpc.h +++ b/arch/mips/include/asm/mips-cpc.h @@ -152,4 +152,31 @@ BUILD_CPC_Cx_RW(other, 0x10) #define CPC_Cx_OTHER_CORENUM_SHF 16 #define CPC_Cx_OTHER_CORENUM_MSK (_ULCAST_(0xff) << 16) +#ifdef CONFIG_MIPS_CPC + +/** + * mips_cpc_lock_other - lock access to another core + * core: the other core to be accessed + * + * Call before operating upon a core via the 'other' register region in + * order to prevent the region being moved during access. Must be followed + * by a call to mips_cpc_unlock_other. + */ +extern void mips_cpc_lock_other(unsigned int core); + +/** + * mips_cpc_unlock_other - unlock access to another core + * + * Call after operating upon another core via the 'other' register region. + * Must be called after mips_cpc_lock_other. + */ +extern void mips_cpc_unlock_other(void); + +#else /* !CONFIG_MIPS_CPC */ + +static inline void mips_cpc_lock_other(unsigned int core) { } +static inline void mips_cpc_unlock_other(void) { } + +#endif /* !CONFIG_MIPS_CPC */ + #endif /* __MIPS_ASM_MIPS_CPC_H__ */ diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index c9dc674..2368fc5 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c @@ -15,6 +15,10 @@ void __iomem *mips_cpc_base; +static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock); + +static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags); + phys_t __weak mips_cpc_phys_base(void) { u32 cpc_base; @@ -39,6 +43,10 @@ phys_t __weak mips_cpc_phys_base(void) int mips_cpc_probe(void) { phys_t addr; + unsigned cpu; + + for_each_possible_cpu(cpu) + spin_lock_init(&per_cpu(cpc_core_lock, cpu)); addr = mips_cpc_phys_base(); if (!addr) @@ -50,3 +58,21 @@ int mips_cpc_probe(void) return 0; } + +void mips_cpc_lock_other(unsigned int core) +{ + unsigned curr_core; + preempt_disable(); + curr_core = current_cpu_data.core; + spin_lock_irqsave(&per_cpu(cpc_core_lock, curr_core), + per_cpu(cpc_core_lock_flags, curr_core)); + write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF); +} + +void mips_cpc_unlock_other(void) +{ + unsigned curr_core = current_cpu_data.core; + spin_unlock_irqrestore(&per_cpu(cpc_core_lock, curr_core), + per_cpu(cpc_core_lock_flags, curr_core)); + preempt_enable(); +} -- cgit v0.10.2 From 64a17a0ff19a938e1246474666635219f2c3bc15 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 00:39:02 +0200 Subject: MIPS: Move definition of __BITFIELD_FIELD to sharable header. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild index be7196e..96fe739 100644 --- a/arch/mips/include/uapi/asm/Kbuild +++ b/arch/mips/include/uapi/asm/Kbuild @@ -4,6 +4,7 @@ include include/uapi/asm-generic/Kbuild.asm generic-y += auxvec.h generic-y += ipcbuf.h +header-y += bitfield.h header-y += bitsperlong.h header-y += break.h header-y += byteorder.h diff --git a/arch/mips/include/uapi/asm/bitfield.h b/arch/mips/include/uapi/asm/bitfield.h new file mode 100644 index 0000000..ad98613 --- /dev/null +++ b/arch/mips/include/uapi/asm/bitfield.h @@ -0,0 +1,29 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2014 by Ralf Baechle + */ +#ifndef __UAPI_ASM_BITFIELD_H +#define __UAPI_ASM_BITFIELD_H + +/* + * * Damn ... bitfields depend from byteorder :-( + * */ +#ifdef __MIPSEB__ +#define __BITFIELD_FIELD(field, more) \ + field; \ + more + +#elif defined(__MIPSEL__) + +#define __BITFIELD_FIELD(field, more) \ + more \ + field; + +#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ +#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" +#endif + +#endif /* __UAPI_ASM_BITFIELD_H */ diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 3125797..fce8367 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -13,6 +13,8 @@ #ifndef _UAPI_ASM_INST_H #define _UAPI_ASM_INST_H +#include + /* * Major opcodes; before MIPS IV cop1x was called cop3. */ @@ -480,24 +482,6 @@ enum MIPS6e_i8_func { */ #define MM_NOP16 0x0c00 -/* - * Damn ... bitfields depend from byteorder :-( - */ -#ifdef __MIPSEB__ -#define __BITFIELD_FIELD(field, more) \ - field; \ - more - -#elif defined(__MIPSEL__) - -#define __BITFIELD_FIELD(field, more) \ - more \ - field; - -#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ -#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?" -#endif - struct j_format { __BITFIELD_FIELD(unsigned int opcode : 6, /* Jump format */ __BITFIELD_FIELD(unsigned int target : 26, -- cgit v0.10.2 From f80cc08d78556bdc66bf0b75ec412688d8ec6907 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 00:40:02 +0200 Subject: MIPS: math-emu: Use __BITFIELD_FIELD to eleminate redundant definitions. Union _ieee754sp was even duplicated even though there are no endian dependencies in it all. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 22796e0..fe61d16 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -27,6 +27,7 @@ #include #include #include +#include /* * Not very pretty, but the Linux kernel's normal va_list definition @@ -36,60 +37,31 @@ #include #endif -#ifdef __LITTLE_ENDIAN struct ieee754dp_konst { - unsigned mantlo:32; - unsigned manthi:20; - unsigned bexp:11; - unsigned sign:1; -}; -struct ieee754sp_konst { - unsigned mant:23; - unsigned bexp:8; - unsigned sign:1; + __BITFIELD_FIELD(unsigned sign:1, + __BITFIELD_FIELD(unsigned bexp:11, + __BITFIELD_FIELD(unsigned manthi:20, + __BITFIELD_FIELD(unsigned mantlo:32, + ;)))) }; typedef union _ieee754dp { struct ieee754dp_konst oparts; struct { - u64 mant:52; - unsigned int bexp:11; - unsigned int sign:1; - } parts; - u64 bits; - double d; -} ieee754dp; - -typedef union _ieee754sp { - struct ieee754sp_konst parts; - float f; - u32 bits; -} ieee754sp; -#endif - -#ifdef __BIG_ENDIAN -struct ieee754dp_konst { - unsigned sign:1; - unsigned bexp:11; - unsigned manthi:20; - unsigned mantlo:32; -}; - -typedef union _ieee754dp { - struct ieee754dp_konst oparts; - struct { - unsigned int sign:1; - unsigned int bexp:11; - u64 mant:52; + __BITFIELD_FIELD(unsigned int sign:1, + __BITFIELD_FIELD(unsigned int bexp:11, + __BITFIELD_FIELD(u64 mant:52, + ;))) } parts; double d; u64 bits; } ieee754dp; struct ieee754sp_konst { - unsigned sign:1; - unsigned bexp:8; - unsigned mant:23; + __BITFIELD_FIELD(unsigned sign:1, + __BITFIELD_FIELD(unsigned bexp:8, + __BITFIELD_FIELD(unsigned mant:23, + ;))) }; typedef union _ieee754sp { @@ -97,7 +69,6 @@ typedef union _ieee754sp { float f; u32 bits; } ieee754sp; -#endif /* * single precision (often aka float) @@ -307,26 +278,15 @@ char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); * The control status register */ struct _ieee754_csr { -#ifdef __BIG_ENDIAN - unsigned pad0:7; - unsigned nod:1; /* set 1 for no denormalised numbers */ - unsigned c:1; /* condition */ - unsigned pad1:5; - unsigned cx:6; /* exceptions this operation */ - unsigned mx:5; /* exception enable mask */ - unsigned sx:5; /* exceptions total */ - unsigned rm:2; /* current rounding mode */ -#endif -#ifdef __LITTLE_ENDIAN - unsigned rm:2; /* current rounding mode */ - unsigned sx:5; /* exceptions total */ - unsigned mx:5; /* exception enable mask */ - unsigned cx:6; /* exceptions this operation */ - unsigned pad1:5; - unsigned c:1; /* condition */ - unsigned nod:1; /* set 1 for no denormalised numbers */ - unsigned pad0:7; -#endif + __BITFIELD_FIELD(unsigned pad0:7, + __BITFIELD_FIELD(unsigned nod:1, /* set 1 for no denormalised numbers */ + __BITFIELD_FIELD(unsigned c:1, /* condition */ + __BITFIELD_FIELD(unsigned pad1:5, + __BITFIELD_FIELD(unsigned cx:6, /* exceptions this operation */ + __BITFIELD_FIELD(unsigned mx:5, /* exception enable mask */ + __BITFIELD_FIELD(unsigned sx:5, /* exceptions total */ + __BITFIELD_FIELD(unsigned rm:2, /* current rounding mode */ + ;)))))))) }; #define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.fcr31)) -- cgit v0.10.2 From cae55066cb1ce3f8572ddddbd3ec3c54b973a89c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 00:47:59 +0200 Subject: MIPS: math-emu: Mark exception handling functions as __cold. Optimizes the code flow and shaves of half a percent of the math-emu code size. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 0015cf1..e7c314c 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -28,6 +28,7 @@ * ######################################################################## */ +#include #include "ieee754int.h" #include "ieee754sp.h" @@ -96,7 +97,7 @@ const struct ieee754sp_konst __ieee754sp_spcvals[] = { }; -int ieee754si_xcpt(int r, const char *op, ...) +int __cold ieee754si_xcpt(int r, const char *op, ...) { struct ieee754xctx ax; @@ -111,7 +112,7 @@ int ieee754si_xcpt(int r, const char *op, ...) return ax.rv.si; } -s64 ieee754di_xcpt(s64 r, const char *op, ...) +s64 __cold ieee754di_xcpt(s64 r, const char *op, ...) { struct ieee754xctx ax; diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index fe61d16..967831e 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -24,6 +24,7 @@ #ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H #define __ARCH_MIPS_MATH_EMU_IEEE754_H +#include #include #include #include @@ -421,7 +422,7 @@ struct ieee754xctx { #define IEEE754_RT_SI 3 #define IEEE754_RT_DI 4 -extern void ieee754_xcpt(struct ieee754xctx *xcp); +extern void __cold ieee754_xcpt(struct ieee754xctx *xcp); /* compat */ #define ieee754dp_fix(x) ieee754dp_tint(x) diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 068e56b..df59d16b 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -23,6 +23,7 @@ * ######################################################################## */ +#include #include "ieee754dp.h" @@ -45,7 +46,7 @@ int ieee754dp_issnan(ieee754dp x) } -ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) +ieee754dp __cold ieee754dp_xcpt(ieee754dp r, const char *op, ...) { struct ieee754xctx ax; if (!TSTX()) @@ -60,7 +61,7 @@ ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) return ax.rv.dp; } -ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) +ieee754dp __cold ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) { struct ieee754xctx ax; diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index f139c72..ce2af5b 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -24,6 +24,7 @@ * ######################################################################## */ +#include #include "ieee754int.h" @@ -62,10 +63,10 @@ static inline ieee754dp builddp(int s, int bx, u64 m) extern int ieee754dp_isnan(ieee754dp); extern int ieee754dp_issnan(ieee754dp); -extern int ieee754si_xcpt(int, const char *, ...); -extern s64 ieee754di_xcpt(s64, const char *, ...); -extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...); -extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...); +extern int __cold ieee754si_xcpt(int, const char *, ...); +extern s64 __cold ieee754di_xcpt(s64, const char *, ...); +extern ieee754dp __cold ieee754dp_xcpt(ieee754dp, const char *, ...); +extern ieee754dp __cold ieee754dp_nanxcpt(ieee754dp, const char *, ...); extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp); extern ieee754dp ieee754dp_format(int, int, u64); diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 15d1e36..dd3ecd6 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -23,6 +23,7 @@ * ######################################################################## */ +#include #include "ieee754sp.h" @@ -45,7 +46,7 @@ int ieee754sp_issnan(ieee754sp x) } -ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) +ieee754sp __cold ieee754sp_xcpt(ieee754sp r, const char *op, ...) { struct ieee754xctx ax; @@ -61,7 +62,7 @@ ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) return ax.rv.sp; } -ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) +ieee754sp __cold ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) { struct ieee754xctx ax; diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 754fd54..e3933be 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -24,6 +24,7 @@ * ######################################################################## */ +#include #include "ieee754int.h" @@ -68,10 +69,10 @@ static inline ieee754sp buildsp(int s, int bx, unsigned m) extern int ieee754sp_isnan(ieee754sp); extern int ieee754sp_issnan(ieee754sp); -extern int ieee754si_xcpt(int, const char *, ...); -extern s64 ieee754di_xcpt(s64, const char *, ...); -extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...); -extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...); +extern int __cold ieee754si_xcpt(int, const char *, ...); +extern s64 __cold ieee754di_xcpt(s64, const char *, ...); +extern ieee754sp __cold ieee754sp_xcpt(ieee754sp, const char *, ...); +extern ieee754sp __cold ieee754sp_nanxcpt(ieee754sp, const char *, ...); extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp); extern ieee754sp ieee754sp_format(int, int, unsigned); diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c index 9671671..005bbb1 100644 --- a/arch/mips/math-emu/ieee754xcpt.c +++ b/arch/mips/math-emu/ieee754xcpt.c @@ -28,6 +28,7 @@ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. *************************************************************************/ +#include #include #include "ieee754.h" @@ -40,7 +41,7 @@ static const char *const rtnames[] = { "sp", "dp", "xp", "si", "di" }; -void ieee754_xcpt(struct ieee754xctx *xcp) +void __cold ieee754_xcpt(struct ieee754xctx *xcp) { printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n", xcp->op, rtnames[xcp->rt]); -- cgit v0.10.2 From 23708818210cec367083ce9c09c6e71a5767d7e3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 01:16:02 +0200 Subject: MIPS: math-emu: Use English spelling of `constant' rather than Danish. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index e7c314c..141f0cb 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -56,7 +56,7 @@ #define DPSTR(s, b, mh, ml) {s, b, mh, ml} #endif -const struct ieee754dp_konst __ieee754dp_spcvals[] = { +const struct ieee754dp_const __ieee754dp_spcvals[] = { DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */ DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */ DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */ @@ -76,7 +76,7 @@ const struct ieee754dp_konst __ieee754dp_spcvals[] = { DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */ }; -const struct ieee754sp_konst __ieee754sp_spcvals[] = { +const struct ieee754sp_const __ieee754sp_spcvals[] = { SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */ SPSTR(0, SP_EBIAS, 0), /* + 1.0 */ diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 967831e..9e8c26e 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -38,7 +38,7 @@ #include #endif -struct ieee754dp_konst { +struct ieee754dp_const { __BITFIELD_FIELD(unsigned sign:1, __BITFIELD_FIELD(unsigned bexp:11, __BITFIELD_FIELD(unsigned manthi:20, @@ -47,7 +47,7 @@ struct ieee754dp_konst { }; typedef union _ieee754dp { - struct ieee754dp_konst oparts; + struct ieee754dp_const oparts; struct { __BITFIELD_FIELD(unsigned int sign:1, __BITFIELD_FIELD(unsigned int bexp:11, @@ -58,7 +58,7 @@ typedef union _ieee754dp { u64 bits; } ieee754dp; -struct ieee754sp_konst { +struct ieee754sp_const { __BITFIELD_FIELD(unsigned sign:1, __BITFIELD_FIELD(unsigned bexp:8, __BITFIELD_FIELD(unsigned mant:23, @@ -66,7 +66,7 @@ struct ieee754sp_konst { }; typedef union _ieee754sp { - struct ieee754sp_konst parts; + struct ieee754sp_const parts; float f; u32 bits; } ieee754sp; @@ -359,8 +359,8 @@ ieee754dp ieee754dp_dump(char *s, ieee754dp x); #define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ #define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ -extern const struct ieee754dp_konst __ieee754dp_spcvals[]; -extern const struct ieee754sp_konst __ieee754sp_spcvals[]; +extern const struct ieee754dp_const __ieee754dp_spcvals[]; +extern const struct ieee754sp_const __ieee754sp_spcvals[]; #define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals) #define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals) -- cgit v0.10.2 From 2209bcb1310ffa9ee1af12573f1413581c712b15 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 01:31:11 +0200 Subject: MIPS: math-emu: Get rid of typedefs. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 7b3c9ac..d670e39 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -1349,8 +1349,8 @@ static const unsigned char cmptab[8] = { */ #define DEF3OP(name, p, f1, f2, f3) \ -static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \ - ieee754##p t) \ +static union ieee754##p fpemu_##p##_##name(union ieee754##p r, union ieee754##p s, \ + union ieee754##p t) \ { \ struct _ieee754_csr ieee754_csr_save; \ s = f1(s, t); \ @@ -1364,22 +1364,22 @@ static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \ return s; \ } -static ieee754dp fpemu_dp_recip(ieee754dp d) +static union ieee754dp fpemu_dp_recip(union ieee754dp d) { return ieee754dp_div(ieee754dp_one(0), d); } -static ieee754dp fpemu_dp_rsqrt(ieee754dp d) +static union ieee754dp fpemu_dp_rsqrt(union ieee754dp d) { return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); } -static ieee754sp fpemu_sp_recip(ieee754sp s) +static union ieee754sp fpemu_sp_recip(union ieee754sp s) { return ieee754sp_div(ieee754sp_one(0), s); } -static ieee754sp fpemu_sp_rsqrt(ieee754sp s) +static union ieee754sp fpemu_sp_rsqrt(union ieee754sp s) { return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); } @@ -1403,8 +1403,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, switch (MIPSInst_FMA_FFMT(ir)) { case s_fmt:{ /* 0 */ - ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); - ieee754sp fd, fr, fs, ft; + union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp); + union ieee754sp fd, fr, fs, ft; u32 __user *va; u32 val; @@ -1492,8 +1492,8 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, } case d_fmt:{ /* 1 */ - ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); - ieee754dp fd, fr, fs, ft; + union ieee754dp(*handler) (union ieee754dp, union ieee754dp, union ieee754dp); + union ieee754dp fd, fr, fs, ft; u64 __user *va; u64 val; @@ -1588,8 +1588,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, unsigned rcsr = 0; /* resulting csr */ unsigned cond; union { - ieee754dp d; - ieee754sp s; + union ieee754dp d; + union ieee754sp s; int w; #ifdef __mips64 s64 l; @@ -1600,8 +1600,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { case s_fmt:{ /* 0 */ union { - ieee754sp(*b) (ieee754sp, ieee754sp); - ieee754sp(*u) (ieee754sp); + union ieee754sp(*b) (union ieee754sp, union ieee754sp); + union ieee754sp(*u) (union ieee754sp); } handler; switch (MIPSInst_FUNC(ir)) { @@ -1666,7 +1666,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* binary op on handler */ scopbop: { - ieee754sp fs, ft; + union ieee754sp fs, ft; SPFROMREG(fs, MIPSInst_FS(ir)); SPFROMREG(ft, MIPSInst_FT(ir)); @@ -1676,7 +1676,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, } scopuop: { - ieee754sp fs; + union ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); rv.s = (*handler.u) (fs); @@ -1699,7 +1699,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case fcvts_op: return SIGILL; /* not defined */ case fcvtd_op:{ - ieee754sp fs; + union ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); rv.d = ieee754dp_fsp(fs); @@ -1707,7 +1707,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, goto copcsr; } case fcvtw_op:{ - ieee754sp fs; + union ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); rv.w = ieee754sp_tint(fs); @@ -1721,7 +1721,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case fceil_op: case ffloor_op:{ unsigned int oldrm = ieee754_csr.rm; - ieee754sp fs; + union ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; @@ -1734,7 +1734,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, #if defined(__mips64) case fcvtl_op:{ - ieee754sp fs; + union ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); rv.l = ieee754sp_tlong(fs); @@ -1747,7 +1747,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case fceill_op: case ffloorl_op:{ unsigned int oldrm = ieee754_csr.rm; - ieee754sp fs; + union ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; @@ -1761,7 +1761,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, default: if (MIPSInst_FUNC(ir) >= fcmp_op) { unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; - ieee754sp fs, ft; + union ieee754sp fs, ft; SPFROMREG(fs, MIPSInst_FS(ir)); SPFROMREG(ft, MIPSInst_FT(ir)); @@ -1785,8 +1785,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case d_fmt:{ union { - ieee754dp(*b) (ieee754dp, ieee754dp); - ieee754dp(*u) (ieee754dp); + union ieee754dp(*b) (union ieee754dp, union ieee754dp); + union ieee754dp(*u) (union ieee754dp); } handler; switch (MIPSInst_FUNC(ir)) { @@ -1852,7 +1852,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* binary op on handler */ dcopbop:{ - ieee754dp fs, ft; + union ieee754dp fs, ft; DPFROMREG(fs, MIPSInst_FS(ir)); DPFROMREG(ft, MIPSInst_FT(ir)); @@ -1861,7 +1861,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, goto copcsr; } dcopuop:{ - ieee754dp fs; + union ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); rv.d = (*handler.u) (fs); @@ -1870,7 +1870,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* unary conv ops */ case fcvts_op:{ - ieee754dp fs; + union ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); rv.s = ieee754sp_fdp(fs); @@ -1881,7 +1881,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return SIGILL; /* not defined */ case fcvtw_op:{ - ieee754dp fs; + union ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); rv.w = ieee754dp_tint(fs); /* wrong */ @@ -1895,7 +1895,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case fceil_op: case ffloor_op:{ unsigned int oldrm = ieee754_csr.rm; - ieee754dp fs; + union ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; @@ -1908,7 +1908,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, #if defined(__mips64) case fcvtl_op:{ - ieee754dp fs; + union ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); rv.l = ieee754dp_tlong(fs); @@ -1921,7 +1921,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case fceill_op: case ffloorl_op:{ unsigned int oldrm = ieee754_csr.rm; - ieee754dp fs; + union ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; @@ -1935,7 +1935,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, default: if (MIPSInst_FUNC(ir) >= fcmp_op) { unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; - ieee754dp fs, ft; + union ieee754dp fs, ft; DPFROMREG(fs, MIPSInst_FS(ir)); DPFROMREG(ft, MIPSInst_FT(ir)); @@ -1960,7 +1960,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, } case w_fmt:{ - ieee754sp fs; + union ieee754sp fs; switch (MIPSInst_FUNC(ir)) { case fcvts_op: diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index c57c8ad..b5aac12 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -27,7 +27,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) { COMPXDP; COMPYDP; diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c index 0f32486..a3b4984 100644 --- a/arch/mips/math-emu/dp_cmp.c +++ b/arch/mips/math-emu/dp_cmp.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig) +int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig) { COMPXDP; COMPYDP; diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c index a1bce1b..30cc7fa 100644 --- a/arch/mips/math-emu/dp_div.c +++ b/arch/mips/math-emu/dp_div.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) { COMPXDP; COMPYDP; diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index 8857128..60ed6ec 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_fint(int x) +union ieee754dp ieee754dp_fint(int x) { u64 xm; int xe; @@ -70,7 +70,7 @@ ieee754dp ieee754dp_fint(int x) #endif } -ieee754dp ieee754dp_funs(unsigned int u) +union ieee754dp ieee754dp_funs(unsigned int u) { if ((int) u < 0) return ieee754dp_add(ieee754dp_1e31(), diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index 14fc01e..2418f9d 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_flong(s64 x) +union ieee754dp ieee754dp_flong(s64 x) { u64 xm; int xe; @@ -68,7 +68,7 @@ ieee754dp ieee754dp_flong(s64 x) DPNORMRET1(xs, xe, xm, "dp_flong", x); } -ieee754dp ieee754dp_fulong(u64 u) +union ieee754dp ieee754dp_fulong(u64 u) { if ((s64) u < 0) return ieee754dp_add(ieee754dp_1e63(), diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c index cb15a5e..6ab7df9 100644 --- a/arch/mips/math-emu/dp_frexp.c +++ b/arch/mips/math-emu/dp_frexp.c @@ -28,7 +28,7 @@ /* close to ieeep754dp_logb */ -ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr) +union ieee754dp ieee754dp_frexp(union ieee754dp x, int *eptr) { COMPXDP; CLEARCX; diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index daed683..d69cb1a 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_fsp(ieee754sp x) +union ieee754dp ieee754dp_fsp(union ieee754sp x) { COMPXSP; diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c index 151127e..80116e2f3 100644 --- a/arch/mips/math-emu/dp_logb.c +++ b/arch/mips/math-emu/dp_logb.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_logb(ieee754dp x) +union ieee754dp ieee754dp_logb(union ieee754dp x) { COMPXDP; diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c index b01f9cf..cbc1386 100644 --- a/arch/mips/math-emu/dp_modf.c +++ b/arch/mips/math-emu/dp_modf.c @@ -28,7 +28,7 @@ /* modf function is always exact for a finite number */ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp *ip) +union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp *ip) { COMPXDP; diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index 09175f4..c4cad69 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) { COMPXDP; COMPYDP; diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c index 6f5df43..4f8b656 100644 --- a/arch/mips/math-emu/dp_scalb.c +++ b/arch/mips/math-emu/dp_scalb.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_scalb(ieee754dp x, int n) +union ieee754dp ieee754dp_scalb(union ieee754dp x, int n) { COMPXDP; @@ -51,7 +51,7 @@ ieee754dp ieee754dp_scalb(ieee754dp x, int n) } -ieee754dp ieee754dp_ldexp(ieee754dp x, int n) +union ieee754dp ieee754dp_ldexp(union ieee754dp x, int n) { return ieee754dp_scalb(x, n); } diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index 79ce267..b341cc8 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -26,12 +26,12 @@ #include "ieee754dp.h" -int ieee754dp_finite(ieee754dp x) +int ieee754dp_finite(union ieee754dp x) { return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; } -ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y) { CLEARCX; DPSIGN(x) = DPSIGN(y); @@ -39,7 +39,7 @@ ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y) } -ieee754dp ieee754dp_neg(ieee754dp x) +union ieee754dp ieee754dp_neg(union ieee754dp x) { COMPXDP; @@ -55,7 +55,7 @@ ieee754dp ieee754dp_neg(ieee754dp x) DPSIGN(x) ^= 1; if (xc == IEEE754_CLASS_SNAN) { - ieee754dp y = ieee754dp_indef(); + union ieee754dp y = ieee754dp_indef(); SETCX(IEEE754_INVALID_OPERATION); DPSIGN(y) = DPSIGN(x); return ieee754dp_nanxcpt(y, "neg"); @@ -65,7 +65,7 @@ ieee754dp ieee754dp_neg(ieee754dp x) } -ieee754dp ieee754dp_abs(ieee754dp x) +union ieee754dp ieee754dp_abs(union ieee754dp x) { COMPXDP; diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index b874d60..cee9f3c 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -34,10 +34,10 @@ static const unsigned table[] = { 1742, 661, 130 }; -ieee754dp ieee754dp_sqrt(ieee754dp x) +union ieee754dp ieee754dp_sqrt(union ieee754dp x) { struct _ieee754_csr oldcsr; - ieee754dp y, z, t; + union ieee754dp y, z, t; unsigned scalx, yh; COMPXDP; diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index 91e0a4b..1e8f19a 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) { COMPXDP; COMPYDP; diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 0ebe859..2a00805 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -27,7 +27,7 @@ #include #include "ieee754dp.h" -int ieee754dp_tint(ieee754dp x) +int ieee754dp_tint(union ieee754dp x) { COMPXDP; @@ -109,9 +109,9 @@ int ieee754dp_tint(ieee754dp x) } -unsigned int ieee754dp_tuns(ieee754dp x) +unsigned int ieee754dp_tuns(union ieee754dp x) { - ieee754dp hb = ieee754dp_1e31(); + union ieee754dp hb = ieee754dp_1e31(); /* what if x < 0 ?? */ if (ieee754dp_lt(x, hb)) diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index 133ce2b..3366399 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -26,7 +26,7 @@ #include "ieee754dp.h" -s64 ieee754dp_tlong(ieee754dp x) +s64 ieee754dp_tlong(union ieee754dp x) { COMPXDP; @@ -112,9 +112,9 @@ s64 ieee754dp_tlong(ieee754dp x) } -u64 ieee754dp_tulong(ieee754dp x) +u64 ieee754dp_tulong(union ieee754dp x) { - ieee754dp hb = ieee754dp_1e63(); + union ieee754dp hb = ieee754dp_1e63(); /* what if x < 0 ?? */ if (ieee754dp_lt(x, hb)) diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 9e8c26e..05705fa 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -46,7 +46,7 @@ struct ieee754dp_const { ;)))) }; -typedef union _ieee754dp { +union ieee754dp { struct ieee754dp_const oparts; struct { __BITFIELD_FIELD(unsigned int sign:1, @@ -56,7 +56,7 @@ typedef union _ieee754dp { } parts; double d; u64 bits; -} ieee754dp; +}; struct ieee754sp_const { __BITFIELD_FIELD(unsigned sign:1, @@ -65,106 +65,106 @@ struct ieee754sp_const { ;))) }; -typedef union _ieee754sp { +union ieee754sp { struct ieee754sp_const parts; float f; u32 bits; -} ieee754sp; +}; /* * single precision (often aka float) */ -int ieee754sp_finite(ieee754sp x); -int ieee754sp_class(ieee754sp x); +int ieee754sp_finite(union ieee754sp x); +int ieee754sp_class(union ieee754sp x); -ieee754sp ieee754sp_abs(ieee754sp x); -ieee754sp ieee754sp_neg(ieee754sp x); -ieee754sp ieee754sp_scalb(ieee754sp x, int); -ieee754sp ieee754sp_logb(ieee754sp x); +union ieee754sp ieee754sp_abs(union ieee754sp x); +union ieee754sp ieee754sp_neg(union ieee754sp x); +union ieee754sp ieee754sp_scalb(union ieee754sp x, int); +union ieee754sp ieee754sp_logb(union ieee754sp x); /* x with sign of y */ -ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y); +union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y); -ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y); +union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y); +union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y); +union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y); +union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y); -ieee754sp ieee754sp_fint(int x); -ieee754sp ieee754sp_funs(unsigned x); -ieee754sp ieee754sp_flong(s64 x); -ieee754sp ieee754sp_fulong(u64 x); -ieee754sp ieee754sp_fdp(ieee754dp x); +union ieee754sp ieee754sp_fint(int x); +union ieee754sp ieee754sp_funs(unsigned x); +union ieee754sp ieee754sp_flong(s64 x); +union ieee754sp ieee754sp_fulong(u64 x); +union ieee754sp ieee754sp_fdp(union ieee754dp x); -int ieee754sp_tint(ieee754sp x); -unsigned int ieee754sp_tuns(ieee754sp x); -s64 ieee754sp_tlong(ieee754sp x); -u64 ieee754sp_tulong(ieee754sp x); +int ieee754sp_tint(union ieee754sp x); +unsigned int ieee754sp_tuns(union ieee754sp x); +s64 ieee754sp_tlong(union ieee754sp x); +u64 ieee754sp_tulong(union ieee754sp x); -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig); +int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cop, int sig); /* * basic sp math */ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip); -ieee754sp ieee754sp_frexp(ieee754sp x, int *exp); -ieee754sp ieee754sp_ldexp(ieee754sp x, int exp); +union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp * ip); +union ieee754sp ieee754sp_frexp(union ieee754sp x, int *exp); +union ieee754sp ieee754sp_ldexp(union ieee754sp x, int exp); -ieee754sp ieee754sp_ceil(ieee754sp x); -ieee754sp ieee754sp_floor(ieee754sp x); -ieee754sp ieee754sp_trunc(ieee754sp x); +union ieee754sp ieee754sp_ceil(union ieee754sp x); +union ieee754sp ieee754sp_floor(union ieee754sp x); +union ieee754sp ieee754sp_trunc(union ieee754sp x); -ieee754sp ieee754sp_sqrt(ieee754sp x); +union ieee754sp ieee754sp_sqrt(union ieee754sp x); /* * double precision (often aka double) */ -int ieee754dp_finite(ieee754dp x); -int ieee754dp_class(ieee754dp x); +int ieee754dp_finite(union ieee754dp x); +int ieee754dp_class(union ieee754dp x); /* x with sign of y */ -ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y); +union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y); -ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y); +union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y); +union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y); +union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y); +union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y); -ieee754dp ieee754dp_abs(ieee754dp x); -ieee754dp ieee754dp_neg(ieee754dp x); -ieee754dp ieee754dp_scalb(ieee754dp x, int); +union ieee754dp ieee754dp_abs(union ieee754dp x); +union ieee754dp ieee754dp_neg(union ieee754dp x); +union ieee754dp ieee754dp_scalb(union ieee754dp x, int); /* return exponent as integer in floating point format */ -ieee754dp ieee754dp_logb(ieee754dp x); +union ieee754dp ieee754dp_logb(union ieee754dp x); -ieee754dp ieee754dp_fint(int x); -ieee754dp ieee754dp_funs(unsigned x); -ieee754dp ieee754dp_flong(s64 x); -ieee754dp ieee754dp_fulong(u64 x); -ieee754dp ieee754dp_fsp(ieee754sp x); +union ieee754dp ieee754dp_fint(int x); +union ieee754dp ieee754dp_funs(unsigned x); +union ieee754dp ieee754dp_flong(s64 x); +union ieee754dp ieee754dp_fulong(u64 x); +union ieee754dp ieee754dp_fsp(union ieee754sp x); -ieee754dp ieee754dp_ceil(ieee754dp x); -ieee754dp ieee754dp_floor(ieee754dp x); -ieee754dp ieee754dp_trunc(ieee754dp x); +union ieee754dp ieee754dp_ceil(union ieee754dp x); +union ieee754dp ieee754dp_floor(union ieee754dp x); +union ieee754dp ieee754dp_trunc(union ieee754dp x); -int ieee754dp_tint(ieee754dp x); -unsigned int ieee754dp_tuns(ieee754dp x); -s64 ieee754dp_tlong(ieee754dp x); -u64 ieee754dp_tulong(ieee754dp x); +int ieee754dp_tint(union ieee754dp x); +unsigned int ieee754dp_tuns(union ieee754dp x); +s64 ieee754dp_tlong(union ieee754dp x); +u64 ieee754dp_tulong(union ieee754dp x); -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig); +int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cop, int sig); /* * basic sp math */ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip); -ieee754dp ieee754dp_frexp(ieee754dp x, int *exp); -ieee754dp ieee754dp_ldexp(ieee754dp x, int exp); +union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp * ip); +union ieee754dp ieee754dp_frexp(union ieee754dp x, int *exp); +union ieee754dp ieee754dp_ldexp(union ieee754dp x, int exp); -ieee754dp ieee754dp_ceil(ieee754dp x); -ieee754dp ieee754dp_floor(ieee754dp x); -ieee754dp ieee754dp_trunc(ieee754dp x); +union ieee754dp ieee754dp_ceil(union ieee754dp x); +union ieee754dp ieee754dp_floor(union ieee754dp x); +union ieee754dp ieee754dp_trunc(union ieee754dp x); -ieee754dp ieee754dp_sqrt(ieee754dp x); +union ieee754dp ieee754dp_sqrt(union ieee754dp x); @@ -204,65 +204,65 @@ ieee754dp ieee754dp_sqrt(ieee754dp x); /* "normal" comparisons */ -static inline int ieee754sp_eq(ieee754sp x, ieee754sp y) +static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y) { return ieee754sp_cmp(x, y, IEEE754_CEQ, 0); } -static inline int ieee754sp_ne(ieee754sp x, ieee754sp y) +static inline int ieee754sp_ne(union ieee754sp x, union ieee754sp y) { return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); } -static inline int ieee754sp_lt(ieee754sp x, ieee754sp y) +static inline int ieee754sp_lt(union ieee754sp x, union ieee754sp y) { return ieee754sp_cmp(x, y, IEEE754_CLT, 0); } -static inline int ieee754sp_le(ieee754sp x, ieee754sp y) +static inline int ieee754sp_le(union ieee754sp x, union ieee754sp y) { return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); } -static inline int ieee754sp_gt(ieee754sp x, ieee754sp y) +static inline int ieee754sp_gt(union ieee754sp x, union ieee754sp y) { return ieee754sp_cmp(x, y, IEEE754_CGT, 0); } -static inline int ieee754sp_ge(ieee754sp x, ieee754sp y) +static inline int ieee754sp_ge(union ieee754sp x, union ieee754sp y) { return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); } -static inline int ieee754dp_eq(ieee754dp x, ieee754dp y) +static inline int ieee754dp_eq(union ieee754dp x, union ieee754dp y) { return ieee754dp_cmp(x, y, IEEE754_CEQ, 0); } -static inline int ieee754dp_ne(ieee754dp x, ieee754dp y) +static inline int ieee754dp_ne(union ieee754dp x, union ieee754dp y) { return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); } -static inline int ieee754dp_lt(ieee754dp x, ieee754dp y) +static inline int ieee754dp_lt(union ieee754dp x, union ieee754dp y) { return ieee754dp_cmp(x, y, IEEE754_CLT, 0); } -static inline int ieee754dp_le(ieee754dp x, ieee754dp y) +static inline int ieee754dp_le(union ieee754dp x, union ieee754dp y) { return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); } -static inline int ieee754dp_gt(ieee754dp x, ieee754dp y) +static inline int ieee754dp_gt(union ieee754dp x, union ieee754dp y) { return ieee754dp_cmp(x, y, IEEE754_CGT, 0); } -static inline int ieee754dp_ge(ieee754dp x, ieee754dp y) +static inline int ieee754dp_ge(union ieee754dp x, union ieee754dp y) { return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); } @@ -271,8 +271,8 @@ static inline int ieee754dp_ge(ieee754dp x, ieee754dp y) /* * Like strtod */ -ieee754dp ieee754dp_fstr(const char *s, char **endp); -char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); +union ieee754dp ieee754dp_fstr(const char *s, char **endp); +char *ieee754dp_tstr(union ieee754dp x, int prec, int fmt, int af); /* @@ -338,8 +338,8 @@ static inline int ieee754_sxtest(unsigned n) } /* debugging */ -ieee754sp ieee754sp_dump(char *s, ieee754sp x); -ieee754dp ieee754dp_dump(char *s, ieee754dp x); +union ieee754sp ieee754sp_dump(char *s, union ieee754sp x); +union ieee754dp ieee754dp_dump(char *s, union ieee754dp x); #define IEEE754_SPCVAL_PZERO 0 #define IEEE754_SPCVAL_NZERO 1 @@ -361,8 +361,8 @@ ieee754dp ieee754dp_dump(char *s, ieee754dp x); extern const struct ieee754dp_const __ieee754dp_spcvals[]; extern const struct ieee754sp_const __ieee754sp_spcvals[]; -#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals) -#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals) +#define ieee754dp_spcvals ((const union ieee754dp *)__ieee754dp_spcvals) +#define ieee754sp_spcvals ((const union ieee754sp *)__ieee754sp_spcvals) /* * Return infinity with given sign @@ -404,8 +404,8 @@ struct ieee754xctx { const char *op; /* operation name */ int rt; /* result type */ union { - ieee754sp sp; /* single precision */ - ieee754dp dp; /* double precision */ + union ieee754sp sp; /* single precision */ + union ieee754dp dp; /* double precision */ #ifdef IEEE854_XP ieee754xp xp; /* extended precision */ #endif diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c index 9599bdd..6279328 100644 --- a/arch/mips/math-emu/ieee754d.c +++ b/arch/mips/math-emu/ieee754d.c @@ -56,7 +56,7 @@ #define DPBEXP(dp) (dp.parts.bexp) #define DPMANT(dp) (dp.parts.mant) -ieee754dp ieee754dp_dump(char *m, ieee754dp x) +union ieee754dp ieee754dp_dump(char *m, union ieee754dp x) { int i; @@ -96,7 +96,7 @@ ieee754dp ieee754dp_dump(char *m, ieee754dp x) return x; } -ieee754sp ieee754sp_dump(char *m, ieee754sp x) +union ieee754sp ieee754sp_dump(char *m, union ieee754sp x) { int i; diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index df59d16b..3692362 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -27,26 +27,26 @@ #include "ieee754dp.h" -int ieee754dp_class(ieee754dp x) +int ieee754dp_class(union ieee754dp x) { COMPXDP; EXPLODEXDP; return xc; } -int ieee754dp_isnan(ieee754dp x) +int ieee754dp_isnan(union ieee754dp x) { return ieee754dp_class(x) >= IEEE754_CLASS_SNAN; } -int ieee754dp_issnan(ieee754dp x) +int ieee754dp_issnan(union ieee754dp x) { assert(ieee754dp_isnan(x)); return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1)); } -ieee754dp __cold ieee754dp_xcpt(ieee754dp r, const char *op, ...) +union ieee754dp __cold ieee754dp_xcpt(union ieee754dp r, const char *op, ...) { struct ieee754xctx ax; if (!TSTX()) @@ -61,7 +61,7 @@ ieee754dp __cold ieee754dp_xcpt(ieee754dp r, const char *op, ...) return ax.rv.dp; } -ieee754dp __cold ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) +union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r, const char *op, ...) { struct ieee754xctx ax; @@ -88,7 +88,7 @@ ieee754dp __cold ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) return ax.rv.dp; } -ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y) +union ieee754dp ieee754dp_bestnan(union ieee754dp x, union ieee754dp y) { assert(ieee754dp_isnan(x)); assert(ieee754dp_isnan(y)); @@ -131,7 +131,7 @@ static u64 get_rounding(int sn, u64 xm) * xe is an unbiased exponent * xm is 3bit extended precision value. */ -ieee754dp ieee754dp_format(int sn, int xe, u64 xm) +union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) { assert(xm); /* we don't gen exact zeros (probably should) */ diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index ce2af5b..ad2568f 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -46,9 +46,9 @@ #define DPDNORMX DPDNORMx(xm, xe) #define DPDNORMY DPDNORMx(ym, ye) -static inline ieee754dp builddp(int s, int bx, u64 m) +static inline union ieee754dp builddp(int s, int bx, u64 m) { - ieee754dp r; + union ieee754dp r; assert((s) == 0 || (s) == 1); assert((bx) >= DP_EMIN - 1 + DP_EBIAS @@ -61,19 +61,19 @@ static inline ieee754dp builddp(int s, int bx, u64 m) return r; } -extern int ieee754dp_isnan(ieee754dp); -extern int ieee754dp_issnan(ieee754dp); +extern int ieee754dp_isnan(union ieee754dp); +extern int ieee754dp_issnan(union ieee754dp); extern int __cold ieee754si_xcpt(int, const char *, ...); extern s64 __cold ieee754di_xcpt(s64, const char *, ...); -extern ieee754dp __cold ieee754dp_xcpt(ieee754dp, const char *, ...); -extern ieee754dp __cold ieee754dp_nanxcpt(ieee754dp, const char *, ...); -extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp); -extern ieee754dp ieee754dp_format(int, int, u64); +extern union ieee754dp __cold ieee754dp_xcpt(union ieee754dp, const char *, ...); +extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp, const char *, ...); +extern union ieee754dp ieee754dp_bestnan(union ieee754dp, union ieee754dp); +extern union ieee754dp ieee754dp_format(int, int, u64); #define DPNORMRET2(s, e, m, name, a0, a1) \ { \ - ieee754dp V = ieee754dp_format(s, e, m); \ + union ieee754dp V = ieee754dp_format(s, e, m); \ if(TSTX()) \ return ieee754dp_xcpt(V, name, a0, a1); \ else \ diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c index 24190f3..0622406 100644 --- a/arch/mips/math-emu/ieee754m.c +++ b/arch/mips/math-emu/ieee754m.c @@ -26,9 +26,9 @@ #include "ieee754.h" -ieee754dp ieee754dp_floor(ieee754dp x) +union ieee754dp ieee754dp_floor(union ieee754dp x) { - ieee754dp i; + union ieee754dp i; if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) return ieee754dp_sub(i, ieee754dp_one(0)); @@ -36,9 +36,9 @@ ieee754dp ieee754dp_floor(ieee754dp x) return i; } -ieee754dp ieee754dp_ceil(ieee754dp x) +union ieee754dp ieee754dp_ceil(union ieee754dp x) { - ieee754dp i; + union ieee754dp i; if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) return ieee754dp_add(i, ieee754dp_one(0)); @@ -46,9 +46,9 @@ ieee754dp ieee754dp_ceil(ieee754dp x) return i; } -ieee754dp ieee754dp_trunc(ieee754dp x) +union ieee754dp ieee754dp_trunc(union ieee754dp x) { - ieee754dp i; + union ieee754dp i; (void) ieee754dp_modf(x, &i); return i; diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index dd3ecd6..ac84d19 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -27,26 +27,26 @@ #include "ieee754sp.h" -int ieee754sp_class(ieee754sp x) +int ieee754sp_class(union ieee754sp x) { COMPXSP; EXPLODEXSP; return xc; } -int ieee754sp_isnan(ieee754sp x) +int ieee754sp_isnan(union ieee754sp x) { return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; } -int ieee754sp_issnan(ieee754sp x) +int ieee754sp_issnan(union ieee754sp x) { assert(ieee754sp_isnan(x)); return (SPMANT(x) & SP_MBIT(SP_MBITS-1)); } -ieee754sp __cold ieee754sp_xcpt(ieee754sp r, const char *op, ...) +union ieee754sp __cold ieee754sp_xcpt(union ieee754sp r, const char *op, ...) { struct ieee754xctx ax; @@ -62,7 +62,7 @@ ieee754sp __cold ieee754sp_xcpt(ieee754sp r, const char *op, ...) return ax.rv.sp; } -ieee754sp __cold ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) +union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r, const char *op, ...) { struct ieee754xctx ax; @@ -89,7 +89,7 @@ ieee754sp __cold ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) return ax.rv.sp; } -ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_bestnan(union ieee754sp x, union ieee754sp y) { assert(ieee754sp_isnan(x)); assert(ieee754sp_isnan(y)); @@ -132,7 +132,7 @@ static unsigned get_rounding(int sn, unsigned xm) * xe is an unbiased exponent * xm is 3bit extended precision value. */ -ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) +union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) { assert(xm); /* we don't gen exact zeros (probably should) */ diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index e3933be..5836fa1 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -51,9 +51,9 @@ #define SPDNORMX SPDNORMx(xm, xe) #define SPDNORMY SPDNORMx(ym, ye) -static inline ieee754sp buildsp(int s, int bx, unsigned m) +static inline union ieee754sp buildsp(int s, int bx, unsigned m) { - ieee754sp r; + union ieee754sp r; assert((s) == 0 || (s) == 1); assert((bx) >= SP_EMIN - 1 + SP_EBIAS @@ -67,19 +67,19 @@ static inline ieee754sp buildsp(int s, int bx, unsigned m) return r; } -extern int ieee754sp_isnan(ieee754sp); -extern int ieee754sp_issnan(ieee754sp); +extern int ieee754sp_isnan(union ieee754sp); +extern int ieee754sp_issnan(union ieee754sp); extern int __cold ieee754si_xcpt(int, const char *, ...); extern s64 __cold ieee754di_xcpt(s64, const char *, ...); -extern ieee754sp __cold ieee754sp_xcpt(ieee754sp, const char *, ...); -extern ieee754sp __cold ieee754sp_nanxcpt(ieee754sp, const char *, ...); -extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp); -extern ieee754sp ieee754sp_format(int, int, unsigned); +extern union ieee754sp __cold ieee754sp_xcpt(union ieee754sp, const char *, ...); +extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp, const char *, ...); +extern union ieee754sp ieee754sp_bestnan(union ieee754sp, union ieee754sp); +extern union ieee754sp ieee754sp_format(int, int, unsigned); #define SPNORMRET2(s, e, m, name, a0, a1) \ { \ - ieee754sp V = ieee754sp_format(s, e, m); \ + union ieee754sp V = ieee754sp_format(s, e, m); \ if(TSTX()) \ return ieee754sp_xcpt(V, name, a0, a1); \ else \ diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index c446e64..4938d8f 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) { COMPXSP; COMPYSP; diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c index 716cf37..b98d686 100644 --- a/arch/mips/math-emu/sp_cmp.c +++ b/arch/mips/math-emu/sp_cmp.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig) +int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig) { COMPXSP; COMPYSP; diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c index d774792..1f62865 100644 --- a/arch/mips/math-emu/sp_div.c +++ b/arch/mips/math-emu/sp_div.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) { COMPXSP; COMPYSP; diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index e1515aa..cbefb88 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -26,10 +26,10 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_fdp(ieee754dp x) +union ieee754sp ieee754sp_fdp(union ieee754dp x) { COMPXDP; - ieee754sp nan; + union ieee754sp nan; EXPLODEXDP; diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 9694d6c..7ba2b40 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_fint(int x) +union ieee754sp ieee754sp_fint(int x) { unsigned xm; int xe; @@ -70,7 +70,7 @@ ieee754sp ieee754sp_fint(int x) } -ieee754sp ieee754sp_funs(unsigned int u) +union ieee754sp ieee754sp_funs(unsigned int u) { if ((int) u < 0) return ieee754sp_add(ieee754sp_1e31(), diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index 16a651f..c457a9f 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_flong(s64 x) +union ieee754sp ieee754sp_flong(s64 x) { u64 xm; /* <--- need 64-bit mantissa temp */ int xe; @@ -69,7 +69,7 @@ ieee754sp ieee754sp_flong(s64 x) } -ieee754sp ieee754sp_fulong(u64 u) +union ieee754sp ieee754sp_fulong(u64 u) { if ((s64) u < 0) return ieee754sp_add(ieee754sp_1e63(), diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c index 5bc993c..668252b 100644 --- a/arch/mips/math-emu/sp_frexp.c +++ b/arch/mips/math-emu/sp_frexp.c @@ -28,7 +28,7 @@ /* close to ieeep754sp_logb */ -ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr) +union ieee754sp ieee754sp_frexp(union ieee754sp x, int *eptr) { COMPXSP; CLEARCX; diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c index 9c14e0c..4dfe538 100644 --- a/arch/mips/math-emu/sp_logb.c +++ b/arch/mips/math-emu/sp_logb.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_logb(ieee754sp x) +union ieee754sp ieee754sp_logb(union ieee754sp x) { COMPXSP; diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c index 25a0fba..30d53ec 100644 --- a/arch/mips/math-emu/sp_modf.c +++ b/arch/mips/math-emu/sp_modf.c @@ -28,7 +28,7 @@ /* modf function is always exact for a finite number */ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp *ip) +union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp *ip) { COMPXSP; diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index fa4675c..c628f3c 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) { COMPXSP; COMPYSP; diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c index dd76196..9831d42 100644 --- a/arch/mips/math-emu/sp_scalb.c +++ b/arch/mips/math-emu/sp_scalb.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_scalb(ieee754sp x, int n) +union ieee754sp ieee754sp_scalb(union ieee754sp x, int n) { COMPXSP; @@ -51,7 +51,7 @@ ieee754sp ieee754sp_scalb(ieee754sp x, int n) } -ieee754sp ieee754sp_ldexp(ieee754sp x, int n) +union ieee754sp ieee754sp_ldexp(union ieee754sp x, int n) { return ieee754sp_scalb(x, n); } diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index ae4fcfa..633c7a5 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -26,12 +26,12 @@ #include "ieee754sp.h" -int ieee754sp_finite(ieee754sp x) +int ieee754sp_finite(union ieee754sp x) { return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; } -ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y) { CLEARCX; SPSIGN(x) = SPSIGN(y); @@ -39,7 +39,7 @@ ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y) } -ieee754sp ieee754sp_neg(ieee754sp x) +union ieee754sp ieee754sp_neg(union ieee754sp x) { COMPXSP; @@ -55,7 +55,7 @@ ieee754sp ieee754sp_neg(ieee754sp x) SPSIGN(x) ^= 1; if (xc == IEEE754_CLASS_SNAN) { - ieee754sp y = ieee754sp_indef(); + union ieee754sp y = ieee754sp_indef(); SETCX(IEEE754_INVALID_OPERATION); SPSIGN(y) = SPSIGN(x); return ieee754sp_nanxcpt(y, "neg"); @@ -65,7 +65,7 @@ ieee754sp ieee754sp_neg(ieee754sp x) } -ieee754sp ieee754sp_abs(ieee754sp x) +union ieee754sp ieee754sp_abs(union ieee754sp x) { COMPXSP; diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index fed2017..4c60d91 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_sqrt(ieee754sp x) +union ieee754sp ieee754sp_sqrt(union ieee754sp x) { int ix, s, q, m, t, i; unsigned int r; diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index e595c6f..ed67acf 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y) +union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) { COMPXSP; COMPYSP; diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 0fe9acc..37cb096 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -27,7 +27,7 @@ #include #include "ieee754sp.h" -int ieee754sp_tint(ieee754sp x) +int ieee754sp_tint(union ieee754sp x) { COMPXSP; @@ -113,9 +113,9 @@ int ieee754sp_tint(ieee754sp x) } -unsigned int ieee754sp_tuns(ieee754sp x) +unsigned int ieee754sp_tuns(union ieee754sp x) { - ieee754sp hb = ieee754sp_1e31(); + union ieee754sp hb = ieee754sp_1e31(); /* what if x < 0 ?? */ if (ieee754sp_lt(x, hb)) diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index d0ca6e2..da412d3 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -26,7 +26,7 @@ #include "ieee754sp.h" -s64 ieee754sp_tlong(ieee754sp x) +s64 ieee754sp_tlong(union ieee754sp x) { COMPXDP; /* <-- need 64-bit mantissa tmp */ @@ -108,9 +108,9 @@ s64 ieee754sp_tlong(ieee754sp x) } -u64 ieee754sp_tulong(ieee754sp x) +u64 ieee754sp_tulong(union ieee754sp x) { - ieee754sp hb = ieee754sp_1e63(); + union ieee754sp hb = ieee754sp_1e63(); /* what if x < 0 ?? */ if (ieee754sp_lt(x, hb)) -- cgit v0.10.2 From 5a7ebbf89395392f16cb5dd342b7edd154ca2d11 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 01:52:32 +0200 Subject: MIPS: branch: New helpers to modify branch delay slot flag in struct pt_regs Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h index e28a3e0..c842e7d 100644 --- a/arch/mips/include/asm/branch.h +++ b/arch/mips/include/asm/branch.h @@ -24,6 +24,16 @@ static inline int delay_slot(struct pt_regs *regs) return regs->cp0_cause & CAUSEF_BD; } +static inline void clear_delay_slot(struct pt_regs *regs) +{ + regs->cp0_cause &= ~CAUSEF_BD; +} + +static inline void set_delay_slot(struct pt_regs *regs) +{ + regs->cp0_cause |= CAUSEF_BD; +} + static inline unsigned long exception_epc(struct pt_regs *regs) { if (likely(!delay_slot(regs))) -- cgit v0.10.2 From e7e9cae5db78030abc73fd3daa93f7cc005177db Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 01:59:03 +0200 Subject: MIPS: math-emu: Use helpers to manipulate CAUSEF_BD flag. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index d670e39..eabbbd9 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -933,17 +933,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int pc_inc; /* XXX NEC Vr54xx bug workaround */ - if (xcp->cp0_cause & CAUSEF_BD) { + if (delay_slot(xcp)) { if (dec_insn.micro_mips_mode) { if (!mm_isBranchInstr(xcp, dec_insn, &contpc)) - xcp->cp0_cause &= ~CAUSEF_BD; + clear_delay_slot(xcp); } else { if (!isBranchInstr(xcp, dec_insn, &contpc)) - xcp->cp0_cause &= ~CAUSEF_BD; + clear_delay_slot(xcp); } } - if (xcp->cp0_cause & CAUSEF_BD) { + if (delay_slot(xcp)) { /* * The instruction to be emulated is in a branch delay slot * which means that we have to emulate the branch instruction @@ -1178,7 +1178,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case bc_op:{ int likely = 0; - if (xcp->cp0_cause & CAUSEF_BD) + if (delay_slot(xcp)) return SIGILL; #if __mips >= 4 @@ -1201,7 +1201,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return SIGILL; } - xcp->cp0_cause |= CAUSEF_BD; + set_delay_slot(xcp); if (cond) { /* branch taken: emulate dslot * instruction @@ -1321,7 +1321,7 @@ sigill: /* we did it !! */ xcp->cp0_epc = contpc; - xcp->cp0_cause &= ~CAUSEF_BD; + clear_delay_slot(xcp); return 0; } diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 7ea622a..cd047fe 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -59,7 +59,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) (ir == 0)) { /* NOP is easy */ regs->cp0_epc = cpc; - regs->cp0_cause &= ~CAUSEF_BD; + clear_delay_slot(regs); return 0; } #ifdef DSEMUL_TRACE -- cgit v0.10.2 From 5160d45dd2f6e72e40f79e3dc77daa7a8337685b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 02:09:04 +0200 Subject: MIPS: branch: Make inclusion of safe. It was relying on other headers having been included before. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h index c842e7d..d109e34 100644 --- a/arch/mips/include/asm/branch.h +++ b/arch/mips/include/asm/branch.h @@ -8,6 +8,8 @@ #ifndef _ASM_BRANCH_H #define _ASM_BRANCH_H +#include +#include #include #include -- cgit v0.10.2 From cd8ee345e8affceaa3f846012db7eb799a6d918f Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 02:09:53 +0200 Subject: MIPS: math-emu: Header file weeding. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index eabbbd9..3ef9d99 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -34,20 +34,18 @@ * better performance by compiling with -msoft-float! */ #include -#include #include #include +#include #include -#include -#include #include #include -#include +#include + +#include #include #include -#include -#include #include "ieee754.h" diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 2a00805..e6bc33f 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -24,7 +24,6 @@ */ -#include #include "ieee754dp.h" int ieee754dp_tint(union ieee754dp x) diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index cd047fe..3aea39d 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -1,20 +1,9 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include #include -#include #include - #include +#include +#include +#include #include "ieee754.h" diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c index 6279328..6d4dc36 100644 --- a/arch/mips/math-emu/ieee754d.c +++ b/arch/mips/math-emu/ieee754d.c @@ -25,7 +25,8 @@ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. */ -#include +#include +#include #include "ieee754.h" #define DP_EBIAS 1023 diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c index 005bbb1..d68408a 100644 --- a/arch/mips/math-emu/ieee754xcpt.c +++ b/arch/mips/math-emu/ieee754xcpt.c @@ -29,7 +29,7 @@ *************************************************************************/ #include -#include +#include #include "ieee754.h" /* diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c index eb58a85..a795900 100644 --- a/arch/mips/math-emu/kernel_linkage.c +++ b/arch/mips/math-emu/kernel_linkage.c @@ -19,11 +19,8 @@ * manipulation primitives for the Algorithmics MIPS * FPU Emulator */ -#include -#include -#include -#include - +#include +#include #include #include diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 37cb096..a69dfe5 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -24,7 +24,6 @@ */ -#include #include "ieee754sp.h" int ieee754sp_tint(union ieee754sp x) -- cgit v0.10.2 From 6d18b6246d2bfb9da2d342553e41565e14422089 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 02:24:08 +0200 Subject: MIPS: math-emu: Remove fine example of cargo cult programming. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index 3aea39d..c6e879c 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -7,13 +7,6 @@ #include "ieee754.h" -/* Strap kernel emulator for full MIPS IV emulation */ - -#ifdef __mips -#undef __mips -#endif -#define __mips 4 - /* * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when * we have to emulate the instruction in a COP1 branch delay slot. Do -- cgit v0.10.2 From 85c51c511d6373d4bc859458fd3f130015db31a5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 02:46:11 +0200 Subject: MIPS: math-emu: Move all debug fs code to a separate file. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 121a848..0803970 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -9,3 +9,5 @@ obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \ sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o + +obj-$(CONFIG_DEBUG_FS) += me-debugfs.o diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 3ef9d99..c4b855e 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -35,6 +35,7 @@ */ #include #include +#include #include #include @@ -66,12 +67,6 @@ static int fpux_emu(struct pt_regs *, struct mips_fpu_struct *, mips_instruction, void *__user *); #endif -/* Further private data for which no space exists in mips_fpu_struct */ - -#ifdef CONFIG_DEBUG_FS -DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); -#endif - /* Control registers */ #define FPCREG_RID 0 /* $0 = revision id */ @@ -2158,53 +2153,3 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return sig; } - -#ifdef CONFIG_DEBUG_FS - -static int fpuemu_stat_get(void *data, u64 *val) -{ - int cpu; - unsigned long sum = 0; - for_each_online_cpu(cpu) { - struct mips_fpu_emulator_stats *ps; - local_t *pv; - ps = &per_cpu(fpuemustats, cpu); - pv = (void *)ps + (unsigned long)data; - sum += local_read(pv); - } - *val = sum; - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n"); - -extern struct dentry *mips_debugfs_dir; -static int __init debugfs_fpuemu(void) -{ - struct dentry *d, *dir; - - if (!mips_debugfs_dir) - return -ENODEV; - dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir); - if (!dir) - return -ENOMEM; - -#define FPU_STAT_CREATE(M) \ - do { \ - d = debugfs_create_file(#M , S_IRUGO, dir, \ - (void *)offsetof(struct mips_fpu_emulator_stats, M), \ - &fops_fpuemu_stat); \ - if (!d) \ - return -ENOMEM; \ - } while (0) - - FPU_STAT_CREATE(emulated); - FPU_STAT_CREATE(loads); - FPU_STAT_CREATE(stores); - FPU_STAT_CREATE(cp1ops); - FPU_STAT_CREATE(cp1xops); - FPU_STAT_CREATE(errors); - - return 0; -} -__initcall(debugfs_fpuemu); -#endif diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c new file mode 100644 index 0000000..d895b38 --- /dev/null +++ b/arch/mips/math-emu/me-debugfs.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); + +static int fpuemu_stat_get(void *data, u64 *val) +{ + int cpu; + unsigned long sum = 0; + + for_each_online_cpu(cpu) { + struct mips_fpu_emulator_stats *ps; + local_t *pv; + + ps = &per_cpu(fpuemustats, cpu); + pv = (void *)ps + (unsigned long)data; + sum += local_read(pv); + } + *val = sum; + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n"); + +extern struct dentry *mips_debugfs_dir; +static int __init debugfs_fpuemu(void) +{ + struct dentry *d, *dir; + + if (!mips_debugfs_dir) + return -ENODEV; + dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir); + if (!dir) + return -ENOMEM; + +#define FPU_STAT_CREATE(M) \ + do { \ + d = debugfs_create_file(#M , S_IRUGO, dir, \ + (void *)offsetof(struct mips_fpu_emulator_stats, M), \ + &fops_fpuemu_stat); \ + if (!d) \ + return -ENOMEM; \ + } while (0) + + FPU_STAT_CREATE(emulated); + FPU_STAT_CREATE(loads); + FPU_STAT_CREATE(stores); + FPU_STAT_CREATE(cp1ops); + FPU_STAT_CREATE(cp1xops); + FPU_STAT_CREATE(errors); + + return 0; +} +__initcall(debugfs_fpuemu); -- cgit v0.10.2 From 47fa0c0251413db66a9018fbac6f6266201195ae Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 16 Apr 2014 11:00:12 +0200 Subject: MIPS: math-emu: Reformat code according to coding style. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index c4b855e..584e0b8 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -869,14 +869,16 @@ static inline int cop1_64bit(struct pt_regs *xcp) #endif } -#define SIFROMREG(si, x) do { \ +#define SIFROMREG(si, x) \ +do { \ if (cop1_64bit(xcp)) \ (si) = get_fpr32(&ctx->fpr[x], 0); \ else \ (si) = get_fpr32(&ctx->fpr[(x) & ~1], (x) & 1); \ } while (0) -#define SITOREG(si, x) do { \ +#define SITOREG(si, x) \ +do { \ if (cop1_64bit(xcp)) { \ unsigned i; \ set_fpr32(&ctx->fpr[x], 0, si); \ @@ -889,17 +891,19 @@ static inline int cop1_64bit(struct pt_regs *xcp) #define SIFROMHREG(si, x) ((si) = get_fpr32(&ctx->fpr[x], 1)) -#define SITOHREG(si, x) do { \ +#define SITOHREG(si, x) \ +do { \ unsigned i; \ set_fpr32(&ctx->fpr[x], 1, si); \ for (i = 2; i < ARRAY_SIZE(ctx->fpr[x].val32); i++) \ set_fpr32(&ctx->fpr[x], i, 0); \ } while (0) -#define DIFROMREG(di, x) \ +#define DIFROMREG(di, x) \ ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) -#define DITOREG(di, x) do { \ +#define DITOREG(di, x) \ +do { \ unsigned fpr, i; \ fpr = (x) & ~(cop1_64bit(xcp) == 0); \ set_fpr64(&ctx->fpr[fpr], 0, di); \ @@ -1341,20 +1345,20 @@ static const unsigned char cmptab[8] = { * Additional MIPS4 instructions */ -#define DEF3OP(name, p, f1, f2, f3) \ -static union ieee754##p fpemu_##p##_##name(union ieee754##p r, union ieee754##p s, \ - union ieee754##p t) \ -{ \ - struct _ieee754_csr ieee754_csr_save; \ - s = f1(s, t); \ - ieee754_csr_save = ieee754_csr; \ - s = f2(s, r); \ - ieee754_csr_save.cx |= ieee754_csr.cx; \ - ieee754_csr_save.sx |= ieee754_csr.sx; \ - s = f3(s); \ - ieee754_csr.cx |= ieee754_csr_save.cx; \ - ieee754_csr.sx |= ieee754_csr_save.sx; \ - return s; \ +#define DEF3OP(name, p, f1, f2, f3) \ +static union ieee754##p fpemu_##p##_##name(union ieee754##p r, \ + union ieee754##p s, union ieee754##p t) \ +{ \ + struct _ieee754_csr ieee754_csr_save; \ + s = f1(s, t); \ + ieee754_csr_save = ieee754_csr; \ + s = f2(s, r); \ + ieee754_csr_save.cx |= ieee754_csr.cx; \ + ieee754_csr_save.sx |= ieee754_csr.sx; \ + s = f3(s); \ + ieee754_csr.cx |= ieee754_csr_save.cx; \ + ieee754_csr.sx |= ieee754_csr_save.sx; \ + return s; \ } static union ieee754dp fpemu_dp_recip(union ieee754dp d) diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 3692362..43fb7fe 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -151,12 +151,12 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) case IEEE754_RZ: return ieee754dp_zero(sn); case IEEE754_RU: /* toward +Infinity */ - if(sn == 0) + if (sn == 0) return ieee754dp_min(0); else return ieee754dp_zero(1); case IEEE754_RD: /* toward -Infinity */ - if(sn == 0) + if (sn == 0) return ieee754dp_zero(0); else return ieee754dp_min(1); diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index ad2568f..3759f3f 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -32,17 +32,17 @@ /* 3bit extended double precision sticky right shift */ #define XDPSRS(v,rs) \ - ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) + ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) #define XDPSRSX1() \ - (xe++, (xm = (xm >> 1) | (xm & 1))) + (xe++, (xm = (xm >> 1) | (xm & 1))) #define XDPSRS1(v) \ - (((v) >> 1) | ((v) & 1)) + (((v) >> 1) | ((v) & 1)) /* convert denormal to normalized with extended exponent */ #define DPDNORMx(m,e) \ - while( (m >> DP_MBITS) == 0) { m <<= 1; e--; } + while ((m >> DP_MBITS) == 0) { m <<= 1; e--; } #define DPDNORMX DPDNORMx(xm, xe) #define DPDNORMY DPDNORMx(ym, ye) @@ -71,13 +71,13 @@ extern union ieee754dp ieee754dp_bestnan(union ieee754dp, union ieee754dp); extern union ieee754dp ieee754dp_format(int, int, u64); -#define DPNORMRET2(s, e, m, name, a0, a1) \ -{ \ - union ieee754dp V = ieee754dp_format(s, e, m); \ - if(TSTX()) \ - return ieee754dp_xcpt(V, name, a0, a1); \ - else \ - return V; \ +#define DPNORMRET2(s, e, m, name, a0, a1) \ +{ \ + union ieee754dp V = ieee754dp_format(s, e, m); \ + if (TSTX()) \ + return ieee754dp_xcpt(V, name, a0, a1); \ + else \ + return V; \ } #define DPNORMRET1(s, e, m, name, a0) DPNORMRET2(s, e, m, name, a0, a0) diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 4b6c6fb3..27ed825 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -57,105 +57,105 @@ #define CLPAIR(x, y) ((x)*6+(y)) #define CLEARCX \ - (ieee754_csr.cx = 0) + (ieee754_csr.cx = 0) #define SETCX(x) \ - (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x)) + (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x)) #define SETANDTESTCX(x) \ - (SETCX(x), ieee754_csr.mx & (x)) + (SETCX(x), ieee754_csr.mx & (x)) #define TSTX() \ (ieee754_csr.cx & ieee754_csr.mx) #define COMPXSP \ - unsigned xm; int xe; int xs __maybe_unused; int xc + unsigned xm; int xe; int xs __maybe_unused; int xc #define COMPYSP \ - unsigned ym; int ye; int ys; int yc - -#define EXPLODESP(v, vc, vs, ve, vm) \ -{\ - vs = SPSIGN(v);\ - ve = SPBEXP(v);\ - vm = SPMANT(v);\ - if(ve == SP_EMAX+1+SP_EBIAS){\ - if(vm == 0)\ - vc = IEEE754_CLASS_INF;\ - else if(vm & SP_MBIT(SP_MBITS-1)) \ - vc = IEEE754_CLASS_SNAN;\ - else \ - vc = IEEE754_CLASS_QNAN;\ - } else if(ve == SP_EMIN-1+SP_EBIAS) {\ - if(vm) {\ - ve = SP_EMIN;\ - vc = IEEE754_CLASS_DNORM;\ - } else\ - vc = IEEE754_CLASS_ZERO;\ - } else {\ - ve -= SP_EBIAS;\ - vm |= SP_HIDDEN_BIT;\ - vc = IEEE754_CLASS_NORM;\ - }\ + unsigned ym; int ye; int ys; int yc + +#define EXPLODESP(v, vc, vs, ve, vm) \ +{ \ + vs = SPSIGN(v); \ + ve = SPBEXP(v); \ + vm = SPMANT(v); \ + if (ve == SP_EMAX+1+SP_EBIAS) { \ + if (vm == 0) \ + vc = IEEE754_CLASS_INF; \ + else if (vm & SP_MBIT(SP_MBITS-1)) \ + vc = IEEE754_CLASS_SNAN; \ + else \ + vc = IEEE754_CLASS_QNAN; \ + } else if (ve == SP_EMIN-1+SP_EBIAS) { \ + if (vm) { \ + ve = SP_EMIN; \ + vc = IEEE754_CLASS_DNORM; \ + } else \ + vc = IEEE754_CLASS_ZERO; \ + } else { \ + ve -= SP_EBIAS; \ + vm |= SP_HIDDEN_BIT; \ + vc = IEEE754_CLASS_NORM; \ + } \ } #define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm) #define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym) #define COMPXDP \ -u64 xm; int xe; int xs __maybe_unused; int xc + u64 xm; int xe; int xs __maybe_unused; int xc #define COMPYDP \ -u64 ym; int ye; int ys; int yc - -#define EXPLODEDP(v, vc, vs, ve, vm) \ -{\ - vm = DPMANT(v);\ - vs = DPSIGN(v);\ - ve = DPBEXP(v);\ - if(ve == DP_EMAX+1+DP_EBIAS){\ - if(vm == 0)\ - vc = IEEE754_CLASS_INF;\ - else if(vm & DP_MBIT(DP_MBITS-1)) \ - vc = IEEE754_CLASS_SNAN;\ - else \ - vc = IEEE754_CLASS_QNAN;\ - } else if(ve == DP_EMIN-1+DP_EBIAS) {\ - if(vm) {\ - ve = DP_EMIN;\ - vc = IEEE754_CLASS_DNORM;\ - } else\ - vc = IEEE754_CLASS_ZERO;\ - } else {\ - ve -= DP_EBIAS;\ - vm |= DP_HIDDEN_BIT;\ - vc = IEEE754_CLASS_NORM;\ - }\ + u64 ym; int ye; int ys; int yc + +#define EXPLODEDP(v, vc, vs, ve, vm) \ +{ \ + vm = DPMANT(v); \ + vs = DPSIGN(v); \ + ve = DPBEXP(v); \ + if (ve == DP_EMAX+1+DP_EBIAS) { \ + if (vm == 0) \ + vc = IEEE754_CLASS_INF; \ + else if (vm & DP_MBIT(DP_MBITS-1)) \ + vc = IEEE754_CLASS_SNAN; \ + else \ + vc = IEEE754_CLASS_QNAN; \ + } else if (ve == DP_EMIN-1+DP_EBIAS) { \ + if (vm) { \ + ve = DP_EMIN; \ + vc = IEEE754_CLASS_DNORM; \ + } else \ + vc = IEEE754_CLASS_ZERO; \ + } else { \ + ve -= DP_EBIAS; \ + vm |= DP_HIDDEN_BIT; \ + vc = IEEE754_CLASS_NORM; \ + } \ } #define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm) #define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym) -#define FLUSHDP(v, vc, vs, ve, vm) \ - if(vc==IEEE754_CLASS_DNORM) {\ - if(ieee754_csr.nod) {\ - SETCX(IEEE754_INEXACT);\ - vc = IEEE754_CLASS_ZERO;\ - ve = DP_EMIN-1+DP_EBIAS;\ - vm = 0;\ - v = ieee754dp_zero(vs);\ - }\ +#define FLUSHDP(v, vc, vs, ve, vm) \ + if (vc==IEEE754_CLASS_DNORM) { \ + if (ieee754_csr.nod) { \ + SETCX(IEEE754_INEXACT); \ + vc = IEEE754_CLASS_ZERO; \ + ve = DP_EMIN-1+DP_EBIAS; \ + vm = 0; \ + v = ieee754dp_zero(vs); \ + } \ } -#define FLUSHSP(v, vc, vs, ve, vm) \ - if(vc==IEEE754_CLASS_DNORM) {\ - if(ieee754_csr.nod) {\ - SETCX(IEEE754_INEXACT);\ - vc = IEEE754_CLASS_ZERO;\ - ve = SP_EMIN-1+SP_EBIAS;\ - vm = 0;\ - v = ieee754sp_zero(vs);\ - }\ +#define FLUSHSP(v, vc, vs, ve, vm) \ + if (vc==IEEE754_CLASS_DNORM) { \ + if (ieee754_csr.nod) { \ + SETCX(IEEE754_INEXACT); \ + vc = IEEE754_CLASS_ZERO; \ + ve = SP_EMIN-1+SP_EBIAS; \ + vm = 0; \ + v = ieee754sp_zero(vs); \ + } \ } #define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm) diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index ac84d19..a15d212 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -152,12 +152,12 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) case IEEE754_RZ: return ieee754sp_zero(sn); case IEEE754_RU: /* toward +Infinity */ - if(sn == 0) + if (sn == 0) return ieee754sp_min(0); else return ieee754sp_zero(1); case IEEE754_RD: /* toward -Infinity */ - if(sn == 0) + if (sn == 0) return ieee754sp_zero(0); else return ieee754sp_min(1); @@ -174,8 +174,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) /* Clear grs bits */ xm &= ~(SP_MBIT(3) - 1); xe++; - } - else { + } else { /* sticky right shift es bits */ SPXSRSXn(es); diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 5836fa1..f007c47 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -31,23 +31,23 @@ #define assert(expr) ((void)0) /* 3bit extended single precision sticky right shift */ -#define SPXSRSXn(rs) \ - (xe += rs, \ - xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) +#define SPXSRSXn(rs) \ + (xe += rs, \ + xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) #define SPXSRSX1() \ - (xe++, (xm = (xm >> 1) | (xm & 1))) + (xe++, (xm = (xm >> 1) | (xm & 1))) -#define SPXSRSYn(rs) \ - (ye+=rs, \ - ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) +#define SPXSRSYn(rs) \ + (ye+=rs, \ + ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) #define SPXSRSY1() \ - (ye++, (ym = (ym >> 1) | (ym & 1))) + (ye++, (ym = (ym >> 1) | (ym & 1))) /* convert denormal to normalized with extended exponent */ #define SPDNORMx(m,e) \ - while( (m >> SP_MBITS) == 0) { m <<= 1; e--; } + while ((m >> SP_MBITS) == 0) { m <<= 1; e--; } #define SPDNORMX SPDNORMx(xm, xe) #define SPDNORMY SPDNORMx(ym, ye) @@ -77,13 +77,14 @@ extern union ieee754sp ieee754sp_bestnan(union ieee754sp, union ieee754sp); extern union ieee754sp ieee754sp_format(int, int, unsigned); -#define SPNORMRET2(s, e, m, name, a0, a1) \ -{ \ - union ieee754sp V = ieee754sp_format(s, e, m); \ - if(TSTX()) \ - return ieee754sp_xcpt(V, name, a0, a1); \ - else \ - return V; \ +#define SPNORMRET2(s, e, m, name, a0, a1) \ +{ \ + union ieee754sp V = ieee754sp_format(s, e, m); \ + \ + if (TSTX()) \ + return ieee754sp_xcpt(V, name, a0, a1); \ + else \ + return V; \ } #define SPNORMRET1(s, e, m, name, a0) SPNORMRET2(s, e, m, name, a0, a0) diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c index d895b38..95ed9f9 100644 --- a/arch/mips/math-emu/me-debugfs.c +++ b/arch/mips/math-emu/me-debugfs.c @@ -38,14 +38,17 @@ static int __init debugfs_fpuemu(void) if (!dir) return -ENOMEM; -#define FPU_STAT_CREATE(M) \ - do { \ - d = debugfs_create_file(#M , S_IRUGO, dir, \ - (void *)offsetof(struct mips_fpu_emulator_stats, M), \ - &fops_fpuemu_stat); \ - if (!d) \ - return -ENOMEM; \ - } while (0) +#define FPU_EMU_STAT_OFFSET(m) \ + offsetof(struct mips_fpu_emulator_stats, m) + +#define FPU_STAT_CREATE(m) \ +do { \ + d = debugfs_create_file(#m , S_IRUGO, dir, \ + (void *)FPU_EMU_STAT_OFFSET(m), \ + &fops_fpuemu_stat); \ + if (!d) \ + return -ENOMEM; \ +} while (0) FPU_STAT_CREATE(emulated); FPU_STAT_CREATE(loads); -- cgit v0.10.2 From bee1653593b39ac85b45a057bb8c22dc1489cf6a Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Apr 2014 00:15:40 +0200 Subject: MIPS: math-emu: Harden ieee754int.h against multiple inclusion. The header file had no include guards; this only happened to work because the file only contains macro definitions and protypes. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 27ed825..62d0fdb 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -23,7 +23,8 @@ * * ######################################################################## */ - +#ifndef __IEEE754INT_H +#define __IEEE754INT_H #include "ieee754.h" @@ -162,3 +163,5 @@ #define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym) #define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm) #define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym) + +#endif /* __IEEE754INT_H */ -- cgit v0.10.2 From 9e8bad1f9c0370b2635175b34d6151b90a53da5c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Apr 2014 00:36:32 +0200 Subject: MIPS: math-emu: Turn macros into functions where possible. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index b5aac12..7daaafc 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -35,7 +35,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) EXPLODEXDP; EXPLODEYDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; FLUSHYDP; @@ -52,7 +52,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -75,7 +75,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs == ys) return x; - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c index a3b4984..a8da725 100644 --- a/arch/mips/math-emu/dp_cmp.c +++ b/arch/mips/math-emu/dp_cmp.c @@ -35,15 +35,15 @@ int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig) EXPLODEYDP; FLUSHXDP; FLUSHYDP; - CLEARCX; /* Even clear inexact flag here */ + ieee754_clearcx(); /* Even clear inexact flag here */ if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) { if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); if (cmp & IEEE754_CUN) return 1; if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) + if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) return ieee754si_xcpt(0, "fcmpf", x); } return 0; diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c index 30cc7fa..3b568b7 100644 --- a/arch/mips/math-emu/dp_div.c +++ b/arch/mips/math-emu/dp_div.c @@ -34,7 +34,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) EXPLODEXDP; EXPLODEYDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; FLUSHYDP; @@ -51,7 +51,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -72,7 +72,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): @@ -89,12 +89,12 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - SETCX(IEEE754_ZERO_DIVIDE); + ieee754_setcx(IEEE754_ZERO_DIVIDE); return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index 60ed6ec..fa75f5d 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -32,7 +32,7 @@ union ieee754dp ieee754dp_fint(int x) int xe; int xs; - CLEARCX; + ieee754_clearcx(); if (x == 0) return ieee754dp_zero(0); diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index 2418f9d..89bd579 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -32,7 +32,7 @@ union ieee754dp ieee754dp_flong(s64 x) int xe; int xs; - CLEARCX; + ieee754_clearcx(); if (x == 0) return ieee754dp_zero(0); diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c index 6ab7df9..25ebce1 100644 --- a/arch/mips/math-emu/dp_frexp.c +++ b/arch/mips/math-emu/dp_frexp.c @@ -31,7 +31,7 @@ union ieee754dp ieee754dp_frexp(union ieee754dp x, int *eptr) { COMPXDP; - CLEARCX; + ieee754_clearcx(); EXPLODEXDP; switch (xc) { diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index d69cb1a..cacd9f3 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -32,13 +32,13 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) EXPLODEXSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; switch (xc) { case IEEE754_CLASS_SNAN: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp"); case IEEE754_CLASS_QNAN: return ieee754dp_nanxcpt(builddp(xs, diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c index 80116e2f3..b412c90 100644 --- a/arch/mips/math-emu/dp_logb.c +++ b/arch/mips/math-emu/dp_logb.c @@ -30,7 +30,7 @@ union ieee754dp ieee754dp_logb(union ieee754dp x) { COMPXDP; - CLEARCX; + ieee754_clearcx(); EXPLODEXDP; diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c index cbc1386..61733ff 100644 --- a/arch/mips/math-emu/dp_modf.c +++ b/arch/mips/math-emu/dp_modf.c @@ -32,7 +32,7 @@ union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp *ip) { COMPXDP; - CLEARCX; + ieee754_clearcx(); EXPLODEXDP; diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index c4cad69..8f1bef9 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -34,7 +34,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) EXPLODEXDP; EXPLODEYDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; FLUSHYDP; @@ -51,7 +51,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -72,7 +72,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c index 4f8b656..dee3755 100644 --- a/arch/mips/math-emu/dp_scalb.c +++ b/arch/mips/math-emu/dp_scalb.c @@ -30,7 +30,7 @@ union ieee754dp ieee754dp_scalb(union ieee754dp x, int n) { COMPXDP; - CLEARCX; + ieee754_clearcx(); EXPLODEXDP; diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index b341cc8..c116502 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -33,7 +33,7 @@ int ieee754dp_finite(union ieee754dp x) union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y) { - CLEARCX; + ieee754_clearcx(); DPSIGN(x) = DPSIGN(y); return x; } @@ -44,7 +44,7 @@ union ieee754dp ieee754dp_neg(union ieee754dp x) COMPXDP; EXPLODEXDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; /* @@ -56,7 +56,7 @@ union ieee754dp ieee754dp_neg(union ieee754dp x) if (xc == IEEE754_CLASS_SNAN) { union ieee754dp y = ieee754dp_indef(); - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); DPSIGN(y) = DPSIGN(x); return ieee754dp_nanxcpt(y, "neg"); } @@ -70,14 +70,14 @@ union ieee754dp ieee754dp_abs(union ieee754dp x) COMPXDP; EXPLODEXDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; /* Clear sign ALWAYS, irrespective of NaN */ DPSIGN(x) = 0; if (xc == IEEE754_CLASS_SNAN) { - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "abs"); } diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index cee9f3c..1e0fbbf 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -42,7 +42,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) COMPXDP; EXPLODEXDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; /* x == INF or NAN? */ @@ -51,7 +51,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) /* sqrt(Nan) = Nan */ return ieee754dp_nanxcpt(x, "sqrt"); case IEEE754_CLASS_SNAN: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ @@ -59,7 +59,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) case IEEE754_CLASS_INF: if (xs) { /* sqrt(-Inf) = Nan */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); } /* sqrt(+Inf) = Inf */ @@ -70,7 +70,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) case IEEE754_CLASS_NORM: if (xs) { /* sqrt(-x) = Nan */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); } break; diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index 1e8f19a..e369c7b 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -34,7 +34,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) EXPLODEXDP; EXPLODEYDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; FLUSHYDP; @@ -51,7 +51,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -74,7 +74,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs != ys) return x; - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index e6bc33f..792470c 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -30,7 +30,7 @@ int ieee754dp_tint(union ieee754dp x) { COMPXDP; - CLEARCX; + ieee754_clearcx(); EXPLODEXDP; FLUSHXDP; @@ -39,7 +39,7 @@ int ieee754dp_tint(union ieee754dp x) case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); case IEEE754_CLASS_ZERO: return 0; @@ -50,7 +50,7 @@ int ieee754dp_tint(union ieee754dp x) if (xe > 31) { /* Set invalid. We will only use overflow for floating point overflow */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); } /* oh gawd */ @@ -95,11 +95,11 @@ int ieee754dp_tint(union ieee754dp x) /* look for valid corner case 0x80000000 */ if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) { /* This can happen after rounding */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); } if (round || sticky) - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); } if (xs) return -xm; diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index 3366399..fcc1c4f 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -30,7 +30,7 @@ s64 ieee754dp_tlong(union ieee754dp x) { COMPXDP; - CLEARCX; + ieee754_clearcx(); EXPLODEXDP; FLUSHXDP; @@ -39,7 +39,7 @@ s64 ieee754dp_tlong(union ieee754dp x) case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); case IEEE754_CLASS_ZERO: return 0; @@ -53,7 +53,7 @@ s64 ieee754dp_tlong(union ieee754dp x) return -0x8000000000000000LL; /* Set invalid. We will only use overflow for floating point overflow */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); } /* oh gawd */ @@ -99,11 +99,11 @@ s64 ieee754dp_tlong(union ieee754dp x) } if ((xm >> 63) != 0) { /* This can happen after rounding */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); } if (round || sticky) - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); } if (xs) return -xm; diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 141f0cb..26f785e 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -101,7 +101,7 @@ int __cold ieee754si_xcpt(int r, const char *op, ...) { struct ieee754xctx ax; - if (!TSTX()) + if (!ieee754_tstx()) return r; ax.op = op; ax.rt = IEEE754_RT_SI; @@ -116,7 +116,7 @@ s64 __cold ieee754di_xcpt(s64 r, const char *op, ...) { struct ieee754xctx ax; - if (!TSTX()) + if (!ieee754_tstx()) return r; ax.op = op; ax.rt = IEEE754_RT_DI; diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 05705fa..a197089 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -170,12 +170,14 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x); /* 5 types of floating point number */ -#define IEEE754_CLASS_NORM 0x00 -#define IEEE754_CLASS_ZERO 0x01 -#define IEEE754_CLASS_DNORM 0x02 -#define IEEE754_CLASS_INF 0x03 -#define IEEE754_CLASS_SNAN 0x04 -#define IEEE754_CLASS_QNAN 0x05 +enum { + IEEE754_CLASS_NORM = 0x00, + IEEE754_CLASS_ZERO = 0x01, + IEEE754_CLASS_DNORM = 0x02, + IEEE754_CLASS_INF = 0x03, + IEEE754_CLASS_SNAN = 0x04, + IEEE754_CLASS_QNAN = 0x05, +}; /* exception numbers */ #define IEEE754_INEXACT 0x01 diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 43fb7fe..53dbb1c 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -49,7 +49,7 @@ int ieee754dp_issnan(union ieee754dp x) union ieee754dp __cold ieee754dp_xcpt(union ieee754dp r, const char *op, ...) { struct ieee754xctx ax; - if (!TSTX()) + if (!ieee754_tstx()) return r; ax.op = op; @@ -70,7 +70,7 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r, const char *op, ...) if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ return r; - if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { + if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) { /* not enabled convert to a quiet NaN */ DPMANT(r) &= (~DP_MBIT(DP_MBITS-1)); if (ieee754dp_isnan(r)) @@ -143,8 +143,8 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) int es = DP_EMIN - xe; if (ieee754_csr.nod) { - SETCX(IEEE754_UNDERFLOW); - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_UNDERFLOW); + ieee754_setcx(IEEE754_INEXACT); switch(ieee754_csr.rm) { case IEEE754_RN: @@ -167,7 +167,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) { /* Not tiny after rounding */ - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); xm = get_rounding(sn, xm); xm >>= 1; /* Clear grs bits */ @@ -184,9 +184,9 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) } } if (xm & (DP_MBIT(3) - 1)) { - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); if ((xm & (DP_HIDDEN_BIT << 3)) == 0) { - SETCX(IEEE754_UNDERFLOW); + ieee754_setcx(IEEE754_UNDERFLOW); } /* inexact must round of 3 bits @@ -207,8 +207,8 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) assert(xe >= DP_EMIN); if (xe > DP_EMAX) { - SETCX(IEEE754_OVERFLOW); - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_OVERFLOW); + ieee754_setcx(IEEE754_INEXACT); /* -O can be table indexed by (rm,sn) */ switch (ieee754_csr.rm) { case IEEE754_RN: @@ -233,7 +233,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) /* we underflow (tiny/zero) */ assert(xe == DP_EMIN); if (ieee754_csr.mx & IEEE754_UNDERFLOW) - SETCX(IEEE754_UNDERFLOW); + ieee754_setcx(IEEE754_UNDERFLOW); return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm); } else { assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 3759f3f..1dc2058 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -74,7 +74,7 @@ extern union ieee754dp ieee754dp_format(int, int, u64); #define DPNORMRET2(s, e, m, name, a0, a1) \ { \ union ieee754dp V = ieee754dp_format(s, e, m); \ - if (TSTX()) \ + if (ieee754_tstx()) \ return ieee754dp_xcpt(V, name, a0, a1); \ else \ return V; \ diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 62d0fdb..39c40d2 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -57,18 +57,28 @@ #define CLPAIR(x, y) ((x)*6+(y)) -#define CLEARCX \ - (ieee754_csr.cx = 0) +static inline void ieee754_clearcx(void) +{ + ieee754_csr.cx = 0; +} -#define SETCX(x) \ - (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x)) +static inline void ieee754_setcx(const unsigned int flags) +{ + ieee754_csr.cx |= flags; + ieee754_csr.sx |= flags; +} -#define SETANDTESTCX(x) \ - (SETCX(x), ieee754_csr.mx & (x)) +static inline int ieee754_setandtestcx(const unsigned int x) +{ + ieee754_setcx(x); -#define TSTX() \ - (ieee754_csr.cx & ieee754_csr.mx) + return ieee754_csr.mx & x; +} +static inline int ieee754_tstx(void) +{ + return ieee754_csr.cx & ieee754_csr.mx; +} #define COMPXSP \ unsigned xm; int xe; int xs __maybe_unused; int xc @@ -140,7 +150,7 @@ #define FLUSHDP(v, vc, vs, ve, vm) \ if (vc==IEEE754_CLASS_DNORM) { \ if (ieee754_csr.nod) { \ - SETCX(IEEE754_INEXACT); \ + ieee754_setcx(IEEE754_INEXACT); \ vc = IEEE754_CLASS_ZERO; \ ve = DP_EMIN-1+DP_EBIAS; \ vm = 0; \ @@ -151,7 +161,7 @@ #define FLUSHSP(v, vc, vs, ve, vm) \ if (vc==IEEE754_CLASS_DNORM) { \ if (ieee754_csr.nod) { \ - SETCX(IEEE754_INEXACT); \ + ieee754_setcx(IEEE754_INEXACT); \ vc = IEEE754_CLASS_ZERO; \ ve = SP_EMIN-1+SP_EBIAS; \ vm = 0; \ diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index a15d212..955e474 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -50,7 +50,7 @@ union ieee754sp __cold ieee754sp_xcpt(union ieee754sp r, const char *op, ...) { struct ieee754xctx ax; - if (!TSTX()) + if (!ieee754_tstx()) return r; ax.op = op; @@ -71,7 +71,7 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r, const char *op, ...) if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ return r; - if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { + if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) { /* not enabled convert to a quiet NaN */ SPMANT(r) &= (~SP_MBIT(SP_MBITS-1)); if (ieee754sp_isnan(r)) @@ -144,8 +144,8 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) int es = SP_EMIN - xe; if (ieee754_csr.nod) { - SETCX(IEEE754_UNDERFLOW); - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_UNDERFLOW); + ieee754_setcx(IEEE754_INEXACT); switch(ieee754_csr.rm) { case IEEE754_RN: @@ -168,7 +168,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) { /* Not tiny after rounding */ - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); xm = get_rounding(sn, xm); xm >>= 1; /* Clear grs bits */ @@ -183,9 +183,9 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) } } if (xm & (SP_MBIT(3) - 1)) { - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); if ((xm & (SP_HIDDEN_BIT << 3)) == 0) { - SETCX(IEEE754_UNDERFLOW); + ieee754_setcx(IEEE754_UNDERFLOW); } /* inexact must round of 3 bits @@ -206,8 +206,8 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) assert(xe >= SP_EMIN); if (xe > SP_EMAX) { - SETCX(IEEE754_OVERFLOW); - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_OVERFLOW); + ieee754_setcx(IEEE754_INEXACT); /* -O can be table indexed by (rm,sn) */ switch (ieee754_csr.rm) { case IEEE754_RN: @@ -232,7 +232,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) /* we underflow (tiny/zero) */ assert(xe == SP_EMIN); if (ieee754_csr.mx & IEEE754_UNDERFLOW) - SETCX(IEEE754_UNDERFLOW); + ieee754_setcx(IEEE754_UNDERFLOW); return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); } else { assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index f007c47..011d034 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -81,7 +81,7 @@ extern union ieee754sp ieee754sp_format(int, int, unsigned); { \ union ieee754sp V = ieee754sp_format(s, e, m); \ \ - if (TSTX()) \ + if (ieee754_tstx()) \ return ieee754sp_xcpt(V, name, a0, a1); \ else \ return V; \ diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index 4938d8f..e67f11a 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -34,7 +34,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) EXPLODEXSP; EXPLODEYSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; FLUSHYSP; @@ -51,7 +51,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -74,7 +74,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs == ys) return x; - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c index b98d686..adf3076 100644 --- a/arch/mips/math-emu/sp_cmp.c +++ b/arch/mips/math-emu/sp_cmp.c @@ -35,15 +35,15 @@ int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig) EXPLODEYSP; FLUSHXSP; FLUSHYSP; - CLEARCX; /* Even clear inexact flag here */ + ieee754_clearcx(); /* Even clear inexact flag here */ if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) { if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); if (cmp & IEEE754_CUN) return 1; if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) + if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) return ieee754si_xcpt(0, "fcmpf", x); } return 0; diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c index 1f62865..4caac97 100644 --- a/arch/mips/math-emu/sp_div.c +++ b/arch/mips/math-emu/sp_div.c @@ -34,7 +34,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) EXPLODEXSP; EXPLODEYSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; FLUSHYSP; @@ -51,7 +51,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -72,7 +72,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): @@ -89,12 +89,12 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - SETCX(IEEE754_ZERO_DIVIDE); + ieee754_setcx(IEEE754_ZERO_DIVIDE); return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index cbefb88..569878d 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -33,13 +33,13 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) EXPLODEXDP; - CLEARCX; + ieee754_clearcx(); FLUSHXDP; switch (xc) { case IEEE754_CLASS_SNAN: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp"); case IEEE754_CLASS_QNAN: nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) @@ -53,8 +53,8 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) return ieee754sp_zero(xs); case IEEE754_CLASS_DNORM: /* can't possibly be sp representable */ - SETCX(IEEE754_UNDERFLOW); - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_UNDERFLOW); + ieee754_setcx(IEEE754_INEXACT); if ((ieee754_csr.rm == IEEE754_RU && !xs) || (ieee754_csr.rm == IEEE754_RD && xs)) return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x); diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 7ba2b40..74619e7 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -32,7 +32,7 @@ union ieee754sp ieee754sp_fint(int x) int xe; int xs; - CLEARCX; + ieee754_clearcx(); if (x == 0) return ieee754sp_zero(0); diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index c457a9f..ea065ae 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -32,7 +32,7 @@ union ieee754sp ieee754sp_flong(s64 x) int xe; int xs; - CLEARCX; + ieee754_clearcx(); if (x == 0) return ieee754sp_zero(0); diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c index 668252b..72cedb0 100644 --- a/arch/mips/math-emu/sp_frexp.c +++ b/arch/mips/math-emu/sp_frexp.c @@ -31,7 +31,7 @@ union ieee754sp ieee754sp_frexp(union ieee754sp x, int *eptr) { COMPXSP; - CLEARCX; + ieee754_clearcx(); EXPLODEXSP; switch (xc) { diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c index 4dfe538..82c122c 100644 --- a/arch/mips/math-emu/sp_logb.c +++ b/arch/mips/math-emu/sp_logb.c @@ -30,7 +30,7 @@ union ieee754sp ieee754sp_logb(union ieee754sp x) { COMPXSP; - CLEARCX; + ieee754_clearcx(); EXPLODEXSP; diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c index 30d53ec..22f19a2 100644 --- a/arch/mips/math-emu/sp_modf.c +++ b/arch/mips/math-emu/sp_modf.c @@ -32,7 +32,7 @@ union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp *ip) { COMPXSP; - CLEARCX; + ieee754_clearcx(); EXPLODEXSP; diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index c628f3c..844b3bd 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -34,7 +34,7 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) EXPLODEXSP; EXPLODEYSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; FLUSHYSP; @@ -51,7 +51,7 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -72,7 +72,7 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c index 9831d42..cc8f1b8 100644 --- a/arch/mips/math-emu/sp_scalb.c +++ b/arch/mips/math-emu/sp_scalb.c @@ -30,7 +30,7 @@ union ieee754sp ieee754sp_scalb(union ieee754sp x, int n) { COMPXSP; - CLEARCX; + ieee754_clearcx(); EXPLODEXSP; diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index 633c7a5..4da597b 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -33,7 +33,7 @@ int ieee754sp_finite(union ieee754sp x) union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y) { - CLEARCX; + ieee754_clearcx(); SPSIGN(x) = SPSIGN(y); return x; } @@ -44,7 +44,7 @@ union ieee754sp ieee754sp_neg(union ieee754sp x) COMPXSP; EXPLODEXSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; /* @@ -56,7 +56,7 @@ union ieee754sp ieee754sp_neg(union ieee754sp x) if (xc == IEEE754_CLASS_SNAN) { union ieee754sp y = ieee754sp_indef(); - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); SPSIGN(y) = SPSIGN(x); return ieee754sp_nanxcpt(y, "neg"); } @@ -70,14 +70,14 @@ union ieee754sp ieee754sp_abs(union ieee754sp x) COMPXSP; EXPLODEXSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; /* Clear sign ALWAYS, irrespective of NaN */ SPSIGN(x) = 0; if (xc == IEEE754_CLASS_SNAN) { - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); } diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index 4c60d91..7e87f46 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -35,7 +35,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) /* take care of Inf and NaN */ EXPLODEXSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; /* x == INF or NAN? */ @@ -44,7 +44,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) /* sqrt(Nan) = Nan */ return ieee754sp_nanxcpt(x, "sqrt"); case IEEE754_CLASS_SNAN: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ @@ -52,7 +52,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) case IEEE754_CLASS_INF: if (xs) { /* sqrt(-Inf) = Nan */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); } /* sqrt(+Inf) = Inf */ @@ -61,7 +61,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) case IEEE754_CLASS_NORM: if (xs) { /* sqrt(-x) = Nan */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); } break; @@ -99,7 +99,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) } if (ix != 0) { - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); switch (ieee754_csr.rm) { case IEEE754_RP: q += 2; diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index ed67acf..7e45ba3 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -34,7 +34,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) EXPLODEXSP; EXPLODEYSP; - CLEARCX; + ieee754_clearcx(); FLUSHXSP; FLUSHYSP; @@ -51,7 +51,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): @@ -74,7 +74,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs != ys) return x; - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index a69dfe5..febcf5c 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -30,7 +30,7 @@ int ieee754sp_tint(union ieee754sp x) { COMPXSP; - CLEARCX; + ieee754_clearcx(); EXPLODEXSP; FLUSHXSP; @@ -39,7 +39,7 @@ int ieee754sp_tint(union ieee754sp x) case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); case IEEE754_CLASS_ZERO: return 0; @@ -53,7 +53,7 @@ int ieee754sp_tint(union ieee754sp x) return -0x80000000; /* Set invalid. We will only use overflow for floating point overflow */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); } /* oh gawd */ @@ -99,11 +99,11 @@ int ieee754sp_tint(union ieee754sp x) } if ((xm >> 31) != 0) { /* This can happen after rounding */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); } if (round || sticky) - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); } if (xs) return -xm; diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index da412d3..a05d093 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -30,7 +30,7 @@ s64 ieee754sp_tlong(union ieee754sp x) { COMPXDP; /* <-- need 64-bit mantissa tmp */ - CLEARCX; + ieee754_clearcx(); EXPLODEXSP; FLUSHXSP; @@ -39,7 +39,7 @@ s64 ieee754sp_tlong(union ieee754sp x) case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); case IEEE754_CLASS_ZERO: return 0; @@ -53,7 +53,7 @@ s64 ieee754sp_tlong(union ieee754sp x) return -0x8000000000000000LL; /* Set invalid. We will only use overflow for floating point overflow */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); } /* oh gawd */ @@ -95,11 +95,11 @@ s64 ieee754sp_tlong(union ieee754sp x) } if ((xm >> 63) != 0) { /* This can happen after rounding */ - SETCX(IEEE754_INVALID_OPERATION); + ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); } if (round || sticky) - SETCX(IEEE754_INEXACT); + ieee754_setcx(IEEE754_INEXACT); } if (xs) return -xm; -- cgit v0.10.2 From 08a07904e182895e1205f399465a3d622c0115b8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Apr 2014 13:11:37 +0200 Subject: MIPS: math-emu: Remove most ifdefery. Most of these tests should be runtime tests. This also finally means that on a MIPS III systems MIPS IV opcodes are going to result in an exception as they're supposed to. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index f56cc97..f75dd70 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -183,6 +183,17 @@ /* * Shortcuts ... */ +#define cpu_has_mips_2_3_4_5 (cpu_has_mips_2 | cpu_has_mips_3_4_5) +#define cpu_has_mips_3_4_5 (cpu_has_mips_3 | cpu_has_mips_4_5) +#define cpu_has_mips_4_5 (cpu_has_mips_4 | cpu_has_mips_5) + +#define cpu_has_mips_2_3_4_5_r (cpu_has_mips_2 | cpu_has_mips_3_4_5_r) +#define cpu_has_mips_3_4_5_r (cpu_has_mips_3 | cpu_has_mips_4_5_r) +#define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r) +#define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r) + +#define cpu_has_mips_4_5_r2 (cpu_has_mips_4_5 | cpu_has_mips_r2) + #define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2) #define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2) #define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1) diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 584e0b8..972a7e2 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -35,6 +35,7 @@ */ #include #include +#include #include #include @@ -50,22 +51,13 @@ #include "ieee754.h" -/* Strap kernel emulator for full MIPS IV emulation */ - -#ifdef __mips -#undef __mips -#endif -#define __mips 4 - /* Function which emulates a floating point instruction. */ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *, mips_instruction); -#if __mips >= 4 && __mips != 32 static int fpux_emu(struct pt_regs *, struct mips_fpu_struct *, mips_instruction, void *__user *); -#endif /* Control registers */ @@ -95,7 +87,6 @@ static const unsigned char mips_rm[4] = { [IEEE754_RU] = FPU_CSR_RU, }; -#if __mips >= 4 /* convert condition code register number to csr bit */ static const unsigned int fpucondbit[8] = { FPU_CSR_COND0, @@ -107,7 +98,6 @@ static const unsigned int fpucondbit[8] = { FPU_CSR_COND6, FPU_CSR_COND7 }; -#endif /* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */ static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7}; @@ -860,13 +850,13 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, */ static inline int cop1_64bit(struct pt_regs *xcp) { -#if defined(CONFIG_64BIT) && !defined(CONFIG_MIPS32_O32) - return 1; -#elif defined(CONFIG_32BIT) && !defined(CONFIG_MIPS_O32_FP64_SUPPORT) - return 0; -#else + if (config_enabled(CONFIG_64BIT) && !config_enabled(CONFIG_MIPS32_O32)) + return 1; + else if (config_enabled(CONFIG_32BIT) && + !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT)) + return 0; + return !test_thread_flag(TIF_32BIT_FPREGS); -#endif } #define SIFROMREG(si, x) \ @@ -1070,8 +1060,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case cop1_op: switch (MIPSInst_RS(ir)) { -#if defined(__mips64) case dmfc_op: + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + /* copregister fs -> gpr[rt] */ if (MIPSInst_RT(ir) != 0) { DIFROMREG(xcp->regs[MIPSInst_RT(ir)], @@ -1080,10 +1072,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; case dmtc_op: + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + /* copregister fs <- rt */ DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); break; -#endif case mfhc_op: if (!cpu_has_mips_r2) @@ -1173,16 +1167,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, } case bc_op:{ + unsigned int cbit; int likely = 0; if (delay_slot(xcp)) return SIGILL; -#if __mips >= 4 - cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2]; -#else - cond = ctx->fcr31 & FPU_CSR_COND; -#endif + if (cpu_has_mips_4_5_r) + cbit = fpucondbit[MIPSInst_RT(ir) >> 2]; + else + cbit = FPU_CSR_COND; + cond = ctx->fcr31 & cbit; + switch (MIPSInst_RT(ir) & 3) { case bcfl_op: likely = 1; @@ -1235,23 +1231,32 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, switch (MIPSInst_OPCODE(ir)) { case lwc1_op: + goto emul; case swc1_op: -#if (__mips >= 2 || defined(__mips64)) + goto emul; case ldc1_op: case sdc1_op: -#endif + if (cpu_has_mips_2_3_4_5 || + cpu_has_mips64) + goto emul; + + return SIGILL; + goto emul; case cop1_op: -#if __mips >= 4 && __mips != 32 - case cop1x_op: -#endif - /* its one of ours */ goto emul; -#if __mips >= 4 + case cop1x_op: + if (cpu_has_mips_4_5 || cpu_has_mips64) + /* its one of ours */ + goto emul; + + return SIGILL; case spec_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + if (MIPSInst_FUNC(ir) == movc_op) goto emul; break; -#endif } /* @@ -1291,17 +1296,22 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, } break; -#if __mips >= 4 && __mips != 32 case cop1x_op:{ - int sig = fpux_emu(xcp, ctx, ir, fault_addr); + int sig; + + if (!cpu_has_mips_4_5 && !cpu_has_mips64) + return SIGILL; + + sig = fpux_emu(xcp, ctx, ir, fault_addr); if (sig) return sig; break; } -#endif -#if __mips >= 4 case spec_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + if (MIPSInst_FUNC(ir) != movc_op) return SIGILL; cond = fpucondbit[MIPSInst_RT(ir) >> 2]; @@ -1309,8 +1319,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)]; break; -#endif - default: sigill: return SIGILL; @@ -1339,8 +1347,6 @@ static const unsigned char cmptab[8] = { }; -#if __mips >= 4 && __mips != 32 - /* * Additional MIPS4 instructions */ @@ -1571,7 +1577,6 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return 0; } -#endif @@ -1588,9 +1593,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, union ieee754dp d; union ieee754sp s; int w; -#ifdef __mips64 s64 l; -#endif } rv; /* resulting value */ MIPS_FPU_EMU_INC_STATS(cp1ops); @@ -1617,21 +1620,34 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, goto scopbop; /* unary ops */ -#if __mips >= 2 || defined(__mips64) case fsqrt_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + handler.u = ieee754sp_sqrt; goto scopuop; -#endif -#if __mips >= 4 && __mips != 32 + /* + * Note that on some MIPS IV implementations such as the + * R5000 and R8000 the FSQRT and FRECIP instructions do not + * achieve full IEEE-754 accuracy - however this emulator does. + */ case frsqrt_op: + if (!cpu_has_mips_4_5_r2) + return SIGILL; + handler.u = fpemu_sp_rsqrt; goto scopuop; case frecip_op: + if (!cpu_has_mips_4_5_r2) + return SIGILL; + handler.u = fpemu_sp_recip; goto scopuop; -#endif -#if __mips >= 4 + case fmovc_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + cond = fpucondbit[MIPSInst_FT(ir) >> 2]; if (((ctx->fcr31 & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0)) @@ -1639,16 +1655,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, SPFROMREG(rv.s, MIPSInst_FS(ir)); break; case fmovz_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + if (xcp->regs[MIPSInst_FT(ir)] != 0) return 0; SPFROMREG(rv.s, MIPSInst_FS(ir)); break; case fmovn_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + if (xcp->regs[MIPSInst_FT(ir)] == 0) return 0; SPFROMREG(rv.s, MIPSInst_FS(ir)); break; -#endif case fabs_op: handler.u = ieee754sp_abs; goto scopuop; @@ -1712,7 +1733,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, goto copcsr; } -#if __mips >= 2 || defined(__mips64) case fround_op: case ftrunc_op: case fceil_op: @@ -1720,6 +1740,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, unsigned int oldrm = ieee754_csr.rm; union ieee754sp fs; + if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64) + return SIGILL; + SPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.w = ieee754sp_tint(fs); @@ -1727,12 +1750,13 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, rfmt = w_fmt; goto copcsr; } -#endif /* __mips >= 2 */ -#if defined(__mips64) case fcvtl_op:{ union ieee754sp fs; + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + SPFROMREG(fs, MIPSInst_FS(ir)); rv.l = ieee754sp_tlong(fs); rfmt = l_fmt; @@ -1746,6 +1770,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, unsigned int oldrm = ieee754_csr.rm; union ieee754sp fs; + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + SPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.l = ieee754sp_tlong(fs); @@ -1753,7 +1780,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, rfmt = l_fmt; goto copcsr; } -#endif /* defined(__mips64) */ default: if (MIPSInst_FUNC(ir) >= fcmp_op) { @@ -1802,21 +1828,33 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, goto dcopbop; /* unary ops */ -#if __mips >= 2 || defined(__mips64) case fsqrt_op: + if (!cpu_has_mips_2_3_4_5_r) + return SIGILL; + handler.u = ieee754dp_sqrt; goto dcopuop; -#endif -#if __mips >= 4 && __mips != 32 + /* + * Note that on some MIPS IV implementations such as the + * R5000 and R8000 the FSQRT and FRECIP instructions do not + * achieve full IEEE-754 accuracy - however this emulator does. + */ case frsqrt_op: + if (!cpu_has_mips_4_5_r2) + return SIGILL; + handler.u = fpemu_dp_rsqrt; goto dcopuop; case frecip_op: + if (!cpu_has_mips_4_5_r2) + return SIGILL; + handler.u = fpemu_dp_recip; goto dcopuop; -#endif -#if __mips >= 4 case fmovc_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + cond = fpucondbit[MIPSInst_FT(ir) >> 2]; if (((ctx->fcr31 & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0)) @@ -1824,16 +1862,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, DPFROMREG(rv.d, MIPSInst_FS(ir)); break; case fmovz_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + if (xcp->regs[MIPSInst_FT(ir)] != 0) return 0; DPFROMREG(rv.d, MIPSInst_FS(ir)); break; case fmovn_op: + if (!cpu_has_mips_4_5_r) + return SIGILL; + if (xcp->regs[MIPSInst_FT(ir)] == 0) return 0; DPFROMREG(rv.d, MIPSInst_FS(ir)); break; -#endif case fabs_op: handler.u = ieee754dp_abs; goto dcopuop; @@ -1886,7 +1929,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, goto copcsr; } -#if __mips >= 2 || defined(__mips64) case fround_op: case ftrunc_op: case fceil_op: @@ -1894,6 +1936,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, unsigned int oldrm = ieee754_csr.rm; union ieee754dp fs; + if (!cpu_has_mips_2_3_4_5_r) + return SIGILL; + DPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.w = ieee754dp_tint(fs); @@ -1901,12 +1946,13 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, rfmt = w_fmt; goto copcsr; } -#endif -#if defined(__mips64) case fcvtl_op:{ union ieee754dp fs; + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + DPFROMREG(fs, MIPSInst_FS(ir)); rv.l = ieee754dp_tlong(fs); rfmt = l_fmt; @@ -1920,6 +1966,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, unsigned int oldrm = ieee754_csr.rm; union ieee754dp fs; + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + DPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.l = ieee754dp_tlong(fs); @@ -1927,7 +1976,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, rfmt = l_fmt; goto copcsr; } -#endif /* __mips >= 3 */ default: if (MIPSInst_FUNC(ir) >= fcmp_op) { @@ -1978,9 +2026,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; } -#if defined(__mips64) case l_fmt:{ u64 bits; + + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + DIFROMREG(bits, MIPSInst_FS(ir)); switch (MIPSInst_FUNC(ir)) { @@ -1999,7 +2050,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, } break; } -#endif default: return SIGILL; @@ -2022,18 +2072,19 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * Now we can safely write the result back to the register file. */ switch (rfmt) { - case -1:{ -#if __mips >= 4 - cond = fpucondbit[MIPSInst_FD(ir) >> 2]; -#else - cond = FPU_CSR_COND; -#endif + unsigned int cbit; + case -1: + + if (cpu_has_mips_4_5_r) + cbit = fpucondbit[MIPSInst_RT(ir) >> 2]; + else + cbit = FPU_CSR_COND; if (rv.w) - ctx->fcr31 |= cond; + ctx->fcr31 |= cbit; else - ctx->fcr31 &= ~cond; + ctx->fcr31 &= ~cbit; break; - } + case d_fmt: DPTOREG(rv.d, MIPSInst_FD(ir)); break; @@ -2043,11 +2094,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, case w_fmt: SITOREG(rv.w, MIPSInst_FD(ir)); break; -#if defined(__mips64) case l_fmt: + if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) + return SIGILL; + DITOREG(rv.l, MIPSInst_FD(ir)); break; -#endif default: return SIGILL; } diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 26f785e..68c2996 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -45,15 +45,14 @@ /* special constants */ - -#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) -#define SPSTR(s, b, m) {m, b, s} -#define DPSTR(s, b, mh, ml) {ml, mh, b, s} -#endif - #ifdef __MIPSEB__ #define SPSTR(s, b, m) {s, b, m} #define DPSTR(s, b, mh, ml) {s, b, mh, ml} +#elif defined(__MIPSEL__) +#define SPSTR(s, b, m) {m, b, s} +#define DPSTR(s, b, mh, ml) {ml, mh, b, s} +#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ +#error "MIPS but neither __MIPSEB__ nor __MIPSEL__?" #endif const struct ieee754dp_const __ieee754dp_spcvals[] = { -- cgit v0.10.2 From 66b047dc9cff4c6e89de7b06038155673e7b6120 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Apr 2014 15:52:18 +0200 Subject: MIPS: IP22: This platform may come with either MIPS III or MIPS IV CPUs. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h index 1bcb642..1dfe474 100644 --- a/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h @@ -39,6 +39,10 @@ #define cpu_has_nofpuex 0 #define cpu_has_64bits 1 +#define cpu_has_mips_2 1 +#define cpu_has_mips_3 1 +#define cpu_has_mips_5 0 + #define cpu_has_mips32r1 0 #define cpu_has_mips32r2 0 #define cpu_has_mips64r1 0 -- cgit v0.10.2 From fcfe2285e5c53cb33309f946ba1fccd6b5db64df Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Apr 2014 13:18:08 +0200 Subject: MIPS: math-emu: Get rid of unuable extended precision support. No usable functionality and nothig does ever define IEEE854_XP anyway. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index a197089..049f63f 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -408,9 +408,6 @@ struct ieee754xctx { union { union ieee754sp sp; /* single precision */ union ieee754dp dp; /* double precision */ -#ifdef IEEE854_XP - ieee754xp xp; /* extended precision */ -#endif int si; /* standard signed integer (32bits) */ s64 di; /* extended signed integer (64bits) */ } rv; /* default result format implied by op */ -- cgit v0.10.2 From 92df0f8b350f28ceebef7e0bc785816d84df626b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Apr 2014 14:03:37 +0200 Subject: MIPS: math-emu: Convert debug printks to pr_debug getting. And another bunch of #ifdefs bite the dust. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 972a7e2..3a0dfa4 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -1119,11 +1119,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, value = ctx->fcr31; value = (value & ~FPU_CSR_RM) | mips_rm[modeindex(value)]; -#ifdef CSRTRACE - printk("%p gpr[%d]<-csr=%08x\n", - (void *) (xcp->cp0_epc), - MIPSInst_RT(ir), value); -#endif + pr_debug("%p gpr[%d]<-csr=%08x\n", + (void *) (xcp->cp0_epc), + MIPSInst_RT(ir), value); } else if (MIPSInst_RD(ir) == FPCREG_RID) value = 0; @@ -1146,11 +1144,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* we only have one writable control reg */ if (MIPSInst_RD(ir) == FPCREG_CSR) { -#ifdef CSRTRACE - printk("%p gpr[%d]->csr=%08x\n", - (void *) (xcp->cp0_epc), - MIPSInst_RT(ir), value); -#endif + pr_debug("%p gpr[%d]->csr=%08x\n", + (void *) (xcp->cp0_epc), + MIPSInst_RT(ir), value); /* * Don't write reserved bits, diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c index c6e879c..4f514f3 100644 --- a/arch/mips/math-emu/dsemul.c +++ b/arch/mips/math-emu/dsemul.c @@ -44,10 +44,8 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc) clear_delay_slot(regs); return 0; } -#ifdef DSEMUL_TRACE - printk("dsemul %lx %lx\n", regs->cp0_epc, cpc); -#endif + pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc); /* * The strategy is to push the instruction onto the user stack @@ -149,9 +147,8 @@ int do_dsemulret(struct pt_regs *xcp) * emulating the branch delay instruction. */ -#ifdef DSEMUL_TRACE - printk("dsemulret\n"); -#endif + pr_debug("dsemulret\n"); + if (__get_user(epc, &fr->epc)) { /* Saved EPC */ /* This is not a good situation to be in */ force_sig(SIGBUS, current); -- cgit v0.10.2 From e812a73932dc0b294c30858ba215305b81391c3c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Apr 2014 14:20:54 +0200 Subject: MIPS: math-emu: Cleanup ieee754si_indef() / ieee754di_indef(). LONG_LONG_MAX is a symbol defined in which may not be available so better rely on something provided by a kernel header. While at it, turn these function-like macros into inline functions. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 049f63f..952c180 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -394,12 +395,15 @@ extern const struct ieee754sp_const __ieee754sp_spcvals[]; /* * Indefinite integer value */ -#define ieee754si_indef() INT_MAX -#ifdef LONG_LONG_MAX -#define ieee754di_indef() LONG_LONG_MAX -#else -#define ieee754di_indef() ((s64)(~0ULL>>1)) -#endif +static inline int ieee754si_indef(void) +{ + return INT_MAX; +} + +static inline s64 ieee754di_indef(void) +{ + return S64_MAX; +} /* IEEE exception context, passed to handler */ struct ieee754xctx { -- cgit v0.10.2 From 08f1faa02ae5e513b10d6e44967a22dc20307158 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 19 Apr 2014 23:01:34 +0200 Subject: MIPS: math-emu: Remove #if 1 and dead code from its #else branch. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index fa75f5d..4b5ee79 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -51,7 +51,6 @@ union ieee754dp ieee754dp_fint(int x) xm = x; } -#if 1 /* normalize - result can never be inexact or overflow */ xe = DP_MBITS; while ((xm >> DP_MBITS) == 0) { @@ -59,15 +58,6 @@ union ieee754dp ieee754dp_fint(int x) xe--; } return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -#else - /* normalize */ - xe = DP_MBITS + 3; - while ((xm >> (DP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - DPNORMRET1(xs, xe, xm, "fint", x); -#endif } union ieee754dp ieee754dp_funs(unsigned int u) -- cgit v0.10.2 From 1eaf198d3aee7b71a5deb9dca45481a706381f80 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 20 Apr 2014 01:20:08 +0200 Subject: MIPS: math-emu: Cleanup stdarg usage including apparently bogus comment. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 68c2996..43a9a08 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -28,6 +28,7 @@ * ######################################################################## */ +#include #include #include "ieee754int.h" diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 952c180..6d9a890 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -24,6 +24,7 @@ #ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H #define __ARCH_MIPS_MATH_EMU_IEEE754_H +#include #include #include #include @@ -31,14 +32,6 @@ #include #include -/* - * Not very pretty, but the Linux kernel's normal va_list definition - * does not allow it to be used as a structure element, as it is here. - */ -#ifndef _STDARG_H -#include -#endif - struct ieee754dp_const { __BITFIELD_FIELD(unsigned sign:1, __BITFIELD_FIELD(unsigned bexp:11, diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 53dbb1c..a8eb014 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -23,6 +23,7 @@ * ######################################################################## */ +#include #include #include "ieee754dp.h" diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 955e474..ed62ffe 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -23,6 +23,7 @@ * ######################################################################## */ +#include #include #include "ieee754sp.h" -- cgit v0.10.2 From f5410d19b07d1d06a2ffa43db6d9b565a3a51c41 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Apr 2014 13:31:24 +0200 Subject: MIPS: math-emu: Call ieee754di_xcpt, not ieee754si_xcpt in ieee754dp_cmp. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c index a8da725..2d9390e 100644 --- a/arch/mips/math-emu/dp_cmp.c +++ b/arch/mips/math-emu/dp_cmp.c @@ -44,7 +44,7 @@ int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig) return 1; if (cmp & (IEEE754_CLT | IEEE754_CGT)) { if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) - return ieee754si_xcpt(0, "fcmpf", x); + return ieee754di_xcpt(0, "fcmpf", x); } return 0; } else { -- cgit v0.10.2 From ad8fb5537a7747187e92434dc096d3914472b51b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Apr 2014 15:51:55 +0200 Subject: MIPS: math-emu: Replace DP_MBITS with DP_FBITS and SP_MBITS with SP_FBITS. Both were defined as 23 rsp. 52 though the mentissa is actually a bit more than the fraction. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index 7daaafc..f1c8e70 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -153,7 +153,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) xe = xe; xs = xs; - if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ + if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */ xm = XDPSRS1(xm); xe++; } @@ -172,7 +172,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) IEEE754_RD); /* normalize to rounding precision */ - while ((xm >> (DP_MBITS + 3)) == 0) { + while ((xm >> (DP_FBITS + 3)) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c index 3b568b7..13ecffa 100644 --- a/arch/mips/math-emu/dp_div.c +++ b/arch/mips/math-emu/dp_div.c @@ -129,7 +129,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) int re = xe - ye; u64 bm; - for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) { + for (bm = DP_MBIT(DP_FBITS + 2); bm; bm >>= 1) { if (xm >= ym) { xm -= ym; rm |= bm; @@ -146,7 +146,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) /* normalise rm to rounding precision ? */ - while ((rm >> (DP_MBITS + 3)) == 0) { + while ((rm >> (DP_FBITS + 3)) == 0) { rm <<= 1; re--; } diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index 4b5ee79..196a010 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -52,8 +52,8 @@ union ieee754dp ieee754dp_fint(int x) } /* normalize - result can never be inexact or overflow */ - xe = DP_MBITS; - while ((xm >> DP_MBITS) == 0) { + xe = DP_FBITS; + while ((xm >> DP_FBITS) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index 89bd579..915072d 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -52,15 +52,15 @@ union ieee754dp ieee754dp_flong(s64 x) } /* normalize */ - xe = DP_MBITS + 3; - if (xm >> (DP_MBITS + 1 + 3)) { + xe = DP_FBITS + 3; + if (xm >> (DP_FBITS + 1 + 3)) { /* shunt out overflow bits */ - while (xm >> (DP_MBITS + 1 + 3)) { + while (xm >> (DP_FBITS + 1 + 3)) { XDPSRSX1(); } } else { /* normalize in grs extended double precision */ - while ((xm >> (DP_MBITS + 3)) == 0) { + while ((xm >> (DP_FBITS + 3)) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index cacd9f3..7ddb506 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -44,8 +44,8 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) return ieee754dp_nanxcpt(builddp(xs, DP_EMAX + 1 + DP_EBIAS, ((u64) xm - << (DP_MBITS - - SP_MBITS))), "fsp", + << (DP_FBITS - + SP_FBITS))), "fsp", x); case IEEE754_CLASS_INF: return ieee754dp_inf(xs); @@ -53,7 +53,7 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) return ieee754dp_zero(xs); case IEEE754_CLASS_DNORM: /* normalize */ - while ((xm >> SP_MBITS) == 0) { + while ((xm >> SP_FBITS) == 0) { xm <<= 1; xe--; } @@ -69,5 +69,5 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) xm &= ~SP_HIDDEN_BIT; return builddp(xs, xe + DP_EBIAS, - (u64) xm << (DP_MBITS - SP_MBITS)); + (u64) xm << (DP_FBITS - SP_FBITS)); } diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c index 61733ff..d83ec44 100644 --- a/arch/mips/math-emu/dp_modf.c +++ b/arch/mips/math-emu/dp_modf.c @@ -54,24 +54,24 @@ union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp *ip) *ip = ieee754dp_zero(xs); return x; } - if (xe >= DP_MBITS) { + if (xe >= DP_FBITS) { *ip = x; return ieee754dp_zero(xs); } /* generate ipart mantissa by clearing bottom bits */ *ip = builddp(xs, xe + DP_EBIAS, - ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) & + ((xm >> (DP_FBITS - xe)) << (DP_FBITS - xe)) & ~DP_HIDDEN_BIT); /* generate fpart mantissa by clearing top bits * and normalizing (must be able to normalize) */ - xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe)); + xm = (xm << (64 - (DP_FBITS - xe))) >> (64 - (DP_FBITS - xe)); if (xm == 0) return ieee754dp_zero(xs); - while ((xm >> DP_MBITS) == 0) { + while ((xm >> DP_FBITS) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index 8f1bef9..56fb309 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -113,8 +113,8 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) u64 rm; /* shunt to top of word */ - xm <<= 64 - (DP_MBITS + 1); - ym <<= 64 - (DP_MBITS + 1); + xm <<= 64 - (DP_FBITS + 1); + ym <<= 64 - (DP_FBITS + 1); /* multiply 32bits xm,ym to give high 32bits rm with stickness */ @@ -162,13 +162,13 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) */ if ((s64) rm < 0) { rm = - (rm >> (64 - (DP_MBITS + 1 + 3))) | - ((rm << (DP_MBITS + 1 + 3)) != 0); + (rm >> (64 - (DP_FBITS + 1 + 3))) | + ((rm << (DP_FBITS + 1 + 3)) != 0); re++; } else { rm = - (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) | - ((rm << (DP_MBITS + 1 + 3 + 1)) != 0); + (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) | + ((rm << (DP_FBITS + 1 + 3 + 1)) != 0); } assert(rm & (DP_HIDDEN_BIT << 3)); DPNORMRET2(rs, re, rm, "mul", x, y); diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index e369c7b..25d25bc 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -158,7 +158,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) xe = xe; xs = xs; - if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ + if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */ xm = XDPSRS1(xm); /* shift preserving sticky */ xe++; } @@ -181,7 +181,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) /* normalize to rounding precision */ - while ((xm >> (DP_MBITS + 3)) == 0) { + while ((xm >> (DP_FBITS + 3)) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 792470c..8c39a40 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -54,9 +54,9 @@ int ieee754dp_tint(union ieee754dp x) return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); } /* oh gawd */ - if (xe > DP_MBITS) { - xm <<= xe - DP_MBITS; - } else if (xe < DP_MBITS) { + if (xe > DP_FBITS) { + xm <<= xe - DP_FBITS; + } else if (xe < DP_FBITS) { u64 residue; int round; int sticky; @@ -68,10 +68,10 @@ int ieee754dp_tint(union ieee754dp x) sticky = residue != 0; xm = 0; } else { - residue = xm << (64 - DP_MBITS + xe); + residue = xm << (64 - DP_FBITS + xe); round = (residue >> 63) != 0; sticky = (residue << 1) != 0; - xm >>= DP_MBITS - xe; + xm >>= DP_FBITS - xe; } /* Note: At this point upper 32 bits of xm are guaranteed to be zero */ diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index fcc1c4f..2653b6e 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -57,9 +57,9 @@ s64 ieee754dp_tlong(union ieee754dp x) return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); } /* oh gawd */ - if (xe > DP_MBITS) { - xm <<= xe - DP_MBITS; - } else if (xe < DP_MBITS) { + if (xe > DP_FBITS) { + xm <<= xe - DP_FBITS; + } else if (xe < DP_FBITS) { u64 residue; int round; int sticky; @@ -75,10 +75,10 @@ s64 ieee754dp_tlong(union ieee754dp x) * so we do it in two steps. Be aware that xe * may be -1 */ residue = xm << (xe + 1); - residue <<= 63 - DP_MBITS; + residue <<= 63 - DP_FBITS; round = (residue >> 63) != 0; sticky = (residue << 1) != 0; - xm >>= DP_MBITS - xe; + xm >>= DP_FBITS - xe; } odd = (xm & 0x1) != 0x0; switch (ieee754_csr.rm) { diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index a8eb014..9be2d78 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -43,7 +43,7 @@ int ieee754dp_isnan(union ieee754dp x) int ieee754dp_issnan(union ieee754dp x) { assert(ieee754dp_isnan(x)); - return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1)); + return ((DPMANT(x) & DP_MBIT(DP_FBITS-1)) == DP_MBIT(DP_FBITS-1)); } @@ -73,7 +73,7 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r, const char *op, ...) if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) { /* not enabled convert to a quiet NaN */ - DPMANT(r) &= (~DP_MBIT(DP_MBITS-1)); + DPMANT(r) &= (~DP_MBIT(DP_FBITS-1)); if (ieee754dp_isnan(r)) return r; else @@ -136,7 +136,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) { assert(xm); /* we don't gen exact zeros (probably should) */ - assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */ + assert((xm >> (DP_FBITS + 1 + 3)) == 0); /* no execess */ assert(xm & (DP_HIDDEN_BIT << 3)); if (xe < DP_EMIN) { @@ -165,7 +165,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) } if (xe == DP_EMIN - 1 - && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) + && get_rounding(sn, xm) >> (DP_FBITS + 1 + 3)) { /* Not tiny after rounding */ ieee754_setcx(IEEE754_INEXACT); @@ -195,7 +195,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) xm = get_rounding(sn, xm); /* adjust exponent for rounding add overflowing */ - if (xm >> (DP_MBITS + 3 + 1)) { + if (xm >> (DP_FBITS + 3 + 1)) { /* add causes mantissa overflow */ xm >>= 1; xe++; @@ -204,7 +204,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) /* strip grs bits */ xm >>= 3; - assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ + assert((xm >> (DP_FBITS + 1)) == 0); /* no execess */ assert(xe >= DP_EMIN); if (xe > DP_EMAX) { @@ -237,7 +237,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) ieee754_setcx(IEEE754_UNDERFLOW); return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm); } else { - assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ + assert((xm >> (DP_FBITS + 1)) == 0); /* no execess */ assert(xm & DP_HIDDEN_BIT); return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 1dc2058..f8f358a 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -32,7 +32,7 @@ /* 3bit extended double precision sticky right shift */ #define XDPSRS(v,rs) \ - ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) + ((rs > (DP_FBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) #define XDPSRSX1() \ (xe++, (xm = (xm >> 1) | (xm & 1))) @@ -42,7 +42,7 @@ /* convert denormal to normalized with extended exponent */ #define DPDNORMx(m,e) \ - while ((m >> DP_MBITS) == 0) { m <<= 1; e--; } + while ((m >> DP_FBITS) == 0) { m <<= 1; e--; } #define DPDNORMX DPDNORMx(xm, xe) #define DPDNORMY DPDNORMx(ym, ye) @@ -53,7 +53,7 @@ static inline union ieee754dp builddp(int s, int bx, u64 m) assert((s) == 0 || (s) == 1); assert((bx) >= DP_EMIN - 1 + DP_EBIAS && (bx) <= DP_EMAX + 1 + DP_EBIAS); - assert(((m) >> DP_MBITS) == 0); + assert(((m) >> DP_FBITS) == 0); r.parts.sign = s; r.parts.bexp = bx; diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 39c40d2..543e8f0 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -31,19 +31,19 @@ #define DP_EBIAS 1023 #define DP_EMIN (-1022) #define DP_EMAX 1023 -#define DP_MBITS 52 +#define DP_FBITS 52 #define SP_EBIAS 127 #define SP_EMIN (-126) #define SP_EMAX 127 -#define SP_MBITS 23 +#define SP_FBITS 23 #define DP_MBIT(x) ((u64)1 << (x)) -#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS) +#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) #define DP_SIGN_BIT DP_MBIT(63) #define SP_MBIT(x) ((u32)1 << (x)) -#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS) +#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) #define SP_SIGN_BIT SP_MBIT(31) @@ -94,7 +94,7 @@ static inline int ieee754_tstx(void) if (ve == SP_EMAX+1+SP_EBIAS) { \ if (vm == 0) \ vc = IEEE754_CLASS_INF; \ - else if (vm & SP_MBIT(SP_MBITS-1)) \ + else if (vm & SP_MBIT(SP_FBITS-1)) \ vc = IEEE754_CLASS_SNAN; \ else \ vc = IEEE754_CLASS_QNAN; \ @@ -128,7 +128,7 @@ static inline int ieee754_tstx(void) if (ve == DP_EMAX+1+DP_EBIAS) { \ if (vm == 0) \ vc = IEEE754_CLASS_INF; \ - else if (vm & DP_MBIT(DP_MBITS-1)) \ + else if (vm & DP_MBIT(DP_FBITS-1)) \ vc = IEEE754_CLASS_SNAN; \ else \ vc = IEEE754_CLASS_QNAN; \ diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index ed62ffe..5b435ec 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -43,7 +43,7 @@ int ieee754sp_isnan(union ieee754sp x) int ieee754sp_issnan(union ieee754sp x) { assert(ieee754sp_isnan(x)); - return (SPMANT(x) & SP_MBIT(SP_MBITS-1)); + return (SPMANT(x) & SP_MBIT(SP_FBITS-1)); } @@ -74,7 +74,7 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r, const char *op, ...) if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) { /* not enabled convert to a quiet NaN */ - SPMANT(r) &= (~SP_MBIT(SP_MBITS-1)); + SPMANT(r) &= (~SP_MBIT(SP_FBITS-1)); if (ieee754sp_isnan(r)) return r; else @@ -137,7 +137,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) { assert(xm); /* we don't gen exact zeros (probably should) */ - assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */ + assert((xm >> (SP_FBITS + 1 + 3)) == 0); /* no execess */ assert(xm & (SP_HIDDEN_BIT << 3)); if (xe < SP_EMIN) { @@ -166,7 +166,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) } if (xe == SP_EMIN - 1 - && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) + && get_rounding(sn, xm) >> (SP_FBITS + 1 + 3)) { /* Not tiny after rounding */ ieee754_setcx(IEEE754_INEXACT); @@ -194,7 +194,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) xm = get_rounding(sn, xm); /* adjust exponent for rounding add overflowing */ - if (xm >> (SP_MBITS + 1 + 3)) { + if (xm >> (SP_FBITS + 1 + 3)) { /* add causes mantissa overflow */ xm >>= 1; xe++; @@ -203,7 +203,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) /* strip grs bits */ xm >>= 3; - assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ + assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */ assert(xe >= SP_EMIN); if (xe > SP_EMAX) { @@ -236,7 +236,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) ieee754_setcx(IEEE754_UNDERFLOW); return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); } else { - assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ + assert((xm >> (SP_FBITS + 1)) == 0); /* no execess */ assert(xm & SP_HIDDEN_BIT); return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 011d034..075ea18 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -33,21 +33,21 @@ /* 3bit extended single precision sticky right shift */ #define SPXSRSXn(rs) \ (xe += rs, \ - xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) + xm = (rs > (SP_FBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) #define SPXSRSX1() \ (xe++, (xm = (xm >> 1) | (xm & 1))) #define SPXSRSYn(rs) \ (ye+=rs, \ - ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) + ym = (rs > (SP_FBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) #define SPXSRSY1() \ (ye++, (ym = (ym >> 1) | (ym & 1))) /* convert denormal to normalized with extended exponent */ #define SPDNORMx(m,e) \ - while ((m >> SP_MBITS) == 0) { m <<= 1; e--; } + while ((m >> SP_FBITS) == 0) { m <<= 1; e--; } #define SPDNORMX SPDNORMx(xm, xe) #define SPDNORMY SPDNORMx(ym, ye) @@ -58,7 +58,7 @@ static inline union ieee754sp buildsp(int s, int bx, unsigned m) assert((s) == 0 || (s) == 1); assert((bx) >= SP_EMIN - 1 + SP_EBIAS && (bx) <= SP_EMAX + 1 + SP_EBIAS); - assert(((m) >> SP_MBITS) == 0); + assert(((m) >> SP_FBITS) == 0); r.parts.sign = s; r.parts.bexp = bx; diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index e67f11a..d107bce 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -148,7 +148,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) xe = xe; xs = xs; - if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ + if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */ SPXSRSX1(); } } else { @@ -166,7 +166,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) IEEE754_RD); /* normalize in extended single precision */ - while ((xm >> (SP_MBITS + 3)) == 0) { + while ((xm >> (SP_FBITS + 3)) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c index 4caac97..095fb20 100644 --- a/arch/mips/math-emu/sp_div.c +++ b/arch/mips/math-emu/sp_div.c @@ -129,7 +129,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) int re = xe - ye; unsigned bm; - for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) { + for (bm = SP_MBIT(SP_FBITS + 2); bm; bm >>= 1) { if (xm >= ym) { xm -= ym; rm |= bm; @@ -146,7 +146,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) /* normalise rm to rounding precision ? */ - while ((rm >> (SP_MBITS + 3)) == 0) { + while ((rm >> (SP_FBITS + 3)) == 0) { rm <<= 1; re--; } diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index 569878d..c22ffca 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -43,7 +43,7 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp"); case IEEE754_CLASS_QNAN: nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) - (xm >> (DP_MBITS - SP_MBITS))); + (xm >> (DP_FBITS - SP_FBITS))); if (!ieee754sp_isnan(nan)) nan = ieee754sp_indef(); return ieee754sp_nanxcpt(nan, "fdp", x); @@ -66,10 +66,10 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) { u32 rm; - /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift + /* convert from DP_FBITS to SP_FBITS+3 with sticky right shift */ - rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) | - ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0); + rm = (xm >> (DP_FBITS - (SP_FBITS + 3))) | + ((xm << (64 - (DP_FBITS - (SP_FBITS + 3)))) != 0); SPNORMRET1(xs, xe, rm, "fdp", x); } diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 74619e7..9574d25 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -50,18 +50,18 @@ union ieee754sp ieee754sp_fint(int x) } else { xm = x; } - xe = SP_MBITS + 3; + xe = SP_FBITS + 3; - if (xm >> (SP_MBITS + 1 + 3)) { + if (xm >> (SP_FBITS + 1 + 3)) { /* shunt out overflow bits */ - while (xm >> (SP_MBITS + 1 + 3)) { + while (xm >> (SP_FBITS + 1 + 3)) { SPXSRSX1(); } } else { /* normalize in grs extended single precision */ - while ((xm >> (SP_MBITS + 3)) == 0) { + while ((xm >> (SP_FBITS + 3)) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index ea065ae..65c7e7e 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -50,17 +50,17 @@ union ieee754sp ieee754sp_flong(s64 x) } else { xm = x; } - xe = SP_MBITS + 3; + xe = SP_FBITS + 3; - if (xm >> (SP_MBITS + 1 + 3)) { + if (xm >> (SP_FBITS + 1 + 3)) { /* shunt out overflow bits */ - while (xm >> (SP_MBITS + 1 + 3)) { + while (xm >> (SP_FBITS + 1 + 3)) { SPXSRSX1(); } } else { /* normalize in grs extended single precision */ - while ((xm >> (SP_MBITS + 3)) == 0) { + while ((xm >> (SP_FBITS + 3)) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c index 22f19a2..5f361a7 100644 --- a/arch/mips/math-emu/sp_modf.c +++ b/arch/mips/math-emu/sp_modf.c @@ -54,24 +54,24 @@ union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp *ip) *ip = ieee754sp_zero(xs); return x; } - if (xe >= SP_MBITS) { + if (xe >= SP_FBITS) { *ip = x; return ieee754sp_zero(xs); } /* generate ipart mantissa by clearing bottom bits */ *ip = buildsp(xs, xe + SP_EBIAS, - ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) & + ((xm >> (SP_FBITS - xe)) << (SP_FBITS - xe)) & ~SP_HIDDEN_BIT); /* generate fpart mantissa by clearing top bits * and normalizing (must be able to normalize) */ - xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe)); + xm = (xm << (32 - (SP_FBITS - xe))) >> (32 - (SP_FBITS - xe)); if (xm == 0) return ieee754sp_zero(xs); - while ((xm >> SP_MBITS) == 0) { + while ((xm >> SP_FBITS) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index 844b3bd..28f608f 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -114,8 +114,8 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) unsigned rm; /* shunt to top of word */ - xm <<= 32 - (SP_MBITS + 1); - ym <<= 32 - (SP_MBITS + 1); + xm <<= 32 - (SP_FBITS + 1); + ym <<= 32 - (SP_FBITS + 1); /* multiply 32bits xm,ym to give high 32bits rm with stickness */ @@ -156,12 +156,12 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) * sticky shift down to normal rounding precision */ if ((int) rm < 0) { - rm = (rm >> (32 - (SP_MBITS + 1 + 3))) | - ((rm << (SP_MBITS + 1 + 3)) != 0); + rm = (rm >> (32 - (SP_FBITS + 1 + 3))) | + ((rm << (SP_FBITS + 1 + 3)) != 0); re++; } else { - rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) | - ((rm << (SP_MBITS + 1 + 3 + 1)) != 0); + rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) | + ((rm << (SP_FBITS + 1 + 3 + 1)) != 0); } assert(rm & (SP_HIDDEN_BIT << 3)); diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index 7e45ba3..1131065 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -153,7 +153,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) xe = xe; xs = xs; - if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ + if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */ SPXSRSX1(); /* shift preserving sticky */ } } else { @@ -174,7 +174,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) } /* normalize to rounding precision */ - while ((xm >> (SP_MBITS + 3)) == 0) { + while ((xm >> (SP_FBITS + 3)) == 0) { xm <<= 1; xe--; } diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index febcf5c..709f6bc 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -57,8 +57,8 @@ int ieee754sp_tint(union ieee754sp x) return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); } /* oh gawd */ - if (xe > SP_MBITS) { - xm <<= xe - SP_MBITS; + if (xe > SP_FBITS) { + xm <<= xe - SP_FBITS; } else { u32 residue; int round; @@ -75,10 +75,10 @@ int ieee754sp_tint(union ieee754sp x) * so we do it in two steps. Be aware that xe * may be -1 */ residue = xm << (xe + 1); - residue <<= 31 - SP_MBITS; + residue <<= 31 - SP_FBITS; round = (residue >> 31) != 0; sticky = (residue << 1) != 0; - xm >>= SP_MBITS - xe; + xm >>= SP_FBITS - xe; } odd = (xm & 0x1) != 0x0; switch (ieee754_csr.rm) { diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index a05d093..155491f 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -57,9 +57,9 @@ s64 ieee754sp_tlong(union ieee754sp x) return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); } /* oh gawd */ - if (xe > SP_MBITS) { - xm <<= xe - SP_MBITS; - } else if (xe < SP_MBITS) { + if (xe > SP_FBITS) { + xm <<= xe - SP_FBITS; + } else if (xe < SP_FBITS) { u32 residue; int round; int sticky; @@ -71,10 +71,10 @@ s64 ieee754sp_tlong(union ieee754sp x) sticky = residue != 0; xm = 0; } else { - residue = xm << (32 - SP_MBITS + xe); + residue = xm << (32 - SP_FBITS + xe); round = (residue >> 31) != 0; sticky = (residue << 1) != 0; - xm >>= SP_MBITS - xe; + xm >>= SP_FBITS - xe; } odd = (xm & 0x1) != 0x0; switch (ieee754_csr.rm) { -- cgit v0.10.2 From 3e160aad0f23cc80743dd44810269c9667e0eb0e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Apr 2014 16:02:03 +0200 Subject: MIPS: math-emu: Use SPSIGN() rather than DPSIGN() in ieee754sp_sub(). Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index 1131065..828de93 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -104,7 +104,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): /* quick fix up */ - DPSIGN(y) ^= 1; + SPSIGN(y) ^= 1; return y; case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): -- cgit v0.10.2 From b3a7ad2b0c48e046ff8a7934f3aa55fc06c54762 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Apr 2014 16:33:07 +0200 Subject: MIPS: math-emu: Eleminate duplicate definitions of identical macros. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index 7ddb506..67ee97f 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -24,6 +24,7 @@ */ +#include "ieee754sp.h" #include "ieee754dp.h" union ieee754dp ieee754dp_fsp(union ieee754sp x) diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 43a9a08..f3b5fa0 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -35,14 +35,6 @@ #include "ieee754sp.h" #include "ieee754dp.h" -#define DP_EBIAS 1023 -#define DP_EMIN (-1022) -#define DP_EMAX 1023 - -#define SP_EBIAS 127 -#define SP_EMIN (-126) -#define SP_EMAX 127 - /* special constants */ diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c index 6d4dc36..ebe34e9 100644 --- a/arch/mips/math-emu/ieee754d.c +++ b/arch/mips/math-emu/ieee754d.c @@ -28,34 +28,8 @@ #include #include #include "ieee754.h" - -#define DP_EBIAS 1023 -#define DP_EMIN (-1022) -#define DP_EMAX 1023 -#define DP_FBITS 52 - -#define SP_EBIAS 127 -#define SP_EMIN (-126) -#define SP_EMAX 127 -#define SP_FBITS 23 - -#define DP_MBIT(x) ((u64)1 << (x)) -#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) -#define DP_SIGN_BIT DP_MBIT(63) - - -#define SP_MBIT(x) ((u32)1 << (x)) -#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) -#define SP_SIGN_BIT SP_MBIT(31) - - -#define SPSIGN(sp) (sp.parts.sign) -#define SPBEXP(sp) (sp.parts.bexp) -#define SPMANT(sp) (sp.parts.mant) - -#define DPSIGN(dp) (dp.parts.sign) -#define DPBEXP(dp) (dp.parts.bexp) -#define DPMANT(dp) (dp.parts.mant) +#include "ieee754sp.h" +#include "ieee754dp.h" union ieee754dp ieee754dp_dump(char *m, union ieee754dp x) { diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index f8f358a..216bab3 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -30,6 +30,20 @@ #define assert(expr) ((void)0) +#define DP_EBIAS 1023 +#define DP_EMIN (-1022) +#define DP_EMAX 1023 +#define DP_FBITS 52 +#define DP_MBITS 52 + +#define DP_MBIT(x) ((u64)1 << (x)) +#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) +#define DP_SIGN_BIT DP_MBIT(63) + +#define DPSIGN(dp) (dp.parts.sign) +#define DPBEXP(dp) (dp.parts.bexp) +#define DPMANT(dp) (dp.parts.mant) + /* 3bit extended double precision sticky right shift */ #define XDPSRS(v,rs) \ ((rs > (DP_FBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 543e8f0..4621a3d 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -28,33 +28,6 @@ #include "ieee754.h" -#define DP_EBIAS 1023 -#define DP_EMIN (-1022) -#define DP_EMAX 1023 -#define DP_FBITS 52 - -#define SP_EBIAS 127 -#define SP_EMIN (-126) -#define SP_EMAX 127 -#define SP_FBITS 23 - -#define DP_MBIT(x) ((u64)1 << (x)) -#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) -#define DP_SIGN_BIT DP_MBIT(63) - -#define SP_MBIT(x) ((u32)1 << (x)) -#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) -#define SP_SIGN_BIT SP_MBIT(31) - - -#define SPSIGN(sp) (sp.parts.sign) -#define SPBEXP(sp) (sp.parts.bexp) -#define SPMANT(sp) (sp.parts.mant) - -#define DPSIGN(dp) (dp.parts.sign) -#define DPBEXP(dp) (dp.parts.bexp) -#define DPMANT(dp) (dp.parts.mant) - #define CLPAIR(x, y) ((x)*6+(y)) static inline void ieee754_clearcx(void) diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 075ea18..a28ced8 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -30,6 +30,20 @@ #define assert(expr) ((void)0) +#define SP_EBIAS 127 +#define SP_EMIN (-126) +#define SP_EMAX 127 +#define SP_FBITS 23 +#define SP_MBITS 23 + +#define SP_MBIT(x) ((u32)1 << (x)) +#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) +#define SP_SIGN_BIT SP_MBIT(31) + +#define SPSIGN(sp) (sp.parts.sign) +#define SPBEXP(sp) (sp.parts.bexp) +#define SPMANT(sp) (sp.parts.mant) + /* 3bit extended single precision sticky right shift */ #define SPXSRSXn(rs) \ (xe += rs, \ diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index c22ffca..ccbed8a 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -25,6 +25,7 @@ #include "ieee754sp.h" +#include "ieee754dp.h" union ieee754sp ieee754sp_fdp(union ieee754dp x) { diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index 155491f..e979aa7 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -25,6 +25,7 @@ #include "ieee754sp.h" +#include "ieee754dp.h" s64 ieee754sp_tlong(union ieee754sp x) { -- cgit v0.10.2 From 3a33db2321759975dba3e6156459c3eeb3f6c1e2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Apr 2014 16:52:01 +0200 Subject: MIPS: math-emu: Inline ieee754dp_finite and ieee754dp_finite(). Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index c116502..cae11b0 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -26,11 +26,6 @@ #include "ieee754dp.h" -int ieee754dp_finite(union ieee754dp x) -{ - return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; -} - union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y) { ieee754_clearcx(); diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 6d9a890..7466230 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -68,7 +68,6 @@ union ieee754sp { /* * single precision (often aka float) */ -int ieee754sp_finite(union ieee754sp x); int ieee754sp_class(union ieee754sp x); union ieee754sp ieee754sp_abs(union ieee754sp x); @@ -112,7 +111,6 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x); /* * double precision (often aka double) */ -int ieee754dp_finite(union ieee754dp x); int ieee754dp_class(union ieee754dp x); /* x with sign of y */ diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 216bab3..c755e1f 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -44,6 +44,11 @@ #define DPBEXP(dp) (dp.parts.bexp) #define DPMANT(dp) (dp.parts.mant) +static inline int ieee754dp_finite(union ieee754dp x) +{ + return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; +} + /* 3bit extended double precision sticky right shift */ #define XDPSRS(v,rs) \ ((rs > (DP_FBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index a28ced8..45a2de3 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -44,6 +44,11 @@ #define SPBEXP(sp) (sp.parts.bexp) #define SPMANT(sp) (sp.parts.mant) +static inline int ieee754sp_finite(union ieee754sp x) +{ + return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; +} + /* 3bit extended single precision sticky right shift */ #define SPXSRSXn(rs) \ (xe += rs, \ diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index 4da597b..b63e9fb 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -26,11 +26,6 @@ #include "ieee754sp.h" -int ieee754sp_finite(union ieee754sp x) -{ - return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; -} - union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y) { ieee754_clearcx(); -- cgit v0.10.2 From 1bc3320d954183031bd3dc1dac36858c3c96e0b3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Apr 2014 17:11:01 +0200 Subject: MIPS: math-emu: Remove unused ieee754sp_bestnan() and ieee754dp_bestnan(). Both are unused since lmo commit fdffbafbb38723618626c70ffdc6ff9175cdffa2 [Lots of FPU bug fixes from Kjeld Borch Egevang.] Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 9be2d78..50b1fbf 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -89,18 +89,6 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r, const char *op, ...) return ax.rv.dp; } -union ieee754dp ieee754dp_bestnan(union ieee754dp x, union ieee754dp y) -{ - assert(ieee754dp_isnan(x)); - assert(ieee754dp_isnan(y)); - - if (DPMANT(x) > DPMANT(y)) - return x; - else - return y; -} - - static u64 get_rounding(int sn, u64 xm) { /* inexact must round of 3 bits diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index c755e1f..830a0d5 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -86,7 +86,6 @@ extern int __cold ieee754si_xcpt(int, const char *, ...); extern s64 __cold ieee754di_xcpt(s64, const char *, ...); extern union ieee754dp __cold ieee754dp_xcpt(union ieee754dp, const char *, ...); extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp, const char *, ...); -extern union ieee754dp ieee754dp_bestnan(union ieee754dp, union ieee754dp); extern union ieee754dp ieee754dp_format(int, int, u64); diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 5b435ec..495295c 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -90,18 +90,6 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r, const char *op, ...) return ax.rv.sp; } -union ieee754sp ieee754sp_bestnan(union ieee754sp x, union ieee754sp y) -{ - assert(ieee754sp_isnan(x)); - assert(ieee754sp_isnan(y)); - - if (SPMANT(x) > SPMANT(y)) - return x; - else - return y; -} - - static unsigned get_rounding(int sn, unsigned xm) { /* inexact must round of 3 bits diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 45a2de3..9511205 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -92,7 +92,6 @@ extern int __cold ieee754si_xcpt(int, const char *, ...); extern s64 __cold ieee754di_xcpt(s64, const char *, ...); extern union ieee754sp __cold ieee754sp_xcpt(union ieee754sp, const char *, ...); extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp, const char *, ...); -extern union ieee754sp ieee754sp_bestnan(union ieee754sp, union ieee754sp); extern union ieee754sp ieee754sp_format(int, int, unsigned); -- cgit v0.10.2 From dfbf42b844a5f307bd66716da65f01be9107bc0b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Apr 2014 00:29:50 +0200 Subject: MIPS: math-emu: Remove unused code. Shrinks the FPU emulator by 4528 bytes. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 0803970..363ce9b 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -2,12 +2,11 @@ # Makefile for the Linux/MIPS kernel FPU emulation. # -obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ - ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \ - dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \ - dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \ - sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \ - sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ - dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o +obj-y := cp1emu.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ + ieee754xcpt.o dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o \ + dp_cmp.o dp_simple.o dp_tint.o dp_fint.o dp_tlong.o dp_flong.o \ + sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \ + sp_tint.o sp_fint.o sp_tlong.o sp_flong.o dp_sqrt.o sp_sqrt.o \ + kernel_linkage.o dsemul.o obj-$(CONFIG_DEBUG_FS) += me-debugfs.o diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index 196a010..98b9d6a 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -59,11 +59,3 @@ union ieee754dp ieee754dp_fint(int x) } return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); } - -union ieee754dp ieee754dp_funs(unsigned int u) -{ - if ((int) u < 0) - return ieee754dp_add(ieee754dp_1e31(), - ieee754dp_fint(u & ~(1 << 31))); - return ieee754dp_fint(u); -} diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index 915072d..fb5eeaa 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -67,11 +67,3 @@ union ieee754dp ieee754dp_flong(s64 x) } DPNORMRET1(xs, xe, xm, "dp_flong", x); } - -union ieee754dp ieee754dp_fulong(u64 u) -{ - if ((s64) u < 0) - return ieee754dp_add(ieee754dp_1e63(), - ieee754dp_flong(u & ~(1ULL << 63))); - return ieee754dp_flong(u); -} diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c deleted file mode 100644 index 25ebce1..0000000 --- a/arch/mips/math-emu/dp_frexp.c +++ /dev/null @@ -1,52 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -/* close to ieeep754dp_logb -*/ -union ieee754dp ieee754dp_frexp(union ieee754dp x, int *eptr) -{ - COMPXDP; - ieee754_clearcx(); - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *eptr = 0; - return x; - case IEEE754_CLASS_DNORM: - DPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - *eptr = xe + 1; - return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c deleted file mode 100644 index b412c90..0000000 --- a/arch/mips/math-emu/dp_logb.c +++ /dev/null @@ -1,53 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -union ieee754dp ieee754dp_logb(union ieee754dp x) -{ - COMPXDP; - - ieee754_clearcx(); - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754dp_nanxcpt(x, "logb", x); - case IEEE754_CLASS_QNAN: - return x; - case IEEE754_CLASS_INF: - return ieee754dp_inf(0); - case IEEE754_CLASS_ZERO: - return ieee754dp_inf(1); - case IEEE754_CLASS_DNORM: - DPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - return ieee754dp_fint(xe); -} diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c deleted file mode 100644 index d83ec44..0000000 --- a/arch/mips/math-emu/dp_modf.c +++ /dev/null @@ -1,79 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -/* modf function is always exact for a finite number -*/ -union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp *ip) -{ - COMPXDP; - - ieee754_clearcx(); - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *ip = x; - return x; - case IEEE754_CLASS_DNORM: - /* far to small */ - *ip = ieee754dp_zero(xs); - return x; - case IEEE754_CLASS_NORM: - break; - } - if (xe < 0) { - *ip = ieee754dp_zero(xs); - return x; - } - if (xe >= DP_FBITS) { - *ip = x; - return ieee754dp_zero(xs); - } - /* generate ipart mantissa by clearing bottom bits - */ - *ip = builddp(xs, xe + DP_EBIAS, - ((xm >> (DP_FBITS - xe)) << (DP_FBITS - xe)) & - ~DP_HIDDEN_BIT); - - /* generate fpart mantissa by clearing top bits - * and normalizing (must be able to normalize) - */ - xm = (xm << (64 - (DP_FBITS - xe))) >> (64 - (DP_FBITS - xe)); - if (xm == 0) - return ieee754dp_zero(xs); - - while ((xm >> DP_FBITS) == 0) { - xm <<= 1; - xe--; - } - return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c deleted file mode 100644 index dee3755..0000000 --- a/arch/mips/math-emu/dp_scalb.c +++ /dev/null @@ -1,57 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -union ieee754dp ieee754dp_scalb(union ieee754dp x, int n) -{ - COMPXDP; - - ieee754_clearcx(); - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754dp_nanxcpt(x, "scalb", x, n); - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - return x; - case IEEE754_CLASS_DNORM: - DPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); -} - - -union ieee754dp ieee754dp_ldexp(union ieee754dp x, int n) -{ - return ieee754dp_scalb(x, n); -} diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index cae11b0..fddeb33 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -26,14 +26,6 @@ #include "ieee754dp.h" -union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y) -{ - ieee754_clearcx(); - DPSIGN(x) = DPSIGN(y); - return x; -} - - union ieee754dp ieee754dp_neg(union ieee754dp x) { COMPXDP; diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 8c39a40..1270009 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -106,16 +106,3 @@ int ieee754dp_tint(union ieee754dp x) else return xm; } - - -unsigned int ieee754dp_tuns(union ieee754dp x) -{ - union ieee754dp hb = ieee754dp_1e31(); - - /* what if x < 0 ?? */ - if (ieee754dp_lt(x, hb)) - return (unsigned) ieee754dp_tint(x); - - return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) | - ((unsigned) 1 << 31); -} diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index 2653b6e..b9a43a2 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -110,16 +110,3 @@ s64 ieee754dp_tlong(union ieee754dp x) else return xm; } - - -u64 ieee754dp_tulong(union ieee754dp x) -{ - union ieee754dp hb = ieee754dp_1e63(); - - /* what if x < 0 ?? */ - if (ieee754dp_lt(x, hb)) - return (u64) ieee754dp_tlong(x); - - return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) | - (1ULL << 63); -} diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 7466230..a62aa5a 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -72,11 +72,6 @@ int ieee754sp_class(union ieee754sp x); union ieee754sp ieee754sp_abs(union ieee754sp x); union ieee754sp ieee754sp_neg(union ieee754sp x); -union ieee754sp ieee754sp_scalb(union ieee754sp x, int); -union ieee754sp ieee754sp_logb(union ieee754sp x); - -/* x with sign of y */ -union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y); union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y); union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y); @@ -84,27 +79,13 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y); union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y); union ieee754sp ieee754sp_fint(int x); -union ieee754sp ieee754sp_funs(unsigned x); union ieee754sp ieee754sp_flong(s64 x); -union ieee754sp ieee754sp_fulong(u64 x); union ieee754sp ieee754sp_fdp(union ieee754dp x); int ieee754sp_tint(union ieee754sp x); -unsigned int ieee754sp_tuns(union ieee754sp x); s64 ieee754sp_tlong(union ieee754sp x); -u64 ieee754sp_tulong(union ieee754sp x); int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cop, int sig); -/* - * basic sp math - */ -union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp * ip); -union ieee754sp ieee754sp_frexp(union ieee754sp x, int *exp); -union ieee754sp ieee754sp_ldexp(union ieee754sp x, int exp); - -union ieee754sp ieee754sp_ceil(union ieee754sp x); -union ieee754sp ieee754sp_floor(union ieee754sp x); -union ieee754sp ieee754sp_trunc(union ieee754sp x); union ieee754sp ieee754sp_sqrt(union ieee754sp x); @@ -113,9 +94,6 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x); */ int ieee754dp_class(union ieee754dp x); -/* x with sign of y */ -union ieee754dp ieee754dp_copysign(union ieee754dp x, union ieee754dp y); - union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y); union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y); union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y); @@ -123,38 +101,15 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y); union ieee754dp ieee754dp_abs(union ieee754dp x); union ieee754dp ieee754dp_neg(union ieee754dp x); -union ieee754dp ieee754dp_scalb(union ieee754dp x, int); - -/* return exponent as integer in floating point format - */ -union ieee754dp ieee754dp_logb(union ieee754dp x); union ieee754dp ieee754dp_fint(int x); -union ieee754dp ieee754dp_funs(unsigned x); union ieee754dp ieee754dp_flong(s64 x); -union ieee754dp ieee754dp_fulong(u64 x); union ieee754dp ieee754dp_fsp(union ieee754sp x); -union ieee754dp ieee754dp_ceil(union ieee754dp x); -union ieee754dp ieee754dp_floor(union ieee754dp x); -union ieee754dp ieee754dp_trunc(union ieee754dp x); - int ieee754dp_tint(union ieee754dp x); -unsigned int ieee754dp_tuns(union ieee754dp x); s64 ieee754dp_tlong(union ieee754dp x); -u64 ieee754dp_tulong(union ieee754dp x); int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cop, int sig); -/* - * basic sp math - */ -union ieee754dp ieee754dp_modf(union ieee754dp x, union ieee754dp * ip); -union ieee754dp ieee754dp_frexp(union ieee754dp x, int *exp); -union ieee754dp ieee754dp_ldexp(union ieee754dp x, int exp); - -union ieee754dp ieee754dp_ceil(union ieee754dp x); -union ieee754dp ieee754dp_floor(union ieee754dp x); -union ieee754dp ieee754dp_trunc(union ieee754dp x); union ieee754dp ieee754dp_sqrt(union ieee754dp x); @@ -261,14 +216,6 @@ static inline int ieee754dp_ge(union ieee754dp x, union ieee754dp y) return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); } - -/* - * Like strtod - */ -union ieee754dp ieee754dp_fstr(const char *s, char **endp); -char *ieee754dp_tstr(union ieee754dp x, int prec, int fmt, int af); - - /* * The control status register */ diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c deleted file mode 100644 index 0622406..0000000 --- a/arch/mips/math-emu/ieee754m.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * floor, trunc, ceil - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754.h" - -union ieee754dp ieee754dp_floor(union ieee754dp x) -{ - union ieee754dp i; - - if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) - return ieee754dp_sub(i, ieee754dp_one(0)); - else - return i; -} - -union ieee754dp ieee754dp_ceil(union ieee754dp x) -{ - union ieee754dp i; - - if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) - return ieee754dp_add(i, ieee754dp_one(0)); - else - return i; -} - -union ieee754dp ieee754dp_trunc(union ieee754dp x) -{ - union ieee754dp i; - - (void) ieee754dp_modf(x, &i); - return i; -} diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 9574d25..0d01200 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -68,12 +68,3 @@ union ieee754sp ieee754sp_fint(int x) } SPNORMRET1(xs, xe, xm, "fint", x); } - - -union ieee754sp ieee754sp_funs(unsigned int u) -{ - if ((int) u < 0) - return ieee754sp_add(ieee754sp_1e31(), - ieee754sp_fint(u & ~(1 << 31))); - return ieee754sp_fint(u); -} diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index 65c7e7e..b26c155 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -67,12 +67,3 @@ union ieee754sp ieee754sp_flong(s64 x) } SPNORMRET1(xs, xe, xm, "sp_flong", x); } - - -union ieee754sp ieee754sp_fulong(u64 u) -{ - if ((s64) u < 0) - return ieee754sp_add(ieee754sp_1e63(), - ieee754sp_flong(u & ~(1ULL << 63))); - return ieee754sp_flong(u); -} diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c deleted file mode 100644 index 72cedb0..0000000 --- a/arch/mips/math-emu/sp_frexp.c +++ /dev/null @@ -1,52 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -/* close to ieeep754sp_logb -*/ -union ieee754sp ieee754sp_frexp(union ieee754sp x, int *eptr) -{ - COMPXSP; - ieee754_clearcx(); - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *eptr = 0; - return x; - case IEEE754_CLASS_DNORM: - SPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - *eptr = xe + 1; - return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c deleted file mode 100644 index 82c122c..0000000 --- a/arch/mips/math-emu/sp_logb.c +++ /dev/null @@ -1,53 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -union ieee754sp ieee754sp_logb(union ieee754sp x) -{ - COMPXSP; - - ieee754_clearcx(); - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754sp_nanxcpt(x, "logb", x); - case IEEE754_CLASS_QNAN: - return x; - case IEEE754_CLASS_INF: - return ieee754sp_inf(0); - case IEEE754_CLASS_ZERO: - return ieee754sp_inf(1); - case IEEE754_CLASS_DNORM: - SPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - return ieee754sp_fint(xe); -} diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c deleted file mode 100644 index 5f361a7..0000000 --- a/arch/mips/math-emu/sp_modf.c +++ /dev/null @@ -1,79 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -/* modf function is always exact for a finite number -*/ -union ieee754sp ieee754sp_modf(union ieee754sp x, union ieee754sp *ip) -{ - COMPXSP; - - ieee754_clearcx(); - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *ip = x; - return x; - case IEEE754_CLASS_DNORM: - /* far to small */ - *ip = ieee754sp_zero(xs); - return x; - case IEEE754_CLASS_NORM: - break; - } - if (xe < 0) { - *ip = ieee754sp_zero(xs); - return x; - } - if (xe >= SP_FBITS) { - *ip = x; - return ieee754sp_zero(xs); - } - /* generate ipart mantissa by clearing bottom bits - */ - *ip = buildsp(xs, xe + SP_EBIAS, - ((xm >> (SP_FBITS - xe)) << (SP_FBITS - xe)) & - ~SP_HIDDEN_BIT); - - /* generate fpart mantissa by clearing top bits - * and normalizing (must be able to normalize) - */ - xm = (xm << (32 - (SP_FBITS - xe))) >> (32 - (SP_FBITS - xe)); - if (xm == 0) - return ieee754sp_zero(xs); - - while ((xm >> SP_FBITS) == 0) { - xm <<= 1; - xe--; - } - return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); -} diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c deleted file mode 100644 index cc8f1b8..0000000 --- a/arch/mips/math-emu/sp_scalb.c +++ /dev/null @@ -1,57 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -union ieee754sp ieee754sp_scalb(union ieee754sp x, int n) -{ - COMPXSP; - - ieee754_clearcx(); - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754sp_nanxcpt(x, "scalb", x, n); - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - return x; - case IEEE754_CLASS_DNORM: - SPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); -} - - -union ieee754sp ieee754sp_ldexp(union ieee754sp x, int n) -{ - return ieee754sp_scalb(x, n); -} diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index b63e9fb..0f5fd57 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -26,14 +26,6 @@ #include "ieee754sp.h" -union ieee754sp ieee754sp_copysign(union ieee754sp x, union ieee754sp y) -{ - ieee754_clearcx(); - SPSIGN(x) = SPSIGN(y); - return x; -} - - union ieee754sp ieee754sp_neg(union ieee754sp x) { COMPXSP; diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 709f6bc..690cb5b 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -110,16 +110,3 @@ int ieee754sp_tint(union ieee754sp x) else return xm; } - - -unsigned int ieee754sp_tuns(union ieee754sp x) -{ - union ieee754sp hb = ieee754sp_1e31(); - - /* what if x < 0 ?? */ - if (ieee754sp_lt(x, hb)) - return (unsigned) ieee754sp_tint(x); - - return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) | - ((unsigned) 1 << 31); -} diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index e979aa7..346cbad 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -107,16 +107,3 @@ s64 ieee754sp_tlong(union ieee754sp x) else return xm; } - - -u64 ieee754sp_tulong(union ieee754sp x) -{ - union ieee754sp hb = ieee754sp_1e63(); - - /* what if x < 0 ?? */ - if (ieee754sp_lt(x, hb)) - return (u64) ieee754sp_tlong(x); - - return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) | - (1ULL << 63); -} -- cgit v0.10.2 From f71baa1168ec3440f51e616c107a6615f5d752f8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Apr 2014 00:40:42 +0200 Subject: MIPS: math-emu: Inline ieee754sp_issnan and ieee754dp_issnan. Shaves another 16 bytes off but more importantly avoids function calls. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 50b1fbf..d9ceb6b 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -40,7 +40,7 @@ int ieee754dp_isnan(union ieee754dp x) return ieee754dp_class(x) >= IEEE754_CLASS_SNAN; } -int ieee754dp_issnan(union ieee754dp x) +static inline int ieee754dp_issnan(union ieee754dp x) { assert(ieee754dp_isnan(x)); return ((DPMANT(x) & DP_MBIT(DP_FBITS-1)) == DP_MBIT(DP_FBITS-1)); diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 830a0d5..179d249 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -81,7 +81,6 @@ static inline union ieee754dp builddp(int s, int bx, u64 m) } extern int ieee754dp_isnan(union ieee754dp); -extern int ieee754dp_issnan(union ieee754dp); extern int __cold ieee754si_xcpt(int, const char *, ...); extern s64 __cold ieee754di_xcpt(s64, const char *, ...); extern union ieee754dp __cold ieee754dp_xcpt(union ieee754dp, const char *, ...); diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 495295c..a90837a 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -40,7 +40,7 @@ int ieee754sp_isnan(union ieee754sp x) return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; } -int ieee754sp_issnan(union ieee754sp x) +static inline int ieee754sp_issnan(union ieee754sp x) { assert(ieee754sp_isnan(x)); return (SPMANT(x) & SP_MBIT(SP_FBITS-1)); diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 9511205..0b44569 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -87,7 +87,6 @@ static inline union ieee754sp buildsp(int s, int bx, unsigned m) } extern int ieee754sp_isnan(union ieee754sp); -extern int ieee754sp_issnan(union ieee754sp); extern int __cold ieee754si_xcpt(int, const char *, ...); extern s64 __cold ieee754di_xcpt(s64, const char *, ...); extern union ieee754sp __cold ieee754sp_xcpt(union ieee754sp, const char *, ...); -- cgit v0.10.2 From 593d33fe334761853890f2f84ed41e7c24051de2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Apr 2014 01:52:46 +0200 Subject: MIPS: math-emu: Move various objects into an ar library. ieee754d.o contains only debug code and dp_sqrt.o and sp_sqrt.o contain code which for MIPS I/II/III systems we don't want to link. Again the savings can be considerable for some systems: $ mips-linux-size --totals ieee754d.o dp_sqrt.o sp_sqrt.o text data bss dec hex filename 1624 0 0 1624 658 ieee754d.o 2016 0 0 2016 7e0 dp_sqrt.o 736 0 0 736 2e0 sp_sqrt.o 4376 0 0 4376 1118 (TOTALS) Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index d2cfe45..cc39966 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild @@ -16,7 +16,6 @@ obj- := $(platform-) obj-y += kernel/ obj-y += mm/ -obj-y += math-emu/ ifdef CONFIG_KVM obj-y += kvm/ diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 1a5b403..4852ae9 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -251,6 +251,7 @@ OBJCOPYFLAGS += --remove-section=.reginfo head-y := arch/mips/kernel/head.o libs-y += arch/mips/lib/ +libs-y += arch/mips/math-emu/ # See arch/mips/Kbuild for content of core part of the kernel core-y += arch/mips/ diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 363ce9b..016736e 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -2,11 +2,12 @@ # Makefile for the Linux/MIPS kernel FPU emulation. # -obj-y := cp1emu.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ - ieee754xcpt.o dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o \ - dp_cmp.o dp_simple.o dp_tint.o dp_fint.o dp_tlong.o dp_flong.o \ - sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \ - sp_tint.o sp_fint.o sp_tlong.o sp_flong.o dp_sqrt.o sp_sqrt.o \ - kernel_linkage.o dsemul.o +obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o ieee754xcpt.o dp_div.o \ + dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \ + dp_fint.o dp_tlong.o dp_flong.o sp_div.o sp_mul.o sp_sub.o \ + sp_add.o sp_fdp.o sp_cmp.o sp_simple.o sp_tint.o sp_fint.o \ + sp_tlong.o sp_flong.o kernel_linkage.o dsemul.o + +lib-y += ieee754d.o dp_sqrt.o sp_sqrt.o obj-$(CONFIG_DEBUG_FS) += me-debugfs.o -- cgit v0.10.2 From 90efba36ed50933c6df92805bd7e5742e9cc0f46 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Apr 2014 03:19:57 +0200 Subject: MIPS: math-emu: Get rid of the useless parts of exception handling. All it really did was throw a printk for no obvious reason. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 016736e..383cc78 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -2,8 +2,8 @@ # Makefile for the Linux/MIPS kernel FPU emulation. # -obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o ieee754xcpt.o dp_div.o \ - dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \ +obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o dp_div.o dp_mul.o \ + dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \ dp_fint.o dp_tlong.o dp_flong.o sp_div.o sp_mul.o sp_sub.o \ sp_add.o sp_fdp.o sp_cmp.o sp_simple.o sp_tint.o sp_fint.o \ sp_tlong.o sp_flong.o kernel_linkage.o dsemul.o diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index f1c8e70..48b9ef6 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -53,7 +53,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y); + return ieee754dp_nanxcpt(ieee754dp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -76,7 +76,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) if (xs == ys) return x; ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y); + return ieee754dp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -178,5 +178,6 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) } } - DPNORMRET2(xs, xe, xm, "add", x, y); + + return ieee754dp_format(xs, xe, xm); } diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c index 2d9390e..fe573cb 100644 --- a/arch/mips/math-emu/dp_cmp.c +++ b/arch/mips/math-emu/dp_cmp.c @@ -44,7 +44,7 @@ int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig) return 1; if (cmp & (IEEE754_CLT | IEEE754_CGT)) { if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) - return ieee754di_xcpt(0, "fcmpf", x); + return 0; } return 0; } else { diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c index 13ecffa..377e114 100644 --- a/arch/mips/math-emu/dp_div.c +++ b/arch/mips/math-emu/dp_div.c @@ -52,7 +52,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y); + return ieee754dp_nanxcpt(ieee754dp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -73,7 +73,7 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); + return ieee754dp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -90,12 +90,12 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); + return ieee754dp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): ieee754_setcx(IEEE754_ZERO_DIVIDE); - return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y); + return ieee754dp_inf(xs ^ ys); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): @@ -151,6 +151,6 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) re--; } - DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); + return ieee754dp_format(xs == ys ? 0 : 1, re, rm); } } diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index fb5eeaa..54c8f00 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -65,5 +65,6 @@ union ieee754dp ieee754dp_flong(s64 x) xe--; } } - DPNORMRET1(xs, xe, xm, "dp_flong", x); + + return ieee754dp_format(xs, xe, xm); } diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index 67ee97f..ba600be 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -40,14 +40,13 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) switch (xc) { case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp"); + return ieee754dp_nanxcpt(ieee754dp_indef()); case IEEE754_CLASS_QNAN: return ieee754dp_nanxcpt(builddp(xs, DP_EMAX + 1 + DP_EBIAS, ((u64) xm << (DP_FBITS - - SP_FBITS))), "fsp", - x); + SP_FBITS)))); case IEEE754_CLASS_INF: return ieee754dp_inf(xs); case IEEE754_CLASS_ZERO: diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index 56fb309..74bc810 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -52,7 +52,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y); + return ieee754dp_nanxcpt(ieee754dp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -73,7 +73,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y); + return ieee754dp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -171,6 +171,7 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) ((rm << (DP_FBITS + 1 + 3 + 1)) != 0); } assert(rm & (DP_HIDDEN_BIT << 3)); - DPNORMRET2(rs, re, rm, "mul", x, y); + + return ieee754dp_format(rs, re, rm); } } diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index fddeb33..4eda759 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -45,7 +45,7 @@ union ieee754dp ieee754dp_neg(union ieee754dp x) union ieee754dp y = ieee754dp_indef(); ieee754_setcx(IEEE754_INVALID_OPERATION); DPSIGN(y) = DPSIGN(x); - return ieee754dp_nanxcpt(y, "neg"); + return ieee754dp_nanxcpt(y); } return x; @@ -65,7 +65,7 @@ union ieee754dp ieee754dp_abs(union ieee754dp x) if (xc == IEEE754_CLASS_SNAN) { ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "abs"); + return ieee754dp_nanxcpt(ieee754dp_indef()); } return x; diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index 1e0fbbf..3c36a86 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -49,10 +49,10 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) switch (xc) { case IEEE754_CLASS_QNAN: /* sqrt(Nan) = Nan */ - return ieee754dp_nanxcpt(x, "sqrt"); + return ieee754dp_nanxcpt(x); case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); + return ieee754dp_nanxcpt(ieee754dp_indef()); case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ return x; @@ -60,7 +60,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) if (xs) { /* sqrt(-Inf) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); + return ieee754dp_nanxcpt(ieee754dp_indef()); } /* sqrt(+Inf) = Inf */ return x; @@ -71,7 +71,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) if (xs) { /* sqrt(-x) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); + return ieee754dp_nanxcpt(ieee754dp_indef()); } break; } diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index 25d25bc..3dd62c1 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -52,7 +52,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y); + return ieee754dp_nanxcpt(ieee754dp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -75,7 +75,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) if (xs != ys) return x; ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y); + return ieee754dp_indef(); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -186,5 +186,6 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) xe--; } } - DPNORMRET2(xs, xe, xm, "sub", x, y); + + return ieee754dp_format(xs, xe, xm); } diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 1270009..3a23c64 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -40,7 +40,7 @@ int ieee754dp_tint(union ieee754dp x) case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); + return ieee754si_indef(); case IEEE754_CLASS_ZERO: return 0; case IEEE754_CLASS_DNORM: @@ -51,7 +51,7 @@ int ieee754dp_tint(union ieee754dp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); + return ieee754si_indef(); } /* oh gawd */ if (xe > DP_FBITS) { @@ -96,7 +96,7 @@ int ieee754dp_tint(union ieee754dp x) if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); + return ieee754si_indef(); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT); diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index b9a43a2..cbeef60 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -40,7 +40,7 @@ s64 ieee754dp_tlong(union ieee754dp x) case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); + return ieee754di_indef(); case IEEE754_CLASS_ZERO: return 0; case IEEE754_CLASS_DNORM: @@ -54,7 +54,7 @@ s64 ieee754dp_tlong(union ieee754dp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); + return ieee754di_indef(); } /* oh gawd */ if (xe > DP_FBITS) { @@ -100,7 +100,7 @@ s64 ieee754dp_tlong(union ieee754dp x) if ((xm >> 63) != 0) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); + return ieee754di_indef(); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT); diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index f3b5fa0..ab53f84 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -28,7 +28,6 @@ * ######################################################################## */ -#include #include #include "ieee754int.h" @@ -38,15 +37,13 @@ /* special constants */ -#ifdef __MIPSEB__ -#define SPSTR(s, b, m) {s, b, m} -#define DPSTR(s, b, mh, ml) {s, b, mh, ml} -#elif defined(__MIPSEL__) -#define SPSTR(s, b, m) {m, b, s} -#define DPSTR(s, b, mh, ml) {ml, mh, b, s} -#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */ -#error "MIPS but neither __MIPSEB__ nor __MIPSEL__?" -#endif +#define DPSTR(s, b, mh, ml) \ +{ \ + .sign = (s), \ + .bexp = (b), \ + .manthi = (mh), \ + .mantlo = (ml) \ +} const struct ieee754dp_const __ieee754dp_spcvals[] = { DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */ @@ -68,6 +65,13 @@ const struct ieee754dp_const __ieee754dp_spcvals[] = { DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */ }; +#define SPSTR(s, b, m) \ +{ \ + .sign = (s), \ + .bexp = (b), \ + .mant = (m) \ +} + const struct ieee754sp_const __ieee754sp_spcvals[] = { SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */ @@ -87,34 +91,3 @@ const struct ieee754sp_const __ieee754sp_spcvals[] = { SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */ SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */ }; - - -int __cold ieee754si_xcpt(int r, const char *op, ...) -{ - struct ieee754xctx ax; - - if (!ieee754_tstx()) - return r; - ax.op = op; - ax.rt = IEEE754_RT_SI; - ax.rv.si = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - va_end(ax.ap); - return ax.rv.si; -} - -s64 __cold ieee754di_xcpt(s64 r, const char *op, ...) -{ - struct ieee754xctx ax; - - if (!ieee754_tstx()) - return r; - ax.op = op; - ax.rt = IEEE754_RT_DI; - ax.rv.di = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - va_end(ax.ap); - return ax.rv.di; -} diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index a62aa5a..e87a636 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -24,7 +24,6 @@ #ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H #define __ARCH_MIPS_MATH_EMU_IEEE754_H -#include #include #include #include @@ -343,19 +342,6 @@ static inline s64 ieee754di_indef(void) return S64_MAX; } -/* IEEE exception context, passed to handler */ -struct ieee754xctx { - const char *op; /* operation name */ - int rt; /* result type */ - union { - union ieee754sp sp; /* single precision */ - union ieee754dp dp; /* double precision */ - int si; /* standard signed integer (32bits) */ - s64 di; /* extended signed integer (64bits) */ - } rv; /* default result format implied by op */ - va_list ap; -}; - /* result types for xctx.rt */ #define IEEE754_RT_SP 0 #define IEEE754_RT_DP 1 @@ -363,8 +349,6 @@ struct ieee754xctx { #define IEEE754_RT_SI 3 #define IEEE754_RT_DI 4 -extern void __cold ieee754_xcpt(struct ieee754xctx *xcp); - /* compat */ #define ieee754dp_fix(x) ieee754dp_tint(x) #define ieee754sp_fix(x) ieee754sp_tint(x) diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index d9ceb6b..39c01885 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -23,7 +23,6 @@ * ######################################################################## */ -#include #include #include "ieee754dp.h" @@ -47,25 +46,8 @@ static inline int ieee754dp_issnan(union ieee754dp x) } -union ieee754dp __cold ieee754dp_xcpt(union ieee754dp r, const char *op, ...) +union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r) { - struct ieee754xctx ax; - if (!ieee754_tstx()) - return r; - - ax.op = op; - ax.rt = IEEE754_RT_DP; - ax.rv.dp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - va_end(ax.ap); - return ax.rv.dp; -} - -union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r, const char *op, ...) -{ - struct ieee754xctx ax; - assert(ieee754dp_isnan(r)); if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ @@ -80,13 +62,7 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r, const char *op, ...) return ieee754dp_indef(); } - ax.op = op; - ax.rt = 0; - ax.rv.dp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - va_end(ax.ap); - return ax.rv.dp; + return r; } static u64 get_rounding(int sn, u64 xm) diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 179d249..91d785e 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -81,20 +81,5 @@ static inline union ieee754dp builddp(int s, int bx, u64 m) } extern int ieee754dp_isnan(union ieee754dp); -extern int __cold ieee754si_xcpt(int, const char *, ...); -extern s64 __cold ieee754di_xcpt(s64, const char *, ...); -extern union ieee754dp __cold ieee754dp_xcpt(union ieee754dp, const char *, ...); -extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp, const char *, ...); +extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp); extern union ieee754dp ieee754dp_format(int, int, u64); - - -#define DPNORMRET2(s, e, m, name, a0, a1) \ -{ \ - union ieee754dp V = ieee754dp_format(s, e, m); \ - if (ieee754_tstx()) \ - return ieee754dp_xcpt(V, name, a0, a1); \ - else \ - return V; \ -} - -#define DPNORMRET1(s, e, m, name, a0) DPNORMRET2(s, e, m, name, a0, a0) diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 4621a3d..58b9087 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -48,11 +48,6 @@ static inline int ieee754_setandtestcx(const unsigned int x) return ieee754_csr.mx & x; } -static inline int ieee754_tstx(void) -{ - return ieee754_csr.cx & ieee754_csr.mx; -} - #define COMPXSP \ unsigned xm; int xe; int xs __maybe_unused; int xc diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index a90837a..1941c12 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -23,7 +23,6 @@ * ######################################################################## */ -#include #include #include "ieee754sp.h" @@ -47,26 +46,8 @@ static inline int ieee754sp_issnan(union ieee754sp x) } -union ieee754sp __cold ieee754sp_xcpt(union ieee754sp r, const char *op, ...) +union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r) { - struct ieee754xctx ax; - - if (!ieee754_tstx()) - return r; - - ax.op = op; - ax.rt = IEEE754_RT_SP; - ax.rv.sp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - va_end(ax.ap); - return ax.rv.sp; -} - -union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r, const char *op, ...) -{ - struct ieee754xctx ax; - assert(ieee754sp_isnan(r)); if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ @@ -81,13 +62,7 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r, const char *op, ...) return ieee754sp_indef(); } - ax.op = op; - ax.rt = 0; - ax.rv.sp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - va_end(ax.ap); - return ax.rv.sp; + return r; } static unsigned get_rounding(int sn, unsigned xm) diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 0b44569..e5295d7 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -87,21 +87,5 @@ static inline union ieee754sp buildsp(int s, int bx, unsigned m) } extern int ieee754sp_isnan(union ieee754sp); -extern int __cold ieee754si_xcpt(int, const char *, ...); -extern s64 __cold ieee754di_xcpt(s64, const char *, ...); -extern union ieee754sp __cold ieee754sp_xcpt(union ieee754sp, const char *, ...); -extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp, const char *, ...); +extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp); extern union ieee754sp ieee754sp_format(int, int, unsigned); - - -#define SPNORMRET2(s, e, m, name, a0, a1) \ -{ \ - union ieee754sp V = ieee754sp_format(s, e, m); \ - \ - if (ieee754_tstx()) \ - return ieee754sp_xcpt(V, name, a0, a1); \ - else \ - return V; \ -} - -#define SPNORMRET1(s, e, m, name, a0) SPNORMRET2(s, e, m, name, a0, a0) diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c deleted file mode 100644 index d68408a..0000000 --- a/arch/mips/math-emu/ieee754xcpt.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - -/************************************************************************** - * Nov 7, 2000 - * Added preprocessor hacks to map to Linux kernel diagnostics. - * - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ - -#include -#include -#include "ieee754.h" - -/* - * Very naff exception handler (you can plug in your own and - * override this). - */ - -static const char *const rtnames[] = { - "sp", "dp", "xp", "si", "di" -}; - -void __cold ieee754_xcpt(struct ieee754xctx *xcp) -{ - printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n", - xcp->op, rtnames[xcp->rt]); -} diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index d107bce..db4d89b 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -52,7 +52,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y); + return ieee754sp_nanxcpt(ieee754sp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -75,7 +75,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) if (xs == ys) return x; ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y); + return ieee754sp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -172,5 +172,6 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) } } - SPNORMRET2(xs, xe, xm, "add", x, y); + + return ieee754sp_format(xs, xe, xm); } diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c index adf3076..fab4988 100644 --- a/arch/mips/math-emu/sp_cmp.c +++ b/arch/mips/math-emu/sp_cmp.c @@ -44,7 +44,7 @@ int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig) return 1; if (cmp & (IEEE754_CLT | IEEE754_CGT)) { if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) - return ieee754si_xcpt(0, "fcmpf", x); + return 0; } return 0; } else { diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c index 095fb20..0d847a4 100644 --- a/arch/mips/math-emu/sp_div.c +++ b/arch/mips/math-emu/sp_div.c @@ -52,7 +52,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y); + return ieee754sp_nanxcpt(ieee754sp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -73,7 +73,7 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); + return ieee754sp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): @@ -90,12 +90,12 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); + return ieee754sp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): ieee754_setcx(IEEE754_ZERO_DIVIDE); - return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y); + return ieee754sp_inf(xs ^ ys); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): @@ -151,6 +151,6 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) re--; } - SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); + return ieee754sp_format(xs == ys ? 0 : 1, re, rm); } } diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index ccbed8a..5c1d8aa 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -41,13 +41,13 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) switch (xc) { case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp"); + return ieee754sp_nanxcpt(ieee754sp_indef()); case IEEE754_CLASS_QNAN: nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) (xm >> (DP_FBITS - SP_FBITS))); if (!ieee754sp_isnan(nan)) nan = ieee754sp_indef(); - return ieee754sp_nanxcpt(nan, "fdp", x); + return ieee754sp_nanxcpt(nan); case IEEE754_CLASS_INF: return ieee754sp_inf(xs); case IEEE754_CLASS_ZERO: @@ -58,8 +58,8 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) ieee754_setcx(IEEE754_INEXACT); if ((ieee754_csr.rm == IEEE754_RU && !xs) || (ieee754_csr.rm == IEEE754_RD && xs)) - return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x); - return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x); + return ieee754sp_mind(xs); + return ieee754sp_zero(xs); case IEEE754_CLASS_NORM: break; } @@ -72,6 +72,6 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) rm = (xm >> (DP_FBITS - (SP_FBITS + 3))) | ((xm << (64 - (DP_FBITS - (SP_FBITS + 3)))) != 0); - SPNORMRET1(xs, xe, rm, "fdp", x); + return ieee754sp_format(xs, xe, rm); } } diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 0d01200..8e8687b 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -66,5 +66,5 @@ union ieee754sp ieee754sp_fint(int x) xe--; } } - SPNORMRET1(xs, xe, xm, "fint", x); + return ieee754sp_format(xs, xe, xm); } diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index b26c155..e56e8760 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -65,5 +65,5 @@ union ieee754sp ieee754sp_flong(s64 x) xe--; } } - SPNORMRET1(xs, xe, xm, "sp_flong", x); + return ieee754sp_format(xs, xe, xm); } diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index 28f608f..0e19d0e 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -52,7 +52,7 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y); + return ieee754sp_nanxcpt(ieee754sp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -73,7 +73,7 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y); + return ieee754sp_indef(); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -165,6 +165,6 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) } assert(rm & (SP_HIDDEN_BIT << 3)); - SPNORMRET2(rs, re, rm, "mul", x, y); + return ieee754sp_format(rs, re, rm); } } diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index 0f5fd57..8f0202d 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -45,7 +45,7 @@ union ieee754sp ieee754sp_neg(union ieee754sp x) union ieee754sp y = ieee754sp_indef(); ieee754_setcx(IEEE754_INVALID_OPERATION); SPSIGN(y) = SPSIGN(x); - return ieee754sp_nanxcpt(y, "neg"); + return ieee754sp_nanxcpt(y); } return x; @@ -65,7 +65,7 @@ union ieee754sp ieee754sp_abs(union ieee754sp x) if (xc == IEEE754_CLASS_SNAN) { ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); + return ieee754sp_nanxcpt(ieee754sp_indef()); } return x; diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index 7e87f46..f4da2cc 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -42,10 +42,10 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) switch (xc) { case IEEE754_CLASS_QNAN: /* sqrt(Nan) = Nan */ - return ieee754sp_nanxcpt(x, "sqrt"); + return ieee754sp_nanxcpt(x); case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); + return ieee754sp_nanxcpt(ieee754sp_indef()); case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ return x; @@ -53,7 +53,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) if (xs) { /* sqrt(-Inf) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); + return ieee754sp_nanxcpt(ieee754sp_indef()); } /* sqrt(+Inf) = Inf */ return x; @@ -62,7 +62,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) if (xs) { /* sqrt(-x) = Nan */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); + return ieee754sp_nanxcpt(ieee754sp_indef()); } break; } diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index 828de93..67a1f9e 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -52,7 +52,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y); + return ieee754sp_nanxcpt(ieee754sp_indef()); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -75,7 +75,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) if (xs != ys) return x; ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y); + return ieee754sp_indef(); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): @@ -179,5 +179,6 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) xe--; } } - SPNORMRET2(xs, xe, xm, "sub", x, y); + + return ieee754sp_format(xs, xe, xm); } diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 690cb5b..53f04dc 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -40,7 +40,7 @@ int ieee754sp_tint(union ieee754sp x) case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); + return ieee754si_indef(); case IEEE754_CLASS_ZERO: return 0; case IEEE754_CLASS_DNORM: @@ -54,7 +54,7 @@ int ieee754sp_tint(union ieee754sp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); + return ieee754si_indef(); } /* oh gawd */ if (xe > SP_FBITS) { @@ -100,7 +100,7 @@ int ieee754sp_tint(union ieee754sp x) if ((xm >> 31) != 0) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); + return ieee754si_indef(); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT); diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index 346cbad..df11792 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -41,7 +41,7 @@ s64 ieee754sp_tlong(union ieee754sp x) case IEEE754_CLASS_QNAN: case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); + return ieee754di_indef(); case IEEE754_CLASS_ZERO: return 0; case IEEE754_CLASS_DNORM: @@ -55,7 +55,7 @@ s64 ieee754sp_tlong(union ieee754sp x) /* Set invalid. We will only use overflow for floating point overflow */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); + return ieee754di_indef(); } /* oh gawd */ if (xe > SP_FBITS) { @@ -97,7 +97,7 @@ s64 ieee754sp_tlong(union ieee754sp x) if ((xm >> 63) != 0) { /* This can happen after rounding */ ieee754_setcx(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); + return ieee754di_indef(); } if (round || sticky) ieee754_setcx(IEEE754_INEXACT); -- cgit v0.10.2 From de2fc342b8be474d0d0377b7771719e924c5549e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Apr 2014 10:54:06 +0200 Subject: MIPS: math-emu: Rename get_rounding() functions. There are two version of get_rounding(), one for single precision, one for double precision. Add a ieee754sp_ rsp. ieee754dp_ prefix for clarity. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 39c01885..3b123f5 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -65,7 +65,7 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r) return r; } -static u64 get_rounding(int sn, u64 xm) +static u64 ieee754dp_get_rounding(int sn, u64 xm) { /* inexact must round of 3 bits */ @@ -128,12 +128,12 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) } } - if (xe == DP_EMIN - 1 - && get_rounding(sn, xm) >> (DP_FBITS + 1 + 3)) + if (xe == DP_EMIN - 1 && + ieee754dp_get_rounding(sn, xm) >> (DP_FBITS + 1 + 3)) { /* Not tiny after rounding */ ieee754_setcx(IEEE754_INEXACT); - xm = get_rounding(sn, xm); + xm = ieee754dp_get_rounding(sn, xm); xm >>= 1; /* Clear grs bits */ xm &= ~(DP_MBIT(3) - 1); @@ -156,7 +156,7 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) /* inexact must round of 3 bits */ - xm = get_rounding(sn, xm); + xm = ieee754dp_get_rounding(sn, xm); /* adjust exponent for rounding add overflowing */ if (xm >> (DP_FBITS + 3 + 1)) { diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index 1941c12..d07bec3 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -65,7 +65,7 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r) return r; } -static unsigned get_rounding(int sn, unsigned xm) +static unsigned ieee754sp_get_rounding(int sn, unsigned xm) { /* inexact must round of 3 bits */ @@ -128,12 +128,12 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) } } - if (xe == SP_EMIN - 1 - && get_rounding(sn, xm) >> (SP_FBITS + 1 + 3)) + if (xe == SP_EMIN - 1 && + ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3)) { /* Not tiny after rounding */ ieee754_setcx(IEEE754_INEXACT); - xm = get_rounding(sn, xm); + xm = ieee754sp_get_rounding(sn, xm); xm >>= 1; /* Clear grs bits */ xm &= ~(SP_MBIT(3) - 1); @@ -154,7 +154,7 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) /* inexact must round of 3 bits */ - xm = get_rounding(sn, xm); + xm = ieee754sp_get_rounding(sn, xm); /* adjust exponent for rounding add overflowing */ if (xm >> (SP_FBITS + 1 + 3)) { -- cgit v0.10.2 From 49548b09e0fa9fddb64e3cd47266193e36b73144 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 25 Apr 2014 15:48:40 +0200 Subject: MIPS: math-emu: Cleanup definition of structs describe sp/dp floats. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index 3c36a86..8e88bde 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -110,13 +110,13 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */ /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */ z = t = ieee754dp_mul(y, y); - t.parts.bexp += 0x001; + t.bexp += 0x001; t = ieee754dp_add(t, z); z = ieee754dp_mul(ieee754dp_sub(x, z), y); /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */ t = ieee754dp_div(z, ieee754dp_add(t, x)); - t.parts.bexp += 0x001; + t.bexp += 0x001; y = ieee754dp_add(y, t); /* twiddle last bit to force y correctly rounded */ @@ -155,7 +155,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) } /* py[n0]=py[n0]+scalx; ...scale back y */ - y.parts.bexp += scalx; + y.bexp += scalx; /* restore rounding mode, possibly set inexact */ ieee754_csr = oldcsr; diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index ab53f84..670d19b 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -30,64 +30,63 @@ #include -#include "ieee754int.h" +#include "ieee754.h" #include "ieee754sp.h" #include "ieee754dp.h" /* special constants */ -#define DPSTR(s, b, mh, ml) \ +#define DPCNST(s, b, m) \ { \ .sign = (s), \ - .bexp = (b), \ - .manthi = (mh), \ - .mantlo = (ml) \ + .bexp = (b) + DP_EBIAS, \ + .mant = (m) \ } -const struct ieee754dp_const __ieee754dp_spcvals[] = { - DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */ - DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */ - DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */ - DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */ - DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */ - DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */ - DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */ - DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */ - DPSTR(0, DP_EMAX+1+DP_EBIAS, 0x7FFFF, 0xFFFFFFFF), /* + indef quiet Nan */ - DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */ - DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */ - DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */ - DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */ - DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */ - DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */ - DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */ - DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */ +const union ieee754dp __ieee754dp_spcvals[] = { + DPCNST(0, DP_EMIN - 1, 0x0000000000000ULL), /* + zero */ + DPCNST(1, DP_EMIN - 1, 0x0000000000000ULL), /* - zero */ + DPCNST(0, 0, 0x0000000000000ULL), /* + 1.0 */ + DPCNST(1, 0, 0x0000000000000ULL), /* - 1.0 */ + DPCNST(0, 3, 0x4000000000000ULL), /* + 10.0 */ + DPCNST(1, 3, 0x4000000000000ULL), /* - 10.0 */ + DPCNST(0, DP_EMAX + 1, 0x0000000000000ULL), /* + infinity */ + DPCNST(1, DP_EMAX + 1, 0x0000000000000ULL), /* - infinity */ + DPCNST(0, DP_EMAX + 1, 0x7FFFFFFFFFFFFULL), /* + indef quiet Nan */ + DPCNST(0, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* + max */ + DPCNST(1, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* - max */ + DPCNST(0, DP_EMIN, 0x0000000000000ULL), /* + min normal */ + DPCNST(1, DP_EMIN, 0x0000000000000ULL), /* - min normal */ + DPCNST(0, DP_EMIN - 1, 0x0000000000001ULL), /* + min denormal */ + DPCNST(1, DP_EMIN - 1, 0x0000000000001ULL), /* - min denormal */ + DPCNST(0, 31, 0x0000000000000ULL), /* + 1.0e31 */ + DPCNST(0, 63, 0x0000000000000ULL), /* + 1.0e63 */ }; -#define SPSTR(s, b, m) \ +#define SPCNST(s, b, m) \ { \ .sign = (s), \ - .bexp = (b), \ + .bexp = (b) + SP_EBIAS, \ .mant = (m) \ } -const struct ieee754sp_const __ieee754sp_spcvals[] = { - SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */ - SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */ - SPSTR(0, SP_EBIAS, 0), /* + 1.0 */ - SPSTR(1, SP_EBIAS, 0), /* - 1.0 */ - SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */ - SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */ - SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */ - SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */ - SPSTR(0, SP_EMAX+1+SP_EBIAS, 0x3FFFFF), /* + indef quiet Nan */ - SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */ - SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */ - SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */ - SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */ - SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */ - SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */ - SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */ - SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */ +const union ieee754sp __ieee754sp_spcvals[] = { + SPCNST(0, SP_EMIN - 1, 0x000000), /* + zero */ + SPCNST(1, SP_EMIN - 1, 0x000000), /* - zero */ + SPCNST(0, 0, 0x000000), /* + 1.0 */ + SPCNST(1, 0, 0x000000), /* - 1.0 */ + SPCNST(0, 3, 0x200000), /* + 10.0 */ + SPCNST(1, 3, 0x200000), /* - 10.0 */ + SPCNST(0, SP_EMAX + 1, 0x000000), /* + infinity */ + SPCNST(1, SP_EMAX + 1, 0x000000), /* - infinity */ + SPCNST(0, SP_EMAX + 1, 0x3FFFFF), /* + indef quiet Nan */ + SPCNST(0, SP_EMAX, 0x7FFFFF), /* + max normal */ + SPCNST(1, SP_EMAX, 0x7FFFFF), /* - max normal */ + SPCNST(0, SP_EMIN, 0x000000), /* + min normal */ + SPCNST(1, SP_EMIN, 0x000000), /* - min normal */ + SPCNST(0, SP_EMIN - 1, 0x000001), /* + min denormal */ + SPCNST(1, SP_EMIN - 1, 0x000001), /* - min denormal */ + SPCNST(0, 31, 0x000000), /* + 1.0e31 */ + SPCNST(0, 63, 0x000000), /* + 1.0e63 */ }; diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index e87a636..4f89f85 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -31,36 +31,23 @@ #include #include -struct ieee754dp_const { - __BITFIELD_FIELD(unsigned sign:1, - __BITFIELD_FIELD(unsigned bexp:11, - __BITFIELD_FIELD(unsigned manthi:20, - __BITFIELD_FIELD(unsigned mantlo:32, - ;)))) -}; - union ieee754dp { - struct ieee754dp_const oparts; struct { __BITFIELD_FIELD(unsigned int sign:1, __BITFIELD_FIELD(unsigned int bexp:11, __BITFIELD_FIELD(u64 mant:52, ;))) - } parts; - double d; + }; u64 bits; }; -struct ieee754sp_const { - __BITFIELD_FIELD(unsigned sign:1, - __BITFIELD_FIELD(unsigned bexp:8, - __BITFIELD_FIELD(unsigned mant:23, - ;))) -}; - union ieee754sp { - struct ieee754sp_const parts; - float f; + struct { + __BITFIELD_FIELD(unsigned sign:1, + __BITFIELD_FIELD(unsigned bexp:8, + __BITFIELD_FIELD(unsigned mant:23, + ;))) + }; u32 bits; }; @@ -299,8 +286,8 @@ union ieee754dp ieee754dp_dump(char *s, union ieee754dp x); #define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ #define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ -extern const struct ieee754dp_const __ieee754dp_spcvals[]; -extern const struct ieee754sp_const __ieee754sp_spcvals[]; +extern const union ieee754dp __ieee754dp_spcvals[]; +extern const union ieee754sp __ieee754sp_spcvals[]; #define ieee754dp_spcvals ((const union ieee754dp *)__ieee754dp_spcvals) #define ieee754sp_spcvals ((const union ieee754sp *)__ieee754sp_spcvals) diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 91d785e..231bd76 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -40,9 +40,9 @@ #define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) #define DP_SIGN_BIT DP_MBIT(63) -#define DPSIGN(dp) (dp.parts.sign) -#define DPBEXP(dp) (dp.parts.bexp) -#define DPMANT(dp) (dp.parts.mant) +#define DPSIGN(dp) (dp.sign) +#define DPBEXP(dp) (dp.bexp) +#define DPMANT(dp) (dp.mant) static inline int ieee754dp_finite(union ieee754dp x) { @@ -74,9 +74,10 @@ static inline union ieee754dp builddp(int s, int bx, u64 m) && (bx) <= DP_EMAX + 1 + DP_EBIAS); assert(((m) >> DP_FBITS) == 0); - r.parts.sign = s; - r.parts.bexp = bx; - r.parts.mant = m; + r.sign = s; + r.bexp = bx; + r.mant = m; + return r; } diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index e5295d7..35da62f 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -40,9 +40,9 @@ #define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) #define SP_SIGN_BIT SP_MBIT(31) -#define SPSIGN(sp) (sp.parts.sign) -#define SPBEXP(sp) (sp.parts.bexp) -#define SPMANT(sp) (sp.parts.mant) +#define SPSIGN(sp) (sp.sign) +#define SPBEXP(sp) (sp.bexp) +#define SPMANT(sp) (sp.mant) static inline int ieee754sp_finite(union ieee754sp x) { @@ -79,9 +79,9 @@ static inline union ieee754sp buildsp(int s, int bx, unsigned m) && (bx) <= SP_EMAX + 1 + SP_EBIAS); assert(((m) >> SP_FBITS) == 0); - r.parts.sign = s; - r.parts.bexp = bx; - r.parts.mant = m; + r.sign = s; + r.bexp = bx; + r.mant = m; return r; } -- cgit v0.10.2 From 3f7cac416b5e62d37aa693538729c6c23e9b938b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 26 Apr 2014 01:49:14 +0200 Subject: MIPS: math-emu: Cleanup coding style. o Only define variables in the outermost block o One empty line at most o Format comments as per CodingStyle o Update FSF address in licensing term comment o Spell FPU and MIPS in all capitals. o Remove ####-type of lines in comments. o Try to make things a bit most consistent between sp_*.c / dp_*.c files. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 3a0dfa4..6258291 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -1,5 +1,5 @@ /* - * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator + * cp1emu.c: a MIPS coprocessor 1 (FPU) instruction emulator * * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. @@ -18,19 +18,19 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * A complete emulator for MIPS coprocessor 1 instructions. This is * required for #float(switch) or #float(trap), where it catches all * COP1 instructions via the "CoProcessor Unusable" exception. * * More surprisingly it is also required for #float(ieee), to help out - * the hardware fpu at the boundaries of the IEEE-754 representation + * the hardware FPU at the boundaries of the IEEE-754 representation * (denormalised values, infinities, underflow, etc). It is made * quite nasty because emulation of some non-COP1 instructions is * required, e.g. in branch delay slots. * - * Note if you know that you won't have an fpu, then you'll get much + * Note if you know that you won't have an FPU, then you'll get much * better performance by compiling with -msoft-float! */ #include @@ -72,14 +72,14 @@ static int fpux_emu(struct pt_regs *, #define MM_POOL32A_MINOR_SHIFT 0x6 #define MM_MIPS32_COND_FC 0x30 -/* Convert Mips rounding mode (0..3) to IEEE library modes. */ +/* Convert MIPS rounding mode (0..3) to IEEE library modes. */ static const unsigned char ieee_rm[4] = { [FPU_CSR_RN] = IEEE754_RN, [FPU_CSR_RZ] = IEEE754_RZ, [FPU_CSR_RU] = IEEE754_RU, [FPU_CSR_RD] = IEEE754_RD, }; -/* Convert IEEE library modes to Mips rounding mode (0..3). */ +/* Convert IEEE library modes to MIPS rounding mode (0..3). */ static const unsigned char mips_rm[4] = { [IEEE754_RN] = FPU_CSR_RN, [IEEE754_RZ] = FPU_CSR_RZ, @@ -914,10 +914,16 @@ do { \ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, struct mm_decoded_insn dec_insn, void *__user *fault_addr) { - mips_instruction ir; unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc; - unsigned int cond; - int pc_inc; + unsigned int cond, cbit; + mips_instruction ir; + int likely, pc_inc; + u32 __user *wva; + u64 __user *dva; + u32 value; + u32 wval; + u64 dval; + int sig; /* XXX NEC Vr54xx bug workaround */ if (delay_slot(xcp)) { @@ -972,94 +978,81 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return SIGILL; } - emul: +emul: perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, xcp, 0); MIPS_FPU_EMU_INC_STATS(emulated); switch (MIPSInst_OPCODE(ir)) { - case ldc1_op:{ - u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + - MIPSInst_SIMM(ir)); - u64 val; - + case ldc1_op: + dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); MIPS_FPU_EMU_INC_STATS(loads); - if (!access_ok(VERIFY_READ, va, sizeof(u64))) { + if (!access_ok(VERIFY_READ, dva, sizeof(u64))) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = dva; return SIGBUS; } - if (__get_user(val, va)) { + if (__get_user(dval, dva)) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = dva; return SIGSEGV; } - DITOREG(val, MIPSInst_RT(ir)); + DITOREG(dval, MIPSInst_RT(ir)); break; - } - - case sdc1_op:{ - u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + - MIPSInst_SIMM(ir)); - u64 val; + case sdc1_op: + dva = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); MIPS_FPU_EMU_INC_STATS(stores); - DIFROMREG(val, MIPSInst_RT(ir)); - if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) { + DIFROMREG(dval, MIPSInst_RT(ir)); + if (!access_ok(VERIFY_WRITE, dva, sizeof(u64))) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = dva; return SIGBUS; } - if (__put_user(val, va)) { + if (__put_user(dval, dva)) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = dva; return SIGSEGV; } break; - } - - case lwc1_op:{ - u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + - MIPSInst_SIMM(ir)); - u32 val; + case lwc1_op: + wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); MIPS_FPU_EMU_INC_STATS(loads); - if (!access_ok(VERIFY_READ, va, sizeof(u32))) { + if (!access_ok(VERIFY_READ, wva, sizeof(u32))) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = wva; return SIGBUS; } - if (__get_user(val, va)) { + if (__get_user(wval, wva)) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = wva; return SIGSEGV; } - SITOREG(val, MIPSInst_RT(ir)); + SITOREG(wval, MIPSInst_RT(ir)); break; - } - - case swc1_op:{ - u32 __user *va = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + - MIPSInst_SIMM(ir)); - u32 val; + case swc1_op: + wva = (u32 __user *) (xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); MIPS_FPU_EMU_INC_STATS(stores); - SIFROMREG(val, MIPSInst_RT(ir)); - if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) { + SIFROMREG(wval, MIPSInst_RT(ir)); + if (!access_ok(VERIFY_WRITE, wva, sizeof(u32))) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = wva; return SIGBUS; } - if (__put_user(val, va)) { + if (__put_user(wval, wva)) { MIPS_FPU_EMU_INC_STATS(errors); - *fault_addr = va; + *fault_addr = wva; return SIGSEGV; } break; - } case cop1_op: switch (MIPSInst_RS(ir)) { - case dmfc_op: if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) return SIGILL; @@ -1111,10 +1104,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); break; - case cfc_op:{ + case cfc_op: /* cop control register rd -> gpr[rt] */ - u32 value; - if (MIPSInst_RD(ir) == FPCREG_CSR) { value = ctx->fcr31; value = (value & ~FPU_CSR_RM) | @@ -1130,12 +1121,9 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, if (MIPSInst_RT(ir)) xcp->regs[MIPSInst_RT(ir)] = value; break; - } - case ctc_op:{ + case ctc_op: /* copregister rd <- rt */ - u32 value; - if (MIPSInst_RT(ir) == 0) value = 0; else @@ -1160,12 +1148,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return SIGFPE; } break; - } - - case bc_op:{ - unsigned int cbit; - int likely = 0; + case bc_op: if (delay_slot(xcp)) return SIGILL; @@ -1175,6 +1159,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, cbit = FPU_CSR_COND; cond = ctx->fcr31 & cbit; + likely = 0; switch (MIPSInst_RT(ir) & 3) { case bcfl_op: likely = 1; @@ -1192,8 +1177,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, set_delay_slot(xcp); if (cond) { - /* branch taken: emulate dslot - * instruction + /* + * Branch taken: emulate dslot instruction */ xcp->cp0_epc += dec_insn.pc_inc; @@ -1228,8 +1213,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, switch (MIPSInst_OPCODE(ir)) { case lwc1_op: goto emul; + case swc1_op: goto emul; + case ldc1_op: case sdc1_op: if (cpu_has_mips_2_3_4_5 || @@ -1238,14 +1225,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return SIGILL; goto emul; + case cop1_op: goto emul; + case cop1x_op: if (cpu_has_mips_4_5 || cpu_has_mips64) /* its one of ours */ goto emul; return SIGILL; + case spec_op: if (!cpu_has_mips_4_5_r) return SIGILL; @@ -1260,10 +1250,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * instruction in the dslot */ return mips_dsemul(xcp, ir, contpc); - } - else { - /* branch not taken */ - if (likely) { + } else if (likely) { /* branch not taken */ /* * branch likely nullifies * dslot if not taken @@ -1275,26 +1262,19 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * dslot as normal insn */ } - } break; - } default: if (!(MIPSInst_RS(ir) & 0x10)) return SIGILL; - { - int sig; - /* a real fpu computation instruction */ - if ((sig = fpu_emu(xcp, ctx, ir))) - return sig; - } + /* a real fpu computation instruction */ + if ((sig = fpu_emu(xcp, ctx, ir))) + return sig; } break; - case cop1x_op:{ - int sig; - + case cop1x_op: if (!cpu_has_mips_4_5 && !cpu_has_mips64) return SIGILL; @@ -1302,7 +1282,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, if (sig) return sig; break; - } case spec_op: if (!cpu_has_mips_4_5_r) @@ -1477,7 +1456,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { - /*printk ("SIGFPE: fpu csr = %08x\n", + /*printk ("SIGFPE: FPU csr = %08x\n", ctx->fcr31); */ return SIGFPE; } @@ -1584,6 +1563,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, { int rfmt; /* resulting format */ unsigned rcsr = 0; /* resulting csr */ + unsigned int oldrm; + unsigned int cbit; unsigned cond; union { union ieee754dp d; @@ -1591,14 +1572,16 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, int w; s64 l; } rv; /* resulting value */ + u64 bits; MIPS_FPU_EMU_INC_STATS(cp1ops); switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { - case s_fmt:{ /* 0 */ + case s_fmt: { /* 0 */ union { union ieee754sp(*b) (union ieee754sp, union ieee754sp); union ieee754sp(*u) (union ieee754sp); } handler; + union ieee754sp fs, ft; switch (MIPSInst_FUNC(ir)) { /* binary ops */ @@ -1622,6 +1605,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, handler.u = ieee754sp_sqrt; goto scopuop; + /* * Note that on some MIPS IV implementations such as the * R5000 and R8000 the FSQRT and FRECIP instructions do not @@ -1633,6 +1617,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, handler.u = fpemu_sp_rsqrt; goto scopuop; + case frecip_op: if (!cpu_has_mips_4_5_r2) return SIGILL; @@ -1650,6 +1635,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return 0; SPFROMREG(rv.s, MIPSInst_FS(ir)); break; + case fmovz_op: if (!cpu_has_mips_4_5_r) return SIGILL; @@ -1658,6 +1644,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return 0; SPFROMREG(rv.s, MIPSInst_FS(ir)); break; + case fmovn_op: if (!cpu_has_mips_4_5_r) return SIGILL; @@ -1666,37 +1653,32 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return 0; SPFROMREG(rv.s, MIPSInst_FS(ir)); break; + case fabs_op: handler.u = ieee754sp_abs; goto scopuop; + case fneg_op: handler.u = ieee754sp_neg; goto scopuop; + case fmov_op: /* an easy one */ SPFROMREG(rv.s, MIPSInst_FS(ir)); goto copcsr; /* binary op on handler */ - scopbop: - { - union ieee754sp fs, ft; - - SPFROMREG(fs, MIPSInst_FS(ir)); - SPFROMREG(ft, MIPSInst_FT(ir)); - - rv.s = (*handler.b) (fs, ft); - goto copcsr; - } - scopuop: - { - union ieee754sp fs; +scopbop: + SPFROMREG(fs, MIPSInst_FS(ir)); + SPFROMREG(ft, MIPSInst_FT(ir)); - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.s = (*handler.u) (fs); - goto copcsr; - } - copcsr: + rv.s = (*handler.b) (fs, ft); + goto copcsr; +scopuop: + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.s = (*handler.u) (fs); + goto copcsr; +copcsr: if (ieee754_cxtest(IEEE754_INEXACT)) rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; if (ieee754_cxtest(IEEE754_UNDERFLOW)) @@ -1712,44 +1694,35 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* unary conv ops */ case fcvts_op: return SIGILL; /* not defined */ - case fcvtd_op:{ - union ieee754sp fs; + case fcvtd_op: SPFROMREG(fs, MIPSInst_FS(ir)); rv.d = ieee754dp_fsp(fs); rfmt = d_fmt; goto copcsr; - } - case fcvtw_op:{ - union ieee754sp fs; + case fcvtw_op: SPFROMREG(fs, MIPSInst_FS(ir)); rv.w = ieee754sp_tint(fs); rfmt = w_fmt; goto copcsr; - } case fround_op: case ftrunc_op: case fceil_op: - case ffloor_op:{ - unsigned int oldrm = ieee754_csr.rm; - union ieee754sp fs; - + case ffloor_op: if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64) return SIGILL; + oldrm = ieee754_csr.rm; SPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.w = ieee754sp_tint(fs); ieee754_csr.rm = oldrm; rfmt = w_fmt; goto copcsr; - } - - case fcvtl_op:{ - union ieee754sp fs; + case fcvtl_op: if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) return SIGILL; @@ -1757,25 +1730,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, rv.l = ieee754sp_tlong(fs); rfmt = l_fmt; goto copcsr; - } case froundl_op: case ftruncl_op: case fceill_op: - case ffloorl_op:{ - unsigned int oldrm = ieee754_csr.rm; - union ieee754sp fs; - + case ffloorl_op: if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) return SIGILL; + oldrm = ieee754_csr.rm; SPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.l = ieee754sp_tlong(fs); ieee754_csr.rm = oldrm; rfmt = l_fmt; goto copcsr; - } default: if (MIPSInst_FUNC(ir) >= fcmp_op) { @@ -1793,16 +1762,15 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, else goto copcsr; - } - else { + } else return SIGILL; - } break; } break; } - case d_fmt:{ + case d_fmt: { + union ieee754dp fs, ft; union { union ieee754dp(*b) (union ieee754dp, union ieee754dp); union ieee754dp(*u) (union ieee754dp); @@ -1887,65 +1855,51 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, goto copcsr; /* binary op on handler */ - dcopbop:{ - union ieee754dp fs, ft; - - DPFROMREG(fs, MIPSInst_FS(ir)); - DPFROMREG(ft, MIPSInst_FT(ir)); - - rv.d = (*handler.b) (fs, ft); - goto copcsr; - } - dcopuop:{ - union ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.d = (*handler.u) (fs); - goto copcsr; - } +dcopbop: + DPFROMREG(fs, MIPSInst_FS(ir)); + DPFROMREG(ft, MIPSInst_FT(ir)); - /* unary conv ops */ - case fcvts_op:{ - union ieee754dp fs; + rv.d = (*handler.b) (fs, ft); + goto copcsr; +dcopuop: + DPFROMREG(fs, MIPSInst_FS(ir)); + rv.d = (*handler.u) (fs); + goto copcsr; + /* + * unary conv ops + */ + case fcvts_op: DPFROMREG(fs, MIPSInst_FS(ir)); rv.s = ieee754sp_fdp(fs); rfmt = s_fmt; goto copcsr; - } + case fcvtd_op: return SIGILL; /* not defined */ - case fcvtw_op:{ - union ieee754dp fs; - + case fcvtw_op: DPFROMREG(fs, MIPSInst_FS(ir)); rv.w = ieee754dp_tint(fs); /* wrong */ rfmt = w_fmt; goto copcsr; - } case fround_op: case ftrunc_op: case fceil_op: - case ffloor_op:{ - unsigned int oldrm = ieee754_csr.rm; - union ieee754dp fs; - + case ffloor_op: if (!cpu_has_mips_2_3_4_5_r) return SIGILL; + oldrm = ieee754_csr.rm; DPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.w = ieee754dp_tint(fs); ieee754_csr.rm = oldrm; rfmt = w_fmt; goto copcsr; - } - - case fcvtl_op:{ - union ieee754dp fs; + case fcvtl_op: if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) return SIGILL; @@ -1953,25 +1907,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, rv.l = ieee754dp_tlong(fs); rfmt = l_fmt; goto copcsr; - } case froundl_op: case ftruncl_op: case fceill_op: - case ffloorl_op:{ - unsigned int oldrm = ieee754_csr.rm; - union ieee754dp fs; - + case ffloorl_op: if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) return SIGILL; + oldrm = ieee754_csr.rm; DPFROMREG(fs, MIPSInst_FS(ir)); ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; rv.l = ieee754dp_tlong(fs); ieee754_csr.rm = oldrm; rfmt = l_fmt; goto copcsr; - } default: if (MIPSInst_FUNC(ir) >= fcmp_op) { @@ -1998,11 +1948,8 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; } break; - } - - case w_fmt:{ - union ieee754sp fs; + case w_fmt: switch (MIPSInst_FUNC(ir)) { case fcvts_op: /* convert word to single precision real */ @@ -2022,8 +1969,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, break; } - case l_fmt:{ - u64 bits; + case l_fmt: if (!cpu_has_mips_3_4_5 && !cpu_has_mips64) return SIGILL; @@ -2045,7 +1991,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, return SIGILL; } break; - } default: return SIGILL; @@ -2060,7 +2005,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, */ ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { - /*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */ + /*printk ("SIGFPE: FPU csr = %08x\n",ctx->fcr31); */ return SIGFPE; } @@ -2068,7 +2013,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * Now we can safely write the result back to the register file. */ switch (rfmt) { - unsigned int cbit; case -1: if (cpu_has_mips_4_5_r) @@ -2200,7 +2144,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, /* SIGILL indicates a non-fpu instruction */ if (sig == SIGILL && xcp->cp0_epc != oldepc) - /* but if epc has advanced, then ignore it */ + /* but if EPC has advanced, then ignore it */ sig = 0; return sig; diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index 48b9ef6..9c98b96 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,17 +16,15 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) { + int s; + COMPXDP; COMPYDP; @@ -69,9 +65,9 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) return x; - /* Infinity handling - */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs == ys) return x; @@ -88,15 +84,14 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): return x; - /* Zero handling - */ - + /* + * Zero handling + */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): if (xs == ys) return x; else - return ieee754dp_zero(ieee754_csr.rm == - IEEE754_RD); + return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -125,20 +120,24 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) assert(xm & DP_HIDDEN_BIT); assert(ym & DP_HIDDEN_BIT); - /* provide guard,round and stick bit space */ + /* + * Provide guard,round and stick bit space. + */ xm <<= 3; ym <<= 3; if (xe > ye) { - /* have to shift y fraction right to align + /* + * Have to shift y fraction right to align. */ - int s = xe - ye; + s = xe - ye; ym = XDPSRS(ym, s); ye += s; } else if (ye > xe) { - /* have to shift x fraction right to align + /* + * Have to shift x fraction right to align. */ - int s = ye - xe; + s = ye - xe; xm = XDPSRS(xm, s); xe += s; } @@ -146,8 +145,9 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) assert(xe <= DP_EMAX); if (xs == ys) { - /* generate 28 bit result of adding two 27 bit numbers - * leaving result in xm,xs,xe + /* + * Generate 28 bit result of adding two 27 bit numbers + * leaving result in xm, xs and xe. */ xm = xm + ym; xe = xe; @@ -168,15 +168,15 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) xs = ys; } if (xm == 0) - return ieee754dp_zero(ieee754_csr.rm == - IEEE754_RD); + return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD); - /* normalize to rounding precision */ + /* + * Normalize to rounding precision. + */ while ((xm >> (DP_FBITS + 3)) == 0) { xm <<= 1; xe--; } - } return ieee754dp_format(xs, xe, xm); diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c index fe573cb..30f95f6 100644 --- a/arch/mips/math-emu/dp_cmp.c +++ b/arch/mips/math-emu/dp_cmp.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,16 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig) { + s64 vx; + s64 vy; + COMPXDP; COMPYDP; @@ -48,8 +46,8 @@ int ieee754dp_cmp(union ieee754dp x, union ieee754dp y, int cmp, int sig) } return 0; } else { - s64 vx = x.bits; - s64 vy = y.bits; + vx = x.bits; + vy = y.bits; if (vx < 0) vx = -vx ^ DP_SIGN_BIT; diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c index 377e114..bef0e55 100644 --- a/arch/mips/math-emu/dp_div.c +++ b/arch/mips/math-emu/dp_div.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,17 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) { + u64 rm; + int re; + u64 bm; + COMPXDP; COMPYDP; @@ -68,9 +67,9 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) return x; - /* Infinity handling - */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_indef(); @@ -85,9 +84,9 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): return ieee754dp_inf(xs ^ ys); - /* Zero handling - */ - + /* + * Zero handling + */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_indef(); @@ -122,35 +121,34 @@ union ieee754dp ieee754dp_div(union ieee754dp x, union ieee754dp y) xm <<= 3; ym <<= 3; - { - /* now the dirty work */ - - u64 rm = 0; - int re = xe - ye; - u64 bm; - - for (bm = DP_MBIT(DP_FBITS + 2); bm; bm >>= 1) { - if (xm >= ym) { - xm -= ym; - rm |= bm; - if (xm == 0) - break; - } - xm <<= 1; - } - rm <<= 1; - if (xm) - rm |= 1; /* have remainder, set sticky */ + /* now the dirty work */ - assert(rm); + rm = 0; + re = xe - ye; - /* normalise rm to rounding precision ? - */ - while ((rm >> (DP_FBITS + 3)) == 0) { - rm <<= 1; - re--; + for (bm = DP_MBIT(DP_FBITS + 2); bm; bm >>= 1) { + if (xm >= ym) { + xm -= ym; + rm |= bm; + if (xm == 0) + break; } + xm <<= 1; + } + + rm <<= 1; + if (xm) + rm |= 1; /* have remainder, set sticky */ - return ieee754dp_format(xs == ys ? 0 : 1, re, rm); + assert(rm); + + /* + * Normalise rm to rounding precision ? + */ + while ((rm >> (DP_FBITS + 3)) == 0) { + rm <<= 1; + re--; } + + return ieee754dp_format(xs == ys ? 0 : 1, re, rm); } diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c index 98b9d6a..10258f0 100644 --- a/arch/mips/math-emu/dp_fint.c +++ b/arch/mips/math-emu/dp_fint.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" union ieee754dp ieee754dp_fint(int x) diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c index 54c8f00..a267c2e 100644 --- a/arch/mips/math-emu/dp_flong.c +++ b/arch/mips/math-emu/dp_flong.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" union ieee754dp ieee754dp_flong(s64 x) diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c index ba600be..ffb69c5 100644 --- a/arch/mips/math-emu/dp_fsp.c +++ b/arch/mips/math-emu/dp_fsp.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" #include "ieee754dp.h" @@ -41,6 +36,7 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef()); + case IEEE754_CLASS_QNAN: return ieee754dp_nanxcpt(builddp(xs, DP_EMAX + 1 + DP_EBIAS, @@ -49,8 +45,10 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) SP_FBITS)))); case IEEE754_CLASS_INF: return ieee754dp_inf(xs); + case IEEE754_CLASS_ZERO: return ieee754dp_zero(xs); + case IEEE754_CLASS_DNORM: /* normalize */ while ((xm >> SP_FBITS) == 0) { @@ -58,11 +56,13 @@ union ieee754dp ieee754dp_fsp(union ieee754sp x) xe--; } break; + case IEEE754_CLASS_NORM: break; } - /* CAN'T possibly overflow,underflow, or need rounding + /* + * Can't possibly overflow,underflow, or need rounding */ /* drop the hidden bit */ diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c index 74bc810..d3acded 100644 --- a/arch/mips/math-emu/dp_mul.c +++ b/arch/mips/math-emu/dp_mul.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,25 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) { + int re; + int rs; + u64 rm; + unsigned lxm; + unsigned hxm; + unsigned lym; + unsigned hym; + u64 lrm; + u64 hrm; + u64 t; + u64 at; + COMPXDP; COMPYDP; @@ -68,8 +75,9 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) return x; - /* Infinity handling */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); @@ -107,71 +115,59 @@ union ieee754dp ieee754dp_mul(union ieee754dp x, union ieee754dp y) /* rm = xm * ym, re = xe+ye basically */ assert(xm & DP_HIDDEN_BIT); assert(ym & DP_HIDDEN_BIT); - { - int re = xe + ye; - int rs = xs ^ ys; - u64 rm; - /* shunt to top of word */ - xm <<= 64 - (DP_FBITS + 1); - ym <<= 64 - (DP_FBITS + 1); + re = xe + ye; + rs = xs ^ ys; + + /* shunt to top of word */ + xm <<= 64 - (DP_FBITS + 1); + ym <<= 64 - (DP_FBITS + 1); - /* multiply 32bits xm,ym to give high 32bits rm with stickness - */ + /* + * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. + */ - /* 32 * 32 => 64 */ + /* 32 * 32 => 64 */ #define DPXMULT(x, y) ((u64)(x) * (u64)y) - { - unsigned lxm = xm; - unsigned hxm = xm >> 32; - unsigned lym = ym; - unsigned hym = ym >> 32; - u64 lrm; - u64 hrm; - - lrm = DPXMULT(lxm, lym); - hrm = DPXMULT(hxm, hym); - - { - u64 t = DPXMULT(lxm, hym); - { - u64 at = - lrm + (t << 32); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 32); - } - - { - u64 t = DPXMULT(hxm, lym); - { - u64 at = - lrm + (t << 32); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 32); - } - rm = hrm | (lrm != 0); - } - - /* - * sticky shift down to normal rounding precision - */ - if ((s64) rm < 0) { - rm = - (rm >> (64 - (DP_FBITS + 1 + 3))) | - ((rm << (DP_FBITS + 1 + 3)) != 0); + lxm = xm; + hxm = xm >> 32; + lym = ym; + hym = ym >> 32; + + lrm = DPXMULT(lxm, lym); + hrm = DPXMULT(hxm, hym); + + t = DPXMULT(lxm, hym); + + at = lrm + (t << 32); + hrm += at < lrm; + lrm = at; + + hrm = hrm + (t >> 32); + + t = DPXMULT(hxm, lym); + + at = lrm + (t << 32); + hrm += at < lrm; + lrm = at; + + hrm = hrm + (t >> 32); + + rm = hrm | (lrm != 0); + + /* + * Sticky shift down to normal rounding precision. + */ + if ((s64) rm < 0) { + rm = (rm >> (64 - (DP_FBITS + 1 + 3))) | + ((rm << (DP_FBITS + 1 + 3)) != 0); re++; - } else { - rm = - (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) | - ((rm << (DP_FBITS + 1 + 3 + 1)) != 0); - } - assert(rm & (DP_HIDDEN_BIT << 3)); - - return ieee754dp_format(rs, re, rm); + } else { + rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) | + ((rm << (DP_FBITS + 1 + 3 + 1)) != 0); } + assert(rm & (DP_HIDDEN_BIT << 3)); + + return ieee754dp_format(rs, re, rm); } diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c index 4eda759..bccbe90 100644 --- a/arch/mips/math-emu/dp_simple.c +++ b/arch/mips/math-emu/dp_simple.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" union ieee754dp ieee754dp_neg(union ieee754dp x) @@ -51,7 +46,6 @@ union ieee754dp ieee754dp_neg(union ieee754dp x) return x; } - union ieee754dp ieee754dp_abs(union ieee754dp x) { COMPXDP; diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index 8e88bde..109878a 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" static const unsigned table[] = { @@ -50,12 +45,15 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) case IEEE754_CLASS_QNAN: /* sqrt(Nan) = Nan */ return ieee754dp_nanxcpt(x); + case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754dp_nanxcpt(ieee754dp_indef()); + case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ return x; + case IEEE754_CLASS_INF: if (xs) { /* sqrt(-Inf) = Nan */ @@ -64,9 +62,11 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) } /* sqrt(+Inf) = Inf */ return x; + case IEEE754_CLASS_DNORM: DPDNORMX; /* fall through */ + case IEEE754_CLASS_NORM: if (xs) { /* sqrt(-x) = Nan */ diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index 3dd62c1..d502984 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,15 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) { + int s; + COMPXDP; COMPYDP; @@ -68,9 +65,9 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) return x; - /* Infinity handling - */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs != ys) return x; @@ -87,15 +84,14 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): return x; - /* Zero handling - */ - + /* + * Zero handling + */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): if (xs != ys) return x; else - return ieee754dp_zero(ieee754_csr.rm == - IEEE754_RD); + return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -136,15 +132,17 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) ym <<= 3; if (xe > ye) { - /* have to shift y fraction right to align + /* + * Have to shift y fraction right to align */ - int s = xe - ye; + s = xe - ye; ym = XDPSRS(ym, s); ye += s; } else if (ye > xe) { - /* have to shift x fraction right to align + /* + * Have to shift x fraction right to align */ - int s = ye - xe; + s = ye - xe; xm = XDPSRS(xm, s); xe += s; } diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 3a23c64..972dba0 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,18 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" int ieee754dp_tint(union ieee754dp x) { + u64 residue; + int round; + int sticky; + int odd; + COMPXDP; ieee754_clearcx(); @@ -41,8 +41,10 @@ int ieee754dp_tint(union ieee754dp x) case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_indef(); + case IEEE754_CLASS_ZERO: return 0; + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; @@ -57,11 +59,6 @@ int ieee754dp_tint(union ieee754dp x) if (xe > DP_FBITS) { xm <<= xe - DP_FBITS; } else if (xe < DP_FBITS) { - u64 residue; - int round; - int sticky; - int odd; - if (xe < -1) { residue = xm; round = 0; diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index cbeef60..afaf953 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,18 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754dp.h" s64 ieee754dp_tlong(union ieee754dp x) { + u64 residue; + int round; + int sticky; + int odd; + COMPXDP; ieee754_clearcx(); @@ -41,8 +41,10 @@ s64 ieee754dp_tlong(union ieee754dp x) case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_indef(); + case IEEE754_CLASS_ZERO: return 0; + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; @@ -60,11 +62,6 @@ s64 ieee754dp_tlong(union ieee754dp x) if (xe > DP_FBITS) { xm <<= xe - DP_FBITS; } else if (xe < DP_FBITS) { - u64 residue; - int round; - int sticky; - int odd; - if (xe < -1) { residue = xm; round = 0; diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c index 670d19b..53f1d22 100644 --- a/arch/mips/math-emu/ieee754.c +++ b/arch/mips/math-emu/ieee754.c @@ -10,8 +10,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -23,9 +21,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -34,8 +30,9 @@ #include "ieee754sp.h" #include "ieee754dp.h" -/* special constants -*/ +/* + * Special constants + */ #define DPCNST(s, b, m) \ { \ diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 4f89f85..fb2fb6b 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Nov 7, 2000 * Modification to allow integration with Linux kernel diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c index ebe34e9..a04e8a7 100644 --- a/arch/mips/math-emu/ieee754d.c +++ b/arch/mips/math-emu/ieee754d.c @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Nov 7, 2000 * Modified to build and operate in Linux kernel environment. diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 3b123f5..087a6f3 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,9 +16,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h index 231bd76..61fd6fd 100644 --- a/arch/mips/math-emu/ieee754dp.h +++ b/arch/mips/math-emu/ieee754dp.h @@ -6,8 +6,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -19,9 +17,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h index 58b9087..f0365bb 100644 --- a/arch/mips/math-emu/ieee754int.h +++ b/arch/mips/math-emu/ieee754int.h @@ -6,8 +6,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -19,9 +17,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __IEEE754INT_H #define __IEEE754INT_H diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index d07bec3..e4cec15 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,9 +16,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h index 35da62f..ad268e3 100644 --- a/arch/mips/math-emu/ieee754sp.h +++ b/arch/mips/math-emu/ieee754sp.h @@ -6,8 +6,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -19,9 +17,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #include diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c index a795900..bee9419 100644 --- a/arch/mips/math-emu/kernel_linkage.c +++ b/arch/mips/math-emu/kernel_linkage.c @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Routines corresponding to Linux kernel FP context * manipulation primitives for the Algorithmics MIPS diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index db4d89b..a0bc95c 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,15 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) { + int s; + COMPXSP; COMPYSP; @@ -68,9 +65,9 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) return x; - /* Infinity handling - */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs == ys) return x; @@ -87,15 +84,14 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): return x; - /* Zero handling - */ - + /* + * Zero handling + */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): if (xs == ys) return x; else - return ieee754sp_zero(ieee754_csr.rm == - IEEE754_RD); + return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -108,6 +104,8 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): SPDNORMX; + /* FALL THROUGH */ + case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): SPDNORMY; break; @@ -122,27 +120,32 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) assert(xm & SP_HIDDEN_BIT); assert(ym & SP_HIDDEN_BIT); - /* provide guard,round and stick bit space */ + /* + * Provide guard, round and stick bit space. + */ xm <<= 3; ym <<= 3; if (xe > ye) { - /* have to shift y fraction right to align + /* + * Have to shift y fraction right to align. */ - int s = xe - ye; + s = xe - ye; SPXSRSYn(s); } else if (ye > xe) { - /* have to shift x fraction right to align + /* + * Have to shift x fraction right to align. */ - int s = ye - xe; + s = ye - xe; SPXSRSXn(s); } assert(xe == ye); assert(xe <= SP_EMAX); if (xs == ys) { - /* generate 28 bit result of adding two 27 bit numbers - * leaving result in xm,xs,xe + /* + * Generate 28 bit result of adding two 27 bit numbers + * leaving result in xm, xs and xe. */ xm = xm + ym; xe = xe; @@ -162,15 +165,15 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) xs = ys; } if (xm == 0) - return ieee754sp_zero(ieee754_csr.rm == - IEEE754_RD); + return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD); - /* normalize in extended single precision */ + /* + * Normalize in extended single precision + */ while ((xm >> (SP_FBITS + 3)) == 0) { xm <<= 1; xe--; } - } return ieee754sp_format(xs, xe, xm); diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c index fab4988..addbccb 100644 --- a/arch/mips/math-emu/sp_cmp.c +++ b/arch/mips/math-emu/sp_cmp.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,16 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig) { + int vx; + int vy; + COMPXSP; COMPYSP; @@ -48,8 +46,8 @@ int ieee754sp_cmp(union ieee754sp x, union ieee754sp y, int cmp, int sig) } return 0; } else { - int vx = x.bits; - int vy = y.bits; + vx = x.bits; + vy = y.bits; if (vx < 0) vx = -vx ^ SP_SIGN_BIT; diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c index 0d847a4..721f317 100644 --- a/arch/mips/math-emu/sp_div.c +++ b/arch/mips/math-emu/sp_div.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,17 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) { + unsigned rm; + int re; + unsigned bm; + COMPXSP; COMPYSP; @@ -68,9 +67,9 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) return x; - /* Infinity handling - */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_indef(); @@ -85,9 +84,9 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): return ieee754sp_inf(xs ^ ys); - /* Zero handling - */ - + /* + * Zero handling + */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_indef(); @@ -122,35 +121,33 @@ union ieee754sp ieee754sp_div(union ieee754sp x, union ieee754sp y) xm <<= 3; ym <<= 3; - { - /* now the dirty work */ - - unsigned rm = 0; - int re = xe - ye; - unsigned bm; - - for (bm = SP_MBIT(SP_FBITS + 2); bm; bm >>= 1) { - if (xm >= ym) { - xm -= ym; - rm |= bm; - if (xm == 0) - break; - } - xm <<= 1; - } - rm <<= 1; - if (xm) - rm |= 1; /* have remainder, set sticky */ + /* now the dirty work */ - assert(rm); + rm = 0; + re = xe - ye; - /* normalise rm to rounding precision ? - */ - while ((rm >> (SP_FBITS + 3)) == 0) { - rm <<= 1; - re--; + for (bm = SP_MBIT(SP_FBITS + 2); bm; bm >>= 1) { + if (xm >= ym) { + xm -= ym; + rm |= bm; + if (xm == 0) + break; } + xm <<= 1; + } + + rm <<= 1; + if (xm) + rm |= 1; /* have remainder, set sticky */ - return ieee754sp_format(xs == ys ? 0 : 1, re, rm); + assert(rm); + + /* normalise rm to rounding precision ? + */ + while ((rm >> (SP_FBITS + 3)) == 0) { + rm <<= 1; + re--; } + + return ieee754sp_format(xs == ys ? 0 : 1, re, rm); } diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index 5c1d8aa..90b9ec4 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,17 +16,16 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" #include "ieee754dp.h" union ieee754sp ieee754sp_fdp(union ieee754dp x) { + u32 rm; + COMPXDP; union ieee754sp nan; @@ -42,16 +39,20 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef()); + case IEEE754_CLASS_QNAN: nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) (xm >> (DP_FBITS - SP_FBITS))); if (!ieee754sp_isnan(nan)) nan = ieee754sp_indef(); return ieee754sp_nanxcpt(nan); + case IEEE754_CLASS_INF: return ieee754sp_inf(xs); + case IEEE754_CLASS_ZERO: return ieee754sp_zero(xs); + case IEEE754_CLASS_DNORM: /* can't possibly be sp representable */ ieee754_setcx(IEEE754_UNDERFLOW); @@ -60,18 +61,16 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) (ieee754_csr.rm == IEEE754_RD && xs)) return ieee754sp_mind(xs); return ieee754sp_zero(xs); + case IEEE754_CLASS_NORM: break; } - { - u32 rm; + /* + * Convert from DP_FBITS to SP_FBITS+3 with sticky right shift. + */ + rm = (xm >> (DP_FBITS - (SP_FBITS + 3))) | + ((xm << (64 - (DP_FBITS - (SP_FBITS + 3)))) != 0); - /* convert from DP_FBITS to SP_FBITS+3 with sticky right shift - */ - rm = (xm >> (DP_FBITS - (SP_FBITS + 3))) | - ((xm << (64 - (DP_FBITS - (SP_FBITS + 3)))) != 0); - - return ieee754sp_format(xs, xe, rm); - } + return ieee754sp_format(xs, xe, rm); } diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c index 8e8687b..d5d8495 100644 --- a/arch/mips/math-emu/sp_fint.c +++ b/arch/mips/math-emu/sp_fint.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_fint(int x) diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c index e56e8760..012e30c 100644 --- a/arch/mips/math-emu/sp_flong.c +++ b/arch/mips/math-emu/sp_flong.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_flong(s64 x) diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c index 0e19d0e..890c13a 100644 --- a/arch/mips/math-emu/sp_mul.c +++ b/arch/mips/math-emu/sp_mul.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,25 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) { + int re; + int rs; + unsigned rm; + unsigned short lxm; + unsigned short hxm; + unsigned short lym; + unsigned short hym; + unsigned lrm; + unsigned hrm; + unsigned t; + unsigned at; + COMPXSP; COMPYSP; @@ -68,8 +75,9 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) return x; - /* Infinity handling */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): ieee754_setcx(IEEE754_INVALID_OPERATION); @@ -108,63 +116,50 @@ union ieee754sp ieee754sp_mul(union ieee754sp x, union ieee754sp y) assert(xm & SP_HIDDEN_BIT); assert(ym & SP_HIDDEN_BIT); - { - int re = xe + ye; - int rs = xs ^ ys; - unsigned rm; - - /* shunt to top of word */ - xm <<= 32 - (SP_FBITS + 1); - ym <<= 32 - (SP_FBITS + 1); - - /* multiply 32bits xm,ym to give high 32bits rm with stickness - */ - { - unsigned short lxm = xm & 0xffff; - unsigned short hxm = xm >> 16; - unsigned short lym = ym & 0xffff; - unsigned short hym = ym >> 16; - unsigned lrm; - unsigned hrm; - - lrm = lxm * lym; /* 16 * 16 => 32 */ - hrm = hxm * hym; /* 16 * 16 => 32 */ - - { - unsigned t = lxm * hym; /* 16 * 16 => 32 */ - { - unsigned at = lrm + (t << 16); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 16); - } - - { - unsigned t = hxm * lym; /* 16 * 16 => 32 */ - { - unsigned at = lrm + (t << 16); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 16); - } - rm = hrm | (lrm != 0); - } - - /* - * sticky shift down to normal rounding precision - */ - if ((int) rm < 0) { - rm = (rm >> (32 - (SP_FBITS + 1 + 3))) | - ((rm << (SP_FBITS + 1 + 3)) != 0); - re++; - } else { - rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) | - ((rm << (SP_FBITS + 1 + 3 + 1)) != 0); - } - assert(rm & (SP_HIDDEN_BIT << 3)); - - return ieee754sp_format(rs, re, rm); + re = xe + ye; + rs = xs ^ ys; + + /* shunt to top of word */ + xm <<= 32 - (SP_FBITS + 1); + ym <<= 32 - (SP_FBITS + 1); + + /* + * Multiply 32 bits xm, ym to give high 32 bits rm with stickness. + */ + lxm = xm & 0xffff; + hxm = xm >> 16; + lym = ym & 0xffff; + hym = ym >> 16; + + lrm = lxm * lym; /* 16 * 16 => 32 */ + hrm = hxm * hym; /* 16 * 16 => 32 */ + + t = lxm * hym; /* 16 * 16 => 32 */ + at = lrm + (t << 16); + hrm += at < lrm; + lrm = at; + hrm = hrm + (t >> 16); + + t = hxm * lym; /* 16 * 16 => 32 */ + at = lrm + (t << 16); + hrm += at < lrm; + lrm = at; + hrm = hrm + (t >> 16); + + rm = hrm | (lrm != 0); + + /* + * Sticky shift down to normal rounding precision. + */ + if ((int) rm < 0) { + rm = (rm >> (32 - (SP_FBITS + 1 + 3))) | + ((rm << (SP_FBITS + 1 + 3)) != 0); + re++; + } else { + rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) | + ((rm << (SP_FBITS + 1 + 3 + 1)) != 0); } + assert(rm & (SP_HIDDEN_BIT << 3)); + + return ieee754sp_format(rs, re, rm); } diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c index 8f0202d..f1ffaa9a 100644 --- a/arch/mips/math-emu/sp_simple.c +++ b/arch/mips/math-emu/sp_simple.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_neg(union ieee754sp x) @@ -51,7 +46,6 @@ union ieee754sp ieee754sp_neg(union ieee754sp x) return x; } - union ieee754sp ieee754sp_abs(union ieee754sp x) { COMPXSP; diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index f4da2cc..33b3e00 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +16,9 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_sqrt(union ieee754sp x) @@ -43,12 +38,15 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) case IEEE754_CLASS_QNAN: /* sqrt(Nan) = Nan */ return ieee754sp_nanxcpt(x); + case IEEE754_CLASS_SNAN: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754sp_nanxcpt(ieee754sp_indef()); + case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ return x; + case IEEE754_CLASS_INF: if (xs) { /* sqrt(-Inf) = Nan */ @@ -57,6 +55,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) } /* sqrt(+Inf) = Inf */ return x; + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: if (xs) { diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index 67a1f9e..e813f4f 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,15 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) { + int s; + COMPXSP; COMPYSP; @@ -68,9 +65,9 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) return x; - /* Infinity handling - */ - + /* + * Infinity handling + */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): if (xs != ys) return x; @@ -87,15 +84,14 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): return x; - /* Zero handling - */ - + /* + * Zero handling + */ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): if (xs != ys) return x; else - return ieee754sp_zero(ieee754_csr.rm == - IEEE754_RD); + return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -133,14 +129,16 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) ym <<= 3; if (xe > ye) { - /* have to shift y fraction right to align + /* + * have to shift y fraction right to align */ - int s = xe - ye; + s = xe - ye; SPXSRSYn(s); } else if (ye > xe) { - /* have to shift x fraction right to align + /* + * have to shift x fraction right to align */ - int s = ye - xe; + s = ye - xe; SPXSRSXn(s); } assert(xe == ye); diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index 53f04dc..e1dee56 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,16 +16,18 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" int ieee754sp_tint(union ieee754sp x) { + u32 residue; + int round; + int sticky; + int odd; + COMPXSP; ieee754_clearcx(); @@ -41,8 +41,10 @@ int ieee754sp_tint(union ieee754sp x) case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754si_indef(); + case IEEE754_CLASS_ZERO: return 0; + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; @@ -60,11 +62,6 @@ int ieee754sp_tint(union ieee754sp x) if (xe > SP_FBITS) { xm <<= xe - SP_FBITS; } else { - u32 residue; - int round; - int sticky; - int odd; - if (xe < -1) { residue = xm; round = 0; diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index df11792..67eff6b 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -5,8 +5,6 @@ * MIPS floating point support * Copyright (C) 1994-2000 Algorithmics Ltd. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,17 +16,19 @@ * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - #include "ieee754sp.h" #include "ieee754dp.h" s64 ieee754sp_tlong(union ieee754sp x) { + u32 residue; + int round; + int sticky; + int odd; + COMPXDP; /* <-- need 64-bit mantissa tmp */ ieee754_clearcx(); @@ -42,8 +42,10 @@ s64 ieee754sp_tlong(union ieee754sp x) case IEEE754_CLASS_INF: ieee754_setcx(IEEE754_INVALID_OPERATION); return ieee754di_indef(); + case IEEE754_CLASS_ZERO: return 0; + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; @@ -61,11 +63,6 @@ s64 ieee754sp_tlong(union ieee754sp x) if (xe > SP_FBITS) { xm <<= xe - SP_FBITS; } else if (xe < SP_FBITS) { - u32 residue; - int round; - int sticky; - int odd; - if (xe < -1) { residue = xm; round = 0; -- cgit v0.10.2 From e0cc3a42eb50593a50e2b99d9dc92b4279f2efda Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 28 Apr 2014 22:34:01 +0200 Subject: MIPS: math-emu: Inline fpu_emulator_init_fpu() Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h index 4d86b72..a939574 100644 --- a/arch/mips/include/asm/fpu.h +++ b/arch/mips/include/asm/fpu.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,6 @@ struct sigcontext; struct sigcontext32; -extern void fpu_emulator_init_fpu(void); extern void _init_fpu(void); extern void _save_fp(struct task_struct *); extern void _restore_fp(struct task_struct *); @@ -156,15 +156,16 @@ static inline int init_fpu(void) int ret = 0; preempt_disable(); + if (cpu_has_fpu) { ret = __own_fpu(); if (!ret) _init_fpu(); - } else { + } else fpu_emulator_init_fpu(); - } preempt_enable(); + return ret; } diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h index 2abb587..f761719 100644 --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h @@ -23,9 +23,12 @@ #ifndef _ASM_FPU_EMULATOR_H #define _ASM_FPU_EMULATOR_H +#include #include +#include #include #include +#include #ifdef CONFIG_DEBUG_FS @@ -71,4 +74,17 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, */ #define BREAK_MATH (0x0000000d | (BRK_MEMU << 16)) +#define SIGNALLING_NAN 0x7ff800007ff80000LL + +static inline void fpu_emulator_init_fpu(void) +{ + struct task_struct *t = current; + int i; + + t->thread.fpu.fcr31 = 0; + + for (i = 0; i < 32; i++) + set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN); +} + #endif /* _ASM_FPU_EMULATOR_H */ diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile index 383cc78..619cfc1 100644 --- a/arch/mips/math-emu/Makefile +++ b/arch/mips/math-emu/Makefile @@ -6,7 +6,7 @@ obj-y += cp1emu.o ieee754dp.o ieee754sp.o ieee754.o dp_div.o dp_mul.o \ dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \ dp_fint.o dp_tlong.o dp_flong.o sp_div.o sp_mul.o sp_sub.o \ sp_add.o sp_fdp.o sp_cmp.o sp_simple.o sp_tint.o sp_fint.o \ - sp_tlong.o sp_flong.o kernel_linkage.o dsemul.o + sp_tlong.o sp_flong.o dsemul.o lib-y += ieee754d.o dp_sqrt.o sp_sqrt.o diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c deleted file mode 100644 index bee9419..0000000 --- a/arch/mips/math-emu/kernel_linkage.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Routines corresponding to Linux kernel FP context - * manipulation primitives for the Algorithmics MIPS - * FPU Emulator - */ -#include -#include -#include -#include - -#define SIGNALLING_NAN 0x7ff800007ff80000LL - -void fpu_emulator_init_fpu(void) -{ - static int first = 1; - int i; - - if (first) { - first = 0; - printk("Algorithmics/MIPS FPU Emulator v1.5\n"); - } - - current->thread.fpu.fcr31 = 0; - for (i = 0; i < 32; i++) - set_fpr64(¤t->thread.fpu.fpr[i], 0, SIGNALLING_NAN); -} -- cgit v0.10.2 From 377cb1b6c16a17e2560a9288f9c8ed5dcdbeba39 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 29 Apr 2014 01:49:24 +0200 Subject: MIPS: Disable MIPS16/microMIPS crap for platforms not supporting these ASEs. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5cd695f..45e75b6 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -83,6 +83,7 @@ config AR7 select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS16 select SYS_SUPPORTS_ZBOOT_UART16550 select ARCH_REQUIRE_GPIOLIB select VLYNQ @@ -106,6 +107,7 @@ config ATH79 select SYS_HAS_EARLY_PRINTK select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MIPS16 help Support for the Atheros AR71XX/AR724X/AR913X SoCs. @@ -122,6 +124,7 @@ config BCM47XX select NO_EXCEPT_FILL select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS16 select SYS_HAS_EARLY_PRINTK select USE_GENERIC_EARLY_PRINTK_8250 help @@ -248,6 +251,7 @@ config LANTIQ select SYS_HAS_CPU_MIPS32_R2 select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_MIPS16 select SYS_SUPPORTS_MULTITHREADING select SYS_HAS_EARLY_PRINTK select ARCH_REQUIRE_GPIOLIB @@ -330,6 +334,7 @@ config MIPS_MALTA select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_MIPS_CMP select SYS_SUPPORTS_MIPS_CPS + select SYS_SUPPORTS_MIPS16 select SYS_SUPPORTS_MULTITHREADING select SYS_SUPPORTS_SMARTMIPS select SYS_SUPPORTS_ZBOOT @@ -361,6 +366,7 @@ config MIPS_SEAD3 select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_SMARTMIPS select SYS_SUPPORTS_MICROMIPS + select SYS_SUPPORTS_MIPS16 select USB_EHCI_BIG_ENDIAN_DESC select USB_EHCI_BIG_ENDIAN_MMIO select USE_OF @@ -380,6 +386,7 @@ config MACH_VR41XX select CEVT_R4K select CSRC_R4K select SYS_HAS_CPU_VR41XX + select SYS_SUPPORTS_MIPS16 select ARCH_REQUIRE_GPIOLIB config NXP_STB220 @@ -407,6 +414,7 @@ config PMC_MSP select SYS_HAS_CPU_MIPS32_R2 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MIPS16 select IRQ_CPU select SERIAL_8250 select SERIAL_8250_CONSOLE @@ -430,6 +438,7 @@ config RALINK select SYS_HAS_CPU_MIPS32_R2 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select SYS_SUPPORTS_MIPS16 select SYS_HAS_EARLY_PRINTK select HAVE_MACH_CLKDEV select CLKDEV_LOOKUP @@ -1059,6 +1068,7 @@ config SOC_PNX833X select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MIPS16 select CPU_MIPSR2_IRQ_VI config SOC_PNX8335 @@ -2199,6 +2209,13 @@ config SYS_SUPPORTS_SMARTMIPS config SYS_SUPPORTS_MICROMIPS bool +config SYS_SUPPORTS_MIPS16 + bool + help + This option must be set if a kernel might be executed on a MIPS16- + enabled CPU even if MIPS16 is not actually being used. In other + words, it makes the kernel MIPS16-tolerant. + config CPU_SUPPORTS_MSA bool diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 3e025b5..88e30d5 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -709,11 +709,18 @@ #ifndef __ASSEMBLY__ /* - * Macros for handling the ISA mode bit for microMIPS. + * Macros for handling the ISA mode bit for MIPS16 and microMIPS. */ +#if defined(CONFIG_SYS_SUPPORTS_MIPS16) || \ + defined(CONFIG_SYS_SUPPORTS_MICROMIPS) #define get_isa16_mode(x) ((x) & 0x1) #define msk_isa16_mode(x) ((x) & ~0x1) #define set_isa16_mode(x) do { (x) |= 0x1; } while(0) +#else +#define get_isa16_mode(x) 0 +#define msk_isa16_mode(x) (x) +#define set_isa16_mode(x) do { } while(0) +#endif /* * microMIPS instructions can be 16-bit or 32-bit in length. This diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig index fbf75f6..e23c25d 100644 --- a/arch/mips/loongson1/Kconfig +++ b/arch/mips/loongson1/Kconfig @@ -14,6 +14,7 @@ config LOONGSON1_LS1B select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_HIGHMEM + select SYS_SUPPORTS_MIPS16 select SYS_HAS_EARLY_PRINTK select COMMON_CLK -- cgit v0.10.2 From 76fbfc318de2eb0eb4823095ece020f999a17c63 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 29 Apr 2014 15:21:24 +0200 Subject: MIPS: Sort out mm_isBranchInstr. mm_isBranchInstr() did reside in the math emu code even though it logically is separate and also is used outside the math emu code. In addition GCC 4.9.0 leaves the following unnnecessarily bloated function body for a non-microMIPS configuration: : 105c: afa50004 sw a1,4(sp) 1060: afa60008 sw a2,8(sp) 1064: afa7000c sw a3,12(sp) 1068: 03e00008 jr ra 106c: 00001021 move v0,zero which stores arguments that are never going to be used on the stack frame. Move mm_isBranchInstr() from cp1emu.c to branch.c, then split mm_isBranchInstr() into a __mm_isBranchInstr() core and a mm_isBranchInstr() wrapper inline function which only invokes __mm_isBranchInstr() on microMIPS configurations. This shaves off 112 bytes off the kernel and improves code flow a bit. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h index d109e34..de781cf 100644 --- a/arch/mips/include/asm/branch.h +++ b/arch/mips/include/asm/branch.h @@ -20,6 +20,24 @@ extern int __compute_return_epc_for_insn(struct pt_regs *regs, extern int __microMIPS_compute_return_epc(struct pt_regs *regs); extern int __MIPS16e_compute_return_epc(struct pt_regs *regs); +/* + * microMIPS bitfields + */ +#define MM_POOL32A_MINOR_MASK 0x3f +#define MM_POOL32A_MINOR_SHIFT 0x6 +#define MM_MIPS32_COND_FC 0x30 + +extern int __mm_isBranchInstr(struct pt_regs *regs, + struct mm_decoded_insn dec_insn, unsigned long *contpc); + +static inline int mm_isBranchInstr(struct pt_regs *regs, + struct mm_decoded_insn dec_insn, unsigned long *contpc) +{ + if (!cpu_has_mmips) + return 0; + + return __mm_isBranchInstr(regs, dec_insn, contpc); +} static inline int delay_slot(struct pt_regs *regs) { diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 4d78bf4..84888d9 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -48,6 +48,202 @@ int __isa_exception_epc(struct pt_regs *regs) return epc; } +/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */ +static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7}; + +int __mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, + unsigned long *contpc) +{ + union mips_instruction insn = (union mips_instruction)dec_insn.insn; + int bc_false = 0; + unsigned int fcr31; + unsigned int bit; + + if (!cpu_has_mmips) + return 0; + + switch (insn.mm_i_format.opcode) { + case mm_pool32a_op: + if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) == + mm_pool32axf_op) { + switch (insn.mm_i_format.simmediate >> + MM_POOL32A_MINOR_SHIFT) { + case mm_jalr_op: + case mm_jalrhb_op: + case mm_jalrs_op: + case mm_jalrshb_op: + if (insn.mm_i_format.rt != 0) /* Not mm_jr */ + regs->regs[insn.mm_i_format.rt] = + regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + *contpc = regs->regs[insn.mm_i_format.rs]; + return 1; + } + } + break; + case mm_pool32i_op: + switch (insn.mm_i_format.rt) { + case mm_bltzals_op: + case mm_bltzal_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ + case mm_bltz_op: + if ((long)regs->regs[insn.mm_i_format.rs] < 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + case mm_bgezals_op: + case mm_bgezal_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + /* Fall through */ + case mm_bgez_op: + if ((long)regs->regs[insn.mm_i_format.rs] >= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + case mm_blez_op: + if ((long)regs->regs[insn.mm_i_format.rs] <= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + case mm_bgtz_op: + if ((long)regs->regs[insn.mm_i_format.rs] <= 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + case mm_bc2f_op: + case mm_bc1f_op: + bc_false = 1; + /* Fall through */ + case mm_bc2t_op: + case mm_bc1t_op: + preempt_disable(); + if (is_fpu_owner()) + asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); + else + fcr31 = current->thread.fpu.fcr31; + preempt_enable(); + + if (bc_false) + fcr31 = ~fcr31; + + bit = (insn.mm_i_format.rs >> 2); + bit += (bit != 0); + bit += 23; + if (fcr31 & (1 << bit)) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + } + break; + case mm_pool16c_op: + switch (insn.mm_i_format.rt) { + case mm_jalr16_op: + case mm_jalrs16_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + /* Fall through */ + case mm_jr16_op: + *contpc = regs->regs[insn.mm_i_format.rs]; + return 1; + } + break; + case mm_beqz16_op: + if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_b1_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + case mm_bnez16_op: + if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_b1_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + case mm_b16_op: + *contpc = regs->cp0_epc + dec_insn.pc_inc + + (insn.mm_b0_format.simmediate << 1); + return 1; + case mm_beq32_op: + if (regs->regs[insn.mm_i_format.rs] == + regs->regs[insn.mm_i_format.rt]) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + dec_insn.next_pc_inc; + return 1; + case mm_bne32_op: + if (regs->regs[insn.mm_i_format.rs] != + regs->regs[insn.mm_i_format.rt]) + *contpc = regs->cp0_epc + + dec_insn.pc_inc + + (insn.mm_i_format.simmediate << 1); + else + *contpc = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + return 1; + case mm_jalx32_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + *contpc = regs->cp0_epc + dec_insn.pc_inc; + *contpc >>= 28; + *contpc <<= 28; + *contpc |= (insn.j_format.target << 2); + return 1; + case mm_jals32_op: + case mm_jal32_op: + regs->regs[31] = regs->cp0_epc + + dec_insn.pc_inc + dec_insn.next_pc_inc; + /* Fall through */ + case mm_j32_op: + *contpc = regs->cp0_epc + dec_insn.pc_inc; + *contpc >>= 27; + *contpc <<= 27; + *contpc |= (insn.j_format.target << 1); + set_isa16_mode(*contpc); + return 1; + } + return 0; +} + /* * Compute return address and emulate branch in microMIPS mode after an * exception only. It does not handle compact branches/jumps and cannot diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 6258291..b31ce6c 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -67,11 +67,6 @@ static int fpux_emu(struct pt_regs *, /* Determine rounding mode from the RM bits of the FCSR */ #define modeindex(v) ((v) & FPU_CSR_RM) -/* microMIPS bitfields */ -#define MM_POOL32A_MINOR_MASK 0x3f -#define MM_POOL32A_MINOR_SHIFT 0x6 -#define MM_MIPS32_COND_FC 0x30 - /* Convert MIPS rounding mode (0..3) to IEEE library modes. */ static const unsigned char ieee_rm[4] = { [FPU_CSR_RN] = IEEE754_RN, @@ -99,9 +94,6 @@ static const unsigned int fpucondbit[8] = { FPU_CSR_COND7 }; -/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */ -static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7}; - /* (microMIPS) Convert certain microMIPS instructions to MIPS32 format. */ static const int sd_format[] = {16, 17, 0, 0, 0, 0, 0, 0}; static const int sdps_format[] = {16, 17, 22, 0, 0, 0, 0, 0}; @@ -449,199 +441,6 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr) return 0; } -int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, - unsigned long *contpc) -{ - union mips_instruction insn = (union mips_instruction)dec_insn.insn; - int bc_false = 0; - unsigned int fcr31; - unsigned int bit; - - if (!cpu_has_mmips) - return 0; - - switch (insn.mm_i_format.opcode) { - case mm_pool32a_op: - if ((insn.mm_i_format.simmediate & MM_POOL32A_MINOR_MASK) == - mm_pool32axf_op) { - switch (insn.mm_i_format.simmediate >> - MM_POOL32A_MINOR_SHIFT) { - case mm_jalr_op: - case mm_jalrhb_op: - case mm_jalrs_op: - case mm_jalrshb_op: - if (insn.mm_i_format.rt != 0) /* Not mm_jr */ - regs->regs[insn.mm_i_format.rt] = - regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - *contpc = regs->regs[insn.mm_i_format.rs]; - return 1; - } - } - break; - case mm_pool32i_op: - switch (insn.mm_i_format.rt) { - case mm_bltzals_op: - case mm_bltzal_op: - regs->regs[31] = regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - /* Fall through */ - case mm_bltz_op: - if ((long)regs->regs[insn.mm_i_format.rs] < 0) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_i_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - return 1; - case mm_bgezals_op: - case mm_bgezal_op: - regs->regs[31] = regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - /* Fall through */ - case mm_bgez_op: - if ((long)regs->regs[insn.mm_i_format.rs] >= 0) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_i_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - return 1; - case mm_blez_op: - if ((long)regs->regs[insn.mm_i_format.rs] <= 0) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_i_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - return 1; - case mm_bgtz_op: - if ((long)regs->regs[insn.mm_i_format.rs] <= 0) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_i_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - return 1; - case mm_bc2f_op: - case mm_bc1f_op: - bc_false = 1; - /* Fall through */ - case mm_bc2t_op: - case mm_bc1t_op: - preempt_disable(); - if (is_fpu_owner()) - asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); - else - fcr31 = current->thread.fpu.fcr31; - preempt_enable(); - - if (bc_false) - fcr31 = ~fcr31; - - bit = (insn.mm_i_format.rs >> 2); - bit += (bit != 0); - bit += 23; - if (fcr31 & (1 << bit)) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_i_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + dec_insn.next_pc_inc; - return 1; - } - break; - case mm_pool16c_op: - switch (insn.mm_i_format.rt) { - case mm_jalr16_op: - case mm_jalrs16_op: - regs->regs[31] = regs->cp0_epc + - dec_insn.pc_inc + dec_insn.next_pc_inc; - /* Fall through */ - case mm_jr16_op: - *contpc = regs->regs[insn.mm_i_format.rs]; - return 1; - } - break; - case mm_beqz16_op: - if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] == 0) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_b1_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + dec_insn.next_pc_inc; - return 1; - case mm_bnez16_op: - if ((long)regs->regs[reg16to32map[insn.mm_b1_format.rs]] != 0) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_b1_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + dec_insn.next_pc_inc; - return 1; - case mm_b16_op: - *contpc = regs->cp0_epc + dec_insn.pc_inc + - (insn.mm_b0_format.simmediate << 1); - return 1; - case mm_beq32_op: - if (regs->regs[insn.mm_i_format.rs] == - regs->regs[insn.mm_i_format.rt]) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_i_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - dec_insn.next_pc_inc; - return 1; - case mm_bne32_op: - if (regs->regs[insn.mm_i_format.rs] != - regs->regs[insn.mm_i_format.rt]) - *contpc = regs->cp0_epc + - dec_insn.pc_inc + - (insn.mm_i_format.simmediate << 1); - else - *contpc = regs->cp0_epc + - dec_insn.pc_inc + dec_insn.next_pc_inc; - return 1; - case mm_jalx32_op: - regs->regs[31] = regs->cp0_epc + - dec_insn.pc_inc + dec_insn.next_pc_inc; - *contpc = regs->cp0_epc + dec_insn.pc_inc; - *contpc >>= 28; - *contpc <<= 28; - *contpc |= (insn.j_format.target << 2); - return 1; - case mm_jals32_op: - case mm_jal32_op: - regs->regs[31] = regs->cp0_epc + - dec_insn.pc_inc + dec_insn.next_pc_inc; - /* Fall through */ - case mm_j32_op: - *contpc = regs->cp0_epc + dec_insn.pc_inc; - *contpc >>= 27; - *contpc <<= 27; - *contpc |= (insn.j_format.target << 1); - set_isa16_mode(*contpc); - return 1; - } - return 0; -} - /* * Redundant with logic already in kernel/branch.c, * embedded in compute_return_epc. At some point, -- cgit v0.10.2 From aef3fb76aa1390ef864db888d06d8fcd5510df2d Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 30 Apr 2014 01:17:19 +0200 Subject: MIPS: math-emu: Nuke alternative names for IEEE-754 rounding modes. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index 109878a..0384c09 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -139,7 +139,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) oldcsr.sx |= IEEE754_INEXACT; switch (oldcsr.rm) { - case IEEE754_RP: + case IEEE754_RU: y.bits += 1; /* drop through */ case IEEE754_RN: diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index fb2fb6b..2fa939c 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -133,10 +133,6 @@ enum { #define IEEE754_RD 2 /* round toward -Infinity */ #define IEEE754_RU 3 /* round toward +Infinity */ -/* other naming */ -#define IEEE754_RM IEEE754_RD -#define IEEE754_RP IEEE754_RU - /* "normal" comparisons */ static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y) diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index 33b3e00..94f5bef 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -100,7 +100,7 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) if (ix != 0) { ieee754_setcx(IEEE754_INEXACT); switch (ieee754_csr.rm) { - case IEEE754_RP: + case IEEE754_RU: q += 2; break; case IEEE754_RN: -- cgit v0.10.2 From 56a6473339dbd2e908cf8c6f2856d5de2bf8d15b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 30 Apr 2014 11:21:55 +0200 Subject: MIPS: math-emu: Switch to using the MIPS rounding modes. Previously math-emu was using the IEEE-754 constants internally. These were differing by having the constants for rounding to +/- infinity switched, so a conversion was necessary. This would be entirely avoidable if the MIPS constants were used throughout, so get rid of the bloat. Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index b31ce6c..03e2332 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -67,21 +67,6 @@ static int fpux_emu(struct pt_regs *, /* Determine rounding mode from the RM bits of the FCSR */ #define modeindex(v) ((v) & FPU_CSR_RM) -/* Convert MIPS rounding mode (0..3) to IEEE library modes. */ -static const unsigned char ieee_rm[4] = { - [FPU_CSR_RN] = IEEE754_RN, - [FPU_CSR_RZ] = IEEE754_RZ, - [FPU_CSR_RU] = IEEE754_RU, - [FPU_CSR_RD] = IEEE754_RD, -}; -/* Convert IEEE library modes to MIPS rounding mode (0..3). */ -static const unsigned char mips_rm[4] = { - [IEEE754_RN] = FPU_CSR_RN, - [IEEE754_RZ] = FPU_CSR_RZ, - [IEEE754_RD] = FPU_CSR_RD, - [IEEE754_RU] = FPU_CSR_RU, -}; - /* convert condition code register number to csr bit */ static const unsigned int fpucondbit[8] = { FPU_CSR_COND0, @@ -907,8 +892,7 @@ emul: /* cop control register rd -> gpr[rt] */ if (MIPSInst_RD(ir) == FPCREG_CSR) { value = ctx->fcr31; - value = (value & ~FPU_CSR_RM) | - mips_rm[modeindex(value)]; + value = (value & ~FPU_CSR_RM) | modeindex(value); pr_debug("%p gpr[%d]<-csr=%08x\n", (void *) (xcp->cp0_epc), MIPSInst_RT(ir), value); @@ -939,9 +923,8 @@ emul: * Don't write reserved bits, * and convert to ieee library modes */ - ctx->fcr31 = (value & - ~(FPU_CSR_RSVD | FPU_CSR_RM)) | - ieee_rm[modeindex(value)]; + ctx->fcr31 = (value & ~(FPU_CSR_RSVD | FPU_CSR_RM)) | + modeindex(value); } if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { return SIGFPE; @@ -1515,7 +1498,7 @@ copcsr: oldrm = ieee754_csr.rm; SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; + ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); rv.w = ieee754sp_tint(fs); ieee754_csr.rm = oldrm; rfmt = w_fmt; @@ -1539,7 +1522,7 @@ copcsr: oldrm = ieee754_csr.rm; SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; + ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); rv.l = ieee754sp_tlong(fs); ieee754_csr.rm = oldrm; rfmt = l_fmt; @@ -1692,7 +1675,7 @@ dcopuop: oldrm = ieee754_csr.rm; DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; + ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); rv.w = ieee754dp_tint(fs); ieee754_csr.rm = oldrm; rfmt = w_fmt; @@ -1716,7 +1699,7 @@ dcopuop: oldrm = ieee754_csr.rm; DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))]; + ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir)); rv.l = ieee754dp_tlong(fs); ieee754_csr.rm = oldrm; rfmt = l_fmt; @@ -1926,11 +1909,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, * ieee754_csr. But ieee754_csr.rm is ieee * library modes. (not mips rounding mode) */ - /* convert to ieee library modes */ - ieee754_csr.rm = ieee_rm[ieee754_csr.rm]; sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr); - /* revert to mips rounding mode */ - ieee754_csr.rm = mips_rm[ieee754_csr.rm]; } if (has_fpu) diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c index 9c98b96..7f64577 100644 --- a/arch/mips/math-emu/dp_add.c +++ b/arch/mips/math-emu/dp_add.c @@ -91,7 +91,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) if (xs == ys) return x; else - return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD); + return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -168,7 +168,7 @@ union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) xs = ys; } if (xm == 0) - return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD); + return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD); /* * Normalize to rounding precision. diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c index 0384c09..041bbb61 100644 --- a/arch/mips/math-emu/dp_sqrt.c +++ b/arch/mips/math-emu/dp_sqrt.c @@ -80,7 +80,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) oldcsr = ieee754_csr; ieee754_csr.mx &= ~IEEE754_INEXACT; ieee754_csr.sx &= ~IEEE754_INEXACT; - ieee754_csr.rm = IEEE754_RN; + ieee754_csr.rm = FPU_CSR_RN; /* adjust exponent to prevent overflow */ scalx = 0; @@ -122,7 +122,7 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) /* twiddle last bit to force y correctly rounded */ /* set RZ, clear INEX flag */ - ieee754_csr.rm = IEEE754_RZ; + ieee754_csr.rm = FPU_CSR_RZ; ieee754_csr.sx &= ~IEEE754_INEXACT; /* t=x/y; ...chopped quotient, possibly inexact */ @@ -139,10 +139,10 @@ union ieee754dp ieee754dp_sqrt(union ieee754dp x) oldcsr.sx |= IEEE754_INEXACT; switch (oldcsr.rm) { - case IEEE754_RU: + case FPU_CSR_RU: y.bits += 1; /* drop through */ - case IEEE754_RN: + case FPU_CSR_RN: t.bits += 1; break; } diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c index d502984..7a17402 100644 --- a/arch/mips/math-emu/dp_sub.c +++ b/arch/mips/math-emu/dp_sub.c @@ -91,7 +91,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) if (xs != ys) return x; else - return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD); + return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -171,7 +171,7 @@ union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y) xs = ys; } if (xm == 0) { - if (ieee754_csr.rm == IEEE754_RD) + if (ieee754_csr.rm == FPU_CSR_RD) return ieee754dp_zero(1); /* round negative inf. => sign = -1 */ else return ieee754dp_zero(0); /* other round modes => sign = 1 */ diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c index 972dba0..6ffc336 100644 --- a/arch/mips/math-emu/dp_tint.c +++ b/arch/mips/math-emu/dp_tint.c @@ -74,17 +74,17 @@ int ieee754dp_tint(union ieee754dp x) to be zero */ odd = (xm & 0x1) != 0x0; switch (ieee754_csr.rm) { - case IEEE754_RN: + case FPU_CSR_RN: if (round && (sticky || odd)) xm++; break; - case IEEE754_RZ: + case FPU_CSR_RZ: break; - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if ((round || sticky) && !xs) xm++; break; - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if ((round || sticky) && xs) xm++; break; diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c index afaf953..9cdc145 100644 --- a/arch/mips/math-emu/dp_tlong.c +++ b/arch/mips/math-emu/dp_tlong.c @@ -79,17 +79,17 @@ s64 ieee754dp_tlong(union ieee754dp x) } odd = (xm & 0x1) != 0x0; switch (ieee754_csr.rm) { - case IEEE754_RN: + case FPU_CSR_RN: if (round && (sticky || odd)) xm++; break; - case IEEE754_RZ: + case FPU_CSR_RZ: break; - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if ((round || sticky) && !xs) xm++; break; - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if ((round || sticky) && xs) xm++; break; diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h index 2fa939c..43c4fb5 100644 --- a/arch/mips/math-emu/ieee754.h +++ b/arch/mips/math-emu/ieee754.h @@ -126,13 +126,6 @@ enum { #define IEEE754_CGT 0x04 #define IEEE754_CUN 0x08 -/* rounding mode -*/ -#define IEEE754_RN 0 /* round to nearest */ -#define IEEE754_RZ 1 /* round toward zero */ -#define IEEE754_RD 2 /* round toward -Infinity */ -#define IEEE754_RU 3 /* round toward +Infinity */ - /* "normal" comparisons */ static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y) diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c index 087a6f3..fd13467 100644 --- a/arch/mips/math-emu/ieee754dp.c +++ b/arch/mips/math-emu/ieee754dp.c @@ -67,17 +67,17 @@ static u64 ieee754dp_get_rounding(int sn, u64 xm) */ if (xm & (DP_MBIT(3) - 1)) { switch (ieee754_csr.rm) { - case IEEE754_RZ: + case FPU_CSR_RZ: break; - case IEEE754_RN: + case FPU_CSR_RN: xm += 0x3 + ((xm >> 3) & 1); /* xm += (xm&0x8)?0x4:0x3 */ break; - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if (!sn) /* ?? */ xm += 0x8; break; - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if (sn) /* ?? */ xm += 0x8; break; @@ -108,15 +108,15 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) ieee754_setcx(IEEE754_INEXACT); switch(ieee754_csr.rm) { - case IEEE754_RN: - case IEEE754_RZ: + case FPU_CSR_RN: + case FPU_CSR_RZ: return ieee754dp_zero(sn); - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if (sn == 0) return ieee754dp_min(0); else return ieee754dp_zero(1); - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if (sn == 0) return ieee754dp_zero(0); else @@ -172,16 +172,16 @@ union ieee754dp ieee754dp_format(int sn, int xe, u64 xm) ieee754_setcx(IEEE754_INEXACT); /* -O can be table indexed by (rm,sn) */ switch (ieee754_csr.rm) { - case IEEE754_RN: + case FPU_CSR_RN: return ieee754dp_inf(sn); - case IEEE754_RZ: + case FPU_CSR_RZ: return ieee754dp_max(sn); - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if (sn == 0) return ieee754dp_inf(0); else return ieee754dp_max(1); - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if (sn == 0) return ieee754dp_max(0); else diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c index e4cec15..d348efe 100644 --- a/arch/mips/math-emu/ieee754sp.c +++ b/arch/mips/math-emu/ieee754sp.c @@ -67,17 +67,17 @@ static unsigned ieee754sp_get_rounding(int sn, unsigned xm) */ if (xm & (SP_MBIT(3) - 1)) { switch (ieee754_csr.rm) { - case IEEE754_RZ: + case FPU_CSR_RZ: break; - case IEEE754_RN: + case FPU_CSR_RN: xm += 0x3 + ((xm >> 3) & 1); /* xm += (xm&0x8)?0x4:0x3 */ break; - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if (!sn) /* ?? */ xm += 0x8; break; - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if (sn) /* ?? */ xm += 0x8; break; @@ -108,15 +108,15 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) ieee754_setcx(IEEE754_INEXACT); switch(ieee754_csr.rm) { - case IEEE754_RN: - case IEEE754_RZ: + case FPU_CSR_RN: + case FPU_CSR_RZ: return ieee754sp_zero(sn); - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if (sn == 0) return ieee754sp_min(0); else return ieee754sp_zero(1); - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if (sn == 0) return ieee754sp_zero(0); else @@ -170,16 +170,16 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) ieee754_setcx(IEEE754_INEXACT); /* -O can be table indexed by (rm,sn) */ switch (ieee754_csr.rm) { - case IEEE754_RN: + case FPU_CSR_RN: return ieee754sp_inf(sn); - case IEEE754_RZ: + case FPU_CSR_RZ: return ieee754sp_max(sn); - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if (sn == 0) return ieee754sp_inf(0); else return ieee754sp_max(1); - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if (sn == 0) return ieee754sp_max(0); else diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c index a0bc95c..2d84d46 100644 --- a/arch/mips/math-emu/sp_add.c +++ b/arch/mips/math-emu/sp_add.c @@ -91,7 +91,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) if (xs == ys) return x; else - return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD); + return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -165,7 +165,7 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y) xs = ys; } if (xm == 0) - return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD); + return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD); /* * Normalize in extended single precision diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c index 90b9ec4..1b266fb 100644 --- a/arch/mips/math-emu/sp_fdp.c +++ b/arch/mips/math-emu/sp_fdp.c @@ -57,8 +57,8 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x) /* can't possibly be sp representable */ ieee754_setcx(IEEE754_UNDERFLOW); ieee754_setcx(IEEE754_INEXACT); - if ((ieee754_csr.rm == IEEE754_RU && !xs) || - (ieee754_csr.rm == IEEE754_RD && xs)) + if ((ieee754_csr.rm == FPU_CSR_RU && !xs) || + (ieee754_csr.rm == FPU_CSR_RD && xs)) return ieee754sp_mind(xs); return ieee754sp_zero(xs); diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c index 94f5bef..b7c098a 100644 --- a/arch/mips/math-emu/sp_sqrt.c +++ b/arch/mips/math-emu/sp_sqrt.c @@ -100,10 +100,10 @@ union ieee754sp ieee754sp_sqrt(union ieee754sp x) if (ix != 0) { ieee754_setcx(IEEE754_INEXACT); switch (ieee754_csr.rm) { - case IEEE754_RU: + case FPU_CSR_RU: q += 2; break; - case IEEE754_RN: + case FPU_CSR_RN: q += (q & 1); break; } diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c index e813f4f..8592e49 100644 --- a/arch/mips/math-emu/sp_sub.c +++ b/arch/mips/math-emu/sp_sub.c @@ -91,7 +91,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) if (xs != ys) return x; else - return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD); + return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD); case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): @@ -165,7 +165,7 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y) xs = ys; } if (xm == 0) { - if (ieee754_csr.rm == IEEE754_RD) + if (ieee754_csr.rm == FPU_CSR_RD) return ieee754sp_zero(1); /* round negative inf. => sign = -1 */ else return ieee754sp_zero(0); /* other round modes => sign = 1 */ diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c index e1dee56..091299a 100644 --- a/arch/mips/math-emu/sp_tint.c +++ b/arch/mips/math-emu/sp_tint.c @@ -79,17 +79,17 @@ int ieee754sp_tint(union ieee754sp x) } odd = (xm & 0x1) != 0x0; switch (ieee754_csr.rm) { - case IEEE754_RN: + case FPU_CSR_RN: if (round && (sticky || odd)) xm++; break; - case IEEE754_RZ: + case FPU_CSR_RZ: break; - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if ((round || sticky) && !xs) xm++; break; - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if ((round || sticky) && xs) xm++; break; diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c index 67eff6b..9f3c742 100644 --- a/arch/mips/math-emu/sp_tlong.c +++ b/arch/mips/math-emu/sp_tlong.c @@ -76,17 +76,17 @@ s64 ieee754sp_tlong(union ieee754sp x) } odd = (xm & 0x1) != 0x0; switch (ieee754_csr.rm) { - case IEEE754_RN: + case FPU_CSR_RN: if (round && (sticky || odd)) xm++; break; - case IEEE754_RZ: + case FPU_CSR_RZ: break; - case IEEE754_RU: /* toward +Infinity */ + case FPU_CSR_RU: /* toward +Infinity */ if ((round || sticky) && !xs) xm++; break; - case IEEE754_RD: /* toward -Infinity */ + case FPU_CSR_RD: /* toward -Infinity */ if ((round || sticky) && xs) xm++; break; -- cgit v0.10.2 From 70e4c234aa48e11c0575364939dfab4cb27b2172 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 30 Apr 2014 11:09:44 +0200 Subject: MIPS: math-emu: Reduce microMIPS bloat. Move microMIPS32_to_MIPS32() to a separate file which only gets built for mipsMIPS configurations; for other configurations the optimizer eleminates calls to microMIPS32_to_MIPS32(). Signed-off-by: Ralf Baechle diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 03e2332..08e6a74 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -709,6 +709,13 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, u64 dval; int sig; + /* + * These are giving gcc a gentle hint about what to expect in + * dec_inst in order to do better optimization. + */ + if (!cpu_has_mmips && dec_insn.micro_mips_mode) + unreachable(); + /* XXX NEC Vr54xx bug workaround */ if (delay_slot(xcp)) { if (dec_insn.micro_mips_mode) { -- cgit v0.10.2 From c836732fa058a62bb8f30a7a03f776f6c488fa58 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 09:55:02 +0200 Subject: MIPS: c-r4k: Call R4600_HIT_CACHEOP_WAR_IMPL only for 32 byte cache lines. R4600_HIT_CACHEOP_WAR_IMPL is only needed on R4600 v1.6 and the R4600 has data cache lines that are always 32 bytes so the call is pointless in r4k_blast_dcache_page_dc64. Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 1c74a6a..7bc14ff 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -105,7 +105,6 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr) static inline void r4k_blast_dcache_page_dc64(unsigned long addr) { - R4600_HIT_CACHEOP_WAR_IMPL; blast_dcache64_page(addr); } -- cgit v0.10.2 From af59674f64db85c31583b49f0b36c158e6e8d9eb Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 20 May 2014 12:50:55 +0200 Subject: MIPS: Remove check for CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC A check for CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC was added in v2.6.29, but without the related Kconfig symbol. Remove this check. Also remove the test for an "ecc_verbose" kernel parameter. It is undocumented and has no effect anyway. Signed-off-by: Paul Bolle Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6955/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 331b837..953ca85 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -779,12 +779,6 @@ void __init prom_init(void) MAX_MEMORY = 32ull << 30; if (*p == '@') RESERVE_LOW_MEM = memparse(p + 1, &p); - } else if (strcmp(arg, "ecc_verbose") == 0) { -#ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC - __cvmx_interrupt_ecc_report_single_bit_errors = 1; - pr_notice("Reporting of single bit ECC errors is " - "turned on\n"); -#endif #ifdef CONFIG_KEXEC } else if (strncmp(arg, "crashkernel=", 12) == 0) { crashk_size = memparse(arg+12, &p); -- cgit v0.10.2 From 261cbc97abc673e575ef6a1a95ed6ada68f04e78 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 20 May 2014 13:34:36 +0200 Subject: MIPS: Remove CONFIG_PMCTWILED completely Commit 8b284dbc2200 ("MIPS: PNX Removing dead CONFIG_PMCTWILED") missed one reference to CONFIG_PMCTWILED in the code. It also missed one related reference to pmctwiled_setup(). Remove these references now. Signed-off-by: Paul Bolle Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6957/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pmcs-msp71xx/msp_setup.c b/arch/mips/pmcs-msp71xx/msp_setup.c index 7e98076..ba9d518 100644 --- a/arch/mips/pmcs-msp71xx/msp_setup.c +++ b/arch/mips/pmcs-msp71xx/msp_setup.c @@ -27,7 +27,6 @@ #endif extern void msp_serial_setup(void); -extern void pmctwiled_setup(void); #if defined(CONFIG_PMC_MSP7120_EVAL) || \ defined(CONFIG_PMC_MSP7120_GW) || \ @@ -235,12 +234,4 @@ void __init prom_init(void) register_smp_ops(&msp_smtc_smp_ops); #endif } - -#ifdef CONFIG_PMCTWILED - /* - * Setup LED states before the subsys_initcall loads other - * dependent drivers/modules. - */ - pmctwiled_setup(); -#endif } -- cgit v0.10.2 From 23634fd3ae24cee64cfb0377a1cdcd595bba749d Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 20 May 2014 13:42:03 +0200 Subject: MIPS: PNX833x: Remove checks for CONFIG_I2C_PNX0105 Checks for CONFIG_I2C_PNX0105 were added in v2.6.28. But the related Kconfig symbol has not been added to the tree. Remove these checks. Signed-off-by: Paul Bolle Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6958/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pnx833x/common/platform.c b/arch/mips/pnx833x/common/platform.c index 2b7e837..b4b774b 100644 --- a/arch/mips/pnx833x/common/platform.c +++ b/arch/mips/pnx833x/common/platform.c @@ -33,11 +33,6 @@ #include #include -#ifdef CONFIG_I2C_PNX0105 -/* Until i2c driver available in kernel.*/ -#include -#endif - #include #include #include @@ -134,70 +129,6 @@ static struct platform_device pnx833x_usb_ehci_device = { .resource = pnx833x_usb_ehci_resources, }; -#ifdef CONFIG_I2C_PNX0105 -static struct resource pnx833x_i2c0_resources[] = { - { - .start = PNX833X_I2C0_PORTS_START, - .end = PNX833X_I2C0_PORTS_END, - .flags = IORESOURCE_MEM, - }, - { - .start = PNX833X_PIC_I2C0_INT, - .end = PNX833X_PIC_I2C0_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource pnx833x_i2c1_resources[] = { - { - .start = PNX833X_I2C1_PORTS_START, - .end = PNX833X_I2C1_PORTS_END, - .flags = IORESOURCE_MEM, - }, - { - .start = PNX833X_PIC_I2C1_INT, - .end = PNX833X_PIC_I2C1_INT, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct i2c_pnx0105_dev pnx833x_i2c_dev[] = { - { - .base = PNX833X_I2C0_PORTS_START, - .irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */ - .clock = 6, /* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Preferred HDCP) */ - .bus_addr = 0, /* no slave support */ - }, - { - .base = PNX833X_I2C1_PORTS_START, - .irq = -1, /* on high freq, polling is faster */ - /*.irq = PNX833X_PIC_I2C1_INT,*/ - .clock = 4, /* 0 == 400 kHz, 4 == 100 kHz. 100 kHz seems a safe default for now */ - .bus_addr = 0, /* no slave support */ - }, -}; - -static struct platform_device pnx833x_i2c0_device = { - .name = "i2c-pnx0105", - .id = 0, - .dev = { - .platform_data = &pnx833x_i2c_dev[0], - }, - .num_resources = ARRAY_SIZE(pnx833x_i2c0_resources), - .resource = pnx833x_i2c0_resources, -}; - -static struct platform_device pnx833x_i2c1_device = { - .name = "i2c-pnx0105", - .id = 1, - .dev = { - .platform_data = &pnx833x_i2c_dev[1], - }, - .num_resources = ARRAY_SIZE(pnx833x_i2c1_resources), - .resource = pnx833x_i2c1_resources, -}; -#endif - static u64 ethernet_dmamask = DMA_BIT_MASK(32); static struct resource pnx833x_ethernet_resources[] = { @@ -294,10 +225,6 @@ static struct platform_device pnx833x_flash_nand = { static struct platform_device *pnx833x_platform_devices[] __initdata = { &pnx833x_uart_device, &pnx833x_usb_ehci_device, -#ifdef CONFIG_I2C_PNX0105 - &pnx833x_i2c0_device, - &pnx833x_i2c1_device, -#endif &pnx833x_ethernet_device, &pnx833x_sata_device, &pnx833x_flash_nand, -- cgit v0.10.2 From d83d44c0e03737d201681c927d6707ae4f283720 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 20 May 2014 18:16:14 +0200 Subject: MIPS: Octeon: Remove checks for CONFIG_CAVIUM_GDB Three checks for CONFIG_CAVIUM_GDB were added in v2.6.29. But the Kconfig symbol CAVIUM_GDB was never added to the tree. Remove these checks. Also remove the last reference to octeon_get_boot_debug_flag(). There is no definition of that function anyway. Signed-off-by: Paul Bolle Tested-by: Andreas Herrmann ) Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6976/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 953ca85..989781f 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -729,17 +729,6 @@ void __init prom_init(void) octeon_write_lcd("Linux"); #endif -#ifdef CONFIG_CAVIUM_GDB - /* - * When debugging the linux kernel, force the cores to enter - * the debug exception handler to break in. - */ - if (octeon_get_boot_debug_flag()) { - cvmx_write_csr(CVMX_CIU_DINT, 1 << cvmx_get_core_num()); - cvmx_read_csr(CVMX_CIU_DINT); - } -#endif - octeon_setup_delays(); /* diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 67a078f..78e1abe 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -218,15 +218,6 @@ void octeon_prepare_cpus(unsigned int max_cpus) */ static void octeon_smp_finish(void) { -#ifdef CONFIG_CAVIUM_GDB - unsigned long tmp; - /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0 - to be not masked by this core so we know the signal is received by - someone */ - asm volatile ("dmfc0 %0, $22\n" - "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp)); -#endif - octeon_user_io_init(); /* to generate the first CPU timer interrupt */ @@ -239,14 +230,6 @@ static void octeon_smp_finish(void) */ static void octeon_cpus_done(void) { -#ifdef CONFIG_CAVIUM_GDB - unsigned long tmp; - /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0 - to be not masked by this core so we know the signal is received by - someone */ - asm volatile ("dmfc0 %0, $22\n" - "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp)); -#endif } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index f5d77b9..d781f9e 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -211,7 +211,6 @@ union octeon_cvmemctl { extern void octeon_write_lcd(const char *s); extern void octeon_check_cpu_bist(void); -extern int octeon_get_boot_debug_flag(void); extern int octeon_get_boot_uart(void); struct uart_port; -- cgit v0.10.2 From d493a85c0486b6240e71db63d1454eab6c3be683 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 22 May 2014 11:34:51 +0200 Subject: MIPS: MSP71xx: Remove checks for two macros Since v2.6.39 there are checks for CONFIG_MSP_HAS_DUAL_USB and checks for CONFIG_MSP_HAS_TSMAC in the code. The related Kconfig symbols have never been added. These checks have evaluated to false for three years now. Remove them and the code they have been hiding. Signed-off-by: Paul Bolle Cc: Alan Stern Cc: Greg Kroah-Hartman Cc: linux-mips@linux-mips.org Cc: linux-usb@vger.kernel.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6982/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h index aa45e6a..fe1566f 100644 --- a/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h +++ b/arch/mips/include/asm/mach-pmcs-msp71xx/msp_usb.h @@ -25,11 +25,7 @@ #ifndef MSP_USB_H_ #define MSP_USB_H_ -#ifdef CONFIG_MSP_HAS_DUAL_USB -#define NUM_USB_DEVS 2 -#else #define NUM_USB_DEVS 1 -#endif /* Register spaces for USB host 0 */ #define MSP_USB0_MAB_START (MSP_USB0_BASE + 0x0) diff --git a/arch/mips/pmcs-msp71xx/msp_eth.c b/arch/mips/pmcs-msp71xx/msp_eth.c index c584df3..15679b4 100644 --- a/arch/mips/pmcs-msp71xx/msp_eth.c +++ b/arch/mips/pmcs-msp71xx/msp_eth.c @@ -38,73 +38,6 @@ #define MSP_ETHERNET_GPIO1 15 #define MSP_ETHERNET_GPIO2 16 -#ifdef CONFIG_MSP_HAS_TSMAC -#define MSP_TSMAC_SIZE 0x10020 -#define MSP_TSMAC_ID "pmc_tsmac" - -static struct resource msp_tsmac0_resources[] = { - [0] = { - .start = MSP_MAC0_BASE, - .end = MSP_MAC0_BASE + MSP_TSMAC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_MAC0, - .end = MSP_INT_MAC0, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource msp_tsmac1_resources[] = { - [0] = { - .start = MSP_MAC1_BASE, - .end = MSP_MAC1_BASE + MSP_TSMAC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_MAC1, - .end = MSP_INT_MAC1, - .flags = IORESOURCE_IRQ, - }, -}; -static struct resource msp_tsmac2_resources[] = { - [0] = { - .start = MSP_MAC2_BASE, - .end = MSP_MAC2_BASE + MSP_TSMAC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_SAR, - .end = MSP_INT_SAR, - .flags = IORESOURCE_IRQ, - }, -}; - - -static struct platform_device tsmac_device[] = { - [0] = { - .name = MSP_TSMAC_ID, - .id = 0, - .num_resources = ARRAY_SIZE(msp_tsmac0_resources), - .resource = msp_tsmac0_resources, - }, - [1] = { - .name = MSP_TSMAC_ID, - .id = 1, - .num_resources = ARRAY_SIZE(msp_tsmac1_resources), - .resource = msp_tsmac1_resources, - }, - [2] = { - .name = MSP_TSMAC_ID, - .id = 2, - .num_resources = ARRAY_SIZE(msp_tsmac2_resources), - .resource = msp_tsmac2_resources, - }, -}; -#define msp_eth_devs tsmac_device - -#else -/* If it is not TSMAC assume MSP_ETH (100Mbps) */ #define MSP_ETH_ID "pmc_mspeth" #define MSP_ETH_SIZE 0xE0 static struct resource msp_eth0_resources[] = { @@ -152,7 +85,6 @@ static struct platform_device mspeth_device[] = { }; #define msp_eth_devs mspeth_device -#endif int __init msp_eth_setup(void) { int i, ret = 0; @@ -161,14 +93,6 @@ int __init msp_eth_setup(void) msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO0); msp_gpio_pin_hi(MSP_ETHERNET_GPIO0); -#ifdef CONFIG_MSP_HAS_TSMAC - /* 3 phys on boards with TSMAC */ - msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO1); - msp_gpio_pin_hi(MSP_ETHERNET_GPIO1); - - msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO2); - msp_gpio_pin_hi(MSP_ETHERNET_GPIO2); -#endif for (i = 0; i < ARRAY_SIZE(msp_eth_devs); i++) { ret = platform_device_register(&msp_eth_devs[i]); printk(KERN_INFO "device: %d, return value = %d\n", i, ret); diff --git a/arch/mips/pmcs-msp71xx/msp_usb.c b/arch/mips/pmcs-msp71xx/msp_usb.c index 4dab915..c87c5f8 100644 --- a/arch/mips/pmcs-msp71xx/msp_usb.c +++ b/arch/mips/pmcs-msp71xx/msp_usb.c @@ -75,47 +75,6 @@ static struct mspusb_device msp_usbhost0_device = { .resource = msp_usbhost0_resources, }, }; - -/* MSP7140/MSP82XX has two USB2 hosts. */ -#ifdef CONFIG_MSP_HAS_DUAL_USB -static u64 msp_usbhost1_dma_mask = 0xffffffffUL; - -static struct resource msp_usbhost1_resources[] = { - [0] = { /* EHCI-HS operational and capabilities registers */ - .start = MSP_USB1_HS_START, - .end = MSP_USB1_HS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_USB, - .end = MSP_INT_USB, - .flags = IORESOURCE_IRQ, - }, - [2] = { /* MSBus-to-AMBA bridge register space */ - .start = MSP_USB1_MAB_START, - .end = MSP_USB1_MAB_END, - .flags = IORESOURCE_MEM, - }, - [3] = { /* Identification and general hardware parameters */ - .start = MSP_USB1_ID_START, - .end = MSP_USB1_ID_END, - .flags = IORESOURCE_MEM, - }, -}; - -static struct mspusb_device msp_usbhost1_device = { - .dev = { - .name = "pmcmsp-ehci", - .id = 1, - .dev = { - .dma_mask = &msp_usbhost1_dma_mask, - .coherent_dma_mask = 0xffffffffUL, - }, - .num_resources = ARRAY_SIZE(msp_usbhost1_resources), - .resource = msp_usbhost1_resources, - }, -}; -#endif /* CONFIG_MSP_HAS_DUAL_USB */ #endif /* CONFIG_USB_EHCI_HCD */ #if defined(CONFIG_USB_GADGET) @@ -157,46 +116,6 @@ static struct mspusb_device msp_usbdev0_device = { .resource = msp_usbdev0_resources, }, }; - -#ifdef CONFIG_MSP_HAS_DUAL_USB -static struct resource msp_usbdev1_resources[] = { - [0] = { /* EHCI-HS operational and capabilities registers */ - .start = MSP_USB1_HS_START, - .end = MSP_USB1_HS_END, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MSP_INT_USB, - .end = MSP_INT_USB, - .flags = IORESOURCE_IRQ, - }, - [2] = { /* MSBus-to-AMBA bridge register space */ - .start = MSP_USB1_MAB_START, - .end = MSP_USB1_MAB_END, - .flags = IORESOURCE_MEM, - }, - [3] = { /* Identification and general hardware parameters */ - .start = MSP_USB1_ID_START, - .end = MSP_USB1_ID_END, - .flags = IORESOURCE_MEM, - }, -}; - -/* This may need to be converted to a mspusb_device, too. */ -static struct mspusb_device msp_usbdev1_device = { - .dev = { - .name = "msp71xx_udc", - .id = 0, - .dev = { - .dma_mask = &msp_usbdev_dma_mask, - .coherent_dma_mask = 0xffffffffUL, - }, - .num_resources = ARRAY_SIZE(msp_usbdev1_resources), - .resource = msp_usbdev1_resources, - }, -}; - -#endif /* CONFIG_MSP_HAS_DUAL_USB */ #endif /* CONFIG_USB_GADGET */ static int __init msp_usb_setup(void) @@ -231,10 +150,6 @@ static int __init msp_usb_setup(void) #if defined(CONFIG_USB_EHCI_HCD) msp_devs[0] = &msp_usbhost0_device.dev; ppfinit("platform add USB HOST done %s.\n", msp_devs[0]->name); -#ifdef CONFIG_MSP_HAS_DUAL_USB - msp_devs[1] = &msp_usbhost1_device.dev; - ppfinit("platform add USB HOST done %s.\n", msp_devs[1]->name); -#endif #else ppfinit("%s: echi_hcd not supported\n", __FILE__); #endif /* CONFIG_USB_EHCI_HCD */ @@ -244,11 +159,6 @@ static int __init msp_usb_setup(void) msp_devs[0] = &msp_usbdev0_device.dev; ppfinit("platform add USB DEVICE done %s.\n" , msp_devs[0]->name); -#ifdef CONFIG_MSP_HAS_DUAL_USB - msp_devs[1] = &msp_usbdev1_device.dev; - ppfinit("platform add USB DEVICE done %s.\n" - , msp_devs[1]->name); -#endif #else ppfinit("%s: usb_gadget not supported\n", __FILE__); #endif /* CONFIG_USB_GADGET */ diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index af3974a..7d75465 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -68,9 +68,6 @@ static void usb_hcd_tdi_set_mode(struct ehci_hcd *ehci) /* set TWI GPIO USB_HOST_DEV pin high */ gpio_direction_output(MSP_PIN_USB0_HOST_DEV, 1); -#ifdef CONFIG_MSP_HAS_DUAL_USB - gpio_direction_output(MSP_PIN_USB1_HOST_DEV, 1); -#endif } /* called during probe() after chip reset completes */ @@ -248,33 +245,6 @@ void usb_hcd_msp_remove(struct usb_hcd *hcd, struct platform_device *dev) usb_put_hcd(hcd); } -#ifdef CONFIG_MSP_HAS_DUAL_USB -/* - * Wrapper around the main ehci_irq. Since both USB host controllers are - * sharing the same IRQ, need to first determine whether we're the intended - * recipient of this interrupt. - */ -static irqreturn_t ehci_msp_irq(struct usb_hcd *hcd) -{ - u32 int_src; - struct device *dev = hcd->self.controller; - struct platform_device *pdev; - struct mspusb_device *mdev; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - /* need to reverse-map a couple of containers to get our device */ - pdev = to_platform_device(dev); - mdev = to_mspusb_device(pdev); - - /* Check to see if this interrupt is for this host controller */ - int_src = ehci_readl(ehci, &mdev->mab_regs->int_stat); - if (int_src & (1 << pdev->id)) - return ehci_irq(hcd); - - /* Not for this device */ - return IRQ_NONE; -} -#endif /* DUAL_USB */ - static const struct hc_driver ehci_msp_hc_driver = { .description = hcd_name, .product_desc = "PMC MSP EHCI", @@ -283,11 +253,7 @@ static const struct hc_driver ehci_msp_hc_driver = { /* * generic hardware linkage */ -#ifdef CONFIG_MSP_HAS_DUAL_USB - .irq = ehci_msp_irq, -#else .irq = ehci_irq, -#endif .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, /* @@ -334,9 +300,6 @@ static int ehci_hcd_msp_drv_probe(struct platform_device *pdev) return -ENODEV; gpio_request(MSP_PIN_USB0_HOST_DEV, "USB0_HOST_DEV_GPIO"); -#ifdef CONFIG_MSP_HAS_DUAL_USB - gpio_request(MSP_PIN_USB1_HOST_DEV, "USB1_HOST_DEV_GPIO"); -#endif ret = usb_hcd_msp_probe(&ehci_msp_hc_driver, pdev); @@ -351,9 +314,6 @@ static int ehci_hcd_msp_drv_remove(struct platform_device *pdev) /* free TWI GPIO USB_HOST_DEV pin */ gpio_free(MSP_PIN_USB0_HOST_DEV); -#ifdef CONFIG_MSP_HAS_DUAL_USB - gpio_free(MSP_PIN_USB1_HOST_DEV); -#endif return 0; } -- cgit v0.10.2 From 66de4859e3072b75c7bb88f306287de6c1d5c4ce Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 22 May 2014 11:24:19 +0200 Subject: MIPS: BCM1480: Remove checks for CONFIG_SIBYTE_BCM1480_PROF There are two checks for CONFIG_SIBYTE_BCM1480_PROF in the tree since v2.6.15. The related Kconfig symbol has never been added to the tree. So these checks have always evaluated to false. Besides, one of these checks guards a call of sbprof_cpu_intr(). But that function is not defined. Remove all this. Signed-off-by: Paul Bolle Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6981/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 59cfe26..373fbbc8 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c @@ -347,19 +347,8 @@ asmlinkage void plat_irq_dispatch(void) unsigned int cpu = smp_processor_id(); unsigned int pending; -#ifdef CONFIG_SIBYTE_BCM1480_PROF - /* Set compare to count to silence count/compare timer interrupts */ - write_c0_compare(read_c0_count()); -#endif - pending = read_c0_cause() & read_c0_status(); -#ifdef CONFIG_SIBYTE_BCM1480_PROF - if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */ - sbprof_cpu_intr(); - else -#endif - if (pending & CAUSEF_IP4) do_IRQ(K_BCM1480_INT_TIMER_0 + cpu); #ifdef CONFIG_SMP -- cgit v0.10.2 From c106ff85e82f7385733e1e45fdab74a0634fe2c2 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 17:06:03 +0200 Subject: MIPS: Remove code protected by CONFIG_SYS_HAS_CPU_RM9000. RM9000 support was removed a while ago but this bit crept back in through commit 69f24d17 [MIPS: Optimize current_cpu_type() for better code.] which had been developed before but merged after RM9000 support was removed. Signed-off-by: Ralf Baechle Reported-by: Paul Bolle diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index 72190613..e3308b4 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -155,9 +155,6 @@ static inline int __pure __get_cpu_type(const int cpu_type) case CPU_RM7000: case CPU_SR71000: #endif -#ifdef CONFIG_SYS_HAS_CPU_RM9000 - case CPU_RM9000: -#endif #ifdef CONFIG_SYS_HAS_CPU_SB1 case CPU_SB1: case CPU_SB1A: -- cgit v0.10.2 From 8a8bbf2a93c8c57db58b3981ff31670bc30a5fc3 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 17:13:59 +0200 Subject: MIPS: Ralink: Remove surviving RM9000 bits. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-ralink/war.h b/arch/mips/include/asm/mach-ralink/war.h index a7b712c..c074b5d 100644 --- a/arch/mips/include/asm/mach-ralink/war.h +++ b/arch/mips/include/asm/mach-ralink/war.h @@ -17,7 +17,6 @@ #define MIPS4K_ICACHE_REFILL_WAR 0 #define MIPS_CACHE_SYNC_WAR 0 #define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define RM9000_CDEX_SMP_WAR 0 #define ICACHE_REFILLS_WORKAROUND_WAR 0 #define R10000_LLSC_WAR 0 #define MIPS34K_MISSED_ITLB_WAR 0 -- cgit v0.10.2 From 9ef988ddb0bd36687501079333e2d8a1c31c5318 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 17:19:20 +0200 Subject: MIPS: RM9000: Remove support for idle loop. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 837ff27..5e3b653 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -224,10 +224,6 @@ void __init check_wait(void) cpu_wait = r4k_wait; */ break; - case CPU_RM9000: - if ((c->processor_id & 0x00ff) >= 0x40) - cpu_wait = r4k_wait; - break; default: break; } -- cgit v0.10.2 From 722640a9898195c94a60b9773176dd9ea0892229 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 17:21:13 +0200 Subject: MIPS: RM9000: Remove support for probing the CPU core. Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 6e8fb85..f83dc70 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -684,21 +684,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) */ c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; break; - case PRID_IMP_RM9000: - c->cputype = CPU_RM9000; - __cpu_name[cpu] = "RM9000"; - set_isa(c, MIPS_CPU_ISA_IV); - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; - /* - * Bit 29 in the info register of the RM9000 - * indicates if the TLB has 48 or 64 entries. - * - * 29 1 => 64 entry JTLB - * 0 => 48 entry JTLB - */ - c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; - break; case PRID_IMP_R8000: c->cputype = CPU_R8000; __cpu_name[cpu] = "RM8000"; -- cgit v0.10.2 From 321b1863ff32a5900e1d8c10a8420b9a8df6c555 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 22 May 2014 17:22:41 +0200 Subject: MIPS: RM9000: Remove the now unused CPU_RM9000 definition. Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 530eb8b..39826a7 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -281,7 +281,7 @@ enum cpu_type_enum { CPU_R4700, CPU_R5000, CPU_R5500, CPU_NEVADA, CPU_R5432, CPU_R10000, CPU_R12000, CPU_R14000, CPU_VR41XX, CPU_VR4111, CPU_VR4121, CPU_VR4122, CPU_VR4131, CPU_VR4133, CPU_VR4181, CPU_VR4181A, CPU_RM7000, - CPU_SR71000, CPU_RM9000, CPU_TX49XX, + CPU_SR71000, CPU_TX49XX, /* * R8000 class processors -- cgit v0.10.2 From 8b2e62cc34feaaf1cac9440a93fb18ac0b1e81bc Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 21 May 2014 10:49:19 +0800 Subject: MIPS: Fix a typo error in AUDIT_ARCH definition Missing a "|" in AUDIT_ARCH_MIPSEL64N32 macro definition. Signed-off-by: Huacai Chen Reviewed-by: Markos Chandras Cc: John Crispin Cc: Steven J. Hill Cc: Aurelien Jarno Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang Cc: Zhangjin Wu Patchwork: https://patchwork.linux-mips.org/patch/6978/ Signed-off-by: Ralf Baechle diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 1b1efdd..4c31a36 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -357,7 +357,7 @@ enum { #define AUDIT_ARCH_MIPS64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #define AUDIT_ARCH_MIPSEL64 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) -#define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE\ +#define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE|\ __AUDIT_ARCH_CONVENTION_MIPS64_N32) #define AUDIT_ARCH_OPENRISC (EM_OPENRISC) #define AUDIT_ARCH_PARISC (EM_PARISC) -- cgit v0.10.2 From b633648c5ad3cfbda0b3daea50d2135d44899259 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 23 May 2014 16:29:44 +0200 Subject: MIPS: MT: Remove SMTC support Nobody is maintaining SMTC anymore and there also seems to be no userbase. Which is a pity - the SMTC technology primarily developed by Kevin D. Kissell is an ingenious demonstration for the MT ASE's power and elegance. Based on Markos Chandras patch https://patchwork.linux-mips.org/patch/6719/ which while very similar did no longer apply cleanly when I tried to merge it plus some additional post-SMTC cleanup - SMTC was a feature as tricky to remove as it was to merge once upon a time. Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 45e75b6..e3f040c 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1852,7 +1852,7 @@ config FORCE_MAX_ZONEORDER config CEVT_GIC bool "Use GIC global counter for clock events" - depends on IRQ_GIC && !(MIPS_SEAD3 || MIPS_MT_SMTC) + depends on IRQ_GIC && !MIPS_SEAD3 help Use the GIC global counter for the clock events. The R4K clock event driver is always present, so if the platform ends up not @@ -1936,24 +1936,6 @@ config MIPS_MT_SMP Intel Hyperthreading feature. For further information go to . -config MIPS_MT_SMTC - bool "Use all TCs on all VPEs for SMP (DEPRECATED)" - depends on CPU_MIPS32_R2 - depends on SYS_SUPPORTS_MULTITHREADING - depends on !MIPS_CPS - select CPU_MIPSR2_IRQ_VI - select CPU_MIPSR2_IRQ_EI - select MIPS_MT - select SMP - select SMP_UP - select SYS_SUPPORTS_SMP - select NR_CPUS_DEFAULT_8 - help - This is a kernel model which is known as SMTC. This is - supported on cores with the MT ASE and presents all TCs - available on all VPEs to support SMP. For further - information see . - endchoice config MIPS_MT @@ -1977,7 +1959,7 @@ config SYS_SUPPORTS_MULTITHREADING config MIPS_MT_FPAFF bool "Dynamic FPU affinity for FP-intensive threads" default y - depends on MIPS_MT_SMP || MIPS_MT_SMTC + depends on MIPS_MT_SMP config MIPS_VPE_LOADER bool "VPE loader support." @@ -1999,29 +1981,6 @@ config MIPS_VPE_LOADER_MT default "y" depends on MIPS_VPE_LOADER && !MIPS_CMP -config MIPS_MT_SMTC_IM_BACKSTOP - bool "Use per-TC register bits as backstop for inhibited IM bits" - depends on MIPS_MT_SMTC - default n - help - To support multiple TC microthreads acting as "CPUs" within - a VPE, VPE-wide interrupt mask bits must be specially manipulated - during interrupt handling. To support legacy drivers and interrupt - controller management code, SMTC has a "backstop" to track and - if necessary restore the interrupt mask. This has some performance - impact on interrupt service overhead. - -config MIPS_MT_SMTC_IRQAFF - bool "Support IRQ affinity API" - depends on MIPS_MT_SMTC - default n - help - Enables SMP IRQ affinity API (/proc/irq/*/smp_affinity, etc.) - for SMTC Linux kernel. Requires platform support, of which - an example can be found in the MIPS kernel i8259 and Malta - platform code. Adds some overhead to interrupt dispatch, and - should be used only if you know what you are doing. - config MIPS_VPE_LOADER_TOM bool "Load VPE program into memory hidden from linux" depends on MIPS_VPE_LOADER @@ -2049,7 +2008,7 @@ config MIPS_VPE_APSP_API_MT config MIPS_CMP bool "MIPS CMP framework support (DEPRECATED)" - depends on SYS_SUPPORTS_MIPS_CMP && !MIPS_MT_SMTC + depends on SYS_SUPPORTS_MIPS_CMP select MIPS_GIC_IPI select SYNC_R4K select WEAK_ORDERING @@ -2256,7 +2215,7 @@ config NODES_SHIFT config HW_PERF_EVENTS bool "Enable hardware performance counter support for perf events" - depends on PERF_EVENTS && !MIPS_MT_SMTC && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP) + depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP) default y help Enable hardware performance counter support for perf events. If diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index 25de292..3a2b775 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug @@ -79,15 +79,6 @@ config CMDLINE_OVERRIDE Normally, you will choose 'N' here. -config SMTC_IDLE_HOOK_DEBUG - bool "Enable additional debug checks before going into CPU idle loop" - depends on DEBUG_KERNEL && MIPS_MT_SMTC - help - This option enables Enable additional debug checks before going into - CPU idle loop. For details on these checks, see - arch/mips/kernel/smtc.c. This debugging option result in significant - overhead so should be disabled in production kernels. - config SB1XXX_CORELIS bool "Corelis Debugger" depends on SIBYTE_SB1xxx_SOC diff --git a/arch/mips/configs/maltasmtc_defconfig b/arch/mips/configs/maltasmtc_defconfig deleted file mode 100644 index eb316447..0000000 --- a/arch/mips/configs/maltasmtc_defconfig +++ /dev/null @@ -1,196 +0,0 @@ -CONFIG_MIPS_MALTA=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_CPU_MIPS32_R2=y -CONFIG_PAGE_SIZE_16KB=y -CONFIG_MIPS_MT_SMTC=y -# CONFIG_MIPS_MT_FPAFF is not set -CONFIG_NR_CPUS=9 -CONFIG_HZ_48=y -CONFIG_LOCALVERSION="smtc" -CONFIG_SYSVIPC=y -CONFIG_POSIX_MQUEUE=y -CONFIG_AUDIT=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=15 -CONFIG_SYSCTL_SYSCALL=y -CONFIG_EMBEDDED=y -CONFIG_SLAB=y -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -CONFIG_MODVERSIONS=y -CONFIG_MODULE_SRCVERSION_ALL=y -# CONFIG_BLK_DEV_BSG is not set -CONFIG_PCI=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_XFRM_USER=m -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -CONFIG_NET_IPIP=m -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -CONFIG_SYN_COOKIES=y -CONFIG_INET_AH=m -CONFIG_INET_ESP=m -CONFIG_INET_IPCOMP=m -# CONFIG_INET_LRO is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -CONFIG_IPV6_TUNNEL=m -CONFIG_BRIDGE=m -CONFIG_VLAN_8021Q=m -CONFIG_ATALK=m -CONFIG_DEV_APPLETALK=m -CONFIG_IPDDP=m -CONFIG_IPDDP_ENCAP=y -CONFIG_NET_SCHED=y -CONFIG_NET_SCH_CBQ=m -CONFIG_NET_SCH_HTB=m -CONFIG_NET_SCH_HFSC=m -CONFIG_NET_SCH_PRIO=m -CONFIG_NET_SCH_RED=m -CONFIG_NET_SCH_SFQ=m -CONFIG_NET_SCH_TEQL=m -CONFIG_NET_SCH_TBF=m -CONFIG_NET_SCH_GRED=m -CONFIG_NET_SCH_DSMARK=m -CONFIG_NET_SCH_NETEM=m -CONFIG_NET_SCH_INGRESS=m -CONFIG_NET_CLS_BASIC=m -CONFIG_NET_CLS_TCINDEX=m -CONFIG_NET_CLS_ROUTE4=m -CONFIG_NET_CLS_FW=m -CONFIG_NET_CLS_U32=m -CONFIG_NET_CLS_RSVP=m -CONFIG_NET_CLS_RSVP6=m -CONFIG_NET_CLS_ACT=y -CONFIG_NET_ACT_POLICE=y -CONFIG_NET_CLS_IND=y -# CONFIG_WIRELESS is not set -CONFIG_DEVTMPFS=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_CRYPTOLOOP=m -CONFIG_IDE=y -# CONFIG_IDE_PROC_FS is not set -# CONFIG_IDEPCI_PCIBUS_ORDER is not set -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_PIIX=y -CONFIG_SCSI=y -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_SG=y -# CONFIG_SCSI_LOWLEVEL is not set -CONFIG_NETDEVICES=y -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_VENDOR_ADAPTEC is not set -# CONFIG_NET_VENDOR_ALTEON is not set -CONFIG_PCNET32=y -# CONFIG_NET_VENDOR_ATHEROS is not set -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_BROCADE is not set -# CONFIG_NET_VENDOR_CHELSIO is not set -# CONFIG_NET_VENDOR_CISCO is not set -# CONFIG_NET_VENDOR_DEC is not set -# CONFIG_NET_VENDOR_DLINK is not set -# CONFIG_NET_VENDOR_EMULEX is not set -# CONFIG_NET_VENDOR_EXAR is not set -# CONFIG_NET_VENDOR_HP is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MELLANOX is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_MYRI is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_NVIDIA is not set -# CONFIG_NET_VENDOR_OKI is not set -# CONFIG_NET_PACKET_ENGINE is not set -# CONFIG_NET_VENDOR_QLOGIC is not set -# CONFIG_NET_VENDOR_REALTEK is not set -# CONFIG_NET_VENDOR_RDC is not set -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SILAN is not set -# CONFIG_NET_VENDOR_SIS is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_SUN is not set -# CONFIG_NET_VENDOR_TEHUTI is not set -# CONFIG_NET_VENDOR_TI is not set -# CONFIG_NET_VENDOR_TOSHIBA is not set -# CONFIG_NET_VENDOR_VIA is not set -# CONFIG_WLAN is not set -# CONFIG_VT is not set -CONFIG_LEGACY_PTY_COUNT=16 -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_HW_RANDOM=y -# CONFIG_HWMON is not set -CONFIG_VIDEO_OUTPUT_CONTROL=m -CONFIG_FB=y -CONFIG_FIRMWARE_EDID=y -CONFIG_FB_MATROX=y -CONFIG_FB_MATROX_G=y -CONFIG_USB=y -CONFIG_USB_EHCI_HCD=y -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -CONFIG_USB_UHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_IDE_DISK=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_BACKLIGHT=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_CMOS=y -CONFIG_EXT2_FS=y -CONFIG_EXT3_FS=y -# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set -CONFIG_XFS_FS=y -CONFIG_XFS_QUOTA=y -CONFIG_XFS_POSIX_ACL=y -CONFIG_QUOTA=y -CONFIG_QFMT_V2=y -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -CONFIG_PROC_KCORE=y -CONFIG_TMPFS=y -CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_CIFS=m -CONFIG_CIFS_WEAK_PW_HASH=y -CONFIG_CIFS_XATTR=y -CONFIG_CIFS_POSIX=y -CONFIG_NLS_CODEPAGE_437=m -CONFIG_NLS_ISO8859_1=m -# CONFIG_FTRACE is not set -CONFIG_CRYPTO_NULL=m -CONFIG_CRYPTO_PCBC=m -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_MICHAEL_MIC=m -CONFIG_CRYPTO_SHA512=m -CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_WP512=m -CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_BLOWFISH=m -CONFIG_CRYPTO_CAST5=m -CONFIG_CRYPTO_CAST6=m -CONFIG_CRYPTO_KHAZAD=m -CONFIG_CRYPTO_SERPENT=m -CONFIG_CRYPTO_TEA=m -CONFIG_CRYPTO_TWOFISH=m -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_HW is not set diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index b464b8b..f7db79a 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -17,26 +17,8 @@ #ifdef CONFIG_64BIT #include #endif -#ifdef CONFIG_MIPS_MT_SMTC -#include -#endif - -#ifdef CONFIG_MIPS_MT_SMTC - .macro local_irq_enable reg=t0 - mfc0 \reg, CP0_TCSTATUS - ori \reg, \reg, TCSTATUS_IXMT - xori \reg, \reg, TCSTATUS_IXMT - mtc0 \reg, CP0_TCSTATUS - _ehb - .endm - .macro local_irq_disable reg=t0 - mfc0 \reg, CP0_TCSTATUS - ori \reg, \reg, TCSTATUS_IXMT - mtc0 \reg, CP0_TCSTATUS - _ehb - .endm -#elif defined(CONFIG_CPU_MIPSR2) +#ifdef CONFIG_CPU_MIPSR2 .macro local_irq_enable reg=t0 ei irq_enable_hazard @@ -71,7 +53,7 @@ sw \reg, TI_PRE_COUNT($28) #endif .endm -#endif /* CONFIG_MIPS_MT_SMTC */ +#endif /* CONFIG_CPU_MIPSR2 */ .macro fpu_save_16even thread tmp=t0 cfc1 \tmp, fcr31 diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h index dc2135b..7ba0e07 100644 --- a/arch/mips/include/asm/cpu-info.h +++ b/arch/mips/include/asm/cpu-info.h @@ -65,18 +65,13 @@ struct cpuinfo_mips { #ifdef CONFIG_64BIT int vmbits; /* Virtual memory size in bits */ #endif -#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) +#ifdef CONFIG_MIPS_MT_SMP /* - * In the MIPS MT "SMTC" model, each TC is considered - * to be a "CPU" for the purposes of scheduling, but - * exception resources, ASID spaces, etc, are common - * to all TCs within the same VPE. + * There is not necessarily a 1:1 mapping of VPE num to CPU number + * in particular on multi-core systems. */ int vpe_id; /* Virtual Processor number */ #endif -#ifdef CONFIG_MIPS_MT_SMTC - int tc_id; /* Thread Context number */ -#endif void *data; /* Additional data */ unsigned int watch_reg_count; /* Number that exist */ unsigned int watch_reg_use_cnt; /* Usable by ptrace */ @@ -117,7 +112,7 @@ struct proc_cpuinfo_notifier_args { unsigned long n; }; -#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) +#ifdef CONFIG_MIPS_MT_SMP # define cpu_vpe_id(cpuinfo) ((cpuinfo)->vpe_id) #else # define cpu_vpe_id(cpuinfo) 0 diff --git a/arch/mips/include/asm/fixmap.h b/arch/mips/include/asm/fixmap.h index 8c012af..6842ffa 100644 --- a/arch/mips/include/asm/fixmap.h +++ b/arch/mips/include/asm/fixmap.h @@ -48,11 +48,7 @@ enum fixed_addresses { #define FIX_N_COLOURS 8 FIX_CMAP_BEGIN, -#ifdef CONFIG_MIPS_MT_SMTC - FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * NR_CPUS * 2), -#else FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * 2), -#endif #ifdef CONFIG_HIGHMEM /* reserved pte's for temporary kernel mappings */ FIX_KMAP_BEGIN = FIX_CMAP_END + 1, diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 7bc2cdb..ae1f7b2 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -26,104 +26,8 @@ static inline int irq_canonicalize(int irq) #define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */ #endif -#ifdef CONFIG_MIPS_MT_SMTC - -struct irqaction; - -extern unsigned long irq_hwmask[]; -extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, - unsigned long hwmask); - -static inline void smtc_im_ack_irq(unsigned int irq) -{ - if (irq_hwmask[irq] & ST0_IM) - set_c0_status(irq_hwmask[irq] & ST0_IM); -} - -#else - -static inline void smtc_im_ack_irq(unsigned int irq) -{ -} - -#endif /* CONFIG_MIPS_MT_SMTC */ - -#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF -#include - -extern int plat_set_irq_affinity(struct irq_data *d, - const struct cpumask *affinity, bool force); -extern void smtc_forward_irq(struct irq_data *d); - -/* - * IRQ affinity hook invoked at the beginning of interrupt dispatch - * if option is enabled. - * - * Up through Linux 2.6.22 (at least) cpumask operations are very - * inefficient on MIPS. Initial prototypes of SMTC IRQ affinity - * used a "fast path" per-IRQ-descriptor cache of affinity information - * to reduce latency. As there is a project afoot to optimize the - * cpumask implementations, this version is optimistically assuming - * that cpumask.h macro overhead is reasonable during interrupt dispatch. - */ -static inline int handle_on_other_cpu(unsigned int irq) -{ - struct irq_data *d = irq_get_irq_data(irq); - - if (cpumask_test_cpu(smp_processor_id(), d->affinity)) - return 0; - smtc_forward_irq(d); - return 1; -} - -#else /* Not doing SMTC affinity */ - -static inline int handle_on_other_cpu(unsigned int irq) { return 0; } - -#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ - -#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP - -static inline void smtc_im_backstop(unsigned int irq) -{ - if (irq_hwmask[irq] & 0x0000ff00) - write_c0_tccontext(read_c0_tccontext() & - ~(irq_hwmask[irq] & 0x0000ff00)); -} - -/* - * Clear interrupt mask handling "backstop" if irq_hwmask - * entry so indicates. This implies that the ack() or end() - * functions will take over re-enabling the low-level mask. - * Otherwise it will be done on return from exception. - */ -static inline int smtc_handle_on_other_cpu(unsigned int irq) -{ - int ret = handle_on_other_cpu(irq); - - if (!ret) - smtc_im_backstop(irq); - return ret; -} - -#else - -static inline void smtc_im_backstop(unsigned int irq) { } -static inline int smtc_handle_on_other_cpu(unsigned int irq) -{ - return handle_on_other_cpu(irq); -} - -#endif - extern void do_IRQ(unsigned int irq); -#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF - -extern void do_IRQ_no_affinity(unsigned int irq); - -#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ - extern void arch_init_irq(void); extern void spurious_interrupt(void); diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h index 45c0095..0fa5fdc 100644 --- a/arch/mips/include/asm/irqflags.h +++ b/arch/mips/include/asm/irqflags.h @@ -17,7 +17,7 @@ #include #include -#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) +#ifdef CONFIG_CPU_MIPSR2 static inline void arch_local_irq_disable(void) { @@ -118,30 +118,15 @@ void arch_local_irq_disable(void); unsigned long arch_local_irq_save(void); void arch_local_irq_restore(unsigned long flags); void __arch_local_irq_restore(unsigned long flags); -#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */ - - -extern void smtc_ipi_replay(void); +#endif /* CONFIG_CPU_MIPSR2 */ static inline void arch_local_irq_enable(void) { -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC kernel needs to do a software replay of queued - * IPIs, at the cost of call overhead on each local_irq_enable() - */ - smtc_ipi_replay(); -#endif __asm__ __volatile__( " .set push \n" " .set reorder \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n" - " ori $1, 0x400 \n" - " xori $1, 0x400 \n" - " mtc0 $1, $2, 1 \n" -#elif defined(CONFIG_CPU_MIPSR2) +#if defined(CONFIG_CPU_MIPSR2) " ei \n" #else " mfc0 $1,$12 \n" @@ -163,11 +148,7 @@ static inline unsigned long arch_local_save_flags(void) asm __volatile__( " .set push \n" " .set reorder \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 %[flags], $2, 1 \n" -#else " mfc0 %[flags], $12 \n" -#endif " .set pop \n" : [flags] "=r" (flags)); @@ -177,14 +158,7 @@ static inline unsigned long arch_local_save_flags(void) static inline int arch_irqs_disabled_flags(unsigned long flags) { -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU - */ - return flags & 0x400; -#else return !(flags & 1); -#endif } #endif /* #ifndef __ASSEMBLY__ */ diff --git a/arch/mips/include/asm/mach-malta/kernel-entry-init.h b/arch/mips/include/asm/mach-malta/kernel-entry-init.h index 7c5e17a..77eeda7 100644 --- a/arch/mips/include/asm/mach-malta/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-malta/kernel-entry-init.h @@ -80,36 +80,6 @@ .endm .macro kernel_entry_setup -#ifdef CONFIG_MIPS_MT_SMTC - mfc0 t0, CP0_CONFIG - bgez t0, 9f - mfc0 t0, CP0_CONFIG, 1 - bgez t0, 9f - mfc0 t0, CP0_CONFIG, 2 - bgez t0, 9f - mfc0 t0, CP0_CONFIG, 3 - and t0, 1<<2 - bnez t0, 0f -9: - /* Assume we came from YAMON... */ - PTR_LA v0, 0x9fc00534 /* YAMON print */ - lw v0, (v0) - move a0, zero - PTR_LA a1, nonmt_processor - jal v0 - - PTR_LA v0, 0x9fc00520 /* YAMON exit */ - lw v0, (v0) - li a0, 1 - jal v0 - -1: b 1b - - __INITDATA -nonmt_processor: - .asciz "SMTC kernel requires the MT ASE to run\n" - __FINIT -#endif #ifdef CONFIG_EVA sync diff --git a/arch/mips/include/asm/mach-sead3/kernel-entry-init.h b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h index 3dfbd8e..6cccd4d 100644 --- a/arch/mips/include/asm/mach-sead3/kernel-entry-init.h +++ b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h @@ -10,37 +10,6 @@ #define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H .macro kernel_entry_setup -#ifdef CONFIG_MIPS_MT_SMTC - mfc0 t0, CP0_CONFIG - bgez t0, 9f - mfc0 t0, CP0_CONFIG, 1 - bgez t0, 9f - mfc0 t0, CP0_CONFIG, 2 - bgez t0, 9f - mfc0 t0, CP0_CONFIG, 3 - and t0, 1<<2 - bnez t0, 0f -9 : - /* Assume we came from YAMON... */ - PTR_LA v0, 0x9fc00534 /* YAMON print */ - lw v0, (v0) - move a0, zero - PTR_LA a1, nonmt_processor - jal v0 - - PTR_LA v0, 0x9fc00520 /* YAMON exit */ - lw v0, (v0) - li a0, 1 - jal v0 - -1 : b 1b - - __INITDATA -nonmt_processor : - .asciz "SMTC kernel requires the MT ASE to run\n" - __FINIT -0 : -#endif .endm /* diff --git a/arch/mips/include/asm/mips_mt.h b/arch/mips/include/asm/mips_mt.h index a3df0c3..f6ba004 100644 --- a/arch/mips/include/asm/mips_mt.h +++ b/arch/mips/include/asm/mips_mt.h @@ -1,7 +1,6 @@ /* - * Definitions and decalrations for MIPS MT support - * that are common between SMTC, VSMP, and/or AP/SP - * kernel models. + * Definitions and decalrations for MIPS MT support that are common between + * the VSMP, and AP/SP kernel models. */ #ifndef __ASM_MIPS_MT_H #define __ASM_MIPS_MT_H diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 88e30d5..fb2d174 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1014,19 +1014,8 @@ do { \ #define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) #define read_c0_status() __read_32bit_c0_register($12, 0) -#ifdef CONFIG_MIPS_MT_SMTC -#define write_c0_status(val) \ -do { \ - __write_32bit_c0_register($12, 0, val); \ - __ehb(); \ -} while (0) -#else -/* - * Legacy non-SMTC code, which may be hazardous - * but which might not support EHB - */ + #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) -#endif /* CONFIG_MIPS_MT_SMTC */ #define read_c0_cause() __read_32bit_c0_register($13, 0) #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) @@ -1750,11 +1739,6 @@ static inline void tlb_write_random(void) /* * Manipulate bits in a c0 register. */ -#ifndef CONFIG_MIPS_MT_SMTC -/* - * SMTC Linux requires shutting-down microthread scheduling - * during CP0 register read-modify-write sequences. - */ #define __BUILD_SET_C0(name) \ static inline unsigned int \ set_c0_##name(unsigned int set) \ @@ -1793,121 +1777,6 @@ change_c0_##name(unsigned int change, unsigned int val) \ return res; \ } -#else /* SMTC versions that manage MT scheduling */ - -#include - -/* - * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with - * header file recursion. - */ -static inline unsigned int __dmt(void) -{ - int res; - - __asm__ __volatile__( - " .set push \n" - " .set mips32r2 \n" - " .set noat \n" - " .word 0x41610BC1 # dmt $1 \n" - " ehb \n" - " move %0, $1 \n" - " .set pop \n" - : "=r" (res)); - - instruction_hazard(); - - return res; -} - -#define __VPECONTROL_TE_SHIFT 15 -#define __VPECONTROL_TE (1UL << __VPECONTROL_TE_SHIFT) - -#define __EMT_ENABLE __VPECONTROL_TE - -static inline void __emt(unsigned int previous) -{ - if ((previous & __EMT_ENABLE)) - __asm__ __volatile__( - " .set mips32r2 \n" - " .word 0x41600be1 # emt \n" - " ehb \n" - " .set mips0 \n"); -} - -static inline void __ehb(void) -{ - __asm__ __volatile__( - " .set mips32r2 \n" - " ehb \n" " .set mips0 \n"); -} - -/* - * Note that local_irq_save/restore affect TC-specific IXMT state, - * not Status.IE as in non-SMTC kernel. - */ - -#define __BUILD_SET_C0(name) \ -static inline unsigned int \ -set_c0_##name(unsigned int set) \ -{ \ - unsigned int res; \ - unsigned int new; \ - unsigned int omt; \ - unsigned long flags; \ - \ - local_irq_save(flags); \ - omt = __dmt(); \ - res = read_c0_##name(); \ - new = res | set; \ - write_c0_##name(new); \ - __emt(omt); \ - local_irq_restore(flags); \ - \ - return res; \ -} \ - \ -static inline unsigned int \ -clear_c0_##name(unsigned int clear) \ -{ \ - unsigned int res; \ - unsigned int new; \ - unsigned int omt; \ - unsigned long flags; \ - \ - local_irq_save(flags); \ - omt = __dmt(); \ - res = read_c0_##name(); \ - new = res & ~clear; \ - write_c0_##name(new); \ - __emt(omt); \ - local_irq_restore(flags); \ - \ - return res; \ -} \ - \ -static inline unsigned int \ -change_c0_##name(unsigned int change, unsigned int newbits) \ -{ \ - unsigned int res; \ - unsigned int new; \ - unsigned int omt; \ - unsigned long flags; \ - \ - local_irq_save(flags); \ - \ - omt = __dmt(); \ - res = read_c0_##name(); \ - new = res & ~change; \ - new |= (newbits & change); \ - write_c0_##name(new); \ - __emt(omt); \ - local_irq_restore(flags); \ - \ - return res; \ -} -#endif - __BUILD_SET_C0(status) __BUILD_SET_C0(cause) __BUILD_SET_C0(config) diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h index e277bba..0f75aac 100644 --- a/arch/mips/include/asm/mmu_context.h +++ b/arch/mips/include/asm/mmu_context.h @@ -18,10 +18,6 @@ #include #include #include -#ifdef CONFIG_MIPS_MT_SMTC -#include -#include -#endif /* SMTC */ #include #define TLBMISS_HANDLER_SETUP_PGD(pgd) \ @@ -63,13 +59,6 @@ extern unsigned long pgd_current[]; #define ASID_INC 0x10 #define ASID_MASK 0xff0 -#elif defined(CONFIG_MIPS_MT_SMTC) - -#define ASID_INC 0x1 -extern unsigned long smtc_asid_mask; -#define ASID_MASK (smtc_asid_mask) -#define HW_ASID_MASK 0xff -/* End SMTC/34K debug hack */ #else /* FIXME: not correct for R6000 */ #define ASID_INC 0x1 @@ -92,7 +81,6 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) #define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1))) #define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1) -#ifndef CONFIG_MIPS_MT_SMTC /* Normal, classic MIPS get_new_mmu_context */ static inline void get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) @@ -115,12 +103,6 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) cpu_context(cpu, mm) = asid_cache(cpu) = asid; } -#else /* CONFIG_MIPS_MT_SMTC */ - -#define get_new_mmu_context(mm, cpu) smtc_get_new_mmu_context((mm), (cpu)) - -#endif /* CONFIG_MIPS_MT_SMTC */ - /* * Initialize the context related info for a new mm_struct * instance. @@ -141,46 +123,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, { unsigned int cpu = smp_processor_id(); unsigned long flags; -#ifdef CONFIG_MIPS_MT_SMTC - unsigned long oldasid; - unsigned long mtflags; - int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id; - local_irq_save(flags); - mtflags = dvpe(); -#else /* Not SMTC */ local_irq_save(flags); -#endif /* CONFIG_MIPS_MT_SMTC */ /* Check if our ASID is of an older version and thus invalid */ if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK) get_new_mmu_context(next, cpu); -#ifdef CONFIG_MIPS_MT_SMTC - /* - * If the EntryHi ASID being replaced happens to be - * the value flagged at ASID recycling time as having - * an extended life, clear the bit showing it being - * in use by this "CPU", and if that's the last bit, - * free up the ASID value for use and flush any old - * instances of it from the TLB. - */ - oldasid = (read_c0_entryhi() & ASID_MASK); - if(smtc_live_asid[mytlb][oldasid]) { - smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); - if(smtc_live_asid[mytlb][oldasid] == 0) - smtc_flush_tlb_asid(oldasid); - } - /* - * Tread softly on EntryHi, and so long as we support - * having ASID_MASK smaller than the hardware maximum, - * make sure no "soft" bits become "hard"... - */ - write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) | - cpu_asid(cpu, next)); - ehb(); /* Make sure it propagates to TCStatus */ - evpe(mtflags); -#else write_c0_entryhi(cpu_asid(cpu, next)); -#endif /* CONFIG_MIPS_MT_SMTC */ TLBMISS_HANDLER_SETUP_PGD(next->pgd); /* @@ -213,34 +161,12 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next) unsigned long flags; unsigned int cpu = smp_processor_id(); -#ifdef CONFIG_MIPS_MT_SMTC - unsigned long oldasid; - unsigned long mtflags; - int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id; -#endif /* CONFIG_MIPS_MT_SMTC */ - local_irq_save(flags); /* Unconditionally get a new ASID. */ get_new_mmu_context(next, cpu); -#ifdef CONFIG_MIPS_MT_SMTC - /* See comments for similar code above */ - mtflags = dvpe(); - oldasid = read_c0_entryhi() & ASID_MASK; - if(smtc_live_asid[mytlb][oldasid]) { - smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); - if(smtc_live_asid[mytlb][oldasid] == 0) - smtc_flush_tlb_asid(oldasid); - } - /* See comments for similar code above */ - write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) | - cpu_asid(cpu, next)); - ehb(); /* Make sure it propagates to TCStatus */ - evpe(mtflags); -#else write_c0_entryhi(cpu_asid(cpu, next)); -#endif /* CONFIG_MIPS_MT_SMTC */ TLBMISS_HANDLER_SETUP_PGD(next->pgd); /* mark mmu ownership change */ @@ -258,48 +184,15 @@ static inline void drop_mmu_context(struct mm_struct *mm, unsigned cpu) { unsigned long flags; -#ifdef CONFIG_MIPS_MT_SMTC - unsigned long oldasid; - /* Can't use spinlock because called from TLB flush within DVPE */ - unsigned int prevvpe; - int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id; -#endif /* CONFIG_MIPS_MT_SMTC */ local_irq_save(flags); if (cpumask_test_cpu(cpu, mm_cpumask(mm))) { get_new_mmu_context(mm, cpu); -#ifdef CONFIG_MIPS_MT_SMTC - /* See comments for similar code above */ - prevvpe = dvpe(); - oldasid = (read_c0_entryhi() & ASID_MASK); - if (smtc_live_asid[mytlb][oldasid]) { - smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu); - if(smtc_live_asid[mytlb][oldasid] == 0) - smtc_flush_tlb_asid(oldasid); - } - /* See comments for similar code above */ - write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) - | cpu_asid(cpu, mm)); - ehb(); /* Make sure it propagates to TCStatus */ - evpe(prevvpe); -#else /* not CONFIG_MIPS_MT_SMTC */ write_c0_entryhi(cpu_asid(cpu, mm)); -#endif /* CONFIG_MIPS_MT_SMTC */ } else { /* will get a new context next time */ -#ifndef CONFIG_MIPS_MT_SMTC cpu_context(cpu, mm) = 0; -#else /* SMTC */ - int i; - - /* SMTC shares the TLB (and ASIDs) across VPEs */ - for_each_online_cpu(i) { - if((smtc_status & SMTC_TLB_SHARED) - || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id)) - cpu_context(i, mm) = 0; - } -#endif /* CONFIG_MIPS_MT_SMTC */ } local_irq_restore(flags); } diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h index c2edae3..800fe57 100644 --- a/arch/mips/include/asm/module.h +++ b/arch/mips/include/asm/module.h @@ -144,13 +144,7 @@ search_module_dbetables(unsigned long addr) #define MODULE_KERNEL_TYPE "64BIT " #endif -#ifdef CONFIG_MIPS_MT_SMTC -#define MODULE_KERNEL_SMTC "MT_SMTC " -#else -#define MODULE_KERNEL_SMTC "" -#endif - #define MODULE_ARCH_VERMAGIC \ - MODULE_PROC_FAMILY MODULE_KERNEL_TYPE MODULE_KERNEL_SMTC + MODULE_PROC_FAMILY MODULE_KERNEL_TYPE #endif /* _ASM_MODULE_H */ diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index bf1ac8d3..7e6e682 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -39,9 +39,6 @@ struct pt_regs { unsigned long cp0_badvaddr; unsigned long cp0_cause; unsigned long cp0_epc; -#ifdef CONFIG_MIPS_MT_SMTC - unsigned long cp0_tcstatus; -#endif /* CONFIG_MIPS_MT_SMTC */ #ifdef CONFIG_CPU_CAVIUM_OCTEON unsigned long long mpl[3]; /* MTM{0,1,2} */ unsigned long long mtp[3]; /* MTP{0,1,2} */ diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index ca64cbe..fe8d1b6 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h @@ -43,11 +43,10 @@ : "i" (op), "R" (*(unsigned char *)(addr))) #ifdef CONFIG_MIPS_MT + /* - * Temporary hacks for SMTC debug. Optionally force single-threaded - * execution during I-cache flushes. + * Optionally force single-threaded execution during I-cache flushes. */ - #define PROTECT_CACHE_FLUSHES 1 #ifdef PROTECT_CACHE_FLUSHES diff --git a/arch/mips/include/asm/smtc.h b/arch/mips/include/asm/smtc.h deleted file mode 100644 index e56b439..0000000 --- a/arch/mips/include/asm/smtc.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _ASM_SMTC_MT_H -#define _ASM_SMTC_MT_H - -/* - * Definitions for SMTC multitasking on MIPS MT cores - */ - -#include -#include - -/* - * System-wide SMTC status information - */ - -extern unsigned int smtc_status; - -#define SMTC_TLB_SHARED 0x00000001 -#define SMTC_MTC_ACTIVE 0x00000002 - -/* - * TLB/ASID Management information - */ - -#define MAX_SMTC_TLBS 2 -#define MAX_SMTC_ASIDS 256 -#if NR_CPUS <= 8 -typedef char asiduse; -#else -#if NR_CPUS <= 16 -typedef short asiduse; -#else -typedef long asiduse; -#endif -#endif - -/* - * VPE Management information - */ - -#define MAX_SMTC_VPES MAX_SMTC_TLBS /* FIXME: May not always be true. */ - -extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; - -struct mm_struct; -struct task_struct; - -void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu); -void self_ipi(struct smtc_ipi *); -void smtc_flush_tlb_asid(unsigned long asid); -extern int smtc_build_cpu_map(int startslot); -extern void smtc_prepare_cpus(int cpus); -extern void smtc_smp_finish(void); -extern void smtc_boot_secondary(int cpu, struct task_struct *t); -extern void smtc_cpus_done(void); -extern void smtc_init_secondary(void); - - -/* - * Sharing the TLB between multiple VPEs means that the - * "random" index selection function is not allowed to - * select the current value of the Index register. To - * avoid additional TLB pressure, the Index registers - * are "parked" with an non-Valid value. - */ - -#define PARKED_INDEX ((unsigned int)0x80000000) - -/* - * Define low-level interrupt mask for IPIs, if necessary. - * By default, use SW interrupt 1, which requires no external - * hardware support, but which works only for single-core - * MIPS MT systems. - */ -#ifndef MIPS_CPU_IPI_IRQ -#define MIPS_CPU_IPI_IRQ 1 -#endif - -#endif /* _ASM_SMTC_MT_H */ diff --git a/arch/mips/include/asm/smtc_ipi.h b/arch/mips/include/asm/smtc_ipi.h deleted file mode 100644 index 15278db..0000000 --- a/arch/mips/include/asm/smtc_ipi.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code. - */ -#ifndef __ASM_SMTC_IPI_H -#define __ASM_SMTC_IPI_H - -#include - -//#define SMTC_IPI_DEBUG - -#ifdef SMTC_IPI_DEBUG -#include -#include -#endif /* SMTC_IPI_DEBUG */ - -/* - * An IPI "message" - */ - -struct smtc_ipi { - struct smtc_ipi *flink; - int type; - void *arg; - int dest; -#ifdef SMTC_IPI_DEBUG - int sender; - long stamp; -#endif /* SMTC_IPI_DEBUG */ -}; - -/* - * Defined IPI Types - */ - -#define LINUX_SMP_IPI 1 -#define SMTC_CLOCK_TICK 2 -#define IRQ_AFFINITY_IPI 3 - -/* - * A queue of IPI messages - */ - -struct smtc_ipi_q { - struct smtc_ipi *head; - spinlock_t lock; - struct smtc_ipi *tail; - int depth; - int resched_flag; /* reschedule already queued */ -}; - -static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) -{ - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - if (q->head == NULL) - q->head = q->tail = p; - else - q->tail->flink = p; - p->flink = NULL; - q->tail = p; - q->depth++; -#ifdef SMTC_IPI_DEBUG - p->sender = read_c0_tcbind(); - p->stamp = read_c0_count(); -#endif /* SMTC_IPI_DEBUG */ - spin_unlock_irqrestore(&q->lock, flags); -} - -static inline struct smtc_ipi *__smtc_ipi_dq(struct smtc_ipi_q *q) -{ - struct smtc_ipi *p; - - if (q->head == NULL) - p = NULL; - else { - p = q->head; - q->head = q->head->flink; - q->depth--; - /* Arguably unnecessary, but leaves queue cleaner */ - if (q->head == NULL) - q->tail = NULL; - } - - return p; -} - -static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q) -{ - unsigned long flags; - struct smtc_ipi *p; - - spin_lock_irqsave(&q->lock, flags); - p = __smtc_ipi_dq(q); - spin_unlock_irqrestore(&q->lock, flags); - - return p; -} - -static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p) -{ - unsigned long flags; - - spin_lock_irqsave(&q->lock, flags); - if (q->head == NULL) { - q->head = q->tail = p; - p->flink = NULL; - } else { - p->flink = q->head; - q->head = p; - } - q->depth++; - spin_unlock_irqrestore(&q->lock, flags); -} - -static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q) -{ - unsigned long flags; - int retval; - - spin_lock_irqsave(&q->lock, flags); - retval = q->depth; - spin_unlock_irqrestore(&q->lock, flags); - return retval; -} - -extern void smtc_send_ipi(int cpu, int type, unsigned int action); - -#endif /* __ASM_SMTC_IPI_H */ diff --git a/arch/mips/include/asm/smtc_proc.h b/arch/mips/include/asm/smtc_proc.h deleted file mode 100644 index 25da651..0000000 --- a/arch/mips/include/asm/smtc_proc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Definitions for SMTC /proc entries - * Copyright(C) 2005 MIPS Technologies Inc. - */ -#ifndef __ASM_SMTC_PROC_H -#define __ASM_SMTC_PROC_H - -/* - * per-"CPU" statistics - */ - -struct smtc_cpu_proc { - unsigned long timerints; - unsigned long selfipis; -}; - -extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS]; - -/* Count of number of recoveries of "stolen" FPU access rights on 34K */ - -extern atomic_t smtc_fpu_recoveries; - -#endif /* __ASM_SMTC_PROC_H */ diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h index d301e10..b188c79 100644 --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -19,22 +19,12 @@ #include #include -/* - * For SMTC kernel, global IE should be left set, and interrupts - * controlled exclusively via IXMT. - */ -#ifdef CONFIG_MIPS_MT_SMTC -#define STATMASK 0x1e -#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) #define STATMASK 0x3f #else #define STATMASK 0x1f #endif -#ifdef CONFIG_MIPS_MT_SMTC -#include -#endif /* CONFIG_MIPS_MT_SMTC */ - .macro SAVE_AT .set push .set noat @@ -186,16 +176,6 @@ mfc0 v1, CP0_STATUS LONG_S $2, PT_R2(sp) LONG_S v1, PT_STATUS(sp) -#ifdef CONFIG_MIPS_MT_SMTC - /* - * Ideally, these instructions would be shuffled in - * to cover the pipeline delay. - */ - .set mips32 - mfc0 k0, CP0_TCSTATUS - .set mips0 - LONG_S k0, PT_TCSTATUS(sp) -#endif /* CONFIG_MIPS_MT_SMTC */ LONG_S $4, PT_R4(sp) mfc0 v1, CP0_CAUSE LONG_S $5, PT_R5(sp) @@ -321,36 +301,6 @@ .set push .set reorder .set noat -#ifdef CONFIG_MIPS_MT_SMTC - .set mips32r2 - /* - * We need to make sure the read-modify-write - * of Status below isn't perturbed by an interrupt - * or cross-TC access, so we need to do at least a DMT, - * protected by an interrupt-inhibit. But setting IXMT - * also creates a few-cycle window where an IPI could - * be queued and not be detected before potentially - * returning to a WAIT or user-mode loop. It must be - * replayed. - * - * We're in the middle of a context switch, and - * we can't dispatch it directly without trashing - * some registers, so we'll try to detect this unlikely - * case and program a software interrupt in the VPE, - * as would be done for a cross-VPE IPI. To accommodate - * the handling of that case, we're doing a DVPE instead - * of just a DMT here to protect against other threads. - * This is a lot of cruft to cover a tiny window. - * If you can find a better design, implement it! - * - */ - mfc0 v0, CP0_TCSTATUS - ori v0, TCSTATUS_IXMT - mtc0 v0, CP0_TCSTATUS - _ehb - DVPE 5 # dvpe a1 - jal mips_ihb -#endif /* CONFIG_MIPS_MT_SMTC */ mfc0 a0, CP0_STATUS ori a0, STATMASK xori a0, STATMASK @@ -362,59 +312,6 @@ and v0, v1 or v0, a0 mtc0 v0, CP0_STATUS -#ifdef CONFIG_MIPS_MT_SMTC -/* - * Only after EXL/ERL have been restored to status can we - * restore TCStatus.IXMT. - */ - LONG_L v1, PT_TCSTATUS(sp) - _ehb - mfc0 a0, CP0_TCSTATUS - andi v1, TCSTATUS_IXMT - bnez v1, 0f - -/* - * We'd like to detect any IPIs queued in the tiny window - * above and request an software interrupt to service them - * when we ERET. - * - * Computing the offset into the IPIQ array of the executing - * TC's IPI queue in-line would be tedious. We use part of - * the TCContext register to hold 16 bits of offset that we - * can add in-line to find the queue head. - */ - mfc0 v0, CP0_TCCONTEXT - la a2, IPIQ - srl v0, v0, 16 - addu a2, a2, v0 - LONG_L v0, 0(a2) - beqz v0, 0f -/* - * If we have a queue, provoke dispatch within the VPE by setting C_SW1 - */ - mfc0 v0, CP0_CAUSE - ori v0, v0, C_SW1 - mtc0 v0, CP0_CAUSE -0: - /* - * This test should really never branch but - * let's be prudent here. Having atomized - * the shared register modifications, we can - * now EVPE, and must do so before interrupts - * are potentially re-enabled. - */ - andi a1, a1, MVPCONTROL_EVP - beqz a1, 1f - evpe -1: - /* We know that TCStatua.IXMT should be set from above */ - xori a0, a0, TCSTATUS_IXMT - or a0, a0, v1 - mtc0 a0, CP0_TCSTATUS - _ehb - - .set mips0 -#endif /* CONFIG_MIPS_MT_SMTC */ LONG_L v1, PT_EPC(sp) MTC0 v1, CP0_EPC LONG_L $31, PT_R31(sp) @@ -467,33 +364,11 @@ * Set cp0 enable bit as sign that we're running on the kernel stack */ .macro CLI -#if !defined(CONFIG_MIPS_MT_SMTC) mfc0 t0, CP0_STATUS li t1, ST0_CU0 | STATMASK or t0, t1 xori t0, STATMASK mtc0 t0, CP0_STATUS -#else /* CONFIG_MIPS_MT_SMTC */ - /* - * For SMTC, we need to set privilege - * and disable interrupts only for the - * current TC, using the TCStatus register. - */ - mfc0 t0, CP0_TCSTATUS - /* Fortunately CU 0 is in the same place in both registers */ - /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */ - li t1, ST0_CU0 | 0x08001c00 - or t0, t1 - /* Clear TKSU, leave IXMT */ - xori t0, 0x00001800 - mtc0 t0, CP0_TCSTATUS - _ehb - /* We need to leave the global IE bit set, but clear EXL...*/ - mfc0 t0, CP0_STATUS - ori t0, ST0_EXL | ST0_ERL - xori t0, ST0_EXL | ST0_ERL - mtc0 t0, CP0_STATUS -#endif /* CONFIG_MIPS_MT_SMTC */ irq_disable_hazard .endm @@ -502,35 +377,11 @@ * Set cp0 enable bit as sign that we're running on the kernel stack */ .macro STI -#if !defined(CONFIG_MIPS_MT_SMTC) mfc0 t0, CP0_STATUS li t1, ST0_CU0 | STATMASK or t0, t1 xori t0, STATMASK & ~1 mtc0 t0, CP0_STATUS -#else /* CONFIG_MIPS_MT_SMTC */ - /* - * For SMTC, we need to set privilege - * and enable interrupts only for the - * current TC, using the TCStatus register. - */ - _ehb - mfc0 t0, CP0_TCSTATUS - /* Fortunately CU 0 is in the same place in both registers */ - /* Set TCU0, TKSU (for later inversion) and IXMT */ - li t1, ST0_CU0 | 0x08001c00 - or t0, t1 - /* Clear TKSU *and* IXMT */ - xori t0, 0x00001c00 - mtc0 t0, CP0_TCSTATUS - _ehb - /* We need to leave the global IE bit set, but clear EXL...*/ - mfc0 t0, CP0_STATUS - ori t0, ST0_EXL - xori t0, ST0_EXL - mtc0 t0, CP0_STATUS - /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */ -#endif /* CONFIG_MIPS_MT_SMTC */ irq_enable_hazard .endm @@ -540,32 +391,6 @@ * Set cp0 enable bit as sign that we're running on the kernel stack */ .macro KMODE -#ifdef CONFIG_MIPS_MT_SMTC - /* - * This gets baroque in SMTC. We want to - * protect the non-atomic clearing of EXL - * with DMT/EMT, but we don't want to take - * an interrupt while DMT is still in effect. - */ - - /* KMODE gets invoked from both reorder and noreorder code */ - .set push - .set mips32r2 - .set noreorder - mfc0 v0, CP0_TCSTATUS - andi v1, v0, TCSTATUS_IXMT - ori v0, TCSTATUS_IXMT - mtc0 v0, CP0_TCSTATUS - _ehb - DMT 2 # dmt v0 - /* - * We don't know a priori if ra is "live" - */ - move t0, ra - jal mips_ihb - nop /* delay slot */ - move ra, t0 -#endif /* CONFIG_MIPS_MT_SMTC */ mfc0 t0, CP0_STATUS li t1, ST0_CU0 | (STATMASK & ~1) #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) @@ -576,25 +401,6 @@ or t0, t1 xori t0, STATMASK & ~1 mtc0 t0, CP0_STATUS -#ifdef CONFIG_MIPS_MT_SMTC - _ehb - andi v0, v0, VPECONTROL_TE - beqz v0, 2f - nop /* delay slot */ - emt -2: - mfc0 v0, CP0_TCSTATUS - /* Clear IXMT, then OR in previous value */ - ori v0, TCSTATUS_IXMT - xori v0, TCSTATUS_IXMT - or v0, v1, v0 - mtc0 v0, CP0_TCSTATUS - /* - * irq_disable_hazard below should expand to EHB - * on 24K/34K CPUS - */ - .set pop -#endif /* CONFIG_MIPS_MT_SMTC */ irq_disable_hazard .endm diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index d2d961d..7de8658 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -159,11 +159,7 @@ static inline struct thread_info *current_thread_info(void) * We stash processor id into a COP0 register to retrieve it fast * at kernel exception entry. */ -#if defined(CONFIG_MIPS_MT_SMTC) -#define SMP_CPUID_REG 2, 2 /* TCBIND */ -#define ASM_SMP_CPUID_REG $2, 2 -#define SMP_CPUID_PTRSHIFT 19 -#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT) +#if defined(CONFIG_MIPS_PGD_C0_CONTEXT) #define SMP_CPUID_REG 20, 0 /* XCONTEXT */ #define ASM_SMP_CPUID_REG $20 #define SMP_CPUID_PTRSHIFT 48 @@ -179,13 +175,8 @@ static inline struct thread_info *current_thread_info(void) #define SMP_CPUID_REGSHIFT (SMP_CPUID_PTRSHIFT + 2) #endif -#ifdef CONFIG_MIPS_MT_SMTC -#define ASM_CPUID_MFC0 mfc0 -#define UASM_i_CPUID_MFC0 uasm_i_mfc0 -#else #define ASM_CPUID_MFC0 MFC0 #define UASM_i_CPUID_MFC0 UASM_i_MFC0 -#endif #endif /* __KERNEL__ */ #endif /* _ASM_THREAD_INFO_H */ diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h index 24f534a..8f3047d 100644 --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h @@ -52,14 +52,11 @@ extern int (*perf_irq)(void); */ extern unsigned int __weak get_c0_compare_int(void); extern int r4k_clockevent_init(void); -extern int smtc_clockevent_init(void); extern int gic_clockevent_init(void); static inline int mips_clockevent_init(void) { -#ifdef CONFIG_MIPS_MT_SMTC - return smtc_clockevent_init(); -#elif defined(CONFIG_CEVT_GIC) +#if defined(CONFIG_CEVT_GIC) return (gic_clockevent_init() | r4k_clockevent_init()); #elif defined(CONFIG_CEVT_R4K) return r4k_clockevent_init(); diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 277dab3..8f8b531 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -17,7 +17,6 @@ endif obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o -obj-$(CONFIG_MIPS_MT_SMTC) += cevt-smtc.o obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o obj-$(CONFIG_CEVT_GIC) += cevt-gic.o obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o @@ -50,7 +49,6 @@ obj-$(CONFIG_CPU_BMIPS) += smp-bmips.o bmips_vec.o obj-$(CONFIG_MIPS_MT) += mips-mt.o obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o -obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o obj-$(CONFIG_MIPS_CMP) += smp-cmp.o obj-$(CONFIG_MIPS_CPS) += smp-cps.o cps-vec.o diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 0ea75c2..08f897e 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -64,9 +64,6 @@ void output_ptreg_defines(void) OFFSET(PT_BVADDR, pt_regs, cp0_badvaddr); OFFSET(PT_STATUS, pt_regs, cp0_status); OFFSET(PT_CAUSE, pt_regs, cp0_cause); -#ifdef CONFIG_MIPS_MT_SMTC - OFFSET(PT_TCSTATUS, pt_regs, cp0_tcstatus); -#endif /* CONFIG_MIPS_MT_SMTC */ #ifdef CONFIG_CPU_CAVIUM_OCTEON OFFSET(PT_MPL, pt_regs, mpl); OFFSET(PT_MTP, pt_regs, mtp); diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 50d3f5a..bff124a 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -12,17 +12,10 @@ #include #include -#include #include #include #include -/* - * The SMTC Kernel for the 34K, 1004K, et. al. replaces several - * of these routines with SMTC-specific variants. - */ - -#ifndef CONFIG_MIPS_MT_SMTC static int mips_next_event(unsigned long delta, struct clock_event_device *evt) { @@ -36,8 +29,6 @@ static int mips_next_event(unsigned long delta, return res; } -#endif /* CONFIG_MIPS_MT_SMTC */ - void mips_set_clock_mode(enum clock_event_mode mode, struct clock_event_device *evt) { @@ -47,7 +38,6 @@ void mips_set_clock_mode(enum clock_event_mode mode, DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); int cp0_timer_irq_installed; -#ifndef CONFIG_MIPS_MT_SMTC irqreturn_t c0_compare_interrupt(int irq, void *dev_id) { const int r2 = cpu_has_mips_r2; @@ -82,8 +72,6 @@ out: return IRQ_HANDLED; } -#endif /* Not CONFIG_MIPS_MT_SMTC */ - struct irqaction c0_compare_irqaction = { .handler = c0_compare_interrupt, .flags = IRQF_PERCPU | IRQF_TIMER, @@ -170,7 +158,6 @@ int c0_compare_int_usable(void) return 1; } -#ifndef CONFIG_MIPS_MT_SMTC int r4k_clockevent_init(void) { unsigned int cpu = smp_processor_id(); @@ -225,4 +212,3 @@ int r4k_clockevent_init(void) return 0; } -#endif /* Not CONFIG_MIPS_MT_SMTC */ diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c deleted file mode 100644 index b6cf0a6..0000000 --- a/arch/mips/kernel/cevt-smtc.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2007 MIPS Technologies, Inc. - * Copyright (C) 2007 Ralf Baechle - * Copyright (C) 2008 Kevin D. Kissell, Paralogos sarl - */ -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * Variant clock event timer support for SMTC on MIPS 34K, 1004K - * or other MIPS MT cores. - * - * Notes on SMTC Support: - * - * SMTC has multiple microthread TCs pretending to be Linux CPUs. - * But there's only one Count/Compare pair per VPE, and Compare - * interrupts are taken opportunisitically by available TCs - * bound to the VPE with the Count register. The new timer - * framework provides for global broadcasts, but we really - * want VPE-level multicasts for best behavior. So instead - * of invoking the high-level clock-event broadcast code, - * this version of SMTC support uses the historical SMTC - * multicast mechanisms "under the hood", appearing to the - * generic clock layer as if the interrupts are per-CPU. - * - * The approach taken here is to maintain a set of NR_CPUS - * virtual timers, and track which "CPU" needs to be alerted - * at each event. - * - * It's unlikely that we'll see a MIPS MT core with more than - * 2 VPEs, but we *know* that we won't need to handle more - * VPEs than we have "CPUs". So NCPUs arrays of NCPUs elements - * is always going to be overkill, but always going to be enough. - */ - -unsigned long smtc_nexttime[NR_CPUS][NR_CPUS]; -static int smtc_nextinvpe[NR_CPUS]; - -/* - * Timestamps stored are absolute values to be programmed - * into Count register. Valid timestamps will never be zero. - * If a Zero Count value is actually calculated, it is converted - * to be a 1, which will introduce 1 or two CPU cycles of error - * roughly once every four billion events, which at 1000 HZ means - * about once every 50 days. If that's actually a problem, one - * could alternate squashing 0 to 1 and to -1. - */ - -#define MAKEVALID(x) (((x) == 0L) ? 1L : (x)) -#define ISVALID(x) ((x) != 0L) - -/* - * Time comparison is subtle, as it's really truncated - * modular arithmetic. - */ - -#define IS_SOONER(a, b, reference) \ - (((a) - (unsigned long)(reference)) < ((b) - (unsigned long)(reference))) - -/* - * CATCHUP_INCREMENT, used when the function falls behind the counter. - * Could be an increasing function instead of a constant; - */ - -#define CATCHUP_INCREMENT 64 - -static int mips_next_event(unsigned long delta, - struct clock_event_device *evt) -{ - unsigned long flags; - unsigned int mtflags; - unsigned long timestamp, reference, previous; - unsigned long nextcomp = 0L; - int vpe = current_cpu_data.vpe_id; - int cpu = smp_processor_id(); - local_irq_save(flags); - mtflags = dmt(); - - /* - * Maintain the per-TC virtual timer - * and program the per-VPE shared Count register - * as appropriate here... - */ - reference = (unsigned long)read_c0_count(); - timestamp = MAKEVALID(reference + delta); - /* - * To really model the clock, we have to catch the case - * where the current next-in-VPE timestamp is the old - * timestamp for the calling CPE, but the new value is - * in fact later. In that case, we have to do a full - * scan and discover the new next-in-VPE CPU id and - * timestamp. - */ - previous = smtc_nexttime[vpe][cpu]; - if (cpu == smtc_nextinvpe[vpe] && ISVALID(previous) - && IS_SOONER(previous, timestamp, reference)) { - int i; - int soonest = cpu; - - /* - * Update timestamp array here, so that new - * value gets considered along with those of - * other virtual CPUs on the VPE. - */ - smtc_nexttime[vpe][cpu] = timestamp; - for_each_online_cpu(i) { - if (ISVALID(smtc_nexttime[vpe][i]) - && IS_SOONER(smtc_nexttime[vpe][i], - smtc_nexttime[vpe][soonest], reference)) { - soonest = i; - } - } - smtc_nextinvpe[vpe] = soonest; - nextcomp = smtc_nexttime[vpe][soonest]; - /* - * Otherwise, we don't have to process the whole array rank, - * we just have to see if the event horizon has gotten closer. - */ - } else { - if (!ISVALID(smtc_nexttime[vpe][smtc_nextinvpe[vpe]]) || - IS_SOONER(timestamp, - smtc_nexttime[vpe][smtc_nextinvpe[vpe]], reference)) { - smtc_nextinvpe[vpe] = cpu; - nextcomp = timestamp; - } - /* - * Since next-in-VPE may me the same as the executing - * virtual CPU, we update the array *after* checking - * its value. - */ - smtc_nexttime[vpe][cpu] = timestamp; - } - - /* - * It may be that, in fact, we don't need to update Compare, - * but if we do, we want to make sure we didn't fall into - * a crack just behind Count. - */ - if (ISVALID(nextcomp)) { - write_c0_compare(nextcomp); - ehb(); - /* - * We never return an error, we just make sure - * that we trigger the handlers as quickly as - * we can if we fell behind. - */ - while ((nextcomp - (unsigned long)read_c0_count()) - > (unsigned long)LONG_MAX) { - nextcomp += CATCHUP_INCREMENT; - write_c0_compare(nextcomp); - ehb(); - } - } - emt(mtflags); - local_irq_restore(flags); - return 0; -} - - -void smtc_distribute_timer(int vpe) -{ - unsigned long flags; - unsigned int mtflags; - int cpu; - struct clock_event_device *cd; - unsigned long nextstamp; - unsigned long reference; - - -repeat: - nextstamp = 0L; - for_each_online_cpu(cpu) { - /* - * Find virtual CPUs within the current VPE who have - * unserviced timer requests whose time is now past. - */ - local_irq_save(flags); - mtflags = dmt(); - if (cpu_data[cpu].vpe_id == vpe && - ISVALID(smtc_nexttime[vpe][cpu])) { - reference = (unsigned long)read_c0_count(); - if ((smtc_nexttime[vpe][cpu] - reference) - > (unsigned long)LONG_MAX) { - smtc_nexttime[vpe][cpu] = 0L; - emt(mtflags); - local_irq_restore(flags); - /* - * We don't send IPIs to ourself. - */ - if (cpu != smp_processor_id()) { - smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0); - } else { - cd = &per_cpu(mips_clockevent_device, cpu); - cd->event_handler(cd); - } - } else { - /* Local to VPE but Valid Time not yet reached. */ - if (!ISVALID(nextstamp) || - IS_SOONER(smtc_nexttime[vpe][cpu], nextstamp, - reference)) { - smtc_nextinvpe[vpe] = cpu; - nextstamp = smtc_nexttime[vpe][cpu]; - } - emt(mtflags); - local_irq_restore(flags); - } - } else { - emt(mtflags); - local_irq_restore(flags); - - } - } - /* Reprogram for interrupt at next soonest timestamp for VPE */ - if (ISVALID(nextstamp)) { - write_c0_compare(nextstamp); - ehb(); - if ((nextstamp - (unsigned long)read_c0_count()) - > (unsigned long)LONG_MAX) - goto repeat; - } -} - - -irqreturn_t c0_compare_interrupt(int irq, void *dev_id) -{ - int cpu = smp_processor_id(); - - /* If we're running SMTC, we've got MIPS MT and therefore MIPS32R2 */ - handle_perf_irq(1); - - if (read_c0_cause() & (1 << 30)) { - /* Clear Count/Compare Interrupt */ - write_c0_compare(read_c0_compare()); - smtc_distribute_timer(cpu_data[cpu].vpe_id); - } - return IRQ_HANDLED; -} - - -int smtc_clockevent_init(void) -{ - uint64_t mips_freq = mips_hpt_frequency; - unsigned int cpu = smp_processor_id(); - struct clock_event_device *cd; - unsigned int irq; - int i; - int j; - - if (!cpu_has_counter || !mips_hpt_frequency) - return -ENXIO; - if (cpu == 0) { - for (i = 0; i < num_possible_cpus(); i++) { - smtc_nextinvpe[i] = 0; - for (j = 0; j < num_possible_cpus(); j++) - smtc_nexttime[i][j] = 0L; - } - /* - * SMTC also can't have the usablility test - * run by secondary TCs once Compare is in use. - */ - if (!c0_compare_int_usable()) - return -ENXIO; - } - - /* - * With vectored interrupts things are getting platform specific. - * get_c0_compare_int is a hook to allow a platform to return the - * interrupt number of it's liking. - */ - irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; - if (get_c0_compare_int) - irq = get_c0_compare_int(); - - cd = &per_cpu(mips_clockevent_device, cpu); - - cd->name = "MIPS"; - cd->features = CLOCK_EVT_FEAT_ONESHOT; - - /* Calculate the min / max delta */ - cd->mult = div_sc((unsigned long) mips_freq, NSEC_PER_SEC, 32); - cd->shift = 32; - cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); - - cd->rating = 300; - cd->irq = irq; - cd->cpumask = cpumask_of(cpu); - cd->set_next_event = mips_next_event; - cd->set_mode = mips_set_clock_mode; - cd->event_handler = mips_event_handler; - - clockevents_register_device(cd); - - /* - * On SMTC we only want to do the data structure - * initialization and IRQ setup once. - */ - if (cpu) - return 0; - /* - * And we need the hwmask associated with the c0_compare - * vector to be initialized. - */ - irq_hwmask[irq] = (0x100 << cp0_compare_irq); - if (cp0_timer_irq_installed) - return 0; - - cp0_timer_irq_installed = 1; - - setup_irq(irq, &c0_compare_irqaction); - - return 0; -} diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f83dc70..e8638c5 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -62,7 +62,7 @@ static inline void check_errata(void) case CPU_34K: /* * Erratum "RPS May Cause Incorrect Instruction Execution" - * This code only handles VPE0, any SMP/SMTC/RTOS code + * This code only handles VPE0, any SMP/RTOS code * making use of VPE1 will be responsable for that VPE. */ if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2) diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index e578685..4353d32 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -16,9 +16,6 @@ #include #include #include -#ifdef CONFIG_MIPS_MT_SMTC -#include -#endif #ifndef CONFIG_PREEMPT #define resume_kernel restore_all @@ -89,41 +86,6 @@ FEXPORT(syscall_exit) bnez t0, syscall_exit_work restore_all: # restore full frame -#ifdef CONFIG_MIPS_MT_SMTC -#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP -/* Re-arm any temporarily masked interrupts not explicitly "acked" */ - mfc0 v0, CP0_TCSTATUS - ori v1, v0, TCSTATUS_IXMT - mtc0 v1, CP0_TCSTATUS - andi v0, TCSTATUS_IXMT - _ehb - mfc0 t0, CP0_TCCONTEXT - DMT 9 # dmt t1 - jal mips_ihb - mfc0 t2, CP0_STATUS - andi t3, t0, 0xff00 - or t2, t2, t3 - mtc0 t2, CP0_STATUS - _ehb - andi t1, t1, VPECONTROL_TE - beqz t1, 1f - EMT -1: - mfc0 v1, CP0_TCSTATUS - /* We set IXMT above, XOR should clear it here */ - xori v1, v1, TCSTATUS_IXMT - or v1, v0, v1 - mtc0 v1, CP0_TCSTATUS - _ehb - xor t0, t0, t3 - mtc0 t0, CP0_TCCONTEXT -#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ -/* Detect and execute deferred IPI "interrupts" */ - LONG_L s0, TI_REGS($28) - LONG_S sp, TI_REGS($28) - jal deferred_smtc_ipi - LONG_S s0, TI_REGS($28) -#endif /* CONFIG_MIPS_MT_SMTC */ .set noat RESTORE_TEMP RESTORE_AT diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index a9ce340..ac35e12 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -21,20 +21,6 @@ #include #include -#ifdef CONFIG_MIPS_MT_SMTC -#define PANIC_PIC(msg) \ - .set push; \ - .set nomicromips; \ - .set reorder; \ - PTR_LA a0,8f; \ - .set noat; \ - PTR_LA AT, panic; \ - jr AT; \ -9: b 9b; \ - .set pop; \ - TEXT(msg) -#endif - __INIT /* @@ -251,15 +237,6 @@ NESTED(except_vec_vi, 0, sp) SAVE_AT .set push .set noreorder -#ifdef CONFIG_MIPS_MT_SMTC - /* - * To keep from blindly blocking *all* interrupts - * during service by SMTC kernel, we also want to - * pass the IM value to be cleared. - */ -FEXPORT(except_vec_vi_mori) - ori a0, $0, 0 -#endif /* CONFIG_MIPS_MT_SMTC */ PTR_LA v1, except_vec_vi_handler FEXPORT(except_vec_vi_lui) lui v0, 0 /* Patched */ @@ -277,37 +254,10 @@ EXPORT(except_vec_vi_end) NESTED(except_vec_vi_handler, 0, sp) SAVE_TEMP SAVE_STATIC -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC has an interesting problem that interrupts are level-triggered, - * and the CLI macro will clear EXL, potentially causing a duplicate - * interrupt service invocation. So we need to clear the associated - * IM bit of Status prior to doing CLI, and restore it after the - * service routine has been invoked - we must assume that the - * service routine will have cleared the state, and any active - * level represents a new or otherwised unserviced event... - */ - mfc0 t1, CP0_STATUS - and t0, a0, t1 -#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP - mfc0 t2, CP0_TCCONTEXT - or t2, t0, t2 - mtc0 t2, CP0_TCCONTEXT -#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */ - xor t1, t1, t0 - mtc0 t1, CP0_STATUS - _ehb -#endif /* CONFIG_MIPS_MT_SMTC */ CLI #ifdef CONFIG_TRACE_IRQFLAGS move s0, v0 -#ifdef CONFIG_MIPS_MT_SMTC - move s1, a0 -#endif TRACE_IRQS_OFF -#ifdef CONFIG_MIPS_MT_SMTC - move a0, s1 -#endif move v0, s0 #endif @@ -496,9 +446,6 @@ NESTED(nmi_handler, PT_SIZE, sp) .align 5 LEAF(handle_ri_rdhwr_vivt) -#ifdef CONFIG_MIPS_MT_SMTC - PANIC_PIC("handle_ri_rdhwr_vivt called") -#else .set push .set noat .set noreorder @@ -517,7 +464,6 @@ NESTED(nmi_handler, PT_SIZE, sp) .set pop bltz k1, handle_ri /* slow path */ /* fall thru */ -#endif END(handle_ri_rdhwr_vivt) LEAF(handle_ri_rdhwr) diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index e712dcf..95afd66 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S @@ -35,33 +35,12 @@ */ .macro setup_c0_status set clr .set push -#ifdef CONFIG_MIPS_MT_SMTC - /* - * For SMTC, we need to set privilege and disable interrupts only for - * the current TC, using the TCStatus register. - */ - mfc0 t0, CP0_TCSTATUS - /* Fortunately CU 0 is in the same place in both registers */ - /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */ - li t1, ST0_CU0 | 0x08001c00 - or t0, t1 - /* Clear TKSU, leave IXMT */ - xori t0, 0x00001800 - mtc0 t0, CP0_TCSTATUS - _ehb - /* We need to leave the global IE bit set, but clear EXL...*/ - mfc0 t0, CP0_STATUS - or t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr - xor t0, ST0_EXL | ST0_ERL | \clr - mtc0 t0, CP0_STATUS -#else mfc0 t0, CP0_STATUS or t0, ST0_CU0|\set|0x1f|\clr xor t0, 0x1f|\clr mtc0 t0, CP0_STATUS .set noreorder sll zero,3 # ehb -#endif .set pop .endm @@ -115,24 +94,6 @@ NESTED(kernel_entry, 16, sp) # kernel entry point jr t0 0: -#ifdef CONFIG_MIPS_MT_SMTC - /* - * In SMTC kernel, "CLI" is thread-specific, in TCStatus. - * We still need to enable interrupts globally in Status, - * and clear EXL/ERL. - * - * TCContext is used to track interrupt levels under - * service in SMTC kernel. Clear for boot TC before - * allowing any interrupts. - */ - mtc0 zero, CP0_TCCONTEXT - - mfc0 t0, CP0_STATUS - ori t0, t0, 0xff1f - xori t0, t0, 0x001e - mtc0 t0, CP0_STATUS -#endif /* CONFIG_MIPS_MT_SMTC */ - PTR_LA t0, __bss_start # clear .bss LONG_S zero, (t0) PTR_LA t1, __bss_stop - LONGSIZE @@ -164,25 +125,8 @@ NESTED(kernel_entry, 16, sp) # kernel entry point * function after setting up the stack and gp registers. */ NESTED(smp_bootstrap, 16, sp) -#ifdef CONFIG_MIPS_MT_SMTC - /* - * Read-modify-writes of Status must be atomic, and this - * is one case where CLI is invoked without EXL being - * necessarily set. The CLI and setup_c0_status will - * in fact be redundant for all but the first TC of - * each VPE being booted. - */ - DMT 10 # dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */ - jal mips_ihb -#endif /* CONFIG_MIPS_MT_SMTC */ smp_slave_setup setup_c0_status_sec -#ifdef CONFIG_MIPS_MT_SMTC - andi t2, t2, VPECONTROL_TE - beqz t2, 2f - EMT # emt -2: -#endif /* CONFIG_MIPS_MT_SMTC */ j start_secondary END(smp_bootstrap) #endif /* CONFIG_SMP */ diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c index 2b91fe8..50b3648 100644 --- a/arch/mips/kernel/i8259.c +++ b/arch/mips/kernel/i8259.c @@ -42,9 +42,6 @@ static struct irq_chip i8259A_chip = { .irq_disable = disable_8259A_irq, .irq_unmask = enable_8259A_irq, .irq_mask_ack = mask_and_ack_8259A, -#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF - .irq_set_affinity = plat_set_irq_affinity, -#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ }; /* @@ -180,7 +177,6 @@ handle_real_irq: outb(cached_master_mask, PIC_MASTER_IMR); outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */ } - smtc_im_ack_irq(irq); raw_spin_unlock_irqrestore(&i8259A_lock, flags); return; diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 5e3b653..c4ceccf 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -229,18 +229,8 @@ void __init check_wait(void) } } -static void smtc_idle_hook(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - void smtc_idle_loop_hook(void); - - smtc_idle_loop_hook(); -#endif -} - void arch_cpu_idle(void) { - smtc_idle_hook(); if (cpu_wait) cpu_wait(); else diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c index fab40f7..4858642 100644 --- a/arch/mips/kernel/irq-msc01.c +++ b/arch/mips/kernel/irq-msc01.c @@ -53,13 +53,9 @@ static inline void unmask_msc_irq(struct irq_data *d) */ static void level_mask_and_ack_msc_irq(struct irq_data *d) { - unsigned int irq = d->irq; - mask_msc_irq(d); if (!cpu_has_veic) MSCIC_WRITE(MSC01_IC_EOI, 0); - /* This actually needs to be a call into platform code */ - smtc_im_ack_irq(irq); } /* @@ -78,7 +74,6 @@ static void edge_mask_and_ack_msc_irq(struct irq_data *d) MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT); MSCIC_WRITE(MSC01_IC_SUP+irq*8, r); } - smtc_im_ack_irq(irq); } /* diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index d1fea7a..5024fa3 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -73,7 +73,6 @@ void free_irqno(unsigned int irq) */ void ack_bad_irq(unsigned int irq) { - smtc_im_ack_irq(irq); printk("unexpected IRQ # %d\n", irq); } @@ -142,23 +141,7 @@ void __irq_entry do_IRQ(unsigned int irq) { irq_enter(); check_stack_overflow(); - if (!smtc_handle_on_other_cpu(irq)) - generic_handle_irq(irq); - irq_exit(); -} - -#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF -/* - * To avoid inefficient and in some cases pathological re-checking of - * IRQ affinity, we have this variant that skips the affinity check. - */ - -void __irq_entry do_IRQ_no_affinity(unsigned int irq) -{ - irq_enter(); - smtc_im_backstop(irq); generic_handle_irq(irq); irq_exit(); } -#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index cb09862..362bb37 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -1,5 +1,5 @@ /* - * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels + * General MIPS MT support routines, usable in AP/SP and SMVP. * Copyright (C) 2005 Mips Technologies, Inc */ #include diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c index 6ded9bd..88b1ef5 100644 --- a/arch/mips/kernel/mips-mt.c +++ b/arch/mips/kernel/mips-mt.c @@ -1,5 +1,5 @@ /* - * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels + * General MIPS MT support routines, usable in AP/SP and SMVP. * Copyright (C) 2005 Mips Technologies, Inc */ @@ -57,9 +57,6 @@ void mips_mt_regdump(unsigned long mvpctl) int tc; unsigned long haltval; unsigned long tcstatval; -#ifdef CONFIG_MIPS_MT_SMTC - void smtc_soft_dump(void); -#endif /* CONFIG_MIPT_MT_SMTC */ local_irq_save(flags); vpflags = dvpe(); @@ -116,9 +113,6 @@ void mips_mt_regdump(unsigned long mvpctl) if (!haltval) write_tc_c0_tchalt(0); } -#ifdef CONFIG_MIPS_MT_SMTC - smtc_soft_dump(); -#endif /* CONFIG_MIPT_MT_SMTC */ printk("===========================\n"); evpe(vpflags); local_irq_restore(flags); @@ -295,21 +289,11 @@ void mips_mt_set_cpuoptions(void) void mt_cflush_lockdown(void) { -#ifdef CONFIG_MIPS_MT_SMTC - void smtc_cflush_lockdown(void); - - smtc_cflush_lockdown(); -#endif /* CONFIG_MIPS_MT_SMTC */ /* FILL IN VSMP and AP/SP VERSIONS HERE */ } void mt_cflush_release(void) { -#ifdef CONFIG_MIPS_MT_SMTC - void smtc_cflush_release(void); - - smtc_cflush_release(); -#endif /* CONFIG_MIPS_MT_SMTC */ /* FILL IN VSMP and AP/SP VERSIONS HERE */ } diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 60e39dc..0a1ec0f 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -140,13 +140,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, */ childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC restores TCStatus after Status, and the CU bits - * are aliased there. - */ - childregs->cp0_tcstatus &= ~(ST0_CU2|ST0_CU1); -#endif clear_tsk_thread_flag(p, TIF_USEDFPU); #ifdef CONFIG_MIPS_MT_FPAFF diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index abacac7..547c522 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -87,18 +87,6 @@ PTR_ADDU t0, $28, _THREAD_SIZE - 32 set_saved_sp t0, t1, t2 -#ifdef CONFIG_MIPS_MT_SMTC - /* Read-modify-writes of Status must be atomic on a VPE */ - mfc0 t2, CP0_TCSTATUS - ori t1, t2, TCSTATUS_IXMT - mtc0 t1, CP0_TCSTATUS - andi t2, t2, TCSTATUS_IXMT - _ehb - DMT 8 # dmt t0 - move t1,ra - jal mips_ihb - move ra,t1 -#endif /* CONFIG_MIPS_MT_SMTC */ mfc0 t1, CP0_STATUS /* Do we really need this? */ li a3, 0xff01 and t1, a3 @@ -107,18 +95,6 @@ and a2, a3 or a2, t1 mtc0 a2, CP0_STATUS -#ifdef CONFIG_MIPS_MT_SMTC - _ehb - andi t0, t0, VPECONTROL_TE - beqz t0, 1f - emt -1: - mfc0 t1, CP0_TCSTATUS - xori t1, t1, TCSTATUS_IXMT - or t1, t1, t2 - mtc0 t1, CP0_TCSTATUS - _ehb -#endif /* CONFIG_MIPS_MT_SMTC */ move v0, a0 jr ra END(resume) @@ -176,19 +152,10 @@ LEAF(_restore_msa) #define FPU_DEFAULT 0x00000000 LEAF(_init_fpu) -#ifdef CONFIG_MIPS_MT_SMTC - /* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */ - mfc0 t0, CP0_TCSTATUS - /* Bit position is the same for Status, TCStatus */ - li t1, ST0_CU1 - or t0, t1 - mtc0 t0, CP0_TCSTATUS -#else /* Normal MIPS CU1 enable */ mfc0 t0, CP0_STATUS li t1, ST0_CU1 or t0, t1 mtc0 t0, CP0_STATUS -#endif /* CONFIG_MIPS_MT_SMTC */ enable_fpu_hazard li t1, FPU_DEFAULT diff --git a/arch/mips/kernel/rtlx-mt.c b/arch/mips/kernel/rtlx-mt.c index 9c1aca0..5a66b97 100644 --- a/arch/mips/kernel/rtlx-mt.c +++ b/arch/mips/kernel/rtlx-mt.c @@ -36,7 +36,6 @@ static irqreturn_t rtlx_interrupt(int irq, void *dev_id) unsigned long flags; int i; - /* Ought not to be strictly necessary for SMTC builds */ local_irq_save(flags); vpeflags = dvpe(); set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ); diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index 3ef55fb7..64d06f6 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c @@ -49,14 +49,11 @@ static void cmp_init_secondary(void) /* Enable per-cpu interrupts: platform specific */ -#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) +#ifdef CONFIG_MIPS_MT_SMP if (cpu_has_mipsmt) c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE; #endif -#ifdef CONFIG_MIPS_MT_SMTC - c->tc_id = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT; -#endif } static void cmp_smp_finish(void) @@ -135,10 +132,6 @@ void __init cmp_smp_setup(void) unsigned int mvpconf0 = read_c0_mvpconf0(); nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; -#elif defined(CONFIG_MIPS_MT_SMTC) - unsigned int mvpconf0 = read_c0_mvpconf0(); - - nvpe = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1; #endif smp_num_siblings = nvpe; } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 0a022ee..35bb05a 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -43,10 +43,6 @@ #include #include -#ifdef CONFIG_MIPS_MT_SMTC -#include -#endif /* CONFIG_MIPS_MT_SMTC */ - volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ @@ -102,12 +98,6 @@ asmlinkage void start_secondary(void) { unsigned int cpu; -#ifdef CONFIG_MIPS_MT_SMTC - /* Only do cpu_probe for first TC of CPU */ - if ((read_c0_tcbind() & TCBIND_CURTC) != 0) - __cpu_name[smp_processor_id()] = __cpu_name[0]; - else -#endif /* CONFIG_MIPS_MT_SMTC */ cpu_probe(); cpu_report(); per_cpu_trap_init(false); @@ -238,13 +228,10 @@ static void flush_tlb_mm_ipi(void *mm) * o collapses to normal function call on UP kernels * o collapses to normal function call on systems with a single shared * primary cache. - * o CONFIG_MIPS_MT_SMTC currently implies there is only one physical core. */ static inline void smp_on_other_tlbs(void (*func) (void *info), void *info) { -#ifndef CONFIG_MIPS_MT_SMTC smp_call_function(func, info, 1); -#endif } static inline void smp_on_each_tlb(void (*func) (void *info), void *info) diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S deleted file mode 100644 index 2866863..0000000 --- a/arch/mips/kernel/smtc-asm.S +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Assembly Language Functions for MIPS MT SMTC support - */ - -/* - * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */ - -#include -#include -#include -#include - -/* - * "Software Interrupt" linkage. - * - * This is invoked when an "Interrupt" is sent from one TC to another, - * where the TC to be interrupted is halted, has it's Restart address - * and Status values saved by the "remote control" thread, then modified - * to cause execution to begin here, in kenel mode. This code then - * disguises the TC state as that of an exception and transfers - * control to the general exception or vectored interrupt handler. - */ - .set noreorder - -/* -The __smtc_ipi_vector would use k0 and k1 as temporaries and -1) Set EXL (this is per-VPE, so this can't be done by proxy!) -2) Restore the K/CU and IXMT bits to the pre "exception" state - (EXL means no interrupts and access to the kernel map). -3) Set EPC to be the saved value of TCRestart. -4) Jump to the exception handler entry point passed by the sender. - -CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED?? -*/ - -/* - * Reviled and slandered vision: Set EXL and restore K/CU/IXMT - * state of pre-halt thread, then save everything and call - * thought some function pointer to imaginary_exception, which - * will parse a register value or memory message queue to - * deliver things like interprocessor interrupts. On return - * from that function, jump to the global ret_from_irq code - * to invoke the scheduler and return as appropriate. - */ - -#define PT_PADSLOT4 (PT_R0-8) -#define PT_PADSLOT5 (PT_R0-4) - - .text - .align 5 -FEXPORT(__smtc_ipi_vector) -#ifdef CONFIG_CPU_MICROMIPS - nop -#endif - .set noat - /* Disable thread scheduling to make Status update atomic */ - DMT 27 # dmt k1 - _ehb - /* Set EXL */ - mfc0 k0,CP0_STATUS - ori k0,k0,ST0_EXL - mtc0 k0,CP0_STATUS - _ehb - /* Thread scheduling now inhibited by EXL. Restore TE state. */ - andi k1,k1,VPECONTROL_TE - beqz k1,1f - emt -1: - /* - * The IPI sender has put some information on the anticipated - * kernel stack frame. If we were in user mode, this will be - * built above the saved kernel SP. If we were already in the - * kernel, it will be built above the current CPU SP. - * - * Were we in kernel mode, as indicated by CU0? - */ - sll k1,k0,3 - .set noreorder - bltz k1,2f - move k1,sp - .set reorder - /* - * If previously in user mode, set CU0 and use kernel stack. - */ - li k1,ST0_CU0 - or k1,k1,k0 - mtc0 k1,CP0_STATUS - _ehb - get_saved_sp - /* Interrupting TC will have pre-set values in slots in the new frame */ -2: subu k1,k1,PT_SIZE - /* Load TCStatus Value */ - lw k0,PT_TCSTATUS(k1) - /* Write it to TCStatus to restore CU/KSU/IXMT state */ - mtc0 k0,$2,1 - _ehb - lw k0,PT_EPC(k1) - mtc0 k0,CP0_EPC - /* Save all will redundantly recompute the SP, but use it for now */ - SAVE_ALL - CLI - TRACE_IRQS_OFF - /* Function to be invoked passed stack pad slot 5 */ - lw t0,PT_PADSLOT5(sp) - /* Argument from sender passed in stack pad slot 4 */ - lw a0,PT_PADSLOT4(sp) - LONG_L s0, TI_REGS($28) - LONG_S sp, TI_REGS($28) - PTR_LA ra, ret_from_irq - jr t0 - -/* - * Called from idle loop to provoke processing of queued IPIs - * First IPI message in queue passed as argument. - */ - -LEAF(self_ipi) - /* Before anything else, block interrupts */ - mfc0 t0,CP0_TCSTATUS - ori t1,t0,TCSTATUS_IXMT - mtc0 t1,CP0_TCSTATUS - _ehb - /* We know we're in kernel mode, so prepare stack frame */ - subu t1,sp,PT_SIZE - sw ra,PT_EPC(t1) - sw a0,PT_PADSLOT4(t1) - la t2,ipi_decode - sw t2,PT_PADSLOT5(t1) - /* Save pre-disable value of TCStatus */ - sw t0,PT_TCSTATUS(t1) - j __smtc_ipi_vector - nop -END(self_ipi) diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c deleted file mode 100644 index 38635a9..0000000 --- a/arch/mips/kernel/smtc-proc.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * /proc hooks for SMTC kernel - * Copyright (C) 2005 Mips Technologies, Inc - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * /proc diagnostic and statistics hooks - */ - -/* - * Statistics gathered - */ -unsigned long selfipis[NR_CPUS]; - -struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS]; - -atomic_t smtc_fpu_recoveries; - -static int smtc_proc_show(struct seq_file *m, void *v) -{ - int i; - extern unsigned long ebase; - - seq_printf(m, "SMTC Status Word: 0x%08x\n", smtc_status); - seq_printf(m, "Config7: 0x%08x\n", read_c0_config7()); - seq_printf(m, "EBASE: 0x%08lx\n", ebase); - seq_printf(m, "Counter Interrupts taken per CPU (TC)\n"); - for (i=0; i < NR_CPUS; i++) - seq_printf(m, "%d: %ld\n", i, smtc_cpu_stats[i].timerints); - seq_printf(m, "Self-IPIs by CPU:\n"); - for(i = 0; i < NR_CPUS; i++) - seq_printf(m, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis); - seq_printf(m, "%d Recoveries of \"stolen\" FPU\n", - atomic_read(&smtc_fpu_recoveries)); - return 0; -} - -static int smtc_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, smtc_proc_show, NULL); -} - -static const struct file_operations smtc_proc_fops = { - .open = smtc_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -void init_smtc_stats(void) -{ - int i; - - for (i=0; im; - unsigned long n = pcn->n; - - if (!cpu_has_mipsmt) - return NOTIFY_OK; - - seq_printf(m, "VPE\t\t\t: %d\n", cpu_data[n].vpe_id); - seq_printf(m, "TC\t\t\t: %d\n", cpu_data[n].tc_id); - - return NOTIFY_OK; -} - -static int __init proc_cpuinfo_notifier_init(void) -{ - return proc_cpuinfo_notifier(proc_cpuinfo_chain_call, 0); -} - -subsys_initcall(proc_cpuinfo_notifier_init); diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c deleted file mode 100644 index c1681d6..0000000 --- a/arch/mips/kernel/smtc.c +++ /dev/null @@ -1,1528 +0,0 @@ -/* - * 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Copyright (C) 2004 Mips Technologies, Inc - * Copyright (C) 2008 Kevin D. Kissell - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * SMTC Kernel needs to manipulate low-level CPU interrupt mask - * in do_IRQ. These are passed in setup_irq_smtc() and stored - * in this table. - */ -unsigned long irq_hwmask[NR_IRQS]; - -#define LOCK_MT_PRA() \ - local_irq_save(flags); \ - mtflags = dmt() - -#define UNLOCK_MT_PRA() \ - emt(mtflags); \ - local_irq_restore(flags) - -#define LOCK_CORE_PRA() \ - local_irq_save(flags); \ - mtflags = dvpe() - -#define UNLOCK_CORE_PRA() \ - evpe(mtflags); \ - local_irq_restore(flags) - -/* - * Data structures purely associated with SMTC parallelism - */ - - -/* - * Table for tracking ASIDs whose lifetime is prolonged. - */ - -asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; - -/* - * Number of InterProcessor Interrupt (IPI) message buffers to allocate - */ - -#define IPIBUF_PER_CPU 4 - -struct smtc_ipi_q IPIQ[NR_CPUS]; -static struct smtc_ipi_q freeIPIq; - - -/* - * Number of FPU contexts for each VPE - */ - -static int smtc_nconf1[MAX_SMTC_VPES]; - - -/* Forward declarations */ - -void ipi_decode(struct smtc_ipi *); -static void post_direct_ipi(int cpu, struct smtc_ipi *pipi); -static void setup_cross_vpe_interrupts(unsigned int nvpe); -void init_smtc_stats(void); - -/* Global SMTC Status */ - -unsigned int smtc_status; - -/* Boot command line configuration overrides */ - -static int vpe0limit; -static int ipibuffers; -static int nostlb; -static int asidmask; -unsigned long smtc_asid_mask = 0xff; - -static int __init vpe0tcs(char *str) -{ - get_option(&str, &vpe0limit); - - return 1; -} - -static int __init ipibufs(char *str) -{ - get_option(&str, &ipibuffers); - return 1; -} - -static int __init stlb_disable(char *s) -{ - nostlb = 1; - return 1; -} - -static int __init asidmask_set(char *str) -{ - get_option(&str, &asidmask); - switch (asidmask) { - case 0x1: - case 0x3: - case 0x7: - case 0xf: - case 0x1f: - case 0x3f: - case 0x7f: - case 0xff: - smtc_asid_mask = (unsigned long)asidmask; - break; - default: - printk("ILLEGAL ASID mask 0x%x from command line\n", asidmask); - } - return 1; -} - -__setup("vpe0tcs=", vpe0tcs); -__setup("ipibufs=", ipibufs); -__setup("nostlb", stlb_disable); -__setup("asidmask=", asidmask_set); - -#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG - -static int hang_trig; - -static int __init hangtrig_enable(char *s) -{ - hang_trig = 1; - return 1; -} - - -__setup("hangtrig", hangtrig_enable); - -#define DEFAULT_BLOCKED_IPI_LIMIT 32 - -static int timerq_limit = DEFAULT_BLOCKED_IPI_LIMIT; - -static int __init tintq(char *str) -{ - get_option(&str, &timerq_limit); - return 1; -} - -__setup("tintq=", tintq); - -static int imstuckcount[MAX_SMTC_VPES][8]; -/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ -static int vpemask[MAX_SMTC_VPES][8] = { - {0, 0, 1, 0, 0, 0, 0, 1}, - {0, 0, 0, 0, 0, 0, 0, 1} -}; -int tcnoprog[NR_CPUS]; -static atomic_t idle_hook_initialized = ATOMIC_INIT(0); -static int clock_hang_reported[NR_CPUS]; - -#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ - -/* - * Configure shared TLB - VPC configuration bit must be set by caller - */ - -static void smtc_configure_tlb(void) -{ - int i, tlbsiz, vpes; - unsigned long mvpconf0; - unsigned long config1val; - - /* Set up ASID preservation table */ - for (vpes=0; vpes> MVPCONF0_PVPE_SHIFT) + 1) > 1) { - /* If we have multiple VPEs, try to share the TLB */ - if ((mvpconf0 & MVPCONF0_TLBS) && !nostlb) { - /* - * If TLB sizing is programmable, shared TLB - * size is the total available complement. - * Otherwise, we have to take the sum of all - * static VPE TLB entries. - */ - if ((tlbsiz = ((mvpconf0 & MVPCONF0_PTLBE) - >> MVPCONF0_PTLBE_SHIFT)) == 0) { - /* - * If there's more than one VPE, there had better - * be more than one TC, because we need one to bind - * to each VPE in turn to be able to read - * its configuration state! - */ - settc(1); - /* Stop the TC from doing anything foolish */ - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - /* No need to un-Halt - that happens later anyway */ - for (i=0; i < vpes; i++) { - write_tc_c0_tcbind(i); - /* - * To be 100% sure we're really getting the right - * information, we exit the configuration state - * and do an IHB after each rebinding. - */ - write_c0_mvpcontrol( - read_c0_mvpcontrol() & ~ MVPCONTROL_VPC ); - mips_ihb(); - /* - * Only count if the MMU Type indicated is TLB - */ - if (((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) { - config1val = read_vpe_c0_config1(); - tlbsiz += ((config1val >> 25) & 0x3f) + 1; - } - - /* Put core back in configuration state */ - write_c0_mvpcontrol( - read_c0_mvpcontrol() | MVPCONTROL_VPC ); - mips_ihb(); - } - } - write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB); - ehb(); - - /* - * Setup kernel data structures to use software total, - * rather than read the per-VPE Config1 value. The values - * for "CPU 0" gets copied to all the other CPUs as part - * of their initialization in smtc_cpu_setup(). - */ - - /* MIPS32 limits TLB indices to 64 */ - if (tlbsiz > 64) - tlbsiz = 64; - cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz; - smtc_status |= SMTC_TLB_SHARED; - local_flush_tlb_all(); - - printk("TLB of %d entry pairs shared by %d VPEs\n", - tlbsiz, vpes); - } else { - printk("WARNING: TLB Not Sharable on SMTC Boot!\n"); - } - } -} - - -/* - * Incrementally build the CPU map out of constituent MIPS MT cores, - * using the specified available VPEs and TCs. Plaform code needs - * to ensure that each MIPS MT core invokes this routine on reset, - * one at a time(!). - * - * This version of the build_cpu_map and prepare_cpus routines assumes - * that *all* TCs of a MIPS MT core will be used for Linux, and that - * they will be spread across *all* available VPEs (to minimise the - * loss of efficiency due to exception service serialization). - * An improved version would pick up configuration information and - * possibly leave some TCs/VPEs as "slave" processors. - * - * Use c0_MVPConf0 to find out how many TCs are available, setting up - * cpu_possible_mask and the logical/physical mappings. - */ - -int __init smtc_build_cpu_map(int start_cpu_slot) -{ - int i, ntcs; - - /* - * The CPU map isn't actually used for anything at this point, - * so it's not clear what else we should do apart from set - * everything up so that "logical" = "physical". - */ - ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1; - for (i=start_cpu_slot; i> 1) & 0xff; -} - -/* - * Tweak to get Count registers synced as closely as possible. The - * value seems good for 34K-class cores. - */ - -#define CP0_SKEW 8 - -void smtc_prepare_cpus(int cpus) -{ - int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu; - unsigned long flags; - unsigned long val; - int nipi; - struct smtc_ipi *pipi; - - /* disable interrupts so we can disable MT */ - local_irq_save(flags); - /* disable MT so we can configure */ - dvpe(); - dmt(); - - spin_lock_init(&freeIPIq.lock); - - /* - * We probably don't have as many VPEs as we do SMP "CPUs", - * but it's possible - and in any case we'll never use more! - */ - for (i=0; i> 1) & 0xff; - cpu++; - - /* Report on boot-time options */ - mips_mt_set_cpuoptions(); - if (vpelimit > 0) - printk("Limit of %d VPEs set\n", vpelimit); - if (tclimit > 0) - printk("Limit of %d TCs set\n", tclimit); - if (nostlb) { - printk("Shared TLB Use Inhibited - UNSAFE for Multi-VPE Operation\n"); - } - if (asidmask) - printk("ASID mask value override to 0x%x\n", asidmask); - - /* Temporary */ -#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG - if (hang_trig) - printk("Logic Analyser Trigger on suspected TC hang\n"); -#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ - - /* Put MVPE's into 'configuration state' */ - write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC ); - - val = read_c0_mvpconf0(); - nvpe = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; - if (vpelimit > 0 && nvpe > vpelimit) - nvpe = vpelimit; - ntc = ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1; - if (ntc > NR_CPUS) - ntc = NR_CPUS; - if (tclimit > 0 && ntc > tclimit) - ntc = tclimit; - slop = ntc % nvpe; - for (i = 0; i < nvpe; i++) { - tcpervpe[i] = ntc / nvpe; - if (slop) { - if((slop - i) > 0) tcpervpe[i]++; - } - } - /* Handle command line override for VPE0 */ - if (vpe0limit > ntc) vpe0limit = ntc; - if (vpe0limit > 0) { - int slopslop; - if (vpe0limit < tcpervpe[0]) { - /* Reducing TC count - distribute to others */ - slop = tcpervpe[0] - vpe0limit; - slopslop = slop % (nvpe - 1); - tcpervpe[0] = vpe0limit; - for (i = 1; i < nvpe; i++) { - tcpervpe[i] += slop / (nvpe - 1); - if(slopslop && ((slopslop - (i - 1) > 0))) - tcpervpe[i]++; - } - } else if (vpe0limit > tcpervpe[0]) { - /* Increasing TC count - steal from others */ - slop = vpe0limit - tcpervpe[0]; - slopslop = slop % (nvpe - 1); - tcpervpe[0] = vpe0limit; - for (i = 1; i < nvpe; i++) { - tcpervpe[i] -= slop / (nvpe - 1); - if(slopslop && ((slopslop - (i - 1) > 0))) - tcpervpe[i]--; - } - } - } - - /* Set up shared TLB */ - smtc_configure_tlb(); - - for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { - /* Get number of CP1 contexts for each VPE. */ - if (tc == 0) - { - /* - * Do not call settc() for TC0 or the FPU context - * value will be incorrect. Besides, we know that - * we are TC0 anyway. - */ - smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() & - VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); - if (nvpe == 2) - { - settc(1); - smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() & - VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT); - settc(0); - } - } - if (tcpervpe[vpe] == 0) - continue; - if (vpe != 0) - printk(", "); - printk("VPE %d: TC", vpe); - for (i = 0; i < tcpervpe[vpe]; i++) { - /* - * TC 0 is bound to VPE 0 at reset, - * and is presumably executing this - * code. Leave it alone! - */ - if (tc != 0) { - smtc_tc_setup(vpe, tc, cpu); - if (vpe != 0) { - /* - * Set MVP bit (possibly again). Do it - * here to catch CPUs that have no TCs - * bound to the VPE at reset. In that - * case, a TC must be bound to the VPE - * before we can set VPEControl[MVP] - */ - write_vpe_c0_vpeconf0( - read_vpe_c0_vpeconf0() | - VPECONF0_MVP); - } - cpu++; - } - printk(" %d", tc); - tc++; - } - if (vpe != 0) { - /* - * Allow this VPE to control others. - */ - write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | - VPECONF0_MVP); - - /* - * Clear any stale software interrupts from VPE's Cause - */ - write_vpe_c0_cause(0); - - /* - * Clear ERL/EXL of VPEs other than 0 - * and set restricted interrupt enable/mask. - */ - write_vpe_c0_status((read_vpe_c0_status() - & ~(ST0_BEV | ST0_ERL | ST0_EXL | ST0_IM)) - | (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7 - | ST0_IE)); - /* - * set config to be the same as vpe0, - * particularly kseg0 coherency alg - */ - write_vpe_c0_config(read_c0_config()); - /* Clear any pending timer interrupt */ - write_vpe_c0_compare(0); - /* Propagate Config7 */ - write_vpe_c0_config7(read_c0_config7()); - write_vpe_c0_count(read_c0_count() + CP0_SKEW); - ehb(); - } - /* enable multi-threading within VPE */ - write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE); - /* enable the VPE */ - write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); - } - - /* - * Pull any physically present but unused TCs out of circulation. - */ - while (tc < (((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1)) { - set_cpu_possible(tc, false); - set_cpu_present(tc, false); - tc++; - } - - /* release config state */ - write_c0_mvpcontrol( read_c0_mvpcontrol() & ~ MVPCONTROL_VPC ); - - printk("\n"); - - /* Set up coprocessor affinity CPU mask(s) */ - -#ifdef CONFIG_MIPS_MT_FPAFF - for (tc = 0; tc < ntc; tc++) { - if (cpu_data[tc].options & MIPS_CPU_FPU) - cpu_set(tc, mt_fpu_cpumask); - } -#endif - - /* set up ipi interrupts... */ - - /* If we have multiple VPEs running, set up the cross-VPE interrupt */ - - setup_cross_vpe_interrupts(nvpe); - - /* Set up queue of free IPI "messages". */ - nipi = NR_CPUS * IPIBUF_PER_CPU; - if (ipibuffers > 0) - nipi = ipibuffers; - - pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL); - if (pipi == NULL) - panic("kmalloc of IPI message buffers failed"); - else - printk("IPI buffer pool of %d buffers\n", nipi); - for (i = 0; i < nipi; i++) { - smtc_ipi_nq(&freeIPIq, pipi); - pipi++; - } - - /* Arm multithreading and enable other VPEs - but all TCs are Halted */ - emt(EMT_ENABLE); - evpe(EVPE_ENABLE); - local_irq_restore(flags); - /* Initialize SMTC /proc statistics/diagnostics */ - init_smtc_stats(); -} - - -/* - * Setup the PC, SP, and GP of a secondary processor and start it - * running! - * smp_bootstrap is the place to resume from - * __KSTK_TOS(idle) is apparently the stack pointer - * (unsigned long)idle->thread_info the gp - * - */ -void smtc_boot_secondary(int cpu, struct task_struct *idle) -{ - extern u32 kernelsp[NR_CPUS]; - unsigned long flags; - int mtflags; - - LOCK_MT_PRA(); - if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { - dvpe(); - } - settc(cpu_data[cpu].tc_id); - - /* pc */ - write_tc_c0_tcrestart((unsigned long)&smp_bootstrap); - - /* stack pointer */ - kernelsp[cpu] = __KSTK_TOS(idle); - write_tc_gpr_sp(__KSTK_TOS(idle)); - - /* global pointer */ - write_tc_gpr_gp((unsigned long)task_thread_info(idle)); - - smtc_status |= SMTC_MTC_ACTIVE; - write_tc_c0_tchalt(0); - if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { - evpe(EVPE_ENABLE); - } - UNLOCK_MT_PRA(); -} - -void smtc_init_secondary(void) -{ -} - -void smtc_smp_finish(void) -{ - int cpu = smp_processor_id(); - - /* - * Lowest-numbered CPU per VPE starts a clock tick. - * Like per_cpu_trap_init() hack, this assumes that - * SMTC init code assigns TCs consdecutively and - * in ascending order across available VPEs. - */ - if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id)) - write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); - - local_irq_enable(); - - printk("TC %d going on-line as CPU %d\n", - cpu_data[smp_processor_id()].tc_id, smp_processor_id()); -} - -void smtc_cpus_done(void) -{ -} - -/* - * Support for SMTC-optimized driver IRQ registration - */ - -/* - * SMTC Kernel needs to manipulate low-level CPU interrupt mask - * in do_IRQ. These are passed in setup_irq_smtc() and stored - * in this table. - */ - -int setup_irq_smtc(unsigned int irq, struct irqaction * new, - unsigned long hwmask) -{ -#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG - unsigned int vpe = current_cpu_data.vpe_id; - - vpemask[vpe][irq - MIPS_CPU_IRQ_BASE] = 1; -#endif - irq_hwmask[irq] = hwmask; - - return setup_irq(irq, new); -} - -#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF -/* - * Support for IRQ affinity to TCs - */ - -void smtc_set_irq_affinity(unsigned int irq, cpumask_t affinity) -{ - /* - * If a "fast path" cache of quickly decodable affinity state - * is maintained, this is where it gets done, on a call up - * from the platform affinity code. - */ -} - -void smtc_forward_irq(struct irq_data *d) -{ - unsigned int irq = d->irq; - int target; - - /* - * OK wise guy, now figure out how to get the IRQ - * to be serviced on an authorized "CPU". - * - * Ideally, to handle the situation where an IRQ has multiple - * eligible CPUS, we would maintain state per IRQ that would - * allow a fair distribution of service requests. Since the - * expected use model is any-or-only-one, for simplicity - * and efficiency, we just pick the easiest one to find. - */ - - target = cpumask_first(d->affinity); - - /* - * We depend on the platform code to have correctly processed - * IRQ affinity change requests to ensure that the IRQ affinity - * mask has been purged of bits corresponding to nonexistent and - * offline "CPUs", and to TCs bound to VPEs other than the VPE - * connected to the physical interrupt input for the interrupt - * in question. Otherwise we have a nasty problem with interrupt - * mask management. This is best handled in non-performance-critical - * platform IRQ affinity setting code, to minimize interrupt-time - * checks. - */ - - /* If no one is eligible, service locally */ - if (target >= NR_CPUS) - do_IRQ_no_affinity(irq); - else - smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq); -} - -#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ - -/* - * IPI model for SMTC is tricky, because interrupts aren't TC-specific. - * Within a VPE one TC can interrupt another by different approaches. - * The easiest to get right would probably be to make all TCs except - * the target IXMT and set a software interrupt, but an IXMT-based - * scheme requires that a handler must run before a new IPI could - * be sent, which would break the "broadcast" loops in MIPS MT. - * A more gonzo approach within a VPE is to halt the TC, extract - * its Restart, Status, and a couple of GPRs, and program the Restart - * address to emulate an interrupt. - * - * Within a VPE, one can be confident that the target TC isn't in - * a critical EXL state when halted, since the write to the Halt - * register could not have issued on the writing thread if the - * halting thread had EXL set. So k0 and k1 of the target TC - * can be used by the injection code. Across VPEs, one can't - * be certain that the target TC isn't in a critical exception - * state. So we try a two-step process of sending a software - * interrupt to the target VPE, which either handles the event - * itself (if it was the target) or injects the event within - * the VPE. - */ - -static void smtc_ipi_qdump(void) -{ - int i; - struct smtc_ipi *temp; - - for (i = 0; i < NR_CPUS ;i++) { - pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n", - i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, - IPIQ[i].depth); - temp = IPIQ[i].head; - - while (temp != IPIQ[i].tail) { - pr_debug("%d %d %d: ", temp->type, temp->dest, - (int)temp->arg); -#ifdef SMTC_IPI_DEBUG - pr_debug("%u %lu\n", temp->sender, temp->stamp); -#else - pr_debug("\n"); -#endif - temp = temp->flink; - } - } -} - -/* - * The standard atomic.h primitives don't quite do what we want - * here: We need an atomic add-and-return-previous-value (which - * could be done with atomic_add_return and a decrement) and an - * atomic set/zero-and-return-previous-value (which can't really - * be done with the atomic.h primitives). And since this is - * MIPS MT, we can assume that we have LL/SC. - */ -static inline int atomic_postincrement(atomic_t *v) -{ - unsigned long result; - - unsigned long temp; - - __asm__ __volatile__( - "1: ll %0, %2 \n" - " addu %1, %0, 1 \n" - " sc %1, %2 \n" - " beqz %1, 1b \n" - __WEAK_LLSC_MB - : "=&r" (result), "=&r" (temp), "=m" (v->counter) - : "m" (v->counter) - : "memory"); - - return result; -} - -void smtc_send_ipi(int cpu, int type, unsigned int action) -{ - int tcstatus; - struct smtc_ipi *pipi; - unsigned long flags; - int mtflags; - unsigned long tcrestart; - int set_resched_flag = (type == LINUX_SMP_IPI && - action == SMP_RESCHEDULE_YOURSELF); - - if (cpu == smp_processor_id()) { - printk("Cannot Send IPI to self!\n"); - return; - } - if (set_resched_flag && IPIQ[cpu].resched_flag != 0) - return; /* There is a reschedule queued already */ - - /* Set up a descriptor, to be delivered either promptly or queued */ - pipi = smtc_ipi_dq(&freeIPIq); - if (pipi == NULL) { - bust_spinlocks(1); - mips_mt_regdump(dvpe()); - panic("IPI Msg. Buffers Depleted"); - } - pipi->type = type; - pipi->arg = (void *)action; - pipi->dest = cpu; - if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { - /* If not on same VPE, enqueue and send cross-VPE interrupt */ - IPIQ[cpu].resched_flag |= set_resched_flag; - smtc_ipi_nq(&IPIQ[cpu], pipi); - LOCK_CORE_PRA(); - settc(cpu_data[cpu].tc_id); - write_vpe_c0_cause(read_vpe_c0_cause() | C_SW1); - UNLOCK_CORE_PRA(); - } else { - /* - * Not sufficient to do a LOCK_MT_PRA (dmt) here, - * since ASID shootdown on the other VPE may - * collide with this operation. - */ - LOCK_CORE_PRA(); - settc(cpu_data[cpu].tc_id); - /* Halt the targeted TC */ - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - - /* - * Inspect TCStatus - if IXMT is set, we have to queue - * a message. Otherwise, we set up the "interrupt" - * of the other TC - */ - tcstatus = read_tc_c0_tcstatus(); - - if ((tcstatus & TCSTATUS_IXMT) != 0) { - /* - * If we're in the the irq-off version of the wait - * loop, we need to force exit from the wait and - * do a direct post of the IPI. - */ - if (cpu_wait == r4k_wait_irqoff) { - tcrestart = read_tc_c0_tcrestart(); - if (address_is_in_r4k_wait_irqoff(tcrestart)) { - write_tc_c0_tcrestart(__pastwait); - tcstatus &= ~TCSTATUS_IXMT; - write_tc_c0_tcstatus(tcstatus); - goto postdirect; - } - } - /* - * Otherwise we queue the message for the target TC - * to pick up when he does a local_irq_restore() - */ - write_tc_c0_tchalt(0); - UNLOCK_CORE_PRA(); - IPIQ[cpu].resched_flag |= set_resched_flag; - smtc_ipi_nq(&IPIQ[cpu], pipi); - } else { -postdirect: - post_direct_ipi(cpu, pipi); - write_tc_c0_tchalt(0); - UNLOCK_CORE_PRA(); - } - } -} - -/* - * Send IPI message to Halted TC, TargTC/TargVPE already having been set - */ -static void post_direct_ipi(int cpu, struct smtc_ipi *pipi) -{ - struct pt_regs *kstack; - unsigned long tcstatus; - unsigned long tcrestart; - extern u32 kernelsp[NR_CPUS]; - extern void __smtc_ipi_vector(void); -//printk("%s: on %d for %d\n", __func__, smp_processor_id(), cpu); - - /* Extract Status, EPC from halted TC */ - tcstatus = read_tc_c0_tcstatus(); - tcrestart = read_tc_c0_tcrestart(); - /* If TCRestart indicates a WAIT instruction, advance the PC */ - if ((tcrestart & 0x80000000) - && ((*(unsigned int *)tcrestart & 0xfe00003f) == 0x42000020)) { - tcrestart += 4; - } - /* - * Save on TC's future kernel stack - * - * CU bit of Status is indicator that TC was - * already running on a kernel stack... - */ - if (tcstatus & ST0_CU0) { - /* Note that this "- 1" is pointer arithmetic */ - kstack = ((struct pt_regs *)read_tc_gpr_sp()) - 1; - } else { - kstack = ((struct pt_regs *)kernelsp[cpu]) - 1; - } - - kstack->cp0_epc = (long)tcrestart; - /* Save TCStatus */ - kstack->cp0_tcstatus = tcstatus; - /* Pass token of operation to be performed kernel stack pad area */ - kstack->pad0[4] = (unsigned long)pipi; - /* Pass address of function to be called likewise */ - kstack->pad0[5] = (unsigned long)&ipi_decode; - /* Set interrupt exempt and kernel mode */ - tcstatus |= TCSTATUS_IXMT; - tcstatus &= ~TCSTATUS_TKSU; - write_tc_c0_tcstatus(tcstatus); - ehb(); - /* Set TC Restart address to be SMTC IPI vector */ - write_tc_c0_tcrestart(__smtc_ipi_vector); -} - -static void ipi_resched_interrupt(void) -{ - scheduler_ipi(); -} - -static void ipi_call_interrupt(void) -{ - /* Invoke generic function invocation code in smp.c */ - smp_call_function_interrupt(); -} - -DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device); - -static void __irq_entry smtc_clock_tick_interrupt(void) -{ - unsigned int cpu = smp_processor_id(); - struct clock_event_device *cd; - int irq = MIPS_CPU_IRQ_BASE + 1; - - irq_enter(); - kstat_incr_irq_this_cpu(irq); - cd = &per_cpu(mips_clockevent_device, cpu); - cd->event_handler(cd); - irq_exit(); -} - -void ipi_decode(struct smtc_ipi *pipi) -{ - void *arg_copy = pipi->arg; - int type_copy = pipi->type; - - smtc_ipi_nq(&freeIPIq, pipi); - - switch (type_copy) { - case SMTC_CLOCK_TICK: - smtc_clock_tick_interrupt(); - break; - - case LINUX_SMP_IPI: - switch ((int)arg_copy) { - case SMP_RESCHEDULE_YOURSELF: - ipi_resched_interrupt(); - break; - case SMP_CALL_FUNCTION: - ipi_call_interrupt(); - break; - default: - printk("Impossible SMTC IPI Argument %p\n", arg_copy); - break; - } - break; -#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF - case IRQ_AFFINITY_IPI: - /* - * Accept a "forwarded" interrupt that was initially - * taken by a TC who doesn't have affinity for the IRQ. - */ - do_IRQ_no_affinity((int)arg_copy); - break; -#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ - default: - printk("Impossible SMTC IPI Type 0x%x\n", type_copy); - break; - } -} - -/* - * Similar to smtc_ipi_replay(), but invoked from context restore, - * so it reuses the current exception frame rather than set up a - * new one with self_ipi. - */ - -void deferred_smtc_ipi(void) -{ - int cpu = smp_processor_id(); - - /* - * Test is not atomic, but much faster than a dequeue, - * and the vast majority of invocations will have a null queue. - * If irq_disabled when this was called, then any IPIs queued - * after we test last will be taken on the next irq_enable/restore. - * If interrupts were enabled, then any IPIs added after the - * last test will be taken directly. - */ - - while (IPIQ[cpu].head != NULL) { - struct smtc_ipi_q *q = &IPIQ[cpu]; - struct smtc_ipi *pipi; - unsigned long flags; - - /* - * It may be possible we'll come in with interrupts - * already enabled. - */ - local_irq_save(flags); - spin_lock(&q->lock); - pipi = __smtc_ipi_dq(q); - spin_unlock(&q->lock); - if (pipi != NULL) { - if (pipi->type == LINUX_SMP_IPI && - (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) - IPIQ[cpu].resched_flag = 0; - ipi_decode(pipi); - } - /* - * The use of the __raw_local restore isn't - * as obviously necessary here as in smtc_ipi_replay(), - * but it's more efficient, given that we're already - * running down the IPI queue. - */ - __arch_local_irq_restore(flags); - } -} - -/* - * Cross-VPE interrupts in the SMTC prototype use "software interrupts" - * set via cross-VPE MTTR manipulation of the Cause register. It would be - * in some regards preferable to have external logic for "doorbell" hardware - * interrupts. - */ - -static int cpu_ipi_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_IRQ; - -static irqreturn_t ipi_interrupt(int irq, void *dev_idm) -{ - int my_vpe = cpu_data[smp_processor_id()].vpe_id; - int my_tc = cpu_data[smp_processor_id()].tc_id; - int cpu; - struct smtc_ipi *pipi; - unsigned long tcstatus; - int sent; - unsigned long flags; - unsigned int mtflags; - unsigned int vpflags; - - /* - * So long as cross-VPE interrupts are done via - * MFTR/MTTR read-modify-writes of Cause, we need - * to stop other VPEs whenever the local VPE does - * anything similar. - */ - local_irq_save(flags); - vpflags = dvpe(); - clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ); - set_c0_status(0x100 << MIPS_CPU_IPI_IRQ); - irq_enable_hazard(); - evpe(vpflags); - local_irq_restore(flags); - - /* - * Cross-VPE Interrupt handler: Try to directly deliver IPIs - * queued for TCs on this VPE other than the current one. - * Return-from-interrupt should cause us to drain the queue - * for the current TC, so we ought not to have to do it explicitly here. - */ - - for_each_online_cpu(cpu) { - if (cpu_data[cpu].vpe_id != my_vpe) - continue; - - pipi = smtc_ipi_dq(&IPIQ[cpu]); - if (pipi != NULL) { - if (cpu_data[cpu].tc_id != my_tc) { - sent = 0; - LOCK_MT_PRA(); - settc(cpu_data[cpu].tc_id); - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - tcstatus = read_tc_c0_tcstatus(); - if ((tcstatus & TCSTATUS_IXMT) == 0) { - post_direct_ipi(cpu, pipi); - sent = 1; - } - write_tc_c0_tchalt(0); - UNLOCK_MT_PRA(); - if (!sent) { - smtc_ipi_req(&IPIQ[cpu], pipi); - } - } else { - /* - * ipi_decode() should be called - * with interrupts off - */ - local_irq_save(flags); - if (pipi->type == LINUX_SMP_IPI && - (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) - IPIQ[cpu].resched_flag = 0; - ipi_decode(pipi); - local_irq_restore(flags); - } - } - } - - return IRQ_HANDLED; -} - -static void ipi_irq_dispatch(void) -{ - do_IRQ(cpu_ipi_irq); -} - -static struct irqaction irq_ipi = { - .handler = ipi_interrupt, - .flags = IRQF_PERCPU, - .name = "SMTC_IPI" -}; - -static void setup_cross_vpe_interrupts(unsigned int nvpe) -{ - if (nvpe < 1) - return; - - if (!cpu_has_vint) - panic("SMTC Kernel requires Vectored Interrupt support"); - - set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch); - - setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ)); - - irq_set_handler(cpu_ipi_irq, handle_percpu_irq); -} - -/* - * SMTC-specific hacks invoked from elsewhere in the kernel. - */ - - /* - * smtc_ipi_replay is called from raw_local_irq_restore - */ - -void smtc_ipi_replay(void) -{ - unsigned int cpu = smp_processor_id(); - - /* - * To the extent that we've ever turned interrupts off, - * we may have accumulated deferred IPIs. This is subtle. - * we should be OK: If we pick up something and dispatch - * it here, that's great. If we see nothing, but concurrent - * with this operation, another TC sends us an IPI, IXMT - * is clear, and we'll handle it as a real pseudo-interrupt - * and not a pseudo-pseudo interrupt. The important thing - * is to do the last check for queued message *after* the - * re-enabling of interrupts. - */ - while (IPIQ[cpu].head != NULL) { - struct smtc_ipi_q *q = &IPIQ[cpu]; - struct smtc_ipi *pipi; - unsigned long flags; - - /* - * It's just possible we'll come in with interrupts - * already enabled. - */ - local_irq_save(flags); - - spin_lock(&q->lock); - pipi = __smtc_ipi_dq(q); - spin_unlock(&q->lock); - /* - ** But use a raw restore here to avoid recursion. - */ - __arch_local_irq_restore(flags); - - if (pipi) { - self_ipi(pipi); - smtc_cpu_stats[cpu].selfipis++; - } - } -} - -EXPORT_SYMBOL(smtc_ipi_replay); - -void smtc_idle_loop_hook(void) -{ -#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG - int im; - int flags; - int mtflags; - int bit; - int vpe; - int tc; - int hook_ntcs; - /* - * printk within DMT-protected regions can deadlock, - * so buffer diagnostic messages for later output. - */ - char *pdb_msg; - char id_ho_db_msg[768]; /* worst-case use should be less than 700 */ - - if (atomic_read(&idle_hook_initialized) == 0) { /* fast test */ - if (atomic_add_return(1, &idle_hook_initialized) == 1) { - int mvpconf0; - /* Tedious stuff to just do once */ - mvpconf0 = read_c0_mvpconf0(); - hook_ntcs = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1; - if (hook_ntcs > NR_CPUS) - hook_ntcs = NR_CPUS; - for (tc = 0; tc < hook_ntcs; tc++) { - tcnoprog[tc] = 0; - clock_hang_reported[tc] = 0; - } - for (vpe = 0; vpe < 2; vpe++) - for (im = 0; im < 8; im++) - imstuckcount[vpe][im] = 0; - printk("Idle loop test hook initialized for %d TCs\n", hook_ntcs); - atomic_set(&idle_hook_initialized, 1000); - } else { - /* Someone else is initializing in parallel - let 'em finish */ - while (atomic_read(&idle_hook_initialized) < 1000) - ; - } - } - - /* Have we stupidly left IXMT set somewhere? */ - if (read_c0_tcstatus() & 0x400) { - write_c0_tcstatus(read_c0_tcstatus() & ~0x400); - ehb(); - printk("Dangling IXMT in cpu_idle()\n"); - } - - /* Have we stupidly left an IM bit turned off? */ -#define IM_LIMIT 2000 - local_irq_save(flags); - mtflags = dmt(); - pdb_msg = &id_ho_db_msg[0]; - im = read_c0_status(); - vpe = current_cpu_data.vpe_id; - for (bit = 0; bit < 8; bit++) { - /* - * In current prototype, I/O interrupts - * are masked for VPE > 0 - */ - if (vpemask[vpe][bit]) { - if (!(im & (0x100 << bit))) - imstuckcount[vpe][bit]++; - else - imstuckcount[vpe][bit] = 0; - if (imstuckcount[vpe][bit] > IM_LIMIT) { - set_c0_status(0x100 << bit); - ehb(); - imstuckcount[vpe][bit] = 0; - pdb_msg += sprintf(pdb_msg, - "Dangling IM %d fixed for VPE %d\n", bit, - vpe); - } - } - } - - emt(mtflags); - local_irq_restore(flags); - if (pdb_msg != &id_ho_db_msg[0]) - printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); -#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ - - smtc_ipi_replay(); -} - -void smtc_soft_dump(void) -{ - int i; - - printk("Counter Interrupts taken per CPU (TC)\n"); - for (i=0; i < NR_CPUS; i++) { - printk("%d: %ld\n", i, smtc_cpu_stats[i].timerints); - } - printk("Self-IPI invocations:\n"); - for (i=0; i < NR_CPUS; i++) { - printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis); - } - smtc_ipi_qdump(); - printk("%d Recoveries of \"stolen\" FPU\n", - atomic_read(&smtc_fpu_recoveries)); -} - - -/* - * TLB management routines special to SMTC - */ - -void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu) -{ - unsigned long flags, mtflags, tcstat, prevhalt, asid; - int tlb, i; - - /* - * It would be nice to be able to use a spinlock here, - * but this is invoked from within TLB flush routines - * that protect themselves with DVPE, so if a lock is - * held by another TC, it'll never be freed. - * - * DVPE/DMT must not be done with interrupts enabled, - * so even so most callers will already have disabled - * them, let's be really careful... - */ - - local_irq_save(flags); - if (smtc_status & SMTC_TLB_SHARED) { - mtflags = dvpe(); - tlb = 0; - } else { - mtflags = dmt(); - tlb = cpu_data[cpu].vpe_id; - } - asid = asid_cache(cpu); - - do { - if (!((asid += ASID_INC) & ASID_MASK) ) { - if (cpu_has_vtag_icache) - flush_icache_all(); - /* Traverse all online CPUs (hack requires contiguous range) */ - for_each_online_cpu(i) { - /* - * We don't need to worry about our own CPU, nor those of - * CPUs who don't share our TLB. - */ - if ((i != smp_processor_id()) && - ((smtc_status & SMTC_TLB_SHARED) || - (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))) { - settc(cpu_data[i].tc_id); - prevhalt = read_tc_c0_tchalt() & TCHALT_H; - if (!prevhalt) { - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - } - tcstat = read_tc_c0_tcstatus(); - smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i); - if (!prevhalt) - write_tc_c0_tchalt(0); - } - } - if (!asid) /* fix version if needed */ - asid = ASID_FIRST_VERSION; - local_flush_tlb_all(); /* start new asid cycle */ - } - } while (smtc_live_asid[tlb][(asid & ASID_MASK)]); - - /* - * SMTC shares the TLB within VPEs and possibly across all VPEs. - */ - for_each_online_cpu(i) { - if ((smtc_status & SMTC_TLB_SHARED) || - (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id)) - cpu_context(i, mm) = asid_cache(i) = asid; - } - - if (smtc_status & SMTC_TLB_SHARED) - evpe(mtflags); - else - emt(mtflags); - local_irq_restore(flags); -} - -/* - * Invoked from macros defined in mmu_context.h - * which must already have disabled interrupts - * and done a DVPE or DMT as appropriate. - */ - -void smtc_flush_tlb_asid(unsigned long asid) -{ - int entry; - unsigned long ehi; - - entry = read_c0_wired(); - - /* Traverse all non-wired entries */ - while (entry < current_cpu_data.tlbsize) { - write_c0_index(entry); - ehb(); - tlb_read(); - ehb(); - ehi = read_c0_entryhi(); - if ((ehi & ASID_MASK) == asid) { - /* - * Invalidate only entries with specified ASID, - * makiing sure all entries differ. - */ - write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1))); - write_c0_entrylo0(0); - write_c0_entrylo1(0); - mtc0_tlbw_hazard(); - tlb_write_indexed(); - } - entry++; - } - write_c0_index(PARKED_INDEX); - tlbw_use_hazard(); -} - -/* - * Support for single-threading cache flush operations. - */ - -static int halt_state_save[NR_CPUS]; - -/* - * To really, really be sure that nothing is being done - * by other TCs, halt them all. This code assumes that - * a DVPE has already been done, so while their Halted - * state is theoretically architecturally unstable, in - * practice, it's not going to change while we're looking - * at it. - */ - -void smtc_cflush_lockdown(void) -{ - int cpu; - - for_each_online_cpu(cpu) { - if (cpu != smp_processor_id()) { - settc(cpu_data[cpu].tc_id); - halt_state_save[cpu] = read_tc_c0_tchalt(); - write_tc_c0_tchalt(TCHALT_H); - } - } - mips_ihb(); -} - -/* It would be cheating to change the cpu_online states during a flush! */ - -void smtc_cflush_release(void) -{ - int cpu; - - /* - * Start with a hazard barrier to ensure - * that all CACHE ops have played through. - */ - mips_ihb(); - - for_each_online_cpu(cpu) { - if (cpu != smp_processor_id()) { - settc(cpu_data[cpu].tc_id); - write_tc_c0_tchalt(halt_state_save[cpu]); - } - } - mips_ihb(); -} diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index c24ad5f..2242bdd 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -6,8 +6,6 @@ * not have done anything significant (but they may have had interrupts * enabled briefly - prom_smp_finish() should not be responsible for enabling * interrupts...) - * - * FIXME: broken for SMTC */ #include @@ -33,14 +31,6 @@ void synchronise_count_master(int cpu) unsigned long flags; unsigned int initcount; -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC needs to synchronise per VPE, not per CPU - * ignore for now - */ - return; -#endif - printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu); local_irq_save(flags); @@ -110,14 +100,6 @@ void synchronise_count_slave(int cpu) int i; unsigned int initcount; -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC needs to synchronise per VPE, not per CPU - * ignore for now - */ - return; -#endif - /* * Not every cpu is online at the time this gets called, * so we first wait for the master to say everyone is ready diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index dcb8e5d..8d01709 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -26,7 +26,6 @@ #include #include #include -#include #include /* diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 074e857..3a26729 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -370,9 +370,6 @@ void __noreturn die(const char *str, struct pt_regs *regs) { static int die_counter; int sig = SIGSEGV; -#ifdef CONFIG_MIPS_MT_SMTC - unsigned long dvpret; -#endif /* CONFIG_MIPS_MT_SMTC */ oops_enter(); @@ -382,13 +379,7 @@ void __noreturn die(const char *str, struct pt_regs *regs) console_verbose(); raw_spin_lock_irq(&die_lock); -#ifdef CONFIG_MIPS_MT_SMTC - dvpret = dvpe(); -#endif /* CONFIG_MIPS_MT_SMTC */ bust_spinlocks(1); -#ifdef CONFIG_MIPS_MT_SMTC - mips_mt_regdump(dvpret); -#endif /* CONFIG_MIPS_MT_SMTC */ printk("%s[#%d]:\n", str, ++die_counter); show_registers(regs); @@ -1759,19 +1750,6 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) extern char rollback_except_vec_vi; char *vec_start = using_rollback_handler() ? &rollback_except_vec_vi : &except_vec_vi; -#ifdef CONFIG_MIPS_MT_SMTC - /* - * We need to provide the SMTC vectored interrupt handler - * not only with the address of the handler, but with the - * Status.IM bit to be masked before going there. - */ - extern char except_vec_vi_mori; -#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN) - const int mori_offset = &except_vec_vi_mori - vec_start + 2; -#else - const int mori_offset = &except_vec_vi_mori - vec_start; -#endif -#endif /* CONFIG_MIPS_MT_SMTC */ #if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN) const int lui_offset = &except_vec_vi_lui - vec_start + 2; const int ori_offset = &except_vec_vi_ori - vec_start + 2; @@ -1795,12 +1773,6 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) #else handler_len); #endif -#ifdef CONFIG_MIPS_MT_SMTC - BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */ - - h = (u16 *)(b + mori_offset); - *h = (0x100 << n); -#endif /* CONFIG_MIPS_MT_SMTC */ h = (u16 *)(b + lui_offset); *h = (handler >> 16) & 0xffff; h = (u16 *)(b + ori_offset); @@ -1870,20 +1842,6 @@ void per_cpu_trap_init(bool is_boot_cpu) unsigned int cpu = smp_processor_id(); unsigned int status_set = ST0_CU0; unsigned int hwrena = cpu_hwrena_impl_bits; -#ifdef CONFIG_MIPS_MT_SMTC - int secondaryTC = 0; - int bootTC = (cpu == 0); - - /* - * Only do per_cpu_trap_init() for first TC of Each VPE. - * Note that this hack assumes that the SMTC init code - * assigns TCs consecutively and in ascending order. - */ - - if (((read_c0_tcbind() & TCBIND_CURTC) != 0) && - ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id)) - secondaryTC = 1; -#endif /* CONFIG_MIPS_MT_SMTC */ /* * Disable coprocessors and select 32-bit or 64-bit addressing @@ -1911,10 +1869,6 @@ void per_cpu_trap_init(bool is_boot_cpu) if (hwrena) write_c0_hwrena(hwrena); -#ifdef CONFIG_MIPS_MT_SMTC - if (!secondaryTC) { -#endif /* CONFIG_MIPS_MT_SMTC */ - if (cpu_has_veic || cpu_has_vint) { unsigned long sr = set_c0_status(ST0_BEV); write_c0_ebase(ebase); @@ -1949,10 +1903,6 @@ void per_cpu_trap_init(bool is_boot_cpu) cp0_perfcount_irq = -1; } -#ifdef CONFIG_MIPS_MT_SMTC - } -#endif /* CONFIG_MIPS_MT_SMTC */ - if (!cpu_data[cpu].asid_cache) cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; @@ -1961,23 +1911,10 @@ void per_cpu_trap_init(bool is_boot_cpu) BUG_ON(current->mm); enter_lazy_tlb(&init_mm, current); -#ifdef CONFIG_MIPS_MT_SMTC - if (bootTC) { -#endif /* CONFIG_MIPS_MT_SMTC */ /* Boot CPU's cache setup in setup_arch(). */ if (!is_boot_cpu) cpu_cache_init(); tlb_init(); -#ifdef CONFIG_MIPS_MT_SMTC - } else if (!secondaryTC) { - /* - * First TC in non-boot VPE must do subset of tlb_init() - * for MMU countrol registers. - */ - write_c0_pagemask(PM_DEFAULT_MASK); - write_c0_wired(0); - } -#endif /* CONFIG_MIPS_MT_SMTC */ TLBMISS_HANDLER_SETUP(); } diff --git a/arch/mips/kernel/vpe-mt.c b/arch/mips/kernel/vpe-mt.c index 949ae0e..2e003b1 100644 --- a/arch/mips/kernel/vpe-mt.c +++ b/arch/mips/kernel/vpe-mt.c @@ -127,9 +127,8 @@ int vpe_run(struct vpe *v) clear_c0_mvpcontrol(MVPCONTROL_VPC); /* - * SMTC/SMVP kernels manage VPE enable independently, - * but uniprocessor kernels need to turn it on, even - * if that wasn't the pre-dvpe() state. + * SMVP kernels manage VPE enable independently, but uniprocessor + * kernels need to turn it on, even if that wasn't the pre-dvpe() state. */ #ifdef CONFIG_SMP evpe(vpeflags); @@ -454,12 +453,11 @@ int __init vpe_module_init(void) settc(tc); - /* Any TC that is bound to VPE0 gets left as is - in - * case we are running SMTC on VPE0. A TC that is bound - * to any other VPE gets bound to VPE0, ideally I'd like - * to make it homeless but it doesn't appear to let me - * bind a TC to a non-existent VPE. Which is perfectly - * reasonable. + /* + * A TC that is bound to any other VPE gets bound to + * VPE0, ideally I'd like to make it homeless but it + * doesn't appear to let me bind a TC to a non-existent + * VPE. Which is perfectly reasonable. * * The (un)bound state is visible to an EJTAG probe so * may notify GDB... diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 85685e1..030568a 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -61,7 +61,7 @@ /* we have a cascade of 8 irqs */ #define MIPS_CPU_IRQ_CASCADE 8 -#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) +#ifdef CONFIG_MIPS_MT_SMP int gic_present; #endif @@ -440,7 +440,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call); #endif -#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) +#ifndef CONFIG_MIPS_MT_SMP set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); #else diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c index 6807f71..57bcdaf1 100644 --- a/arch/mips/lib/mips-atomic.c +++ b/arch/mips/lib/mips-atomic.c @@ -15,7 +15,7 @@ #include #include -#if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) +#ifndef CONFIG_CPU_MIPSR2 /* * For cli() we have to insert nops to make sure that the new value @@ -42,12 +42,7 @@ notrace void arch_local_irq_disable(void) __asm__ __volatile__( " .set push \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 $1, $2, 1 \n" - " ori $1, 0x400 \n" - " .set noreorder \n" - " mtc0 $1, $2, 1 \n" -#elif defined(CONFIG_CPU_MIPSR2) +#if defined(CONFIG_CPU_MIPSR2) /* see irqflags.h for inline function */ #else " mfc0 $1,$12 \n" @@ -77,13 +72,7 @@ notrace unsigned long arch_local_irq_save(void) " .set push \n" " .set reorder \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 %[flags], $2, 1 \n" - " ori $1, %[flags], 0x400 \n" - " .set noreorder \n" - " mtc0 $1, $2, 1 \n" - " andi %[flags], %[flags], 0x400 \n" -#elif defined(CONFIG_CPU_MIPSR2) +#if defined(CONFIG_CPU_MIPSR2) /* see irqflags.h for inline function */ #else " mfc0 %[flags], $12 \n" @@ -108,29 +97,13 @@ notrace void arch_local_irq_restore(unsigned long flags) { unsigned long __tmp1; -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC kernel needs to do a software replay of queued - * IPIs, at the cost of branch and call overhead on each - * local_irq_restore() - */ - if (unlikely(!(flags & 0x0400))) - smtc_ipi_replay(); -#endif preempt_disable(); __asm__ __volatile__( " .set push \n" " .set noreorder \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 $1, $2, 1 \n" - " andi %[flags], 0x400 \n" - " ori $1, 0x400 \n" - " xori $1, 0x400 \n" - " or %[flags], $1 \n" - " mtc0 %[flags], $2, 1 \n" -#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) +#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) /* see irqflags.h for inline function */ #elif defined(CONFIG_CPU_MIPSR2) /* see irqflags.h for inline function */ @@ -163,14 +136,7 @@ notrace void __arch_local_irq_restore(unsigned long flags) " .set push \n" " .set noreorder \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 $1, $2, 1 \n" - " andi %[flags], 0x400 \n" - " ori $1, 0x400 \n" - " xori $1, 0x400 \n" - " or %[flags], $1 \n" - " mtc0 %[flags], $2, 1 \n" -#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) +#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) /* see irqflags.h for inline function */ #elif defined(CONFIG_CPU_MIPSR2) /* see irqflags.h for inline function */ @@ -192,4 +158,4 @@ notrace void __arch_local_irq_restore(unsigned long flags) } EXPORT_SYMBOL(__arch_local_irq_restore); -#endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */ +#endif /* !CONFIG_CPU_MIPSR2 */ diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 7bc14ff..5c21282 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -50,7 +50,7 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info) { preempt_disable(); -#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) +#ifndef CONFIG_MIPS_MT_SMP smp_call_function(func, info, 1); #endif func(info); @@ -427,7 +427,7 @@ static void r4k___flush_cache_all(void) static inline int has_valid_asid(const struct mm_struct *mm) { -#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) +#ifdef CONFIG_MIPS_MT_SMP int i; for_each_online_cpu(i) diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 4fc74c7..609a0cd 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -44,27 +44,6 @@ #include #include -/* Atomicity and interruptability */ -#ifdef CONFIG_MIPS_MT_SMTC - -#include - -#define ENTER_CRITICAL(flags) \ - { \ - unsigned int mvpflags; \ - local_irq_save(flags);\ - mvpflags = dvpe() -#define EXIT_CRITICAL(flags) \ - evpe(mvpflags); \ - local_irq_restore(flags); \ - } -#else - -#define ENTER_CRITICAL(flags) local_irq_save(flags) -#define EXIT_CRITICAL(flags) local_irq_restore(flags) - -#endif /* CONFIG_MIPS_MT_SMTC */ - /* * We have up to 8 empty zeroed pages so we can map one of the right colour * when needed. This is necessary only on R4000 / R4400 SC and MC versions @@ -100,20 +79,6 @@ void setup_zero_pages(void) zero_page_mask = ((PAGE_SIZE << order) - 1) & PAGE_MASK; } -#ifdef CONFIG_MIPS_MT_SMTC -static pte_t *kmap_coherent_pte; -static void __init kmap_coherent_init(void) -{ - unsigned long vaddr; - - /* cache the first coherent kmap pte */ - vaddr = __fix_to_virt(FIX_CMAP_BEGIN); - kmap_coherent_pte = kmap_get_fixmap_pte(vaddr); -} -#else -static inline void kmap_coherent_init(void) {} -#endif - void *kmap_coherent(struct page *page, unsigned long addr) { enum fixed_addresses idx; @@ -126,12 +91,7 @@ void *kmap_coherent(struct page *page, unsigned long addr) pagefault_disable(); idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1); -#ifdef CONFIG_MIPS_MT_SMTC - idx += FIX_N_COLOURS * smp_processor_id() + - (in_interrupt() ? (FIX_N_COLOURS * NR_CPUS) : 0); -#else idx += in_interrupt() ? FIX_N_COLOURS : 0; -#endif vaddr = __fix_to_virt(FIX_CMAP_END - idx); pte = mk_pte(page, PAGE_KERNEL); #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) @@ -140,44 +100,29 @@ void *kmap_coherent(struct page *page, unsigned long addr) entrylo = pte_to_entrylo(pte_val(pte)); #endif - ENTER_CRITICAL(flags); + local_irq_save(flags); old_ctx = read_c0_entryhi(); write_c0_entryhi(vaddr & (PAGE_MASK << 1)); write_c0_entrylo0(entrylo); write_c0_entrylo1(entrylo); -#ifdef CONFIG_MIPS_MT_SMTC - set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte); - /* preload TLB instead of local_flush_tlb_one() */ - mtc0_tlbw_hazard(); - tlb_probe(); - tlb_probe_hazard(); - tlbidx = read_c0_index(); - mtc0_tlbw_hazard(); - if (tlbidx < 0) - tlb_write_random(); - else - tlb_write_indexed(); -#else tlbidx = read_c0_wired(); write_c0_wired(tlbidx + 1); write_c0_index(tlbidx); mtc0_tlbw_hazard(); tlb_write_indexed(); -#endif tlbw_use_hazard(); write_c0_entryhi(old_ctx); - EXIT_CRITICAL(flags); + local_irq_restore(flags); return (void*) vaddr; } void kunmap_coherent(void) { -#ifndef CONFIG_MIPS_MT_SMTC unsigned int wired; unsigned long flags, old_ctx; - ENTER_CRITICAL(flags); + local_irq_save(flags); old_ctx = read_c0_entryhi(); wired = read_c0_wired() - 1; write_c0_wired(wired); @@ -189,8 +134,7 @@ void kunmap_coherent(void) tlb_write_indexed(); tlbw_use_hazard(); write_c0_entryhi(old_ctx); - EXIT_CRITICAL(flags); -#endif + local_irq_restore(flags); pagefault_enable(); } @@ -256,7 +200,7 @@ EXPORT_SYMBOL_GPL(copy_from_user_page); void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) { -#if defined(CONFIG_HIGHMEM) || defined(CONFIG_MIPS_MT_SMTC) +#ifdef CONFIG_HIGHMEM pgd_t *pgd; pud_t *pud; pmd_t *pmd; @@ -327,8 +271,6 @@ void __init paging_init(void) #ifdef CONFIG_HIGHMEM kmap_init(); #endif - kmap_coherent_init(); - #ifdef CONFIG_ZONE_DMA max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN; #endif diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index eeaf50f..403fa80 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -25,28 +25,6 @@ extern void build_tlb_refill_handler(void); -/* Atomicity and interruptability */ -#ifdef CONFIG_MIPS_MT_SMTC - -#include -#include - -#define ENTER_CRITICAL(flags) \ - { \ - unsigned int mvpflags; \ - local_irq_save(flags);\ - mvpflags = dvpe() -#define EXIT_CRITICAL(flags) \ - evpe(mvpflags); \ - local_irq_restore(flags); \ - } -#else - -#define ENTER_CRITICAL(flags) local_irq_save(flags) -#define EXIT_CRITICAL(flags) local_irq_restore(flags) - -#endif /* CONFIG_MIPS_MT_SMTC */ - /* * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb, * unfortunately, itlb is not totally transparent to software. @@ -75,7 +53,7 @@ void local_flush_tlb_all(void) unsigned long old_ctx; int entry, ftlbhighset; - ENTER_CRITICAL(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi(); write_c0_entrylo0(0); @@ -112,7 +90,7 @@ void local_flush_tlb_all(void) tlbw_use_hazard(); write_c0_entryhi(old_ctx); flush_itlb(); - EXIT_CRITICAL(flags); + local_irq_restore(flags); } EXPORT_SYMBOL(local_flush_tlb_all); @@ -142,7 +120,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, if (cpu_context(cpu, mm) != 0) { unsigned long size, flags; - ENTER_CRITICAL(flags); + local_irq_save(flags); start = round_down(start, PAGE_SIZE << 1); end = round_up(end, PAGE_SIZE << 1); size = (end - start) >> (PAGE_SHIFT + 1); @@ -176,7 +154,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, drop_mmu_context(mm, cpu); } flush_itlb(); - EXIT_CRITICAL(flags); + local_irq_restore(flags); } } @@ -184,7 +162,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) { unsigned long size, flags; - ENTER_CRITICAL(flags); + local_irq_save(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if (size <= (current_cpu_data.tlbsizeftlbsets ? @@ -220,7 +198,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) local_flush_tlb_all(); } flush_itlb(); - EXIT_CRITICAL(flags); + local_irq_restore(flags); } void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) @@ -233,7 +211,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) newpid = cpu_asid(cpu, vma->vm_mm); page &= (PAGE_MASK << 1); - ENTER_CRITICAL(flags); + local_irq_save(flags); oldpid = read_c0_entryhi(); write_c0_entryhi(page | newpid); mtc0_tlbw_hazard(); @@ -253,7 +231,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) finish: write_c0_entryhi(oldpid); flush_itlb_vm(vma); - EXIT_CRITICAL(flags); + local_irq_restore(flags); } } @@ -266,7 +244,7 @@ void local_flush_tlb_one(unsigned long page) unsigned long flags; int oldpid, idx; - ENTER_CRITICAL(flags); + local_irq_save(flags); oldpid = read_c0_entryhi(); page &= (PAGE_MASK << 1); write_c0_entryhi(page); @@ -285,7 +263,7 @@ void local_flush_tlb_one(unsigned long page) } write_c0_entryhi(oldpid); flush_itlb(); - EXIT_CRITICAL(flags); + local_irq_restore(flags); } /* @@ -308,7 +286,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) if (current->active_mm != vma->vm_mm) return; - ENTER_CRITICAL(flags); + local_irq_save(flags); pid = read_c0_entryhi() & ASID_MASK; address &= (PAGE_MASK << 1); @@ -358,7 +336,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) } tlbw_use_hazard(); flush_itlb_vm(vma); - EXIT_CRITICAL(flags); + local_irq_restore(flags); } void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, @@ -369,7 +347,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long old_pagemask; unsigned long old_ctx; - ENTER_CRITICAL(flags); + local_irq_save(flags); /* Save old context and create impossible VPN2 value */ old_ctx = read_c0_entryhi(); old_pagemask = read_c0_pagemask(); @@ -389,7 +367,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, tlbw_use_hazard(); /* What is the hazard here? */ write_c0_pagemask(old_pagemask); local_flush_tlb_all(); - EXIT_CRITICAL(flags); + local_irq_restore(flags); } #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -399,13 +377,13 @@ int __init has_transparent_hugepage(void) unsigned int mask; unsigned long flags; - ENTER_CRITICAL(flags); + local_irq_save(flags); write_c0_pagemask(PM_HUGE_MASK); back_to_back_c0_hazard(); mask = read_c0_pagemask(); write_c0_pagemask(PM_DEFAULT_MASK); - EXIT_CRITICAL(flags); + local_irq_restore(flags); return mask == PM_HUGE_MASK; } diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index eae0ba3..a851601 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -8,6 +8,3 @@ obj-y := malta-amon.o malta-display.o malta-init.o \ malta-int.o malta-memory.o malta-platform.o \ malta-reset.o malta-setup.o malta-time.o - -# FIXME FIXME FIXME -obj-$(CONFIG_MIPS_MT_SMTC) += malta-smtc.o diff --git a/arch/mips/mti-malta/malta-init.c b/arch/mips/mti-malta/malta-init.c index 4f9e44d..0f60256 100644 --- a/arch/mips/mti-malta/malta-init.c +++ b/arch/mips/mti-malta/malta-init.c @@ -116,8 +116,6 @@ phys_t mips_cpc_default_phys_base(void) return CPC_BASE_ADDR; } -extern struct plat_smp_ops msmtc_smp_ops; - void __init prom_init(void) { mips_display_message("LINUX"); @@ -304,8 +302,4 @@ mips_pci_controller: return; if (!register_vsmp_smp_ops()) return; - -#ifdef CONFIG_MIPS_MT_SMTC - register_smp_ops(&msmtc_smp_ops); -#endif } diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index b71ee80..ecc2785 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -504,28 +504,9 @@ void __init arch_init_irq(void) } else if (cpu_has_vint) { set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); -#ifdef CONFIG_MIPS_MT_SMTC - setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq, - (0x100 << MIPSCPU_INT_I8259A)); - setup_irq_smtc(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, - &corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI)); - /* - * Temporary hack to ensure that the subsidiary device - * interrupts coing in via the i8259A, but associated - * with low IRQ numbers, will restore the Status.IM - * value associated with the i8259A. - */ - { - int i; - - for (i = 0; i < 16; i++) - irq_hwmask[i] = (0x100 << MIPSCPU_INT_I8259A); - } -#else /* Not SMTC */ setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); -#endif /* CONFIG_MIPS_MT_SMTC */ } else { setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c index bf62151..db7c9e5 100644 --- a/arch/mips/mti-malta/malta-setup.c +++ b/arch/mips/mti-malta/malta-setup.c @@ -77,11 +77,7 @@ const char *get_system_type(void) return "MIPS Malta"; } -#if defined(CONFIG_MIPS_MT_SMTC) -const char display_string[] = " SMTC LINUX ON MALTA "; -#else const char display_string[] = " LINUX ON MALTA "; -#endif /* CONFIG_MIPS_MT_SMTC */ #ifdef CONFIG_BLK_DEV_FD static void __init fd_activate(void) diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c deleted file mode 100644 index c484990..0000000 --- a/arch/mips/mti-malta/malta-smtc.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Malta Platform-specific hooks for SMP operation - */ -#include -#include - -#include -#include -#include -#include - -/* VPE/SMP Prototype implements platform interfaces directly */ - -/* - * Cause the specified action to be performed on a targeted "CPU" - */ - -static void msmtc_send_ipi_single(int cpu, unsigned int action) -{ - /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ - smtc_send_ipi(cpu, LINUX_SMP_IPI, action); -} - -static void msmtc_send_ipi_mask(const struct cpumask *mask, unsigned int action) -{ - unsigned int i; - - for_each_cpu(i, mask) - msmtc_send_ipi_single(i, action); -} - -/* - * Post-config but pre-boot cleanup entry point - */ -static void msmtc_init_secondary(void) -{ - int myvpe; - - /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ - myvpe = read_c0_tcbind() & TCBIND_CURVPE; - if (myvpe != 0) { - /* Ideally, this should be done only once per VPE, but... */ - clear_c0_status(ST0_IM); - set_c0_status((0x100 << cp0_compare_irq) - | (0x100 << MIPS_CPU_IPI_IRQ)); - if (cp0_perfcount_irq >= 0) - set_c0_status(0x100 << cp0_perfcount_irq); - } - - smtc_init_secondary(); -} - -/* - * Platform "CPU" startup hook - */ -static void msmtc_boot_secondary(int cpu, struct task_struct *idle) -{ - smtc_boot_secondary(cpu, idle); -} - -/* - * SMP initialization finalization entry point - */ -static void msmtc_smp_finish(void) -{ - smtc_smp_finish(); -} - -/* - * Hook for after all CPUs are online - */ - -static void msmtc_cpus_done(void) -{ -} - -/* - * Platform SMP pre-initialization - * - * As noted above, we can assume a single CPU for now - * but it may be multithreaded. - */ - -static void __init msmtc_smp_setup(void) -{ - /* - * we won't get the definitive value until - * we've run smtc_prepare_cpus later, but - * we would appear to need an upper bound now. - */ - smp_num_siblings = smtc_build_cpu_map(0); -} - -static void __init msmtc_prepare_cpus(unsigned int max_cpus) -{ - smtc_prepare_cpus(max_cpus); -} - -struct plat_smp_ops msmtc_smp_ops = { - .send_ipi_single = msmtc_send_ipi_single, - .send_ipi_mask = msmtc_send_ipi_mask, - .init_secondary = msmtc_init_secondary, - .smp_finish = msmtc_smp_finish, - .cpus_done = msmtc_cpus_done, - .boot_secondary = msmtc_boot_secondary, - .smp_setup = msmtc_smp_setup, - .prepare_cpus = msmtc_prepare_cpus, -}; - -#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF -/* - * IRQ affinity hook - */ - - -int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, - bool force) -{ - cpumask_t tmask; - int cpu = 0; - void smtc_set_irq_affinity(unsigned int irq, cpumask_t aff); - - /* - * On the legacy Malta development board, all I/O interrupts - * are routed through the 8259 and combined in a single signal - * to the CPU daughterboard, and on the CoreFPGA2/3 34K models, - * that signal is brought to IP2 of both VPEs. To avoid racing - * concurrent interrupt service events, IP2 is enabled only on - * one VPE, by convention VPE0. So long as no bits are ever - * cleared in the affinity mask, there will never be any - * interrupt forwarding. But as soon as a program or operator - * sets affinity for one of the related IRQs, we need to make - * sure that we don't ever try to forward across the VPE boundary, - * at least not until we engineer a system where the interrupt - * _ack() or _end() function can somehow know that it corresponds - * to an interrupt taken on another VPE, and perform the appropriate - * restoration of Status.IM state using MFTR/MTTR instead of the - * normal local behavior. We also ensure that no attempt will - * be made to forward to an offline "CPU". - */ - - cpumask_copy(&tmask, affinity); - for_each_cpu(cpu, affinity) { - if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu)) - cpu_clear(cpu, tmask); - } - cpumask_copy(d->affinity, &tmask); - - if (cpus_empty(tmask)) - /* - * We could restore a default mask here, but the - * runtime code can anyway deal with the null set - */ - printk(KERN_WARNING - "IRQ affinity leaves no legal CPU for IRQ %d\n", d->irq); - - /* Do any generic SMTC IRQ affinity setup */ - smtc_set_irq_affinity(d->irq, tmask); - - return IRQ_SET_MASK_OK_NOCOPY; -} -#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */ diff --git a/arch/mips/pmcs-msp71xx/Makefile b/arch/mips/pmcs-msp71xx/Makefile index 9201c8b..d4f7220 100644 --- a/arch/mips/pmcs-msp71xx/Makefile +++ b/arch/mips/pmcs-msp71xx/Makefile @@ -10,4 +10,3 @@ obj-$(CONFIG_PCI) += msp_pci.o obj-$(CONFIG_MSP_HAS_MAC) += msp_eth.o obj-$(CONFIG_MSP_HAS_USB) += msp_usb.o obj-$(CONFIG_MIPS_MT_SMP) += msp_smp.o -obj-$(CONFIG_MIPS_MT_SMTC) += msp_smtc.o diff --git a/arch/mips/pmcs-msp71xx/msp_irq.c b/arch/mips/pmcs-msp71xx/msp_irq.c index 9da5619..941744a 100644 --- a/arch/mips/pmcs-msp71xx/msp_irq.c +++ b/arch/mips/pmcs-msp71xx/msp_irq.c @@ -32,7 +32,7 @@ extern void msp_vsmp_int_init(void); /* vectored interrupt implementation */ -/* SW0/1 interrupts are used for SMP/SMTC */ +/* SW0/1 interrupts are used for SMP */ static inline void mac0_int_dispatch(void) { do_IRQ(MSP_INT_MAC0); } static inline void mac1_int_dispatch(void) { do_IRQ(MSP_INT_MAC1); } static inline void mac2_int_dispatch(void) { do_IRQ(MSP_INT_SAR); } @@ -138,14 +138,6 @@ void __init arch_init_irq(void) set_vi_handler(MSP_INT_SEC, sec_int_dispatch); #ifdef CONFIG_MIPS_MT_SMP msp_vsmp_int_init(); -#elif defined CONFIG_MIPS_MT_SMTC - /*Set hwmask for all platform devices */ - irq_hwmask[MSP_INT_MAC0] = C_IRQ0; - irq_hwmask[MSP_INT_MAC1] = C_IRQ1; - irq_hwmask[MSP_INT_USB] = C_IRQ2; - irq_hwmask[MSP_INT_SAR] = C_IRQ3; - irq_hwmask[MSP_INT_SEC] = C_IRQ5; - #endif /* CONFIG_MIPS_MT_SMP */ #endif /* CONFIG_MIPS_MT */ /* setup the cascaded interrupts */ @@ -153,8 +145,10 @@ void __init arch_init_irq(void) setup_irq(MSP_INT_PER, &per_cascade_msp); #else - /* setup the 2nd-level SLP register based interrupt controller */ - /* VSMP /SMTC support support is not enabled for SLP */ + /* + * Setup the 2nd-level SLP register based interrupt controller. + * VSMP support support is not enabled for SLP. + */ msp_slp_irq_init(); /* setup the cascaded SLP/PER interrupts */ diff --git a/arch/mips/pmcs-msp71xx/msp_irq_cic.c b/arch/mips/pmcs-msp71xx/msp_irq_cic.c index e49b499..b8df2f7 100644 --- a/arch/mips/pmcs-msp71xx/msp_irq_cic.c +++ b/arch/mips/pmcs-msp71xx/msp_irq_cic.c @@ -120,10 +120,9 @@ static void msp_cic_irq_ack(struct irq_data *d) * hurt for the others */ *CIC_STS_REG = (1 << (d->irq - MSP_CIC_INTBASE)); - smtc_im_ack_irq(d->irq); } -/*Note: Limiting to VSMP . Not tested in SMTC */ +/* Note: Limiting to VSMP. */ #ifdef CONFIG_MIPS_MT_SMP static int msp_cic_irq_set_affinity(struct irq_data *d, @@ -183,10 +182,6 @@ void __init msp_cic_irq_init(void) for (i = MSP_CIC_INTBASE ; i < MSP_CIC_INTBASE + 32 ; i++) { irq_set_chip_and_handler(i, &msp_cic_irq_controller, handle_level_irq); -#ifdef CONFIG_MIPS_MT_SMTC - /* Mask of CIC interrupt */ - irq_hwmask[i] = C_IRQ4; -#endif } /* Initialize the PER interrupt sub-system */ diff --git a/arch/mips/pmcs-msp71xx/msp_irq_per.c b/arch/mips/pmcs-msp71xx/msp_irq_per.c index d1fd530..a111836 100644 --- a/arch/mips/pmcs-msp71xx/msp_irq_per.c +++ b/arch/mips/pmcs-msp71xx/msp_irq_per.c @@ -113,9 +113,6 @@ void __init msp_per_irq_init(void) /* initialize all the IRQ descriptors */ for (i = MSP_PER_INTBASE; i < MSP_PER_INTBASE + 32; i++) { irq_set_chip(i, &msp_per_irq_controller); -#ifdef CONFIG_MIPS_MT_SMTC - irq_hwmask[i] = C_IRQ4; -#endif } } diff --git a/arch/mips/pmcs-msp71xx/msp_setup.c b/arch/mips/pmcs-msp71xx/msp_setup.c index ba9d518..4f925e0 100644 --- a/arch/mips/pmcs-msp71xx/msp_setup.c +++ b/arch/mips/pmcs-msp71xx/msp_setup.c @@ -147,8 +147,6 @@ void __init plat_mem_setup(void) pm_power_off = msp_power_off; } -extern struct plat_smp_ops msp_smtc_smp_ops; - void __init prom_init(void) { unsigned long family; @@ -229,9 +227,5 @@ void __init prom_init(void) */ msp_serial_setup(); - if (register_vsmp_smp_ops()) { -#ifdef CONFIG_MIPS_MT_SMTC - register_smp_ops(&msp_smtc_smp_ops); -#endif - } + register_vsmp_smp_ops(); } diff --git a/arch/mips/pmcs-msp71xx/msp_smtc.c b/arch/mips/pmcs-msp71xx/msp_smtc.c deleted file mode 100644 index 6b5607f..0000000 --- a/arch/mips/pmcs-msp71xx/msp_smtc.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * MSP71xx Platform-specific hooks for SMP operation - */ -#include -#include - -#include -#include -#include -#include - -/* VPE/SMP Prototype implements platform interfaces directly */ - -/* - * Cause the specified action to be performed on a targeted "CPU" - */ - -static void msp_smtc_send_ipi_single(int cpu, unsigned int action) -{ - /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ - smtc_send_ipi(cpu, LINUX_SMP_IPI, action); -} - -static void msp_smtc_send_ipi_mask(const struct cpumask *mask, - unsigned int action) -{ - unsigned int i; - - for_each_cpu(i, mask) - msp_smtc_send_ipi_single(i, action); -} - -/* - * Post-config but pre-boot cleanup entry point - */ -static void msp_smtc_init_secondary(void) -{ - int myvpe; - - /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ - myvpe = read_c0_tcbind() & TCBIND_CURVPE; - if (myvpe > 0) - change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 | - STATUSF_IP6 | STATUSF_IP7); - smtc_init_secondary(); -} - -/* - * Platform "CPU" startup hook - */ -static void msp_smtc_boot_secondary(int cpu, struct task_struct *idle) -{ - smtc_boot_secondary(cpu, idle); -} - -/* - * SMP initialization finalization entry point - */ -static void msp_smtc_smp_finish(void) -{ - smtc_smp_finish(); -} - -/* - * Hook for after all CPUs are online - */ - -static void msp_smtc_cpus_done(void) -{ -} - -/* - * Platform SMP pre-initialization - * - * As noted above, we can assume a single CPU for now - * but it may be multithreaded. - */ - -static void __init msp_smtc_smp_setup(void) -{ - /* - * we won't get the definitive value until - * we've run smtc_prepare_cpus later, but - */ - - if (read_c0_config3() & (1 << 2)) - smp_num_siblings = smtc_build_cpu_map(0); -} - -static void __init msp_smtc_prepare_cpus(unsigned int max_cpus) -{ - smtc_prepare_cpus(max_cpus); -} - -struct plat_smp_ops msp_smtc_smp_ops = { - .send_ipi_single = msp_smtc_send_ipi_single, - .send_ipi_mask = msp_smtc_send_ipi_mask, - .init_secondary = msp_smtc_init_secondary, - .smp_finish = msp_smtc_smp_finish, - .cpus_done = msp_smtc_cpus_done, - .boot_secondary = msp_smtc_boot_secondary, - .smp_setup = msp_smtc_smp_setup, - .prepare_cpus = msp_smtc_prepare_cpus, -}; -- cgit v0.10.2 From a92b7f87d679580fbfe64236605a7a5b08815a7b Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 11:59:10 +0100 Subject: MIPS: Kconfig: Make MIPS_MT_SMP a regular Kconfig symbol Following the removal of SMTC, MIPS_MT_SMP is the only available MT/SMP option so make it a regular Kconfig symbol. Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/6720/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e3f040c..125edd4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1905,19 +1905,8 @@ config CPU_R4K_CACHE_TLB bool default y if !(CPU_R3000 || CPU_R8000 || CPU_SB1 || CPU_TX39XX || CPU_CAVIUM_OCTEON) -choice - prompt "MIPS MT options" - -config MIPS_MT_DISABLED - bool "Disable multithreading support" - help - Use this option if your platform does not support the MT ASE - which is hardware multithreading support. On systems without - an MT-enabled processor, this will be the only option that is - available in this menu. - config MIPS_MT_SMP - bool "Use 1 TC on each available VPE for SMP" + bool "MIPS MT SMP support (1 TC on each available VPE)" depends on SYS_SUPPORTS_MULTITHREADING select CPU_MIPSR2_IRQ_VI select CPU_MIPSR2_IRQ_EI @@ -1936,8 +1925,6 @@ config MIPS_MT_SMP Intel Hyperthreading feature. For further information go to . -endchoice - config MIPS_MT bool -- cgit v0.10.2 From acd8bc1a70ffff39018cd5cd1977e20d0ffce8d3 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Fri, 23 May 2014 13:31:32 +0100 Subject: MIPS: malta: Remove 'maybe_unused' attribute from ememsize{, _str} First introduced in e6ca4e5bf11466b5e9423a1e4ea51a8216c4b9b6 "MIPS: malta: malta-memory: Add support for the 'ememsize' variable" but it is not needed since both variables are visible to the compiler. Signed-off-by: Markos Chandras Cc: # v3.15+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6985/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c index 6d0f4ab..1ca3488 100644 --- a/arch/mips/mti-malta/malta-memory.c +++ b/arch/mips/mti-malta/malta-memory.c @@ -26,8 +26,8 @@ unsigned long physical_memsize = 0L; fw_memblock_t * __init fw_getmdesc(int eva) { - char *memsize_str, *ememsize_str __maybe_unused = NULL, *ptr; - unsigned long memsize, ememsize __maybe_unused = 0; + char *memsize_str, *ememsize_str = NULL, *ptr; + unsigned long memsize, ememsize = 0; static char cmdline[COMMAND_LINE_SIZE] __initdata; int tmp; -- cgit v0.10.2 From bfb7971c30a3dbca1d3bbc3ada47d72a4ea688f9 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Tue, 20 May 2014 23:39:42 +0530 Subject: MIPS: SEAD3: Introduce the use of the managed version of kzalloc This patch moves data allocated using kzalloc to managed data allocated using devm_kzalloc and cleans now unnecessary kfrees in probe and remove functions. Also, the now unnecessary labels out_mem and out are done away with. The error handling code is moved under if and return 0 is now at the end of the function. The following Coccinelle semantic patch was used for making the change: @platform@ identifier p, probefn, removefn; @@ struct platform_driver p = { .probe = probefn, .remove = removefn, }; @prb@ identifier platform.probefn, pdev; expression e, e1, e2; @@ probefn(struct platform_device *pdev, ...) { <+... - e = kzalloc(e1, e2) + e = devm_kzalloc(&pdev->dev, e1, e2) ... ?-kfree(e); ...+> } @rem depends on prb@ identifier platform.removefn; expression e; @@ removefn(...) { <... - kfree(e); ...> } Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Tested-by: Markos Chandras Reviewed-by: Markos Chandras Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6977/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c index b921e5ec..80fe194 100644 --- a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c +++ b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c @@ -312,16 +312,13 @@ static int i2c_platform_probe(struct platform_device *pdev) pr_debug("i2c_platform_probe\n"); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - ret = -ENODEV; - goto out; - } + if (!r) + return -ENODEV; - priv = kzalloc(sizeof(struct i2c_platform_data), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto out; - } + priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_platform_data), + GFP_KERNEL); + if (!priv) + return -ENOMEM; /* FIXME: need to allocate resource in PIC32 space */ #if 0 @@ -330,10 +327,8 @@ static int i2c_platform_probe(struct platform_device *pdev) #else priv->base = r->start; #endif - if (!priv->base) { - ret = -EBUSY; - goto out_mem; - } + if (!priv->base) + return -EBUSY; priv->xfer_timeout = 200; priv->ack_timeout = 200; @@ -348,17 +343,13 @@ static int i2c_platform_probe(struct platform_device *pdev) i2c_platform_setup(priv); ret = i2c_add_numbered_adapter(&priv->adap); - if (ret == 0) { - platform_set_drvdata(pdev, priv); - return 0; + if (ret) { + i2c_platform_disable(priv); + return ret; } - i2c_platform_disable(priv); - -out_mem: - kfree(priv); -out: - return ret; + platform_set_drvdata(pdev, priv); + return 0; } static int i2c_platform_remove(struct platform_device *pdev) @@ -369,7 +360,6 @@ static int i2c_platform_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); i2c_del_adapter(&priv->adap); i2c_platform_disable(priv); - kfree(priv); return 0; } -- cgit v0.10.2 From 1d530fa42a317deca1c4a4780d18e2dbf316e0cb Mon Sep 17 00:00:00 2001 From: Leif Lindholm Date: Mon, 26 May 2014 14:42:49 +0100 Subject: MIPS: DTS: Fix missing device_type="memory" property in memory nodes A few platforms lack a 'device_type = "memory"' for their memory nodes, relying on an old ppc quirk in order to discover its memory. Add the missing data so that all parsing code can find memory nodes correctly. Signed-off-by: Leif Lindholm Acked-by: John Crispin Signed-off-by: Grant Likely Cc: linux-mips@linux-mips.org Cc: devicetree@vger.kernel.org Cc: Mark Rutland Cc: Cc: gaurav.minocha@alumni.ubc.ca Patchwork: https://patchwork.linux-mips.org/patch/6989/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/lantiq/dts/easy50712.dts b/arch/mips/lantiq/dts/easy50712.dts index fac1f5b..143b8a3 100644 --- a/arch/mips/lantiq/dts/easy50712.dts +++ b/arch/mips/lantiq/dts/easy50712.dts @@ -8,6 +8,7 @@ }; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; diff --git a/arch/mips/ralink/dts/mt7620a_eval.dts b/arch/mips/ralink/dts/mt7620a_eval.dts index 35eb874..709f581 100644 --- a/arch/mips/ralink/dts/mt7620a_eval.dts +++ b/arch/mips/ralink/dts/mt7620a_eval.dts @@ -7,6 +7,7 @@ model = "Ralink MT7620A evaluation board"; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; diff --git a/arch/mips/ralink/dts/rt2880_eval.dts b/arch/mips/ralink/dts/rt2880_eval.dts index 322d700..0a685db 100644 --- a/arch/mips/ralink/dts/rt2880_eval.dts +++ b/arch/mips/ralink/dts/rt2880_eval.dts @@ -7,6 +7,7 @@ model = "Ralink RT2880 evaluation board"; memory@0 { + device_type = "memory"; reg = <0x8000000 0x2000000>; }; diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts index 0ac73ea..ec9e9a0 100644 --- a/arch/mips/ralink/dts/rt3052_eval.dts +++ b/arch/mips/ralink/dts/rt3052_eval.dts @@ -7,6 +7,7 @@ model = "Ralink RT3052 evaluation board"; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; diff --git a/arch/mips/ralink/dts/rt3883_eval.dts b/arch/mips/ralink/dts/rt3883_eval.dts index 2fa6b33..e8df21a 100644 --- a/arch/mips/ralink/dts/rt3883_eval.dts +++ b/arch/mips/ralink/dts/rt3883_eval.dts @@ -7,6 +7,7 @@ model = "Ralink RT3883 evaluation board"; memory@0 { + device_type = "memory"; reg = <0x0 0x2000000>; }; -- cgit v0.10.2 From 1461df59f0de0ecdebf9db090164d793e5b94442 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 27 May 2014 10:56:23 +0200 Subject: MIPS: SMP: Remove plat_smp_ops cpus_done method. Nothing was using the method and there isn't any need for this hook. This leaves smp_cpus_done() empty for the moment. As suggested by Paul Bolle . Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 78e1abe..a7b3ae1 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -225,13 +225,6 @@ static void octeon_smp_finish(void) local_irq_enable(); } -/** - * Hook for after all CPUs are online - */ -static void octeon_cpus_done(void) -{ -} - #ifdef CONFIG_HOTPLUG_CPU /* State of each CPU. */ @@ -388,7 +381,6 @@ struct plat_smp_ops octeon_smp_ops = { .send_ipi_mask = octeon_send_ipi_mask, .init_secondary = octeon_init_secondary, .smp_finish = octeon_smp_finish, - .cpus_done = octeon_cpus_done, .boot_secondary = octeon_boot_secondary, .smp_setup = octeon_smp_setup, .prepare_cpus = octeon_prepare_cpus, diff --git a/arch/mips/include/asm/cmp.h b/arch/mips/include/asm/cmp.h index 89a73fb..033d973 100644 --- a/arch/mips/include/asm/cmp.h +++ b/arch/mips/include/asm/cmp.h @@ -10,7 +10,6 @@ extern void cmp_smp_setup(void); extern void cmp_smp_finish(void); extern void cmp_boot_secondary(int cpu, struct task_struct *t); extern void cmp_init_secondary(void); -extern void cmp_cpus_done(void); extern void cmp_prepare_cpus(unsigned int max_cpus); /* This is platform specific */ diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h index 73d35b1..6ba1fb8 100644 --- a/arch/mips/include/asm/smp-ops.h +++ b/arch/mips/include/asm/smp-ops.h @@ -26,7 +26,6 @@ struct plat_smp_ops { void (*send_ipi_mask)(const struct cpumask *mask, unsigned int action); void (*init_secondary)(void); void (*smp_finish)(void); - void (*cpus_done)(void); void (*boot_secondary)(int cpu, struct task_struct *idle); void (*smp_setup)(void); void (*prepare_cpus)(unsigned int max_cpus); diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index ea4c2dc..df9e2bd 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -281,13 +281,6 @@ static void bmips_smp_finish(void) } /* - * Runs on CPU0 after all CPUs have been booted - */ -static void bmips_cpus_done(void) -{ -} - -/* * BMIPS5000 raceless IPIs * * Each CPU has two inbound SW IRQs which are independent of all other CPUs. @@ -434,7 +427,6 @@ struct plat_smp_ops bmips43xx_smp_ops = { .boot_secondary = bmips_boot_secondary, .smp_finish = bmips_smp_finish, .init_secondary = bmips_init_secondary, - .cpus_done = bmips_cpus_done, .send_ipi_single = bmips43xx_send_ipi_single, .send_ipi_mask = bmips43xx_send_ipi_mask, #ifdef CONFIG_HOTPLUG_CPU @@ -449,7 +441,6 @@ struct plat_smp_ops bmips5000_smp_ops = { .boot_secondary = bmips_boot_secondary, .smp_finish = bmips_smp_finish, .init_secondary = bmips_init_secondary, - .cpus_done = bmips_cpus_done, .send_ipi_single = bmips5000_send_ipi_single, .send_ipi_mask = bmips5000_send_ipi_mask, #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index 64d06f6..fc8a515 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c @@ -72,11 +72,6 @@ static void cmp_smp_finish(void) local_irq_enable(); } -static void cmp_cpus_done(void) -{ - pr_debug("SMPCMP: CPU%d: %s\n", smp_processor_id(), __func__); -} - /* * Setup the PC, SP, and GP of a secondary processor and start it running * smp_bootstrap is the place to resume from @@ -158,7 +153,6 @@ struct plat_smp_ops cmp_smp_ops = { .send_ipi_mask = gic_send_ipi_mask, .init_secondary = cmp_init_secondary, .smp_finish = cmp_smp_finish, - .cpus_done = cmp_cpus_done, .boot_secondary = cmp_boot_secondary, .smp_setup = cmp_smp_setup, .prepare_cpus = cmp_prepare_cpus, diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 536eec0..bb36b4e 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -302,10 +302,6 @@ static void cps_smp_finish(void) local_irq_enable(); } -static void cps_cpus_done(void) -{ -} - static struct plat_smp_ops cps_smp_ops = { .smp_setup = cps_smp_setup, .prepare_cpus = cps_prepare_cpus, @@ -314,7 +310,6 @@ static struct plat_smp_ops cps_smp_ops = { .smp_finish = cps_smp_finish, .send_ipi_single = gic_send_ipi_single, .send_ipi_mask = gic_send_ipi_mask, - .cpus_done = cps_cpus_done, }; int register_cps_smp_ops(void) diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index f8e1314..3babf6e 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -183,10 +183,6 @@ static void vsmp_smp_finish(void) local_irq_enable(); } -static void vsmp_cpus_done(void) -{ -} - /* * Setup the PC, SP, and GP of a secondary processor and start it * running! @@ -287,7 +283,6 @@ struct plat_smp_ops vsmp_smp_ops = { .send_ipi_mask = vsmp_send_ipi_mask, .init_secondary = vsmp_init_secondary, .smp_finish = vsmp_smp_finish, - .cpus_done = vsmp_cpus_done, .boot_secondary = vsmp_boot_secondary, .smp_setup = vsmp_smp_setup, .prepare_cpus = vsmp_prepare_cpus, diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c index 7fde3e4..17878d7 100644 --- a/arch/mips/kernel/smp-up.c +++ b/arch/mips/kernel/smp-up.c @@ -36,11 +36,6 @@ static void up_smp_finish(void) { } -/* Hook for after all CPUs are online */ -static void up_cpus_done(void) -{ -} - /* * Firmware CPU startup hook */ @@ -73,7 +68,6 @@ struct plat_smp_ops up_smp_ops = { .send_ipi_mask = up_send_ipi_mask, .init_secondary = up_init_secondary, .smp_finish = up_smp_finish, - .cpus_done = up_cpus_done, .boot_secondary = up_boot_secondary, .smp_setup = up_smp_setup, .prepare_cpus = up_prepare_cpus, diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 35bb05a..ce76775 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -163,7 +163,6 @@ void smp_send_stop(void) void __init smp_cpus_done(unsigned int max_cpus) { - mp_ops->cpus_done(); } /* called from main before smp_init() */ diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c index c665fe1..1e88940 100644 --- a/arch/mips/loongson/loongson-3/smp.c +++ b/arch/mips/loongson/loongson-3/smp.c @@ -279,13 +279,6 @@ static void loongson3_boot_secondary(int cpu, struct task_struct *idle) loongson3_ipi_write64(startargs[0], (void *)(ipi_mailbox_buf[cpu]+0x0)); } -/* - * Final cleanup after all secondaries booted - */ -static void __init loongson3_cpus_done(void) -{ -} - #ifdef CONFIG_HOTPLUG_CPU static int loongson3_cpu_disable(void) @@ -432,7 +425,6 @@ struct plat_smp_ops loongson3_smp_ops = { .send_ipi_mask = loongson3_send_ipi_mask, .init_secondary = loongson3_init_secondary, .smp_finish = loongson3_smp_finish, - .cpus_done = loongson3_cpus_done, .boot_secondary = loongson3_boot_secondary, .smp_setup = loongson3_smp_setup, .prepare_cpus = loongson3_prepare_cpus, diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index 6baae15..d81b443 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -135,10 +135,6 @@ void nlm_smp_finish(void) local_irq_enable(); } -void nlm_cpus_done(void) -{ -} - /* * Boot all other cpus in the system, initialize them, and bring them into * the boot function @@ -277,7 +273,6 @@ struct plat_smp_ops nlm_smp_ops = { .send_ipi_mask = nlm_send_ipi_mask, .init_secondary = nlm_init_secondary, .smp_finish = nlm_smp_finish, - .cpus_done = nlm_cpus_done, .boot_secondary = nlm_boot_secondary, .smp_setup = nlm_smp_setup, .prepare_cpus = nlm_prepare_cpus, diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index f4ea8aa..f9ae6a8 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -186,10 +186,6 @@ static void ip27_smp_finish(void) local_irq_enable(); } -static void __init ip27_cpus_done(void) -{ -} - /* * Launch a slave into smp_bootstrap(). It doesn't take an argument, and we * set sp to the kernel stack of the newly created idle process, gp to the proc @@ -236,7 +232,6 @@ struct plat_smp_ops ip27_smp_ops = { .send_ipi_mask = ip27_send_ipi_mask, .init_secondary = ip27_init_secondary, .smp_finish = ip27_smp_finish, - .cpus_done = ip27_cpus_done, .boot_secondary = ip27_boot_secondary, .smp_setup = ip27_smp_setup, .prepare_cpus = ip27_prepare_cpus, diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 70d9182..af7d44e 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -115,13 +115,6 @@ static void bcm1480_smp_finish(void) } /* - * Final cleanup after all secondaries booted - */ -static void bcm1480_cpus_done(void) -{ -} - -/* * Setup the PC, SP, and GP of a secondary processor and start it * running! */ @@ -170,7 +163,6 @@ struct plat_smp_ops bcm1480_smp_ops = { .send_ipi_mask = bcm1480_send_ipi_mask, .init_secondary = bcm1480_init_secondary, .smp_finish = bcm1480_smp_finish, - .cpus_done = bcm1480_cpus_done, .boot_secondary = bcm1480_boot_secondary, .smp_setup = bcm1480_smp_setup, .prepare_cpus = bcm1480_prepare_cpus, diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index db97611..c0c4b3f 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -103,13 +103,6 @@ static void sb1250_smp_finish(void) } /* - * Final cleanup after all secondaries booted - */ -static void sb1250_cpus_done(void) -{ -} - -/* * Setup the PC, SP, and GP of a secondary processor and start it * running! */ @@ -158,7 +151,6 @@ struct plat_smp_ops sb_smp_ops = { .send_ipi_mask = sb1250_send_ipi_mask, .init_secondary = sb1250_init_secondary, .smp_finish = sb1250_smp_finish, - .cpus_done = sb1250_cpus_done, .boot_secondary = sb1250_boot_secondary, .smp_setup = sb1250_smp_setup, .prepare_cpus = sb1250_prepare_cpus, -- cgit v0.10.2 From 4fd4db4f6e05d66f1f437d9d24566ff6af44650f Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 13 May 2014 17:07:05 +0200 Subject: MIPS: Lemote 2F: cs5536: mfgpt: depend on !highres This timer does not support oneshot mode and as such the system remains in periodic mode and won't support high res timers. This patch adds a note about this in Kconfig and lets it depend on !highres so users which want to use high timers don' stuck with this timer. Signed-off-by: Sebastian Andrzej Siewior Cc: linux-mips@linux-mips.org Cc: Hua Yan Cc: Huacai Chen Cc: Alex Smith Cc: Hongliang Tao Cc: Wu Zhangjin Patchwork: https://patchwork.linux-mips.org/patch/6935/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 603d79a..e6a86cc 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -95,10 +95,11 @@ config CS5536 config CS5536_MFGPT bool "CS5536 MFGPT Timer" - depends on CS5536 + depends on CS5536 && !HIGH_RES_TIMERS select MIPS_EXTERNAL_TIMER help - This option enables the mfgpt0 timer of AMD CS5536. + This option enables the mfgpt0 timer of AMD CS5536. With this timer + switched on you can not use high resolution timers. If you want to enable the Loongson2 CPUFreq Driver, Please enable this option at first, otherwise, You will get wrong system time. -- cgit v0.10.2 From f4b3aa7cd9d32407670e67238c5ee752bb98f481 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 6 May 2014 15:55:43 +0300 Subject: MIPS: Add __SANE_USERSPACE_TYPES__ to asm/types.h for LL64 Allow 64-bit userspace programs to use ll64 types. The define name comes from commit 2c9c6ce0199a4d252e20c531cfdc9d24e39235c0 (powerpc: Add __SANE_USERSPACE_TYPES__ to asm/types.h for LL64). The patch allows to compile perf on MIPS64 and eliminates the following warnings: tests/attr.c:74:4: error: format '%llu' expects argument of type 'long long unsigned int', but argument 6 has type '__u64' [-Werror=format=] Signed-off-by: Aaro Koskinen Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6890/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/uapi/asm/types.h b/arch/mips/include/uapi/asm/types.h index 7ac9d0b..f3dd9ff 100644 --- a/arch/mips/include/uapi/asm/types.h +++ b/arch/mips/include/uapi/asm/types.h @@ -14,9 +14,12 @@ /* * We don't use int-l64.h for the kernel anymore but still use it for * userspace to avoid code changes. + * + * However, some user programs (e.g. perf) may not want this. They can + * flag __SANE_USERSPACE_TYPES__ to get int-ll64.h here. */ #ifndef __KERNEL__ -# if _MIPS_SZLONG == 64 +# if _MIPS_SZLONG == 64 && !defined(__SANE_USERSPACE_TYPES__) # include # else # include -- cgit v0.10.2 From b8bca000f6d43f772628a72b325bdefe431129f6 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 30 Apr 2014 23:26:45 -0700 Subject: MIPS: defconfigs: add MTD_SPI_NOR (new dependency for M25P80) These defconfigs contain the CONFIG_M25P80 symbol, which is now dependent on the MTD_SPI_NOR symbol. Add CONFIG_MTD_SPI_NOR to satisfy the new dependency. At the same time, drop the now-nonexistent CONFIG_MTD_CHAR symbol. Signed-off-by: Brian Norris Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: Huang Shijie Cc: Marek Vasut Cc: linux-mtd@lists.infradead.org Patchwork: https://patchwork.linux-mips.org/patch/6878/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/configs/ath79_defconfig b/arch/mips/configs/ath79_defconfig index e3a3836..134879c 100644 --- a/arch/mips/configs/ath79_defconfig +++ b/arch/mips/configs/ath79_defconfig @@ -46,7 +46,6 @@ CONFIG_MTD=y CONFIG_MTD_REDBOOT_PARTS=y CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_JEDECPROBE=y @@ -54,7 +53,7 @@ CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_M25P80=y -# CONFIG_M25PXX_USE_FAST_READ is not set +CONFIG_MTD_SPI_NOR=y CONFIG_NETDEVICES=y # CONFIG_NET_PACKET_ENGINE is not set CONFIG_ATH_COMMON=m diff --git a/arch/mips/configs/db1xxx_defconfig b/arch/mips/configs/db1xxx_defconfig index c99b6ee..a64b30b 100644 --- a/arch/mips/configs/db1xxx_defconfig +++ b/arch/mips/configs/db1xxx_defconfig @@ -113,6 +113,7 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_ECC_BCH=y CONFIG_MTD_NAND_AU1550=y CONFIG_MTD_NAND_PLATFORM=y +CONFIG_MTD_SPI_NOR=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y CONFIG_SCSI_TGT=y diff --git a/arch/mips/configs/rt305x_defconfig b/arch/mips/configs/rt305x_defconfig index d1741bc..d14ae2f 100644 --- a/arch/mips/configs/rt305x_defconfig +++ b/arch/mips/configs/rt305x_defconfig @@ -81,7 +81,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_FIRMWARE_IN_KERNEL is not set CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_CFI=y CONFIG_MTD_CFI_AMDSTD=y @@ -89,6 +88,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_OF=y CONFIG_MTD_M25P80=y +CONFIG_MTD_SPI_NOR=y CONFIG_EEPROM_93CX6=m CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y -- cgit v0.10.2 From d19648d7f3b047bac9922fe097f62afbb48fee62 Mon Sep 17 00:00:00 2001 From: Eunbong Song Date: Fri, 11 Apr 2014 08:32:54 +0000 Subject: MIPS: Octeon: Add PCIe2 support in arch_setup_msi_irq() In arch_setup_msi_irq(), there is no case for PCIe2. So board which have PCIe2 functionality fails to boot with "Kernel panic - not syncing: arch_setup_msi_irq: Invalid octeon_dma_bar_type" message. This patch solve this problem. Signed-off-by: Eunbong Song Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/6747/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index 2b91b0e..ab0c5d1 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -162,6 +163,11 @@ msi_irq_allocated: msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff; msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; break; + case OCTEON_DMA_BAR_TYPE_PCIE2: + /* When using PCIe2, Bar 0 is based at 0 */ + msg.address_lo = (0 + CVMX_SLI_PCIE_MSI_RCV) & 0xffffffff; + msg.address_hi = (0 + CVMX_SLI_PCIE_MSI_RCV) >> 32; + break; default: panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type"); } -- cgit v0.10.2 From 739cec8f187f1ea920b8821ef4ae733bc097085c Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 10 Apr 2014 22:57:59 +0200 Subject: MIPS: Alchemy: Default to noncoherent IO on Au1200 AB CONFIG_DMA_COHERENT is no longer set; default to noncoherent io on Au1200 revision AB to make USB work. Signed-off-by: Manuel Lauss Cc: Linux-MIPS Patchwork: https://patchwork.linux-mips.org/patch/6745/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c index 566a1743..8267e3c 100644 --- a/arch/mips/alchemy/common/setup.c +++ b/arch/mips/alchemy/common/setup.c @@ -67,6 +67,12 @@ void __init plat_mem_setup(void) case ALCHEMY_CPU_AU1500: case ALCHEMY_CPU_AU1100: coherentio = 0; + break; + case ALCHEMY_CPU_AU1200: + /* Au1200 AB USB does not support coherent memory */ + if (0 == (read_c0_prid() & PRID_REV_MASK)) + coherentio = 0; + break; } board_setup(); /* board specific setup */ diff --git a/arch/mips/alchemy/common/usb.c b/arch/mips/alchemy/common/usb.c index 2adc7ed..d193dbe 100644 --- a/arch/mips/alchemy/common/usb.c +++ b/arch/mips/alchemy/common/usb.c @@ -355,47 +355,25 @@ static inline void __au1200_udc_control(void __iomem *base, int enable) } } -static inline int au1200_coherency_bug(void) -{ -#if defined(CONFIG_DMA_COHERENT) - /* Au1200 AB USB does not support coherent memory */ - if (!(read_c0_prid() & PRID_REV_MASK)) { - printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n"); - printk(KERN_INFO "Au1200 USB: update your board or re-configure" - " the kernel\n"); - return -ENODEV; - } -#endif - return 0; -} - static inline int au1200_usb_control(int block, int enable) { void __iomem *base = (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); - int ret = 0; switch (block) { case ALCHEMY_USB_OHCI0: - ret = au1200_coherency_bug(); - if (ret && enable) - goto out; __au1200_ohci_control(base, enable); break; case ALCHEMY_USB_UDC0: __au1200_udc_control(base, enable); break; case ALCHEMY_USB_EHCI0: - ret = au1200_coherency_bug(); - if (ret && enable) - goto out; __au1200_ehci_control(base, enable); break; default: - ret = -ENODEV; + return -ENODEV; } -out: - return ret; + return 0; } -- cgit v0.10.2 From 5ec79bf919ddb53fd98893b7217897c839aa19cc Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Tue, 8 Apr 2014 00:22:26 +0200 Subject: MIPS: SNI: Remove USE_GENERIC_EARLY_PRINTK_8250 SNI RM code has its own EARLY_PRINTK support no need for some generic 8250 stuff. Signed-off-by: Thomas Bogendoerfer Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6715/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 125edd4..feb96cb 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -683,7 +683,6 @@ config SNI_RM select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_HIGHMEM select SYS_SUPPORTS_LITTLE_ENDIAN - select USE_GENERIC_EARLY_PRINTK_8250 help The SNI RM200/300/400 are MIPS-based machines manufactured by Siemens Nixdorf Informationssysteme (SNI), parent company of Pyramid -- cgit v0.10.2 From e2a9e5ad719fb424ab3c30520733aa0e8fbcf1ce Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 3 Mar 2014 12:08:40 +0000 Subject: MIPS: add kmap_noncoherent to wire a cached non-coherent TLB entry This is identical to kmap_coherent apart from the cache coherency attribute used for the TLB entry, so kmap_coherent is abstracted to kmap_prot which is then called for both kmap_coherent & kmap_noncoherent. This will be used by a subsequent patch. Suggested-by: Leonid Yegoshin Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h index 69468de..e08381a 100644 --- a/arch/mips/include/asm/cacheflush.h +++ b/arch/mips/include/asm/cacheflush.h @@ -113,6 +113,12 @@ unsigned long run_uncached(void *func); extern void *kmap_coherent(struct page *page, unsigned long addr); extern void kunmap_coherent(void); +extern void *kmap_noncoherent(struct page *page, unsigned long addr); + +static inline void kunmap_noncoherent(void) +{ + kunmap_coherent(); +} #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE static inline void flush_kernel_dcache_page(struct page *page) diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 008324d..539ddd1 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -32,6 +32,8 @@ struct vm_area_struct; _page_cachable_default) #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ _PAGE_GLOBAL | _page_cachable_default) +#define PAGE_KERNEL_NC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ + _PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT) #define PAGE_USERIO __pgprot(_PAGE_PRESENT | (cpu_has_rixi ? 0 : _PAGE_READ) | _PAGE_WRITE | \ _page_cachable_default) #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \ diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 4fc74c7..80ff52e 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -114,7 +114,7 @@ static void __init kmap_coherent_init(void) static inline void kmap_coherent_init(void) {} #endif -void *kmap_coherent(struct page *page, unsigned long addr) +static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot) { enum fixed_addresses idx; unsigned long vaddr, flags, entrylo; @@ -133,7 +133,7 @@ void *kmap_coherent(struct page *page, unsigned long addr) idx += in_interrupt() ? FIX_N_COLOURS : 0; #endif vaddr = __fix_to_virt(FIX_CMAP_END - idx); - pte = mk_pte(page, PAGE_KERNEL); + pte = mk_pte(page, prot); #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) entrylo = pte.pte_high; #else @@ -171,6 +171,16 @@ void *kmap_coherent(struct page *page, unsigned long addr) return (void*) vaddr; } +void *kmap_coherent(struct page *page, unsigned long addr) +{ + return __kmap_pgprot(page, addr, PAGE_KERNEL); +} + +void *kmap_noncoherent(struct page *page, unsigned long addr) +{ + return __kmap_pgprot(page, addr, PAGE_KERNEL_NC); +} + void kunmap_coherent(void) { #ifndef CONFIG_MIPS_MT_SMTC -- cgit v0.10.2 From 27476f3bf45cf61976bc85b66a0bcd0019feae41 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sun, 16 Mar 2014 16:21:34 +0000 Subject: MIPS: MT: define write_c0_tchalt macro Define a macro to write to the current TCs TCHalt register. This will be used by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h index 6efa79a..5f8052c 100644 --- a/arch/mips/include/asm/mipsmtregs.h +++ b/arch/mips/include/asm/mipsmtregs.h @@ -36,6 +36,8 @@ #define read_c0_tcbind() __read_32bit_c0_register($2, 2) +#define write_c0_tchalt(val) __write_32bit_c0_register($2, 4, val) + #define read_c0_tccontext() __read_32bit_c0_register($2, 5) #define write_c0_tccontext(val) __write_32bit_c0_register($2, 5, val) -- cgit v0.10.2 From b0a3eae2b943ef62cb8265aa604c78bb6565a2cd Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 24 Dec 2013 03:44:28 +0000 Subject: MIPS: inst.h: define COP0 wait op The func field for the wait instruction was missing from inst.h - this patch adds it. Signed-off-by: Paul Burton diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index df6e775..044123b 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -125,7 +125,8 @@ enum bcop_op { enum cop0_coi_func { tlbr_op = 0x01, tlbwi_op = 0x02, tlbwr_op = 0x06, tlbp_op = 0x08, - rfe_op = 0x10, eret_op = 0x18 + rfe_op = 0x10, eret_op = 0x18, + wait_op = 0x20, }; /* -- cgit v0.10.2 From 6f5bb42498b0c7901d32a81d163962fd8e37f827 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 4 Mar 2014 15:11:12 +0000 Subject: MIPS: inst.h: define MT yield op The opcode for the MT ASE yield instruction within the spec3 group was missing. This patch adds it for use by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 044123b..b7492c6 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -74,16 +74,17 @@ enum spec2_op { enum spec3_op { ext_op, dextm_op, dextu_op, dext_op, ins_op, dinsm_op, dinsu_op, dins_op, - lx_op = 0x0a, lwle_op = 0x19, - lwre_op = 0x1a, cachee_op = 0x1b, - sbe_op = 0x1c, she_op = 0x1d, - sce_op = 0x1e, swe_op = 0x1f, - bshfl_op = 0x20, swle_op = 0x21, - swre_op = 0x22, prefe_op = 0x23, - dbshfl_op = 0x24, lbue_op = 0x28, - lhue_op = 0x29, lbe_op = 0x2c, - lhe_op = 0x2d, lle_op = 0x2e, - lwe_op = 0x2f, rdhwr_op = 0x3b + yield_op = 0x09, lx_op = 0x0a, + lwle_op = 0x19, lwre_op = 0x1a, + cachee_op = 0x1b, sbe_op = 0x1c, + she_op = 0x1d, sce_op = 0x1e, + swe_op = 0x1f, bshfl_op = 0x20, + swle_op = 0x21, swre_op = 0x22, + prefe_op = 0x23, dbshfl_op = 0x24, + lbue_op = 0x28, lhue_op = 0x29, + lbe_op = 0x2c, lhe_op = 0x2d, + lle_op = 0x2e, lwe_op = 0x2f, + rdhwr_op = 0x3b }; /* -- cgit v0.10.2 From 7ed82ad12c1553a40a5dd7e9c0b34a80c2c02e47 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 9 Jan 2014 15:27:32 +0000 Subject: MIPS: inst.h: define microMIPS sync op The opcode for the sync instruction within POOL32AXf was missing. This patch adds it for use by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index b7492c6..89e9155 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -303,6 +303,7 @@ enum mm_32axf_minor_op { mm_tlbwr_op = 0x0cd, mm_jalrs_op = 0x13c, mm_jalrshb_op = 0x17c, + mm_sync_op = 0x1ad, mm_syscall_op = 0x22d, mm_eret_op = 0x3cd, }; -- cgit v0.10.2 From f263839ab59a7f4beb74fc9a7ce0234b62ab2b52 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 9 Jan 2014 15:30:37 +0000 Subject: MIPS: inst.h: define microMIPS wait op The opcode for the wait instruction within POOL32AXf was missing. This patch adds it for use by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 89e9155..e6e7fe3 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -305,6 +305,7 @@ enum mm_32axf_minor_op { mm_jalrshb_op = 0x17c, mm_sync_op = 0x1ad, mm_syscall_op = 0x22d, + mm_wait_op = 0x24d, mm_eret_op = 0x3cd, }; -- cgit v0.10.2 From 8dee5901b20c5c95278aa3a462eb82826ff98b37 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 24 Dec 2013 03:51:39 +0000 Subject: MIPS: uasm: add a label variant of beq This patch allows for use of the beq instruction with labels from uasm, much as bne & others already do. It will be used by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index c33a956..d1275a2 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -264,6 +264,8 @@ void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid); void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg, unsigned int bit, int lid); +void uasm_il_beq(u32 **p, struct uasm_reloc **r, unsigned int r1, + unsigned int r2, int lid); void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index b9d14b6..ae18b82 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -469,6 +469,14 @@ void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid) } UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b)); +void ISAFUNC(uasm_il_beq)(u32 **p, struct uasm_reloc **r, unsigned int r1, + unsigned int r2, int lid) +{ + uasm_r_mips_pc16(r, *p, lid); + ISAFUNC(uasm_i_beq)(p, r1, r2, 0); +} +UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq)); + void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid) { -- cgit v0.10.2 From 49e9529b9d43773307b8c73bd251b71784830c3d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sun, 16 Mar 2014 12:58:05 +0000 Subject: MIPS: uasm: add jalr instruction This patch allows use of the jalr instruction from uasm. It will be used by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index d1275a2..a3d88ae 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -74,6 +74,9 @@ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \ #define Ip_u1u2(op) \ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b) +#define Ip_u2u1(op) \ +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b) + #define Ip_u1s2(op) \ void ISAOPC(op)(u32 **buf, unsigned int a, signed int b) @@ -114,6 +117,7 @@ Ip_u2u1msbu3(_ext); Ip_u2u1msbu3(_ins); Ip_u1(_j); Ip_u1(_jal); +Ip_u2u1(_jalr); Ip_u1(_jr); Ip_u2s3u1(_ld); Ip_u3u1u2(_ldx); diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 3abd609..45e3dc5 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -82,6 +82,7 @@ static struct insn insn_table[] = { { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE }, { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, + { insn_jalr, M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD }, { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index ae18b82..a77a4b8 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -49,10 +49,10 @@ enum opcode { insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, - insn_ext, insn_ins, insn_j, insn_jal, insn_jr, insn_ld, insn_ldx, - insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, - insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, - insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, + insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, + insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, + insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, + insn_scd, insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, }; @@ -250,6 +250,7 @@ I_u2u1msbdu3(_ext) I_u2u1msbu3(_ins) I_u1(_j) I_u1(_jal) +I_u2u1(_jalr) I_u1(_jr) I_u2s3u1(_ld) I_u2s3u1(_ll) -- cgit v0.10.2 From 729ff56169395cb3e467e4e3c1e2637f4d3436ce Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 24 Dec 2013 03:49:45 +0000 Subject: MIPS: uasm: add sync instruction This patch allows use of the sync instruction from uasm. It will be used by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index a3d88ae..306892c 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -141,6 +141,7 @@ Ip_u2u1u3(_sra); Ip_u2u1u3(_srl); Ip_u3u1u2(_subu); Ip_u2s3u1(_sw); +Ip_u1(_sync); Ip_u1(_syscall); Ip_0(_tlbp); Ip_0(_tlbr); diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index b8d580c..9500f2a 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -99,6 +99,7 @@ static struct insn insn_table_MM[] = { { insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD }, { insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD }, { insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, + { insn_sync, M(mm_pool32a_op, 0, 0, 0, mm_sync_op, mm_pool32axf_op), RS }, { insn_tlbp, M(mm_pool32a_op, 0, 0, 0, mm_tlbp_op, mm_pool32axf_op), 0 }, { insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 }, { insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 45e3dc5..51063fd 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -107,6 +107,7 @@ static struct insn insn_table[] = { { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_sync, M(spec_op, 0, 0, 0, 0, sync_op), RE }, { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 }, { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index a77a4b8..7c13801 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -53,8 +53,8 @@ enum opcode { insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, - insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, - insn_xori, + insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, + insn_xor, insn_xori, }; struct insn { @@ -271,6 +271,7 @@ I_u2u1u3(_srl) I_u2u1u3(_rotr) I_u3u1u2(_subu) I_u2s3u1(_sw) +I_u1(_sync) I_0(_tlbp) I_0(_tlbr) I_0(_tlbwi) -- cgit v0.10.2 From 53ed138986e1022c2b6fef7f8e9731f5bf3e6af1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 24 Dec 2013 03:50:35 +0000 Subject: MIPS: uasm: add wait instruction This patch allows use of the wait instruction from uasm. It will be used by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 306892c..8810801 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -147,6 +147,7 @@ Ip_0(_tlbp); Ip_0(_tlbr); Ip_0(_tlbwi); Ip_0(_tlbwr); +Ip_u1(_wait); Ip_u3u1u2(_xor); Ip_u2u1u3(_xori); diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 9500f2a..bcbcf4a 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -104,6 +104,7 @@ static struct insn insn_table_MM[] = { { insn_tlbr, M(mm_pool32a_op, 0, 0, 0, mm_tlbr_op, mm_pool32axf_op), 0 }, { insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 }, { insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 }, + { insn_wait, M(mm_pool32a_op, 0, 0, 0, mm_wait_op, mm_pool32axf_op), SCIMM }, { insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD }, { insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, { insn_dins, 0, 0 }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 51063fd..c69f785 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -113,6 +113,7 @@ static struct insn insn_table[] = { { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 }, { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 }, { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, + { insn_wait, M(cop0_op, cop_op, 0, 0, 0, wait_op), SCIMM }, { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, { insn_invalid, 0, 0 } diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 7c13801..46d2173 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -54,7 +54,7 @@ enum opcode { insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, - insn_xor, insn_xori, + insn_wait, insn_xor, insn_xori, }; struct insn { @@ -276,6 +276,7 @@ I_0(_tlbp) I_0(_tlbr) I_0(_tlbwi) I_0(_tlbwr) +I_u1(_wait); I_u3u1u2(_xor) I_u2u1u3(_xori) I_u2u1msbu3(_dins); -- cgit v0.10.2 From d674dd14e85c49ca0e422de53a4c2b5bf44a339a Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 4 Mar 2014 15:12:36 +0000 Subject: MIPS: uasm: add MT ASE yield instruction This patch allows use of the MT ASE yield instruction from uasm. It will be used by a subsequent patch. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 8810801..3d80387 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -150,6 +150,7 @@ Ip_0(_tlbwr); Ip_u1(_wait); Ip_u3u1u2(_xor); Ip_u2u1u3(_xori); +Ip_u2u1(_yield); /* Handle labels. */ diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index c69f785..4a2fc82 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -116,6 +116,7 @@ static struct insn insn_table[] = { { insn_wait, M(cop0_op, cop_op, 0, 0, 0, wait_op), SCIMM }, { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, + { insn_yield, M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD }, { insn_invalid, 0, 0 } }; diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 46d2173..55a1fdf 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -54,7 +54,7 @@ enum opcode { insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, - insn_wait, insn_xor, insn_xori, + insn_wait, insn_xor, insn_xori, insn_yield, }; struct insn { @@ -200,6 +200,13 @@ Ip_u1u2(op) \ } \ UASM_EXPORT_SYMBOL(uasm_i##op); +#define I_u2u1(op) \ +Ip_u1u2(op) \ +{ \ + build_insn(buf, insn##op, b, a); \ +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); + #define I_u1s2(op) \ Ip_u1s2(op) \ { \ @@ -279,6 +286,7 @@ I_0(_tlbwr) I_u1(_wait); I_u3u1u2(_xor) I_u2u1u3(_xori) +I_u2u1(_yield) I_u2u1msbu3(_dins); I_u2u1msb32u3(_dinsm); I_u1(_syscall); -- cgit v0.10.2 From 245a7868d2f2e54a9a9b084de00d003a9badb2a5 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 12:04:27 +0100 Subject: MIPS: smp-cps: rework core/VPE initialisation When hotplug and/or a powered down idle state are supported cases will arise where a non-zero VPE must be brought online without VPE 0, and it where multiple VPEs must be onlined simultaneously. This patch prepares for that by: - Splitting struct boot_config into core & VPE boot config structures, allocated one per core or VPE respectively. This allows for multiple VPEs to be onlined simultaneously without clobbering each others configuration. - Indicating which VPEs should be online within a core at any given time using a bitmap. This allows multiple VPEs to be brought online simultaneously and also indicates to VPE 0 whether it should halt after starting any non-zero VPEs that should be online within the core. For example if all VPEs within a core are offlined via hotplug and the user onlines the second VPE within that core: 1) The core will be powered up. 2) VPE 0 will run from the BEV (ie. mips_cps_core_entry) to initialise the core. 3) VPE 0 will start VPE 1 because its bit is set in the cores bitmap. 4) VPE 0 will halt itself because its bit is clear in the cores bitmap. - Moving the core & VPE initialisation to assembly code which does not make any use of the stack. This is because if a non-zero VPE is to be brought online in a powered down core then when VPE 0 of that core runs it may not have a valid stack, and even if it did then it's messy to run through parts of generic kernel code on VPE 0 before starting the correct VPE. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h index d60d1a2..d49279e 100644 --- a/arch/mips/include/asm/smp-cps.h +++ b/arch/mips/include/asm/smp-cps.h @@ -13,17 +13,23 @@ #ifndef __ASSEMBLY__ -struct boot_config { - unsigned int core; - unsigned int vpe; +struct vpe_boot_config { unsigned long pc; unsigned long sp; unsigned long gp; }; -extern struct boot_config mips_cps_bootcfg; +struct core_boot_config { + atomic_t vpe_mask; + struct vpe_boot_config *vpe_config; +}; + +extern struct core_boot_config *mips_cps_core_bootcfg; extern void mips_cps_core_entry(void); +extern void mips_cps_core_init(void); + +extern struct vpe_boot_config *mips_cps_boot_vpes(void); #else /* __ASSEMBLY__ */ diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index e085cde..d63490d 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -487,10 +487,14 @@ void output_kvm_defines(void) void output_cps_defines(void) { COMMENT(" MIPS CPS offsets. "); - OFFSET(BOOTCFG_CORE, boot_config, core); - OFFSET(BOOTCFG_VPE, boot_config, vpe); - OFFSET(BOOTCFG_PC, boot_config, pc); - OFFSET(BOOTCFG_SP, boot_config, sp); - OFFSET(BOOTCFG_GP, boot_config, gp); + + OFFSET(COREBOOTCFG_VPEMASK, core_boot_config, vpe_mask); + OFFSET(COREBOOTCFG_VPECONFIG, core_boot_config, vpe_config); + DEFINE(COREBOOTCFG_SIZE, sizeof(struct core_boot_config)); + + OFFSET(VPEBOOTCFG_PC, vpe_boot_config, pc); + OFFSET(VPEBOOTCFG_SP, vpe_boot_config, sp); + OFFSET(VPEBOOTCFG_GP, vpe_boot_config, gp); + DEFINE(VPEBOOTCFG_SIZE, sizeof(struct vpe_boot_config)); } #endif diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index f7a46db..57ec18c 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -14,12 +14,33 @@ #include #include #include +#include -#define GCR_CL_COHERENCE_OFS 0x2008 +#define GCR_CL_COHERENCE_OFS 0x2008 +#define GCR_CL_ID_OFS 0x2028 + +.extern mips_cm_base + +.set noreorder + + /* + * Set dest to non-zero if the core supports the MT ASE, else zero. If + * MT is not supported then branch to nomt. + */ + .macro has_mt dest, nomt + mfc0 \dest, CP0_CONFIG + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 1 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 2 + bgez \dest, \nomt + mfc0 \dest, CP0_CONFIG, 3 + andi \dest, \dest, MIPS_CONF3_MT + beqz \dest, \nomt + .endm .section .text.cps-vec .balign 0x1000 -.set noreorder LEAF(mips_cps_core_entry) /* @@ -134,21 +155,24 @@ dcache_done: jr t0 nop -1: /* We're up, cached & coherent */ + /* + * We're up, cached & coherent. Perform any further required core-level + * initialisation. + */ +1: jal mips_cps_core_init + nop /* - * TODO: We should check the VPE number we intended to boot here, and - * if non-zero we should start that VPE and stop this one. For - * the moment this doesn't matter since CPUs are brought up - * sequentially and in order, but once hotplug is implemented - * this will need revisiting. + * Boot any other VPEs within this core that should be online, and + * deactivate this VPE if it should be offline. */ + jal mips_cps_boot_vpes + nop /* Off we go! */ - la t0, mips_cps_bootcfg - lw t1, BOOTCFG_PC(t0) - lw gp, BOOTCFG_GP(t0) - lw sp, BOOTCFG_SP(t0) + lw t1, VPEBOOTCFG_PC(v0) + lw gp, VPEBOOTCFG_GP(v0) + lw sp, VPEBOOTCFG_SP(v0) jr t1 nop END(mips_cps_core_entry) @@ -189,3 +213,237 @@ LEAF(excep_ejtag) jr k0 nop END(excep_ejtag) + +LEAF(mips_cps_core_init) +#ifdef CONFIG_MIPS_MT + /* Check that the core implements the MT ASE */ + has_mt t0, 3f + nop + + .set push + .set mt + + /* Only allow 1 TC per VPE to execute... */ + dmt + + /* ...and for the moment only 1 VPE */ + dvpe + la t1, 1f + jr.hb t1 + nop + + /* Enter VPE configuration state */ +1: mfc0 t0, CP0_MVPCONTROL + ori t0, t0, MVPCONTROL_VPC + mtc0 t0, CP0_MVPCONTROL + + /* Retrieve the number of VPEs within the core */ + mfc0 t0, CP0_MVPCONF0 + srl t0, t0, MVPCONF0_PVPE_SHIFT + andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT) + addi t7, t0, 1 + + /* If there's only 1, we're done */ + beqz t0, 2f + nop + + /* Loop through each VPE within this core */ + li t5, 1 + +1: /* Operate on the appropriate TC */ + mtc0 t5, CP0_VPECONTROL + ehb + + /* Bind TC to VPE (1:1 TC:VPE mapping) */ + mttc0 t5, CP0_TCBIND + + /* Set exclusive TC, non-active, master */ + li t0, VPECONF0_MVP + sll t1, t5, VPECONF0_XTC_SHIFT + or t0, t0, t1 + mttc0 t0, CP0_VPECONF0 + + /* Set TC non-active, non-allocatable */ + mttc0 zero, CP0_TCSTATUS + + /* Set TC halted */ + li t0, TCHALT_H + mttc0 t0, CP0_TCHALT + + /* Next VPE */ + addi t5, t5, 1 + slt t0, t5, t7 + bnez t0, 1b + nop + + /* Leave VPE configuration state */ +2: mfc0 t0, CP0_MVPCONTROL + xori t0, t0, MVPCONTROL_VPC + mtc0 t0, CP0_MVPCONTROL + +3: .set pop +#endif + jr ra + nop + END(mips_cps_core_init) + +LEAF(mips_cps_boot_vpes) + /* Retrieve CM base address */ + la t0, mips_cm_base + lw t0, 0(t0) + + /* Calculate a pointer to this cores struct core_boot_config */ + lw t0, GCR_CL_ID_OFS(t0) + li t1, COREBOOTCFG_SIZE + mul t0, t0, t1 + la t1, mips_cps_core_bootcfg + lw t1, 0(t1) + addu t0, t0, t1 + + /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ + has_mt t6, 1f + li t9, 0 + + /* Find the number of VPEs present in the core */ + mfc0 t1, CP0_MVPCONF0 + srl t1, t1, MVPCONF0_PVPE_SHIFT + andi t1, t1, MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT + addi t1, t1, 1 + + /* Calculate a mask for the VPE ID from EBase.CPUNum */ + clz t1, t1 + li t2, 31 + subu t1, t2, t1 + li t2, 1 + sll t1, t2, t1 + addiu t1, t1, -1 + + /* Retrieve the VPE ID from EBase.CPUNum */ + mfc0 t9, $15, 1 + and t9, t9, t1 + +1: /* Calculate a pointer to this VPEs struct vpe_boot_config */ + li t1, VPEBOOTCFG_SIZE + mul v0, t9, t1 + lw t7, COREBOOTCFG_VPECONFIG(t0) + addu v0, v0, t7 + +#ifdef CONFIG_MIPS_MT + + /* If the core doesn't support MT then return */ + bnez t6, 1f + nop + jr ra + nop + + .set push + .set mt + +1: /* Enter VPE configuration state */ + dvpe + la t1, 1f + jr.hb t1 + nop +1: mfc0 t1, CP0_MVPCONTROL + ori t1, t1, MVPCONTROL_VPC + mtc0 t1, CP0_MVPCONTROL + ehb + + /* Loop through each VPE */ + lw t6, COREBOOTCFG_VPEMASK(t0) + move t8, t6 + li t5, 0 + + /* Check whether the VPE should be running. If not, skip it */ +1: andi t0, t6, 1 + beqz t0, 2f + nop + + /* Operate on the appropriate TC */ + mfc0 t0, CP0_VPECONTROL + ori t0, t0, VPECONTROL_TARGTC + xori t0, t0, VPECONTROL_TARGTC + or t0, t0, t5 + mtc0 t0, CP0_VPECONTROL + ehb + + /* Skip the VPE if its TC is not halted */ + mftc0 t0, CP0_TCHALT + beqz t0, 2f + nop + + /* Calculate a pointer to the VPEs struct vpe_boot_config */ + li t0, VPEBOOTCFG_SIZE + mul t0, t0, t5 + addu t0, t0, t7 + + /* Set the TC restart PC */ + lw t1, VPEBOOTCFG_PC(t0) + mttc0 t1, CP0_TCRESTART + + /* Set the TC stack pointer */ + lw t1, VPEBOOTCFG_SP(t0) + mttgpr t1, sp + + /* Set the TC global pointer */ + lw t1, VPEBOOTCFG_GP(t0) + mttgpr t1, gp + + /* Copy config from this VPE */ + mfc0 t0, CP0_CONFIG + mttc0 t0, CP0_CONFIG + + /* Ensure no software interrupts are pending */ + mttc0 zero, CP0_CAUSE + mttc0 zero, CP0_STATUS + + /* Set TC active, not interrupt exempt */ + mftc0 t0, CP0_TCSTATUS + li t1, ~TCSTATUS_IXMT + and t0, t0, t1 + ori t0, t0, TCSTATUS_A + mttc0 t0, CP0_TCSTATUS + + /* Clear the TC halt bit */ + mttc0 zero, CP0_TCHALT + + /* Set VPE active */ + mftc0 t0, CP0_VPECONF0 + ori t0, t0, VPECONF0_VPA + mttc0 t0, CP0_VPECONF0 + + /* Next VPE */ +2: srl t6, t6, 1 + addi t5, t5, 1 + bnez t6, 1b + nop + + /* Leave VPE configuration state */ + mfc0 t1, CP0_MVPCONTROL + xori t1, t1, MVPCONTROL_VPC + mtc0 t1, CP0_MVPCONTROL + ehb + evpe + + /* Check whether this VPE is meant to be running */ + li t0, 1 + sll t0, t0, t9 + and t0, t0, t8 + bnez t0, 2f + nop + + /* This VPE should be offline, halt the TC */ + li t0, TCHALT_H + mtc0 t0, CP0_TCHALT + la t0, 1f +1: jr.hb t0 + nop + +2: .set pop + +#endif /* CONFIG_MIPS_MT */ + + /* Return */ + jr ra + nop + END(mips_cps_boot_vpes) diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index 2368fc5..ba47360 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c @@ -9,6 +9,8 @@ */ #include +#include +#include #include #include diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 536eec0..af90e82 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -26,98 +26,37 @@ static DECLARE_BITMAP(core_power, NR_CPUS); -struct boot_config mips_cps_bootcfg; +struct core_boot_config *mips_cps_core_bootcfg; -static void init_core(void) +static unsigned core_vpe_count(unsigned core) { - unsigned int nvpes, t; - u32 mvpconf0, vpeconf0, vpecontrol, tcstatus, tcbind, status; + unsigned cfg; - if (!cpu_has_mipsmt) - return; - - /* Enter VPE configuration state */ - dvpe(); - set_c0_mvpcontrol(MVPCONTROL_VPC); - - /* Retrieve the count of VPEs in this core */ - mvpconf0 = read_c0_mvpconf0(); - nvpes = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; - smp_num_siblings = nvpes; - - for (t = 1; t < nvpes; t++) { - /* Use a 1:1 mapping of TC index to VPE index */ - settc(t); - - /* Bind 1 TC to this VPE */ - tcbind = read_tc_c0_tcbind(); - tcbind &= ~TCBIND_CURVPE; - tcbind |= t << TCBIND_CURVPE_SHIFT; - write_tc_c0_tcbind(tcbind); - - /* Set exclusive TC, non-active, master */ - vpeconf0 = read_vpe_c0_vpeconf0(); - vpeconf0 &= ~(VPECONF0_XTC | VPECONF0_VPA); - vpeconf0 |= t << VPECONF0_XTC_SHIFT; - vpeconf0 |= VPECONF0_MVP; - write_vpe_c0_vpeconf0(vpeconf0); - - /* Declare TC non-active, non-allocatable & interrupt exempt */ - tcstatus = read_tc_c0_tcstatus(); - tcstatus &= ~(TCSTATUS_A | TCSTATUS_DA); - tcstatus |= TCSTATUS_IXMT; - write_tc_c0_tcstatus(tcstatus); - - /* Halt the TC */ - write_tc_c0_tchalt(TCHALT_H); - - /* Allow only 1 TC to execute */ - vpecontrol = read_vpe_c0_vpecontrol(); - vpecontrol &= ~VPECONTROL_TE; - write_vpe_c0_vpecontrol(vpecontrol); - - /* Copy (most of) Status from VPE 0 */ - status = read_c0_status(); - status &= ~(ST0_IM | ST0_IE | ST0_KSU); - status |= ST0_CU0; - write_vpe_c0_status(status); - - /* Copy Config from VPE 0 */ - write_vpe_c0_config(read_c0_config()); - write_vpe_c0_config7(read_c0_config7()); - - /* Ensure no software interrupts are pending */ - write_vpe_c0_cause(0); - - /* Sync Count */ - write_vpe_c0_count(read_c0_count()); - } + if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt) + return 1; - /* Leave VPE configuration state */ - clear_c0_mvpcontrol(MVPCONTROL_VPC); + write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF); + cfg = read_gcr_co_config() & CM_GCR_Cx_CONFIG_PVPE_MSK; + return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1; } static void __init cps_smp_setup(void) { unsigned int ncores, nvpes, core_vpes; int c, v; - u32 core_cfg, *entry_code; + u32 *entry_code; /* Detect & record VPE topology */ ncores = mips_cm_numcores(); pr_info("VPE topology "); for (c = nvpes = 0; c < ncores; c++) { - if (cpu_has_mipsmt && config_enabled(CONFIG_MIPS_MT_SMP)) { - write_gcr_cl_other(c << CM_GCR_Cx_OTHER_CORENUM_SHF); - core_cfg = read_gcr_co_config(); - core_vpes = ((core_cfg & CM_GCR_Cx_CONFIG_PVPE_MSK) >> - CM_GCR_Cx_CONFIG_PVPE_SHF) + 1; - } else { - core_vpes = 1; - } - + core_vpes = core_vpe_count(c); pr_cont("%c%u", c ? ',' : '{', core_vpes); + /* Use the number of VPEs in core 0 for smp_num_siblings */ + if (!c) + smp_num_siblings = core_vpes; + for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) { cpu_data[nvpes + v].core = c; #ifdef CONFIG_MIPS_MT_SMP @@ -140,12 +79,8 @@ static void __init cps_smp_setup(void) /* Core 0 is powered up (we're running on it) */ bitmap_set(core_power, 0, 1); - /* Disable MT - we only want to run 1 TC per VPE */ - if (cpu_has_mipsmt) - dmt(); - /* Initialise core 0 */ - init_core(); + mips_cps_core_init(); /* Patch the start of mips_cps_core_entry to provide the CM base */ entry_code = (u32 *)&mips_cps_core_entry; @@ -157,15 +92,60 @@ static void __init cps_smp_setup(void) static void __init cps_prepare_cpus(unsigned int max_cpus) { + unsigned ncores, core_vpes, c; + mips_mt_set_cpuoptions(); + + /* Allocate core boot configuration structs */ + ncores = mips_cm_numcores(); + mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg), + GFP_KERNEL); + if (!mips_cps_core_bootcfg) { + pr_err("Failed to allocate boot config for %u cores\n", ncores); + goto err_out; + } + + /* Allocate VPE boot configuration structs */ + for (c = 0; c < ncores; c++) { + core_vpes = core_vpe_count(c); + mips_cps_core_bootcfg[c].vpe_config = kcalloc(core_vpes, + sizeof(*mips_cps_core_bootcfg[c].vpe_config), + GFP_KERNEL); + if (!mips_cps_core_bootcfg[c].vpe_config) { + pr_err("Failed to allocate %u VPE boot configs\n", + core_vpes); + goto err_out; + } + } + + /* Mark this CPU as booted */ + atomic_set(&mips_cps_core_bootcfg[current_cpu_data.core].vpe_mask, + 1 << cpu_vpe_id(¤t_cpu_data)); + + return; +err_out: + /* Clean up allocations */ + if (mips_cps_core_bootcfg) { + for (c = 0; c < ncores; c++) + kfree(mips_cps_core_bootcfg[c].vpe_config); + kfree(mips_cps_core_bootcfg); + mips_cps_core_bootcfg = NULL; + } + + /* Effectively disable SMP by declaring CPUs not present */ + for_each_possible_cpu(c) { + if (c == 0) + continue; + set_cpu_present(c, false); + } } -static void boot_core(struct boot_config *cfg) +static void boot_core(unsigned core) { u32 access; /* Select the appropriate core */ - write_gcr_cl_other(cfg->core << CM_GCR_Cx_OTHER_CORENUM_SHF); + write_gcr_cl_other(core << CM_GCR_Cx_OTHER_CORENUM_SHF); /* Set its reset vector */ write_gcr_co_reset_base(CKSEG1ADDR((unsigned long)mips_cps_core_entry)); @@ -175,15 +155,12 @@ static void boot_core(struct boot_config *cfg) /* Ensure the core can access the GCRs */ access = read_gcr_access(); - access |= 1 << (CM_GCR_ACCESS_ACCESSEN_SHF + cfg->core); + access |= 1 << (CM_GCR_ACCESS_ACCESSEN_SHF + core); write_gcr_access(access); - /* Copy cfg */ - mips_cps_bootcfg = *cfg; - if (mips_cpc_present()) { /* Select the appropriate core */ - write_cpc_cl_other(cfg->core << CPC_Cx_OTHER_CORENUM_SHF); + write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF); /* Reset the core */ write_cpc_co_cmd(CPC_Cx_CMD_RESET); @@ -193,77 +170,47 @@ static void boot_core(struct boot_config *cfg) } /* The core is now powered up */ - bitmap_set(core_power, cfg->core, 1); + bitmap_set(core_power, core, 1); } -static void boot_vpe(void *info) +static void remote_vpe_boot(void *dummy) { - struct boot_config *cfg = info; - u32 tcstatus, vpeconf0; - - /* Enter VPE configuration state */ - dvpe(); - set_c0_mvpcontrol(MVPCONTROL_VPC); - - settc(cfg->vpe); - - /* Set the TC restart PC */ - write_tc_c0_tcrestart((unsigned long)&smp_bootstrap); - - /* Activate the TC, allow interrupts */ - tcstatus = read_tc_c0_tcstatus(); - tcstatus &= ~TCSTATUS_IXMT; - tcstatus |= TCSTATUS_A; - write_tc_c0_tcstatus(tcstatus); - - /* Clear the TC halt bit */ - write_tc_c0_tchalt(0); - - /* Activate the VPE */ - vpeconf0 = read_vpe_c0_vpeconf0(); - vpeconf0 |= VPECONF0_VPA; - write_vpe_c0_vpeconf0(vpeconf0); - - /* Set the stack & global pointer registers */ - write_tc_gpr_sp(cfg->sp); - write_tc_gpr_gp(cfg->gp); - - /* Leave VPE configuration state */ - clear_c0_mvpcontrol(MVPCONTROL_VPC); - - /* Enable other VPEs to execute */ - evpe(EVPE_ENABLE); + mips_cps_boot_vpes(); } static void cps_boot_secondary(int cpu, struct task_struct *idle) { - struct boot_config cfg; + unsigned core = cpu_data[cpu].core; + unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); + struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; + struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id]; unsigned int remote; int err; - cfg.core = cpu_data[cpu].core; - cfg.vpe = cpu_vpe_id(&cpu_data[cpu]); - cfg.pc = (unsigned long)&smp_bootstrap; - cfg.sp = __KSTK_TOS(idle); - cfg.gp = (unsigned long)task_thread_info(idle); + vpe_cfg->pc = (unsigned long)&smp_bootstrap; + vpe_cfg->sp = __KSTK_TOS(idle); + vpe_cfg->gp = (unsigned long)task_thread_info(idle); - if (!test_bit(cfg.core, core_power)) { + atomic_or(1 << cpu_vpe_id(&cpu_data[cpu]), &core_cfg->vpe_mask); + + if (!test_bit(core, core_power)) { /* Boot a VPE on a powered down core */ - boot_core(&cfg); + boot_core(core); return; } - if (cfg.core != current_cpu_data.core) { + if (core != current_cpu_data.core) { /* Boot a VPE on another powered up core */ for (remote = 0; remote < NR_CPUS; remote++) { - if (cpu_data[remote].core != cfg.core) + if (cpu_data[remote].core != core) continue; if (cpu_online(remote)) break; } BUG_ON(remote >= NR_CPUS); - err = smp_call_function_single(remote, boot_vpe, &cfg, 1); + err = smp_call_function_single(remote, remote_vpe_boot, + NULL, 1); if (err) panic("Failed to call remote CPU\n"); return; @@ -272,7 +219,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) BUG_ON(!cpu_has_mipsmt); /* Boot a VPE on this core */ - boot_vpe(&cfg); + mips_cps_boot_vpes(); } static void cps_init_secondary(void) @@ -281,10 +228,6 @@ static void cps_init_secondary(void) if (cpu_has_mipsmt) dmt(); - /* TODO: revisit this assumption once hotplug is implemented */ - if (cpu_vpe_id(¤t_cpu_data) == 0) - init_core(); - change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 | STATUSF_IP7); } -- cgit v0.10.2 From 68c1232f51350b007cb1f05260e9e784770ec513 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 14 Mar 2014 16:06:16 +0000 Subject: MIPS: smp-cps: function to determine whether CPS SMP is in use The core power down state for cpuidle will require that the CPS SMP implementation is in use. This patch provides a mips_cps_smp_in_use function which determines whether or not the CPS SMP implementation is currently in use. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h index d49279e..324df2c 100644 --- a/arch/mips/include/asm/smp-cps.h +++ b/arch/mips/include/asm/smp-cps.h @@ -31,6 +31,8 @@ extern void mips_cps_core_init(void); extern struct vpe_boot_config *mips_cps_boot_vpes(void); +extern bool mips_cps_smp_in_use(void); + #else /* __ASSEMBLY__ */ .extern mips_cps_bootcfg; diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index af90e82..c7879fb 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -260,6 +260,12 @@ static struct plat_smp_ops cps_smp_ops = { .cpus_done = cps_cpus_done, }; +bool mips_cps_smp_in_use(void) +{ + extern struct plat_smp_ops *mp_ops; + return mp_ops == &cps_smp_ops; +} + int register_cps_smp_ops(void) { if (!mips_cm_present()) { -- cgit v0.10.2 From 0f4d3d1155d9a5e71e74658ac50b61141e370cf3 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 12:21:49 +0100 Subject: MIPS: smp-cps: flush cache after patching mips_cps_core_entry The start of mips_cps_core_entry is patched in order to provide the code with the address of the CM register region at a point where it will be running non-coherent with the rest of the system. However the cache wasn't being flushed after that patching which could in principle lead to secondary cores using an invalid CM base address. The patching is moved to cps_prepare_cpus since local_flush_icache_range has not been initialised at the point cps_smp_setup is called. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index c7879fb..c3661ca 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -44,7 +44,6 @@ static void __init cps_smp_setup(void) { unsigned int ncores, nvpes, core_vpes; int c, v; - u32 *entry_code; /* Detect & record VPE topology */ ncores = mips_cm_numcores(); @@ -82,10 +81,6 @@ static void __init cps_smp_setup(void) /* Initialise core 0 */ mips_cps_core_init(); - /* Patch the start of mips_cps_core_entry to provide the CM base */ - entry_code = (u32 *)&mips_cps_core_entry; - UASM_i_LA(&entry_code, 3, (long)mips_cm_base); - /* Make core 0 coherent with everything */ write_gcr_cl_coherence(0xff); } @@ -93,9 +88,16 @@ static void __init cps_smp_setup(void) static void __init cps_prepare_cpus(unsigned int max_cpus) { unsigned ncores, core_vpes, c; + u32 *entry_code; mips_mt_set_cpuoptions(); + /* Patch the start of mips_cps_core_entry to provide the CM base */ + entry_code = (u32 *)&mips_cps_core_entry; + UASM_i_LA(&entry_code, 3, (long)mips_cm_base); + dma_cache_wback_inv((unsigned long)&mips_cps_core_entry, + (void *)entry_code - (void *)&mips_cps_core_entry); + /* Allocate core boot configuration structs */ ncores = mips_cm_numcores(); mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg), -- cgit v0.10.2 From dd9233d0470bb8b02b30982c1de0a2dbffb407d5 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 7 Mar 2014 10:42:52 +0000 Subject: MIPS: smp-cps: use CPC core-other locking The core which the CPC core-other region relates to is based upon the core-local core-other addressing register. As its name suggests this register is shared between all VPEs within a core, and if there is a possibility that multiple VPEs within a core will attempt to access another core simultaneously then locking is required. This wasn't previously a problem with the only user being cpu0 during boot, but will be an issue once hotplug is implemented & may race with other users such as cpuidle. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index c3661ca..b519c85 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -161,11 +161,10 @@ static void boot_core(unsigned core) write_gcr_access(access); if (mips_cpc_present()) { - /* Select the appropriate core */ - write_cpc_cl_other(core << CPC_Cx_OTHER_CORENUM_SHF); - /* Reset the core */ + mips_cpc_lock_other(core); write_cpc_co_cmd(CPC_Cx_CMD_RESET); + mips_cpc_unlock_other(); } else { /* Take the core out of reset */ write_gcr_co_reset_release(0); -- cgit v0.10.2 From 3179d37ee1ed602770a8b8ed975bd30faa85b4a3 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 11:00:56 +0100 Subject: MIPS: pm-cps: add PM state entry code for CPS systems This patch adds code to generate entry & exit code for various low power states available on systems based around the MIPS Coherent Processing System architecture (ie. those with a Coherence Manager, Global Interrupt Controller & for >=CM2 a Cluster Power Controller). States supported are: - Non-coherent wait. This state first leaves the coherent domain and then executes a regular MIPS wait instruction. Power savings are found from the elimination of coherency interventions between the core and any other coherent requestors in the system. - Clock gated. This state leaves the coherent domain and then gates the clock input to the core. This removes all dynamic power from the core but leaves the core at the mercy of another to restart its clock. Register state is preserved, but the core can not service interrupts whilst its clock is gated. - Power gated. This deepest state removes all power input to the core. All register state is lost and the core will restart execution from its BEV when another core powers it back up. Because register state is lost this state requires cooperation with the CONFIG_MIPS_CPS SMP implementation in order for the core to exit the state successfully. The code will detect which states are available on the current system during boot & generate the entry/exit code for those states. This will be used by cpuidle & hotplug implementations. Signed-off-by: Paul Burton diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5cdc53b..c79e6a4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2071,6 +2071,9 @@ config MIPS_CPS no external assistance. It is safe to enable this when hardware support is unavailable. +config MIPS_CPS_PM + bool + config MIPS_GIC_IPI bool diff --git a/arch/mips/include/asm/pm-cps.h b/arch/mips/include/asm/pm-cps.h new file mode 100644 index 0000000..625eda5 --- /dev/null +++ b/arch/mips/include/asm/pm-cps.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2014 Imagination Technologies + * Author: Paul Burton + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __MIPS_ASM_PM_CPS_H__ +#define __MIPS_ASM_PM_CPS_H__ + +/* + * The CM & CPC can only handle coherence & power control on a per-core basis, + * thus in an MT system the VPEs within each core are coupled and can only + * enter or exit states requiring CM or CPC assistance in unison. + */ +#ifdef CONFIG_MIPS_MT +# define coupled_coherence cpu_has_mipsmt +#else +# define coupled_coherence 0 +#endif + +/* Enumeration of possible PM states */ +enum cps_pm_state { + CPS_PM_NC_WAIT, /* MIPS wait instruction, non-coherent */ + CPS_PM_CLOCK_GATED, /* Core clock gated */ + CPS_PM_POWER_GATED, /* Core power gated */ + CPS_PM_STATE_COUNT, +}; + +/** + * cps_pm_support_state - determine whether the system supports a PM state + * @state: the state to test for support + * + * Returns true if the system supports the given state, otherwise false. + */ +extern bool cps_pm_support_state(enum cps_pm_state state); + +/** + * cps_pm_enter_state - enter a PM state + * @state: the state to enter + * + * Enter the given PM state. If coupled_coherence is non-zero then it is + * expected that this function be called at approximately the same time on + * each coupled CPU. Returns 0 on successful entry & exit, otherwise -errno. + */ +extern int cps_pm_enter_state(enum cps_pm_state state); + +#endif /* __MIPS_ASM_PM_CPS_H__ */ diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h index 324df2c..a06a08a 100644 --- a/arch/mips/include/asm/smp-cps.h +++ b/arch/mips/include/asm/smp-cps.h @@ -33,6 +33,9 @@ extern struct vpe_boot_config *mips_cps_boot_vpes(void); extern bool mips_cps_smp_in_use(void); +extern void mips_cps_pm_save(void); +extern void mips_cps_pm_restore(void); + #else /* __ASSEMBLY__ */ .extern mips_cps_bootcfg; diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 97540a8..6133e8b 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_MIPS_CM) += mips-cm.o obj-$(CONFIG_MIPS_CPC) += mips-cpc.o obj-$(CONFIG_CPU_PM) += pm.o +obj-$(CONFIG_MIPS_CPS_PM) += pm-cps.o # # DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 57ec18c..1c865ae 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -15,6 +15,7 @@ #include #include #include +#include #define GCR_CL_COHERENCE_OFS 0x2008 #define GCR_CL_ID_OFS 0x2028 @@ -447,3 +448,37 @@ LEAF(mips_cps_boot_vpes) jr ra nop END(mips_cps_boot_vpes) + +#if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM) + + /* Calculate a pointer to this CPUs struct mips_static_suspend_state */ + .macro psstate dest + .set push + .set noat + lw $1, TI_CPU(gp) + sll $1, $1, LONGLOG + la \dest, __per_cpu_offset + addu $1, $1, \dest + lw $1, 0($1) + la \dest, cps_cpu_state + addu \dest, \dest, $1 + .set pop + .endm + +LEAF(mips_cps_pm_save) + /* Save CPU state */ + SUSPEND_SAVE_REGS + psstate t1 + SUSPEND_SAVE_STATIC + jr v0 + nop + END(mips_cps_pm_save) + +LEAF(mips_cps_pm_restore) + /* Restore CPU state */ + psstate t1 + RESUME_RESTORE_STATIC + RESUME_RESTORE_REGS_RETURN + END(mips_cps_pm_restore) + +#endif /* CONFIG_MIPS_CPS_PM && CONFIG_CPU_PM */ diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c new file mode 100644 index 0000000..5aa4c6f --- /dev/null +++ b/arch/mips/kernel/pm-cps.c @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2014 Imagination Technologies + * Author: Paul Burton + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * cps_nc_entry_fn - type of a generated non-coherent state entry function + * @online: the count of online coupled VPEs + * @nc_ready_count: pointer to a non-coherent mapping of the core ready_count + * + * The code entering & exiting non-coherent states is generated at runtime + * using uasm, in order to ensure that the compiler cannot insert a stray + * memory access at an unfortunate time and to allow the generation of optimal + * core-specific code particularly for cache routines. If coupled_coherence + * is non-zero and this is the entry function for the CPS_PM_NC_WAIT state, + * returns the number of VPEs that were in the wait state at the point this + * VPE left it. Returns garbage if coupled_coherence is zero or this is not + * the entry function for CPS_PM_NC_WAIT. + */ +typedef unsigned (*cps_nc_entry_fn)(unsigned online, u32 *nc_ready_count); + +/* + * The entry point of the generated non-coherent idle state entry/exit + * functions. Actually per-core rather than per-CPU. + */ +static DEFINE_PER_CPU_READ_MOSTLY(cps_nc_entry_fn[CPS_PM_STATE_COUNT], + nc_asm_enter); + +/* Bitmap indicating which states are supported by the system */ +DECLARE_BITMAP(state_support, CPS_PM_STATE_COUNT); + +/* + * Indicates the number of coupled VPEs ready to operate in a non-coherent + * state. Actually per-core rather than per-CPU. + */ +static DEFINE_PER_CPU_ALIGNED(u32*, ready_count); +static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc); + +/* Indicates online CPUs coupled with the current CPU */ +static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled); + +/* + * Used to synchronize entry to deep idle states. Actually per-core rather + * than per-CPU. + */ +static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier); + +/* Saved CPU state across the CPS_PM_POWER_GATED state */ +DEFINE_PER_CPU_ALIGNED(struct mips_static_suspend_state, cps_cpu_state); + +/* A somewhat arbitrary number of labels & relocs for uasm */ +static struct uasm_label labels[32] __initdata; +static struct uasm_reloc relocs[32] __initdata; + +/* CPU dependant sync types */ +static unsigned stype_intervention; +static unsigned stype_memory; +static unsigned stype_ordering; + +enum mips_reg { + zero, at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, k0, k1, gp, sp, fp, ra, +}; + +bool cps_pm_support_state(enum cps_pm_state state) +{ + return test_bit(state, state_support); +} + +static void coupled_barrier(atomic_t *a, unsigned online) +{ + /* + * This function is effectively the same as + * cpuidle_coupled_parallel_barrier, which can't be used here since + * there's no cpuidle device. + */ + + if (!coupled_coherence) + return; + + smp_mb__before_atomic_inc(); + atomic_inc(a); + + while (atomic_read(a) < online) + cpu_relax(); + + if (atomic_inc_return(a) == online * 2) { + atomic_set(a, 0); + return; + } + + while (atomic_read(a) > online) + cpu_relax(); +} + +int cps_pm_enter_state(enum cps_pm_state state) +{ + unsigned cpu = smp_processor_id(); + unsigned core = current_cpu_data.core; + unsigned online, left; + cpumask_t *coupled_mask = this_cpu_ptr(&online_coupled); + u32 *core_ready_count, *nc_core_ready_count; + void *nc_addr; + cps_nc_entry_fn entry; + struct core_boot_config *core_cfg; + struct vpe_boot_config *vpe_cfg; + + /* Check that there is an entry function for this state */ + entry = per_cpu(nc_asm_enter, core)[state]; + if (!entry) + return -EINVAL; + + /* Calculate which coupled CPUs (VPEs) are online */ +#ifdef CONFIG_MIPS_MT + if (cpu_online(cpu)) { + cpumask_and(coupled_mask, cpu_online_mask, + &cpu_sibling_map[cpu]); + online = cpumask_weight(coupled_mask); + cpumask_clear_cpu(cpu, coupled_mask); + } else +#endif + { + cpumask_clear(coupled_mask); + online = 1; + } + + /* Setup the VPE to run mips_cps_pm_restore when started again */ + if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) { + core_cfg = &mips_cps_core_bootcfg[core]; + vpe_cfg = &core_cfg->vpe_config[current_cpu_data.vpe_id]; + vpe_cfg->pc = (unsigned long)mips_cps_pm_restore; + vpe_cfg->gp = (unsigned long)current_thread_info(); + vpe_cfg->sp = 0; + } + + /* Indicate that this CPU might not be coherent */ + cpumask_clear_cpu(cpu, &cpu_coherent_mask); + smp_mb__after_clear_bit(); + + /* Create a non-coherent mapping of the core ready_count */ + core_ready_count = per_cpu(ready_count, core); + nc_addr = kmap_noncoherent(virt_to_page(core_ready_count), + (unsigned long)core_ready_count); + nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK); + nc_core_ready_count = nc_addr; + + /* Ensure ready_count is zero-initialised before the assembly runs */ + ACCESS_ONCE(*nc_core_ready_count) = 0; + coupled_barrier(&per_cpu(pm_barrier, core), online); + + /* Run the generated entry code */ + left = entry(online, nc_core_ready_count); + + /* Remove the non-coherent mapping of ready_count */ + kunmap_noncoherent(); + + /* Indicate that this CPU is definitely coherent */ + cpumask_set_cpu(cpu, &cpu_coherent_mask); + + /* + * If this VPE is the first to leave the non-coherent wait state then + * it needs to wake up any coupled VPEs still running their wait + * instruction so that they return to cpuidle, which can then complete + * coordination between the coupled VPEs & provide the governor with + * a chance to reflect on the length of time the VPEs were in the + * idle state. + */ + if (coupled_coherence && (state == CPS_PM_NC_WAIT) && (left == online)) + arch_send_call_function_ipi_mask(coupled_mask); + + return 0; +} + +static void __init cps_gen_cache_routine(u32 **pp, struct uasm_label **pl, + struct uasm_reloc **pr, + const struct cache_desc *cache, + unsigned op, int lbl) +{ + unsigned cache_size = cache->ways << cache->waybit; + unsigned i; + const unsigned unroll_lines = 32; + + /* If the cache isn't present this function has it easy */ + if (cache->flags & MIPS_CACHE_NOT_PRESENT) + return; + + /* Load base address */ + UASM_i_LA(pp, t0, (long)CKSEG0); + + /* Calculate end address */ + if (cache_size < 0x8000) + uasm_i_addiu(pp, t1, t0, cache_size); + else + UASM_i_LA(pp, t1, (long)(CKSEG0 + cache_size)); + + /* Start of cache op loop */ + uasm_build_label(pl, *pp, lbl); + + /* Generate the cache ops */ + for (i = 0; i < unroll_lines; i++) + uasm_i_cache(pp, op, i * cache->linesz, t0); + + /* Update the base address */ + uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz); + + /* Loop if we haven't reached the end address yet */ + uasm_il_bne(pp, pr, t0, t1, lbl); + uasm_i_nop(pp); +} + +static int __init cps_gen_flush_fsb(u32 **pp, struct uasm_label **pl, + struct uasm_reloc **pr, + const struct cpuinfo_mips *cpu_info, + int lbl) +{ + unsigned i, fsb_size = 8; + unsigned num_loads = (fsb_size * 3) / 2; + unsigned line_stride = 2; + unsigned line_size = cpu_info->dcache.linesz; + unsigned perf_counter, perf_event; + unsigned revision = cpu_info->processor_id & PRID_REV_MASK; + + /* + * Determine whether this CPU requires an FSB flush, and if so which + * performance counter/event reflect stalls due to a full FSB. + */ + switch (__get_cpu_type(cpu_info->cputype)) { + case CPU_INTERAPTIV: + perf_counter = 1; + perf_event = 51; + break; + + case CPU_PROAPTIV: + /* Newer proAptiv cores don't require this workaround */ + if (revision >= PRID_REV_ENCODE_332(1, 1, 0)) + return 0; + + /* On older ones it's unavailable */ + return -1; + + /* CPUs which do not require the workaround */ + case CPU_P5600: + return 0; + + default: + WARN_ONCE(1, "pm-cps: FSB flush unsupported for this CPU\n"); + return -1; + } + + /* + * Ensure that the fill/store buffer (FSB) is not holding the results + * of a prefetch, since if it is then the CPC sequencer may become + * stuck in the D3 (ClrBus) state whilst entering a low power state. + */ + + /* Preserve perf counter setup */ + uasm_i_mfc0(pp, t2, 25, (perf_counter * 2) + 0); /* PerfCtlN */ + uasm_i_mfc0(pp, t3, 25, (perf_counter * 2) + 1); /* PerfCntN */ + + /* Setup perf counter to count FSB full pipeline stalls */ + uasm_i_addiu(pp, t0, zero, (perf_event << 5) | 0xf); + uasm_i_mtc0(pp, t0, 25, (perf_counter * 2) + 0); /* PerfCtlN */ + uasm_i_ehb(pp); + uasm_i_mtc0(pp, zero, 25, (perf_counter * 2) + 1); /* PerfCntN */ + uasm_i_ehb(pp); + + /* Base address for loads */ + UASM_i_LA(pp, t0, (long)CKSEG0); + + /* Start of clear loop */ + uasm_build_label(pl, *pp, lbl); + + /* Perform some loads to fill the FSB */ + for (i = 0; i < num_loads; i++) + uasm_i_lw(pp, zero, i * line_size * line_stride, t0); + + /* + * Invalidate the new D-cache entries so that the cache will need + * refilling (via the FSB) if the loop is executed again. + */ + for (i = 0; i < num_loads; i++) { + uasm_i_cache(pp, Hit_Invalidate_D, + i * line_size * line_stride, t0); + uasm_i_cache(pp, Hit_Writeback_Inv_SD, + i * line_size * line_stride, t0); + } + + /* Completion barrier */ + uasm_i_sync(pp, stype_memory); + uasm_i_ehb(pp); + + /* Check whether the pipeline stalled due to the FSB being full */ + uasm_i_mfc0(pp, t1, 25, (perf_counter * 2) + 1); /* PerfCntN */ + + /* Loop if it didn't */ + uasm_il_beqz(pp, pr, t1, lbl); + uasm_i_nop(pp); + + /* Restore perf counter 1. The count may well now be wrong... */ + uasm_i_mtc0(pp, t2, 25, (perf_counter * 2) + 0); /* PerfCtlN */ + uasm_i_ehb(pp); + uasm_i_mtc0(pp, t3, 25, (perf_counter * 2) + 1); /* PerfCntN */ + uasm_i_ehb(pp); + + return 0; +} + +static void __init cps_gen_set_top_bit(u32 **pp, struct uasm_label **pl, + struct uasm_reloc **pr, + unsigned r_addr, int lbl) +{ + uasm_i_lui(pp, t0, uasm_rel_hi(0x80000000)); + uasm_build_label(pl, *pp, lbl); + uasm_i_ll(pp, t1, 0, r_addr); + uasm_i_or(pp, t1, t1, t0); + uasm_i_sc(pp, t1, 0, r_addr); + uasm_il_beqz(pp, pr, t1, lbl); + uasm_i_nop(pp); +} + +static void * __init cps_gen_entry_code(unsigned cpu, enum cps_pm_state state) +{ + struct uasm_label *l = labels; + struct uasm_reloc *r = relocs; + u32 *buf, *p; + const unsigned r_online = a0; + const unsigned r_nc_count = a1; + const unsigned r_pcohctl = t7; + const unsigned max_instrs = 256; + unsigned cpc_cmd; + int err; + enum { + lbl_incready = 1, + lbl_poll_cont, + lbl_secondary_hang, + lbl_disable_coherence, + lbl_flush_fsb, + lbl_invicache, + lbl_flushdcache, + lbl_hang, + lbl_set_cont, + lbl_secondary_cont, + lbl_decready, + }; + + /* Allocate a buffer to hold the generated code */ + p = buf = kcalloc(max_instrs, sizeof(u32), GFP_KERNEL); + if (!buf) + return NULL; + + /* Clear labels & relocs ready for (re)use */ + memset(labels, 0, sizeof(labels)); + memset(relocs, 0, sizeof(relocs)); + + if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) { + /* + * Save CPU state. Note the non-standard calling convention + * with the return address placed in v0 to avoid clobbering + * the ra register before it is saved. + */ + UASM_i_LA(&p, t0, (long)mips_cps_pm_save); + uasm_i_jalr(&p, v0, t0); + uasm_i_nop(&p); + } + + /* + * Load addresses of required CM & CPC registers. This is done early + * because they're needed in both the enable & disable coherence steps + * but in the coupled case the enable step will only run on one VPE. + */ + UASM_i_LA(&p, r_pcohctl, (long)addr_gcr_cl_coherence()); + + if (coupled_coherence) { + /* Increment ready_count */ + uasm_i_sync(&p, stype_ordering); + uasm_build_label(&l, p, lbl_incready); + uasm_i_ll(&p, t1, 0, r_nc_count); + uasm_i_addiu(&p, t2, t1, 1); + uasm_i_sc(&p, t2, 0, r_nc_count); + uasm_il_beqz(&p, &r, t2, lbl_incready); + uasm_i_addiu(&p, t1, t1, 1); + + /* Ordering barrier */ + uasm_i_sync(&p, stype_ordering); + + /* + * If this is the last VPE to become ready for non-coherence + * then it should branch below. + */ + uasm_il_beq(&p, &r, t1, r_online, lbl_disable_coherence); + uasm_i_nop(&p); + + if (state < CPS_PM_POWER_GATED) { + /* + * Otherwise this is not the last VPE to become ready + * for non-coherence. It needs to wait until coherence + * has been disabled before proceeding, which it will do + * by polling for the top bit of ready_count being set. + */ + uasm_i_addiu(&p, t1, zero, -1); + uasm_build_label(&l, p, lbl_poll_cont); + uasm_i_lw(&p, t0, 0, r_nc_count); + uasm_il_bltz(&p, &r, t0, lbl_secondary_cont); + uasm_i_ehb(&p); + uasm_i_yield(&p, zero, t1); + uasm_il_b(&p, &r, lbl_poll_cont); + uasm_i_nop(&p); + } else { + /* + * The core will lose power & this VPE will not continue + * so it can simply halt here. + */ + uasm_i_addiu(&p, t0, zero, TCHALT_H); + uasm_i_mtc0(&p, t0, 2, 4); + uasm_build_label(&l, p, lbl_secondary_hang); + uasm_il_b(&p, &r, lbl_secondary_hang); + uasm_i_nop(&p); + } + } + + /* + * This is the point of no return - this VPE will now proceed to + * disable coherence. At this point we *must* be sure that no other + * VPE within the core will interfere with the L1 dcache. + */ + uasm_build_label(&l, p, lbl_disable_coherence); + + /* Invalidate the L1 icache */ + cps_gen_cache_routine(&p, &l, &r, &cpu_data[cpu].icache, + Index_Invalidate_I, lbl_invicache); + + /* Writeback & invalidate the L1 dcache */ + cps_gen_cache_routine(&p, &l, &r, &cpu_data[cpu].dcache, + Index_Writeback_Inv_D, lbl_flushdcache); + + /* Completion barrier */ + uasm_i_sync(&p, stype_memory); + uasm_i_ehb(&p); + + /* + * Disable all but self interventions. The load from COHCTL is defined + * by the interAptiv & proAptiv SUMs as ensuring that the operation + * resulting from the preceeding store is complete. + */ + uasm_i_addiu(&p, t0, zero, 1 << cpu_data[cpu].core); + uasm_i_sw(&p, t0, 0, r_pcohctl); + uasm_i_lw(&p, t0, 0, r_pcohctl); + + /* Sync to ensure previous interventions are complete */ + uasm_i_sync(&p, stype_intervention); + uasm_i_ehb(&p); + + /* Disable coherence */ + uasm_i_sw(&p, zero, 0, r_pcohctl); + uasm_i_lw(&p, t0, 0, r_pcohctl); + + if (state >= CPS_PM_CLOCK_GATED) { + err = cps_gen_flush_fsb(&p, &l, &r, &cpu_data[cpu], + lbl_flush_fsb); + if (err) + goto out_err; + + /* Determine the CPC command to issue */ + switch (state) { + case CPS_PM_CLOCK_GATED: + cpc_cmd = CPC_Cx_CMD_CLOCKOFF; + break; + case CPS_PM_POWER_GATED: + cpc_cmd = CPC_Cx_CMD_PWRDOWN; + break; + default: + BUG(); + goto out_err; + } + + /* Issue the CPC command */ + UASM_i_LA(&p, t0, (long)addr_cpc_cl_cmd()); + uasm_i_addiu(&p, t1, zero, cpc_cmd); + uasm_i_sw(&p, t1, 0, t0); + + if (state == CPS_PM_POWER_GATED) { + /* If anything goes wrong just hang */ + uasm_build_label(&l, p, lbl_hang); + uasm_il_b(&p, &r, lbl_hang); + uasm_i_nop(&p); + + /* + * There's no point generating more code, the core is + * powered down & if powered back up will run from the + * reset vector not from here. + */ + goto gen_done; + } + + /* Completion barrier */ + uasm_i_sync(&p, stype_memory); + uasm_i_ehb(&p); + } + + if (state == CPS_PM_NC_WAIT) { + /* + * At this point it is safe for all VPEs to proceed with + * execution. This VPE will set the top bit of ready_count + * to indicate to the other VPEs that they may continue. + */ + if (coupled_coherence) + cps_gen_set_top_bit(&p, &l, &r, r_nc_count, + lbl_set_cont); + + /* + * VPEs which did not disable coherence will continue + * executing, after coherence has been disabled, from this + * point. + */ + uasm_build_label(&l, p, lbl_secondary_cont); + + /* Now perform our wait */ + uasm_i_wait(&p, 0); + } + + /* + * Re-enable coherence. Note that for CPS_PM_NC_WAIT all coupled VPEs + * will run this. The first will actually re-enable coherence & the + * rest will just be performing a rather unusual nop. + */ + uasm_i_addiu(&p, t0, zero, CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK); + uasm_i_sw(&p, t0, 0, r_pcohctl); + uasm_i_lw(&p, t0, 0, r_pcohctl); + + /* Completion barrier */ + uasm_i_sync(&p, stype_memory); + uasm_i_ehb(&p); + + if (coupled_coherence && (state == CPS_PM_NC_WAIT)) { + /* Decrement ready_count */ + uasm_build_label(&l, p, lbl_decready); + uasm_i_sync(&p, stype_ordering); + uasm_i_ll(&p, t1, 0, r_nc_count); + uasm_i_addiu(&p, t2, t1, -1); + uasm_i_sc(&p, t2, 0, r_nc_count); + uasm_il_beqz(&p, &r, t2, lbl_decready); + uasm_i_andi(&p, v0, t1, (1 << fls(smp_num_siblings)) - 1); + + /* Ordering barrier */ + uasm_i_sync(&p, stype_ordering); + } + + if (coupled_coherence && (state == CPS_PM_CLOCK_GATED)) { + /* + * At this point it is safe for all VPEs to proceed with + * execution. This VPE will set the top bit of ready_count + * to indicate to the other VPEs that they may continue. + */ + cps_gen_set_top_bit(&p, &l, &r, r_nc_count, lbl_set_cont); + + /* + * This core will be reliant upon another core sending a + * power-up command to the CPC in order to resume operation. + * Thus an arbitrary VPE can't trigger the core leaving the + * idle state and the one that disables coherence might as well + * be the one to re-enable it. The rest will continue from here + * after that has been done. + */ + uasm_build_label(&l, p, lbl_secondary_cont); + + /* Ordering barrier */ + uasm_i_sync(&p, stype_ordering); + } + + /* The core is coherent, time to return to C code */ + uasm_i_jr(&p, ra); + uasm_i_nop(&p); + +gen_done: + /* Ensure the code didn't exceed the resources allocated for it */ + BUG_ON((p - buf) > max_instrs); + BUG_ON((l - labels) > ARRAY_SIZE(labels)); + BUG_ON((r - relocs) > ARRAY_SIZE(relocs)); + + /* Patch branch offsets */ + uasm_resolve_relocs(relocs, labels); + + /* Flush the icache */ + local_flush_icache_range((unsigned long)buf, (unsigned long)p); + + return buf; +out_err: + kfree(buf); + return NULL; +} + +static int __init cps_gen_core_entries(unsigned cpu) +{ + enum cps_pm_state state; + unsigned core = cpu_data[cpu].core; + unsigned dlinesz = cpu_data[cpu].dcache.linesz; + void *entry_fn, *core_rc; + + for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) { + if (per_cpu(nc_asm_enter, core)[state]) + continue; + if (!test_bit(state, state_support)) + continue; + + entry_fn = cps_gen_entry_code(cpu, state); + if (!entry_fn) { + pr_err("Failed to generate core %u state %u entry\n", + core, state); + clear_bit(state, state_support); + } + + per_cpu(nc_asm_enter, core)[state] = entry_fn; + } + + if (!per_cpu(ready_count, core)) { + core_rc = kmalloc(dlinesz * 2, GFP_KERNEL); + if (!core_rc) { + pr_err("Failed allocate core %u ready_count\n", core); + return -ENOMEM; + } + per_cpu(ready_count_alloc, core) = core_rc; + + /* Ensure ready_count is aligned to a cacheline boundary */ + core_rc += dlinesz - 1; + core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1)); + per_cpu(ready_count, core) = core_rc; + } + + return 0; +} + +static int __init cps_pm_init(void) +{ + unsigned cpu; + int err; + + /* Detect appropriate sync types for the system */ + switch (current_cpu_data.cputype) { + case CPU_INTERAPTIV: + case CPU_PROAPTIV: + case CPU_M5150: + case CPU_P5600: + stype_intervention = 0x2; + stype_memory = 0x3; + stype_ordering = 0x10; + break; + + default: + pr_warn("Power management is using heavyweight sync 0\n"); + } + + /* A CM is required for all non-coherent states */ + if (!mips_cm_present()) { + pr_warn("pm-cps: no CM, non-coherent states unavailable\n"); + goto out; + } + + /* + * If interrupts were enabled whilst running a wait instruction on a + * non-coherent core then the VPE may end up processing interrupts + * whilst non-coherent. That would be bad. + */ + if (cpu_wait == r4k_wait_irqoff) + set_bit(CPS_PM_NC_WAIT, state_support); + else + pr_warn("pm-cps: non-coherent wait unavailable\n"); + + /* Detect whether a CPC is present */ + if (mips_cpc_present()) { + /* Detect whether clock gating is implemented */ + if (read_cpc_cl_stat_conf() & CPC_Cx_STAT_CONF_CLKGAT_IMPL_MSK) + set_bit(CPS_PM_CLOCK_GATED, state_support); + else + pr_warn("pm-cps: CPC does not support clock gating\n"); + + /* Power gating is available with CPS SMP & any CPC */ + if (mips_cps_smp_in_use()) + set_bit(CPS_PM_POWER_GATED, state_support); + else + pr_warn("pm-cps: CPS SMP not in use, power gating unavailable\n"); + } else { + pr_warn("pm-cps: no CPC, clock & power gating unavailable\n"); + } + + for_each_present_cpu(cpu) { + err = cps_gen_core_entries(cpu); + if (err) + return err; + } +out: + return 0; +} +arch_initcall(cps_pm_init); -- cgit v0.10.2 From 1d8f1f5a780abe51257f7d2e33142f33d983a9ed Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 14:13:57 +0100 Subject: MIPS: smp-cps: hotplug support This patch adds support for offlining CPUs via hotplug when using the CONFIG_MIPS_CPS SMP implementation. When a CPU is offlined one of 2 things will happen: - If the CPU is part of a core which implements the MT ASE and there is at least one other VPE online within that core then the VPE will be halted by settings its TCHalt bit. - Otherwise if supported the core will be powered down via the CPC. - Otherwise the CPU will hang by executing an infinite loop. Bringing CPUs back online is then a process of either clearing the appropriate VPEs TCHalt bit or powering up the appropriate core via the CPC. Throughout the process the struct core_boot_config vpe_mask field must be maintained such that mips_cps_boot_vpes will start & stop the correct VPEs. Signed-off-by: Paul Burton diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c79e6a4..860a1e9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2059,9 +2059,11 @@ config MIPS_CPS depends on SYS_SUPPORTS_MIPS_CPS select MIPS_CM select MIPS_CPC + select MIPS_CPS_PM if HOTPLUG_CPU select MIPS_GIC_IPI select SMP select SYNC_R4K if (CEVT_R4K || CSRC_R4K) + select SYS_SUPPORTS_HOTPLUG_CPU select SYS_SUPPORTS_SMP select WEAK_ORDERING help diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index b519c85..3c30891 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -194,10 +195,12 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) atomic_or(1 << cpu_vpe_id(&cpu_data[cpu]), &core_cfg->vpe_mask); + preempt_disable(); + if (!test_bit(core, core_power)) { /* Boot a VPE on a powered down core */ boot_core(core); - return; + goto out; } if (core != current_cpu_data.core) { @@ -214,13 +217,15 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle) NULL, 1); if (err) panic("Failed to call remote CPU\n"); - return; + goto out; } BUG_ON(!cpu_has_mipsmt); /* Boot a VPE on this core */ mips_cps_boot_vpes(); +out: + preempt_enable(); } static void cps_init_secondary(void) @@ -250,6 +255,148 @@ static void cps_cpus_done(void) { } +#ifdef CONFIG_HOTPLUG_CPU + +static int cps_cpu_disable(void) +{ + unsigned cpu = smp_processor_id(); + struct core_boot_config *core_cfg; + + if (!cpu) + return -EBUSY; + + if (!cps_pm_support_state(CPS_PM_POWER_GATED)) + return -EINVAL; + + core_cfg = &mips_cps_core_bootcfg[current_cpu_data.core]; + atomic_sub(1 << cpu_vpe_id(¤t_cpu_data), &core_cfg->vpe_mask); + smp_mb__after_atomic_dec(); + set_cpu_online(cpu, false); + cpu_clear(cpu, cpu_callin_map); + + return 0; +} + +static DECLARE_COMPLETION(cpu_death_chosen); +static unsigned cpu_death_sibling; +static enum { + CPU_DEATH_HALT, + CPU_DEATH_POWER, +} cpu_death; + +void play_dead(void) +{ + unsigned cpu, core; + + local_irq_disable(); + idle_task_exit(); + cpu = smp_processor_id(); + cpu_death = CPU_DEATH_POWER; + + if (cpu_has_mipsmt) { + core = cpu_data[cpu].core; + + /* Look for another online VPE within the core */ + for_each_online_cpu(cpu_death_sibling) { + if (cpu_data[cpu_death_sibling].core != core) + continue; + + /* + * There is an online VPE within the core. Just halt + * this TC and leave the core alone. + */ + cpu_death = CPU_DEATH_HALT; + break; + } + } + + /* This CPU has chosen its way out */ + complete(&cpu_death_chosen); + + if (cpu_death == CPU_DEATH_HALT) { + /* Halt this TC */ + write_c0_tchalt(TCHALT_H); + instruction_hazard(); + } else { + /* Power down the core */ + cps_pm_enter_state(CPS_PM_POWER_GATED); + } + + /* This should never be reached */ + panic("Failed to offline CPU %u", cpu); +} + +static void wait_for_sibling_halt(void *ptr_cpu) +{ + unsigned cpu = (unsigned)ptr_cpu; + unsigned vpe_id = cpu_data[cpu].vpe_id; + unsigned halted; + unsigned long flags; + + do { + local_irq_save(flags); + settc(vpe_id); + halted = read_tc_c0_tchalt(); + local_irq_restore(flags); + } while (!(halted & TCHALT_H)); +} + +static void cps_cpu_die(unsigned int cpu) +{ + unsigned core = cpu_data[cpu].core; + unsigned stat; + int err; + + /* Wait for the cpu to choose its way out */ + if (!wait_for_completion_timeout(&cpu_death_chosen, + msecs_to_jiffies(5000))) { + pr_err("CPU%u: didn't offline\n", cpu); + return; + } + + /* + * Now wait for the CPU to actually offline. Without doing this that + * offlining may race with one or more of: + * + * - Onlining the CPU again. + * - Powering down the core if another VPE within it is offlined. + * - A sibling VPE entering a non-coherent state. + * + * In the non-MT halt case (ie. infinite loop) the CPU is doing nothing + * with which we could race, so do nothing. + */ + if (cpu_death == CPU_DEATH_POWER) { + /* + * Wait for the core to enter a powered down or clock gated + * state, the latter happening when a JTAG probe is connected + * in which case the CPC will refuse to power down the core. + */ + do { + mips_cpc_lock_other(core); + stat = read_cpc_co_stat_conf(); + stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK; + mips_cpc_unlock_other(); + } while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 && + stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 && + stat != CPC_Cx_STAT_CONF_SEQSTATE_U2); + + /* Indicate the core is powered off */ + bitmap_clear(core_power, core, 1); + } else if (cpu_has_mipsmt) { + /* + * Have a CPU with access to the offlined CPUs registers wait + * for its TC to halt. + */ + err = smp_call_function_single(cpu_death_sibling, + wait_for_sibling_halt, + (void *)cpu, 1); + if (err) + panic("Failed to call remote sibling CPU\n"); + } +} + +#endif /* CONFIG_HOTPLUG_CPU */ + static struct plat_smp_ops cps_smp_ops = { .smp_setup = cps_smp_setup, .prepare_cpus = cps_prepare_cpus, @@ -259,6 +406,10 @@ static struct plat_smp_ops cps_smp_ops = { .send_ipi_single = gic_send_ipi_single, .send_ipi_mask = gic_send_ipi_mask, .cpus_done = cps_cpus_done, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = cps_cpu_disable, + .cpu_die = cps_cpu_die, +#endif }; bool mips_cps_smp_in_use(void) -- cgit v0.10.2 From 5c399f6eb2c3911d94509f8f39bfd9aed6568f86 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 15:21:25 +0100 Subject: MIPS: smp-cps: prevent multi-core SMP with unsuitable CCA If the user or bootloader sets the CCA to a value which is not suited for multi-core SMP (ie. anything non-coherent) then limit the system to using only a single core and warn the user. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 3c30891..e2f78b3 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -88,11 +88,38 @@ static void __init cps_smp_setup(void) static void __init cps_prepare_cpus(unsigned int max_cpus) { - unsigned ncores, core_vpes, c; + unsigned ncores, core_vpes, c, cca; + bool cca_unsuitable; u32 *entry_code; mips_mt_set_cpuoptions(); + /* Detect whether the CCA is unsuited to multi-core SMP */ + cca = read_c0_config() & CONF_CM_CMASK; + switch (cca) { + case 0x4: /* CWBE */ + case 0x5: /* CWB */ + /* The CCA is coherent, multi-core is fine */ + cca_unsuitable = false; + break; + + default: + /* CCA is not coherent, multi-core is not usable */ + cca_unsuitable = true; + } + + /* Warn the user if the CCA prevents multi-core */ + ncores = mips_cm_numcores(); + if (cca_unsuitable && ncores > 1) { + pr_warn("Using only one core due to unsuitable CCA 0x%x\n", + cca); + + for_each_present_cpu(c) { + if (cpu_data[c].core) + set_cpu_present(c, false); + } + } + /* Patch the start of mips_cps_core_entry to provide the CM base */ entry_code = (u32 *)&mips_cps_core_entry; UASM_i_LA(&entry_code, 3, (long)mips_cm_base); @@ -100,7 +127,6 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) (void *)entry_code - (void *)&mips_cps_core_entry); /* Allocate core boot configuration structs */ - ncores = mips_cm_numcores(); mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg), GFP_KERNEL); if (!mips_cps_core_bootcfg) { -- cgit v0.10.2 From 33b6866568acce808361fcf25c107c2c94f8eadb Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 15:58:45 +0100 Subject: MIPS: smp-cps: set a coherent default CCA This patch sets a default CCA suited for use with multi-core SMP on all current MIPS CPS based systems. It may still be overriden by the cca= argument on the kernel command line. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index e2f78b3..6b96fed 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -76,6 +76,9 @@ static void __init cps_smp_setup(void) __cpu_logical_map[v] = v; } + /* Set a coherent default CCA (CWB) */ + change_c0_config(CONF_CM_CMASK, 0x5); + /* Core 0 is powered up (we're running on it) */ bitmap_set(core_power, 0, 1); -- cgit v0.10.2 From 0155a06529d4c8425573596720829b6c578c05f2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 16 Apr 2014 11:10:57 +0100 Subject: MIPS: smp-cps: duplicate core0 CCA on secondary cores Rather than hardcoding CCA=0x5 for secondary cores, re-use the CCA from the boot CPU. This allows overrides of the CCA using the cca= kernel parameter to take effect on all CPUs for consistency. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 1c865ae..6f4f739 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -45,10 +45,12 @@ LEAF(mips_cps_core_entry) /* - * These first 8 bytes will be patched by cps_smp_setup to load the - * base address of the CM GCRs into register v1. + * These first 12 bytes will be patched by cps_smp_setup to load the + * base address of the CM GCRs into register v1 and the CCA to use into + * register s0. */ .quad 0 + .word 0 /* Check whether we're here due to an NMI */ mfc0 k0, CP0_STATUS @@ -139,10 +141,11 @@ icache_done: add a0, a0, t0 dcache_done: - /* Set Kseg0 cacheable, coherent, write-back, write-allocate */ + /* Set Kseg0 CCA to that in s0 */ mfc0 t0, CP0_CONFIG ori t0, 0x7 - xori t0, 0x2 + xori t0, 0x7 + or t0, t0, s0 mtc0 t0, CP0_CONFIG ehb diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 6b96fed..9e21bdd 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -123,9 +123,15 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) } } - /* Patch the start of mips_cps_core_entry to provide the CM base */ + /* + * Patch the start of mips_cps_core_entry to provide: + * + * v0 = CM base address + * s0 = kseg0 CCA + */ entry_code = (u32 *)&mips_cps_core_entry; UASM_i_LA(&entry_code, 3, (long)mips_cm_base); + uasm_i_addiu(&entry_code, 16, 0, cca); dma_cache_wback_inv((unsigned long)&mips_cps_core_entry, (void *)entry_code - (void *)&mips_cps_core_entry); -- cgit v0.10.2 From da9f970fdd55a018ab97ec2d25653756407bdaaf Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 16:16:41 +0100 Subject: MIPS: cpuidle wait instruction state Defines a macro intended to allow trivial use of the regular MIPS wait instruction from cpuidle drivers, which may simply invoke the macro within their array of states. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/idle.h b/arch/mips/include/asm/idle.h index d192158..d9f932d 100644 --- a/arch/mips/include/asm/idle.h +++ b/arch/mips/include/asm/idle.h @@ -1,6 +1,7 @@ #ifndef __ASM_IDLE_H #define __ASM_IDLE_H +#include #include extern void (*cpu_wait)(void); @@ -20,4 +21,17 @@ static inline int address_is_in_r4k_wait_irqoff(unsigned long addr) addr < (unsigned long)__pastwait; } +extern int mips_cpuidle_wait_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index); + +#define MIPS_CPUIDLE_WAIT_STATE {\ + .enter = mips_cpuidle_wait_enter,\ + .exit_latency = 1,\ + .target_residency = 1,\ + .power_usage = UINT_MAX,\ + .flags = CPUIDLE_FLAG_TIME_VALID,\ + .name = "wait",\ + .desc = "MIPS wait",\ +} + #endif /* __ASM_IDLE_H */ diff --git a/arch/mips/kernel/idle.c b/arch/mips/kernel/idle.c index 837ff27..2879e2e 100644 --- a/arch/mips/kernel/idle.c +++ b/arch/mips/kernel/idle.c @@ -250,3 +250,14 @@ void arch_cpu_idle(void) else local_irq_enable(); } + +#ifdef CONFIG_CPU_IDLE + +int mips_cpuidle_wait_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + arch_cpu_idle(); + return index; +} + +#endif -- cgit v0.10.2 From c095ebafeae302c8403d7ca5e78c7afe97a1afbb Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 16:24:22 +0100 Subject: MIPS: include cpuidle Kconfig menu This patch simply includes the cpuidle Kconfig entries in preparation for cpuidle drivers used on MIPS systems. Signed-off-by: Paul Burton diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 860a1e9..a3f32e7 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2678,12 +2678,16 @@ endmenu config MIPS_EXTERNAL_TIMER bool -if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER menu "CPU Power Management" + +if CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER source "drivers/cpufreq/Kconfig" -endmenu endif +source "drivers/cpuidle/Kconfig" + +endmenu + source "net/Kconfig" source "drivers/Kconfig" -- cgit v0.10.2 From f08dbf8a61462aa122b9b5077849a3f4bd84702a Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 8 Jan 2014 11:23:35 +0000 Subject: cpuidle: declare cpuidle_dev in cpuidle.h Declaring this allows drivers which need to initialise each struct cpuidle_device at initialisation time to make use of the structures already defined in cpuidle.c, rather than having to wastefully define their own. Signed-off-by: Paul Burton diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index b0238cb..99cbd7a 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -84,6 +84,7 @@ struct cpuidle_device { }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); +DECLARE_PER_CPU(struct cpuidle_device, cpuidle_dev); /** * cpuidle_get_last_residency - retrieves the last state's residency time -- cgit v0.10.2 From d050894435cdc78807e714a0148527542a583e87 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 14 Apr 2014 16:25:29 +0100 Subject: cpuidle: cpuidle-cps: add MIPS CPS cpuidle driver This patch adds a cpuidle driver for systems based around the MIPS Coherent Processing System (CPS) architecture. It supports four idle states: - The standard MIPS wait instruction. - The non-coherent wait, clock gated & power gated states exposed by the recently added pm-cps layer. The pm-cps layer is used to enter all the deep idle states. Since cores in the clock or power gated states cannot service interrupts, the gic_send_ipi_single function is modified to send a power up command for the appropriate core to the CPC in cases where the target CPU has marked itself potentially incoherent. Signed-off-by: Paul Burton diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c index 3bb1f92..3b21a96 100644 --- a/arch/mips/kernel/smp-gic.c +++ b/arch/mips/kernel/smp-gic.c @@ -15,12 +15,14 @@ #include #include +#include #include void gic_send_ipi_single(int cpu, unsigned int action) { unsigned long flags; unsigned int intr; + unsigned int core = cpu_data[cpu].core; pr_debug("CPU%d: %s cpu %d action %u status %08x\n", smp_processor_id(), __func__, cpu, action, read_c0_status()); @@ -41,6 +43,15 @@ void gic_send_ipi_single(int cpu, unsigned int action) } gic_send_ipi(intr); + + if (mips_cpc_present() && (core != current_cpu_data.core)) { + while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) { + mips_cpc_lock_other(core); + write_cpc_co_cmd(CPC_Cx_CMD_PWRUP); + mips_cpc_unlock_other(); + } + } + local_irq_restore(flags); } diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index f04e25f..1b96fb9 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -35,6 +35,11 @@ depends on ARM source "drivers/cpuidle/Kconfig.arm" endmenu +menu "MIPS CPU Idle Drivers" +depends on MIPS +source "drivers/cpuidle/Kconfig.mips" +endmenu + menu "POWERPC CPU Idle Drivers" depends on PPC source "drivers/cpuidle/Kconfig.powerpc" diff --git a/drivers/cpuidle/Kconfig.mips b/drivers/cpuidle/Kconfig.mips new file mode 100644 index 0000000..0e70ee2 --- /dev/null +++ b/drivers/cpuidle/Kconfig.mips @@ -0,0 +1,17 @@ +# +# MIPS CPU Idle Drivers +# +config MIPS_CPS_CPUIDLE + bool "CPU Idle driver for MIPS CPS platforms" + depends on CPU_IDLE + depends on SYS_SUPPORTS_MIPS_CPS + select ARCH_NEEDS_CPU_IDLE_COUPLED if MIPS_MT + select GENERIC_CLOCKEVENTS_BROADCAST if SMP + select MIPS_CPS_PM + default y + help + Select this option to enable processor idle state management + through cpuidle for systems built around the MIPS Coherent + Processing System (CPS) architecture. In order to make use of + the deepest idle states you will need to ensure that you are + also using the CONFIG_MIPS_CPS SMP implementation. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index f71ae1b..a7fc96b 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -15,6 +15,10 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o ############################################################################### +# MIPS drivers +obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o + +############################################################################### # POWERPC drivers obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o diff --git a/drivers/cpuidle/cpuidle-cps.c b/drivers/cpuidle/cpuidle-cps.c new file mode 100644 index 0000000..fc7b627 --- /dev/null +++ b/drivers/cpuidle/cpuidle-cps.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2014 Imagination Technologies + * Author: Paul Burton + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include + +#include +#include + +/* Enumeration of the various idle states this driver may enter */ +enum cps_idle_state { + STATE_WAIT = 0, /* MIPS wait instruction, coherent */ + STATE_NC_WAIT, /* MIPS wait instruction, non-coherent */ + STATE_CLOCK_GATED, /* Core clock gated */ + STATE_POWER_GATED, /* Core power gated */ + STATE_COUNT +}; + +static int cps_nc_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + enum cps_pm_state pm_state; + int err; + + /* + * At least one core must remain powered up & clocked in order for the + * system to have any hope of functioning. + * + * TODO: don't treat core 0 specially, just prevent the final core + * TODO: remap interrupt affinity temporarily + */ + if (!cpu_data[dev->cpu].core && (index > STATE_NC_WAIT)) + index = STATE_NC_WAIT; + + /* Select the appropriate cps_pm_state */ + switch (index) { + case STATE_NC_WAIT: + pm_state = CPS_PM_NC_WAIT; + break; + case STATE_CLOCK_GATED: + pm_state = CPS_PM_CLOCK_GATED; + break; + case STATE_POWER_GATED: + pm_state = CPS_PM_POWER_GATED; + break; + default: + BUG(); + return -EINVAL; + } + + /* Notify listeners the CPU is about to power down */ + if ((pm_state == CPS_PM_POWER_GATED) && cpu_pm_enter()) + return -EINTR; + + /* Enter that state */ + err = cps_pm_enter_state(pm_state); + + /* Notify listeners the CPU is back up */ + if (pm_state == CPS_PM_POWER_GATED) + cpu_pm_exit(); + + return err ?: index; +} + +static struct cpuidle_driver cps_driver = { + .name = "cpc_cpuidle", + .owner = THIS_MODULE, + .states = { + [STATE_WAIT] = MIPS_CPUIDLE_WAIT_STATE, + [STATE_NC_WAIT] = { + .enter = cps_nc_enter, + .exit_latency = 200, + .target_residency = 450, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "nc-wait", + .desc = "non-coherent MIPS wait", + }, + [STATE_CLOCK_GATED] = { + .enter = cps_nc_enter, + .exit_latency = 300, + .target_residency = 700, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .name = "clock-gated", + .desc = "core clock gated", + }, + [STATE_POWER_GATED] = { + .enter = cps_nc_enter, + .exit_latency = 600, + .target_residency = 1000, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .name = "power-gated", + .desc = "core power gated", + }, + }, + .state_count = STATE_COUNT, + .safe_state_index = 0, +}; + +static void __init cps_cpuidle_unregister(void) +{ + int cpu; + struct cpuidle_device *device; + + for_each_possible_cpu(cpu) { + device = &per_cpu(cpuidle_dev, cpu); + cpuidle_unregister_device(device); + } + + cpuidle_unregister_driver(&cps_driver); +} + +static int __init cps_cpuidle_init(void) +{ + int err, cpu, core, i; + struct cpuidle_device *device; + + /* Detect supported states */ + if (!cps_pm_support_state(CPS_PM_POWER_GATED)) + cps_driver.state_count = STATE_CLOCK_GATED + 1; + if (!cps_pm_support_state(CPS_PM_CLOCK_GATED)) + cps_driver.state_count = STATE_NC_WAIT + 1; + if (!cps_pm_support_state(CPS_PM_NC_WAIT)) + cps_driver.state_count = STATE_WAIT + 1; + + /* Inform the user if some states are unavailable */ + if (cps_driver.state_count < STATE_COUNT) { + pr_info("cpuidle-cps: limited to "); + switch (cps_driver.state_count - 1) { + case STATE_WAIT: + pr_cont("coherent wait\n"); + break; + case STATE_NC_WAIT: + pr_cont("non-coherent wait\n"); + break; + case STATE_CLOCK_GATED: + pr_cont("clock gating\n"); + break; + } + } + + /* + * Set the coupled flag on the appropriate states if this system + * requires it. + */ + if (coupled_coherence) + for (i = STATE_NC_WAIT; i < cps_driver.state_count; i++) + cps_driver.states[i].flags |= CPUIDLE_FLAG_COUPLED; + + err = cpuidle_register_driver(&cps_driver); + if (err) { + pr_err("Failed to register CPS cpuidle driver\n"); + return err; + } + + for_each_possible_cpu(cpu) { + core = cpu_data[cpu].core; + device = &per_cpu(cpuidle_dev, cpu); + device->cpu = cpu; +#ifdef CONFIG_MIPS_MT + cpumask_copy(&device->coupled_cpus, &cpu_sibling_map[cpu]); +#endif + + err = cpuidle_register_device(device); + if (err) { + pr_err("Failed to register CPU%d cpuidle device\n", + cpu); + goto err_out; + } + } + + return 0; +err_out: + cps_cpuidle_unregister(); + return err; +} +device_initcall(cps_cpuidle_init); -- cgit v0.10.2 From 322014531e1fac4674b8eef67e4f80aca1e9f003 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 15 Apr 2014 12:24:23 +0100 Subject: MIPS: Malta: CPS SMP by default The CONFIG_MIPS_CPS SMP implementation should be able to handle all cases the CONFIG_MIPS_CMP implementation does, but without requiring bootloader assistance. It is also required in order to make use of features such as hotplug & cpuidle core power gating. Enable it by default for Malta configs that previously enabled the now deprecated CONFIG_MIPS_CMP, and disable the latter. The local version suffix "cmp" is removed rather than replaced with "cps" since there are other ways to tell that the CPS SMP implementation is in use (the "VPE topology" line in the boot log being one). Signed-off-by: Paul Burton diff --git a/arch/mips/configs/maltasmvp_defconfig b/arch/mips/configs/maltasmvp_defconfig index 10ef3be..f8a3231 100644 --- a/arch/mips/configs/maltasmvp_defconfig +++ b/arch/mips/configs/maltasmvp_defconfig @@ -4,10 +4,9 @@ CONFIG_CPU_MIPS32_R2=y CONFIG_PAGE_SIZE_16KB=y CONFIG_MIPS_MT_SMP=y CONFIG_SCHED_SMT=y -CONFIG_MIPS_CMP=y +CONFIG_MIPS_CPS=y CONFIG_NR_CPUS=8 CONFIG_HZ_100=y -CONFIG_LOCALVERSION="cmp" CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y diff --git a/arch/mips/configs/maltasmvp_eva_defconfig b/arch/mips/configs/maltasmvp_eva_defconfig index 2d3002c..c83338a 100644 --- a/arch/mips/configs/maltasmvp_eva_defconfig +++ b/arch/mips/configs/maltasmvp_eva_defconfig @@ -5,10 +5,9 @@ CONFIG_CPU_MIPS32_3_5_FEATURES=y CONFIG_PAGE_SIZE_16KB=y CONFIG_MIPS_MT_SMP=y CONFIG_SCHED_SMT=y -CONFIG_MIPS_CMP=y +CONFIG_MIPS_CPS=y CONFIG_NR_CPUS=8 CONFIG_HZ_100=y -CONFIG_LOCALVERSION="cmp" CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_AUDIT=y -- cgit v0.10.2 From d8ce75934b888df0bd73dfd9c030a2b034a04977 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 29 May 2014 11:10:01 +0100 Subject: MIPS: octeon: Add interface mode detection for Octeon II Add interface mode detection for Octeon II. This is necessary to detect the interface modes correctly on the UBNT E200 board. Code is taken from the UBNT GPL source release, with some alterations: SRIO, ILK and RXAUI interface modes are removed and instead return disabled as these modes are not currently supported. Signed-off-by: Alex Smith Tested-by: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/7039/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c index 8553ad5..7e5cf7a 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-helper.c +++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c @@ -106,6 +106,158 @@ int cvmx_helper_ports_on_interface(int interface) EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface); /** + * @INTERNAL + * Return interface mode for CN68xx. + */ +static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface) +{ + union cvmx_mio_qlmx_cfg qlm_cfg; + switch (interface) { + case 0: + qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); + /* QLM is disabled when QLM SPD is 15. */ + if (qlm_cfg.s.qlm_spd == 15) + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + + if (qlm_cfg.s.qlm_cfg == 2) + return CVMX_HELPER_INTERFACE_MODE_SGMII; + else if (qlm_cfg.s.qlm_cfg == 3) + return CVMX_HELPER_INTERFACE_MODE_XAUI; + else + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + case 2: + case 3: + case 4: + qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface)); + /* QLM is disabled when QLM SPD is 15. */ + if (qlm_cfg.s.qlm_spd == 15) + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + + if (qlm_cfg.s.qlm_cfg == 2) + return CVMX_HELPER_INTERFACE_MODE_SGMII; + else if (qlm_cfg.s.qlm_cfg == 3) + return CVMX_HELPER_INTERFACE_MODE_XAUI; + else + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + case 7: + qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3)); + /* QLM is disabled when QLM SPD is 15. */ + if (qlm_cfg.s.qlm_spd == 15) { + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } else if (qlm_cfg.s.qlm_cfg != 0) { + qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); + if (qlm_cfg.s.qlm_cfg != 0) + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } + return CVMX_HELPER_INTERFACE_MODE_NPI; + case 8: + return CVMX_HELPER_INTERFACE_MODE_LOOP; + default: + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } +} + +/** + * @INTERNAL + * Return interface mode for an Octeon II + */ +static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface) +{ + union cvmx_gmxx_inf_mode mode; + + if (OCTEON_IS_MODEL(OCTEON_CN68XX)) + return __cvmx_get_mode_cn68xx(interface); + + if (interface == 2) + return CVMX_HELPER_INTERFACE_MODE_NPI; + + if (interface == 3) + return CVMX_HELPER_INTERFACE_MODE_LOOP; + + /* Only present in CN63XX & CN66XX Octeon model */ + if ((OCTEON_IS_MODEL(OCTEON_CN63XX) && + (interface == 4 || interface == 5)) || + (OCTEON_IS_MODEL(OCTEON_CN66XX) && + interface >= 4 && interface <= 7)) { + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } + + if (OCTEON_IS_MODEL(OCTEON_CN66XX)) { + union cvmx_mio_qlmx_cfg mio_qlm_cfg; + + /* QLM2 is SGMII0 and QLM1 is SGMII1 */ + if (interface == 0) + mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2)); + else if (interface == 1) + mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); + else + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + + if (mio_qlm_cfg.s.qlm_spd == 15) + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + + if (mio_qlm_cfg.s.qlm_cfg == 9) + return CVMX_HELPER_INTERFACE_MODE_SGMII; + else if (mio_qlm_cfg.s.qlm_cfg == 11) + return CVMX_HELPER_INTERFACE_MODE_XAUI; + else + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) { + union cvmx_mio_qlmx_cfg qlm_cfg; + + if (interface == 0) { + qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2)); + if (qlm_cfg.s.qlm_cfg == 2) + return CVMX_HELPER_INTERFACE_MODE_SGMII; + else if (qlm_cfg.s.qlm_cfg == 3) + return CVMX_HELPER_INTERFACE_MODE_XAUI; + else + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } else if (interface == 1) { + qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); + if (qlm_cfg.s.qlm_cfg == 2) + return CVMX_HELPER_INTERFACE_MODE_SGMII; + else if (qlm_cfg.s.qlm_cfg == 3) + return CVMX_HELPER_INTERFACE_MODE_XAUI; + else + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } + } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) { + if (interface == 0) { + union cvmx_mio_qlmx_cfg qlm_cfg; + qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); + if (qlm_cfg.s.qlm_cfg == 2) + return CVMX_HELPER_INTERFACE_MODE_SGMII; + } + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } + + if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX)) + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + + mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); + + if (OCTEON_IS_MODEL(OCTEON_CN63XX)) { + switch (mode.cn63xx.mode) { + case 0: + return CVMX_HELPER_INTERFACE_MODE_SGMII; + case 1: + return CVMX_HELPER_INTERFACE_MODE_XAUI; + default: + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + } + } else { + if (!mode.s.en) + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + + if (mode.s.type) + return CVMX_HELPER_INTERFACE_MODE_GMII; + else + return CVMX_HELPER_INTERFACE_MODE_RGMII; + } +} + +/** * Get the operating mode of an interface. Depending on the Octeon * chip and configuration, this function returns an enumeration * of the type of packet I/O supported by an interface. @@ -118,6 +270,20 @@ EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface); cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) { union cvmx_gmxx_inf_mode mode; + + if (interface < 0 || + interface >= cvmx_helper_get_number_of_interfaces()) + return CVMX_HELPER_INTERFACE_MODE_DISABLED; + + /* + * Octeon II models + */ + if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) + return __cvmx_get_mode_octeon2(interface); + + /* + * Octeon and Octeon Plus models + */ if (interface == 2) return CVMX_HELPER_INTERFACE_MODE_NPI; -- cgit v0.10.2 From 96a8123e5f965825a61a74617b8da1199646d392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Sat, 19 Apr 2014 12:49:46 +0200 Subject: MIPS: BCM47XX: Slightly clean memory detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch was tested on devices with 64 MiB and 256 MiB of RAM. It documents every part nicely and drops this hacky part of code: max = off | ((128 << 20) - 1); Signed-off-by: RafaÅ‚ MiÅ‚ecki Cc: linux-mips@linux-mips.org Cc: Hauke Mehrtens Patchwork: https://patchwork.linux-mips.org/patch/6808/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c index 0af808d..1a03a2f 100644 --- a/arch/mips/bcm47xx/prom.c +++ b/arch/mips/bcm47xx/prom.c @@ -69,15 +69,18 @@ static __init void prom_init_mem(void) * BCM47XX uses 128MB for addressing the ram, if the system contains * less that that amount of ram it remaps the ram more often into the * available space. - * Accessing memory after 128MB will cause an exception. - * max contains the biggest possible address supported by the platform. - * If the method wants to try something above we assume 128MB ram. */ - off = (unsigned long)prom_init; - max = off | ((128 << 20) - 1); - for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) { - if ((off + mem) > max) { - mem = (128 << 20); + + /* Physical address, without mapping to any kernel segment */ + off = CPHYSADDR((unsigned long)prom_init); + + /* Accessing memory after 128 MiB will cause an exception */ + max = 128 << 20; + + for (mem = 1 << 20; mem < max; mem += 1 << 20) { + /* Loop condition may be not enough, off may be over 1 MiB */ + if (off + mem >= max) { + mem = max; printk(KERN_DEBUG "assume 128MB RAM\n"); break; } -- cgit v0.10.2 From c410352699e2a1adc77969f19eb63030e610d048 Mon Sep 17 00:00:00 2001 From: Deng-Cheng Zhu Date: Thu, 29 May 2014 12:26:45 -0700 Subject: MIPS: math-emu: Add IEEE754 exception statistics to debugfs Sometimes it's useful to let the user, while doing performance research, know what in the IEEE754 exceptions has caused many times of FP emulation when running a specific application. This patch adds 5 more files to /sys/kernel/debug/mips/fpuemustats/, whose filenames begin with "ieee754". These stats are in addition to the existing cp1ops, cp1xops, errors, loads and stores, which may not be useful in understanding the reasons of ieee754 exceptions. [ralf@linux-mips.org: Fixed reject due to other changes to the kernel FP assist software.] Signed-off-by: Deng-Cheng Zhu Cc: linux-mips@linux-mips.org Cc: Steven.Hill@imgtec.com Cc: james.hogan@imgtec.com Patchwork: http://patchwork.linux-mips.org/patch/7044/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h index f761719..0195745 100644 --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h @@ -39,6 +39,11 @@ struct mips_fpu_emulator_stats { local_t cp1ops; local_t cp1xops; local_t errors; + local_t ieee754_inexact; + local_t ieee754_underflow; + local_t ieee754_overflow; + local_t ieee754_zerodiv; + local_t ieee754_invalidop; }; DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 08e6a74..cdfed28 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -1234,14 +1234,22 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, SPTOREG(fd, MIPSInst_FD(ir)); copcsr: - if (ieee754_cxtest(IEEE754_INEXACT)) + if (ieee754_cxtest(IEEE754_INEXACT)) { + MIPS_FPU_EMU_INC_STATS(ieee754_inexact); rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; - if (ieee754_cxtest(IEEE754_UNDERFLOW)) + } + if (ieee754_cxtest(IEEE754_UNDERFLOW)) { + MIPS_FPU_EMU_INC_STATS(ieee754_underflow); rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; - if (ieee754_cxtest(IEEE754_OVERFLOW)) + } + if (ieee754_cxtest(IEEE754_OVERFLOW)) { + MIPS_FPU_EMU_INC_STATS(ieee754_overflow); rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; - if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) + } + if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) { + MIPS_FPU_EMU_INC_STATS(ieee754_invalidop); rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; + } ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr; if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { @@ -1468,16 +1476,26 @@ scopuop: rv.s = (*handler.u) (fs); goto copcsr; copcsr: - if (ieee754_cxtest(IEEE754_INEXACT)) + if (ieee754_cxtest(IEEE754_INEXACT)) { + MIPS_FPU_EMU_INC_STATS(ieee754_inexact); rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; - if (ieee754_cxtest(IEEE754_UNDERFLOW)) + } + if (ieee754_cxtest(IEEE754_UNDERFLOW)) { + MIPS_FPU_EMU_INC_STATS(ieee754_underflow); rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; - if (ieee754_cxtest(IEEE754_OVERFLOW)) + } + if (ieee754_cxtest(IEEE754_OVERFLOW)) { + MIPS_FPU_EMU_INC_STATS(ieee754_overflow); rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; - if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) + } + if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) { + MIPS_FPU_EMU_INC_STATS(ieee754_zerodiv); rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; - if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) + } + if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) { + MIPS_FPU_EMU_INC_STATS(ieee754_invalidop); rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; + } break; /* unary conv ops */ diff --git a/arch/mips/math-emu/me-debugfs.c b/arch/mips/math-emu/me-debugfs.c index 95ed9f9..becdd63 100644 --- a/arch/mips/math-emu/me-debugfs.c +++ b/arch/mips/math-emu/me-debugfs.c @@ -56,6 +56,11 @@ do { \ FPU_STAT_CREATE(cp1ops); FPU_STAT_CREATE(cp1xops); FPU_STAT_CREATE(errors); + FPU_STAT_CREATE(ieee754_inexact); + FPU_STAT_CREATE(ieee754_underflow); + FPU_STAT_CREATE(ieee754_overflow); + FPU_STAT_CREATE(ieee754_zerodiv); + FPU_STAT_CREATE(ieee754_invalidop); return 0; } -- cgit v0.10.2 From beef8e020d43c31a8741d3fb4781914ad1f4e420 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:02 +0100 Subject: MIPS: uasm: Add u3u2u1 instruction builders It will be used later on by the sllv and srlv instructions. Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6723/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 3d80387..fd9e50a 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -55,6 +55,9 @@ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) #define Ip_u2u1u3(op) \ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) +#define Ip_u3u2u1(op) \ +void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) + #define Ip_u3u1u2(op) \ void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c) diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 55a1fdf..0969a52 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -144,6 +144,13 @@ Ip_u2u1u3(op) \ } \ UASM_EXPORT_SYMBOL(uasm_i##op); +#define I_u3u2u1(op) \ +Ip_u3u2u1(op) \ +{ \ + build_insn(buf, insn##op, c, b, a); \ +} \ +UASM_EXPORT_SYMBOL(uasm_i##op); + #define I_u3u1u2(op) \ Ip_u3u1u2(op) \ { \ -- cgit v0.10.2 -- cgit v0.10.2 From bef581ba1c240cda9c550d314ca70c2b8deb6e87 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:04 +0100 Subject: MIPS: uasm: Add sllv uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Fixed conflict with 49e9529b9d43773307b8c73bd251b71784830c3d [MIPS: uasm: add jalr instruction]. Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6725/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index fd9e50a..3001b18 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -140,6 +140,7 @@ Ip_u2s3u1(_sc); Ip_u2s3u1(_scd); Ip_u2s3u1(_sd); Ip_u2u1u3(_sll); +Ip_u3u2u1(_sllv); Ip_u2u1u3(_sra); Ip_u2u1u3(_srl); Ip_u3u1u2(_subu); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index a1ad551..217d696 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -248,6 +248,7 @@ enum mm_32i_minor_op { enum mm_32a_minor_op { mm_sll32_op = 0x000, mm_ins_op = 0x00c, + mm_sllv32_op = 0x010, mm_ext_op = 0x02c, mm_pool32axf_op = 0x03c, mm_srl32_op = 0x040, diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index bcbcf4a..e0a8df0 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -94,6 +94,7 @@ static struct insn insn_table_MM[] = { { insn_scd, 0, 0 }, { insn_sd, 0, 0 }, { insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD }, + { insn_sllv, M(mm_pool32a_op, 0, 0, 0, 0, mm_sllv32_op), RT | RS | RD }, { insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD }, { insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD }, { insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 4a2fc82..086c590 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -103,6 +103,7 @@ static struct insn insn_table[] = { { insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, + { insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD }, { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 0969a52..9372d82 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -52,9 +52,9 @@ enum opcode { insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, - insn_scd, insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw, - insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, - insn_wait, insn_xor, insn_xori, insn_yield, + insn_scd, insn_sd, insn_sll, insn_sllv, insn_sra, insn_srl, insn_subu, + insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, + insn_tlbwr, insn_wait, insn_xor, insn_xori, insn_yield, }; struct insn { @@ -280,6 +280,7 @@ I_u2s3u1(_sc) I_u2s3u1(_scd) I_u2s3u1(_sd) I_u2u1u3(_sll) +I_u3u2u1(_sllv) I_u2u1u3(_sra) I_u2u1u3(_srl) I_u2u1u3(_rotr) -- cgit v0.10.2 From f31318fdf324901ce5a17ccc3d71213117fb44af Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:05 +0100 Subject: MIPS: uasm: Add srlv uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Fixed conflict due to other preceeding conflicts.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6726/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 3001b18..f1315ce 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -143,6 +143,7 @@ Ip_u2u1u3(_sll); Ip_u3u2u1(_sllv); Ip_u2u1u3(_sra); Ip_u2u1u3(_srl); +Ip_u3u2u1(_srlv); Ip_u3u1u2(_subu); Ip_u2s3u1(_sw); Ip_u1(_sync); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 217d696..abcdebe 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -253,6 +253,7 @@ enum mm_32a_minor_op { mm_pool32axf_op = 0x03c, mm_srl32_op = 0x040, mm_sra_op = 0x080, + mm_srlv32_op = 0x090, mm_rotr_op = 0x0c0, mm_lwxs_op = 0x118, mm_addu32_op = 0x150, diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index e0a8df0..b234800 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -97,6 +97,7 @@ static struct insn insn_table_MM[] = { { insn_sllv, M(mm_pool32a_op, 0, 0, 0, 0, mm_sllv32_op), RT | RS | RD }, { insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD }, { insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD }, + { insn_srlv, M(mm_pool32a_op, 0, 0, 0, 0, mm_srlv32_op), RT | RS | RD }, { insn_rotr, M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD }, { insn_subu, M(mm_pool32a_op, 0, 0, 0, 0, mm_subu32_op), RT | RS | RD }, { insn_sw, M(mm_sw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 086c590..3d68c00 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -106,6 +106,7 @@ static struct insn insn_table[] = { { insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD }, { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, + { insn_srlv, M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD }, { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sync, M(spec_op, 0, 0, 0, 0, sync_op), RE }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 9372d82..567003c 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -52,9 +52,9 @@ enum opcode { insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, - insn_scd, insn_sd, insn_sll, insn_sllv, insn_sra, insn_srl, insn_subu, - insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, - insn_tlbwr, insn_wait, insn_xor, insn_xori, insn_yield, + insn_scd, insn_sd, insn_sll, insn_sllv, insn_sra, insn_srl, insn_srlv, + insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, + insn_tlbwi, insn_tlbwr, insn_wait, insn_xor, insn_xori, insn_yield, }; struct insn { @@ -283,6 +283,7 @@ I_u2u1u3(_sll) I_u3u2u1(_sllv) I_u2u1u3(_sra) I_u2u1u3(_srl) +I_u3u2u1(_srlv) I_u2u1u3(_rotr) I_u3u1u2(_subu) I_u2s3u1(_sw) -- cgit v0.10.2 From 4c12a854d81db5454436c015ec30f39882e923a4 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:06 +0100 Subject: MIPS: uasm: Add divu uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6727/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index f1315ce..676c123 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -105,6 +105,7 @@ Ip_u2u1s3(_daddiu); Ip_u3u1u2(_daddu); Ip_u2u1msbu3(_dins); Ip_u2u1msbu3(_dinsm); +Ip_u1u2(_divu); Ip_u1u2u3(_dmfc0); Ip_u1u2u3(_dmtc0); Ip_u2u1u3(_drotr); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index abcdebe..a4bef36 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -311,6 +311,7 @@ enum mm_32axf_minor_op { mm_syscall_op = 0x22d, mm_wait_op = 0x24d, mm_eret_op = 0x3cd, + mm_divu_op = 0x5dc, }; /* diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index b234800..aefe744 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -63,6 +63,7 @@ static struct insn insn_table_MM[] = { { insn_cache, M(mm_pool32b_op, 0, 0, mm_cache_func, 0, 0), RT | RS | SIMM }, { insn_daddu, 0, 0 }, { insn_daddiu, 0, 0 }, + { insn_divu, M(mm_pool32a_op, 0, 0, 0, mm_divu_op, mm_pool32axf_op), RT | RS }, { insn_dmfc0, 0, 0 }, { insn_dmtc0, 0, 0 }, { insn_dsll, 0, 0 }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 3d68c00..6f51543 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -67,6 +67,7 @@ static struct insn insn_table[] = { { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD }, { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE }, { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, + { insn_divu, M(spec_op, 0, 0, 0, 0, divu_op), RS | RT }, { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 567003c..31873cd 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -47,7 +47,7 @@ enum opcode { insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1, insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, - insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, + insn_divu, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, @@ -251,6 +251,7 @@ I_u1u2u3(_dmfc0) I_u1u2u3(_dmtc0) I_u2u1s3(_daddiu) I_u3u1u2(_daddu) +I_u1u2(_divu) I_u2u1u3(_dsll) I_u2u1u3(_dsll32) I_u2u1u3(_dsra) -- cgit v0.10.2 From f3ec7a23b640a064410e31afe9a203f7c125460e Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:07 +0100 Subject: MIPS: uasm: Add mfhi uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Cc: Markos Chandras Patchwork: http://patchwork.linux-mips.org/patch/6728/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 676c123..38312d8 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -131,6 +131,7 @@ Ip_u1s2(_lui); Ip_u2s3u1(_lw); Ip_u3u1u2(_lwx); Ip_u1u2u3(_mfc0); +Ip_u1(_mfhi); Ip_u1u2u3(_mtc0); Ip_u3u1u2(_or); Ip_u2u1u3(_ori); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index a4bef36..a7f6a16 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -300,6 +300,7 @@ enum mm_32axf_minor_op { mm_mfc0_op = 0x003, mm_mtc0_op = 0x00b, mm_tlbp_op = 0x00d, + mm_mfhi32_op = 0x035, mm_jalr_op = 0x03c, mm_tlbr_op = 0x04d, mm_jalrhb_op = 0x07c, diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index aefe744..c04c9c9 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -86,6 +86,7 @@ static struct insn insn_table_MM[] = { { insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM }, { insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, { insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD }, + { insn_mfhi, M(mm_pool32a_op, 0, 0, 0, mm_mfhi32_op, mm_pool32axf_op), RS }, { insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD }, { insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD }, { insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 6f51543..0718492 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -94,6 +94,7 @@ static struct insn insn_table[] = { { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, + { insn_mfhi, M(spec_op, 0, 0, 0, 0, mfhi_op), RD }, { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 31873cd..29fc432 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -51,10 +51,11 @@ enum opcode { insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, - insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, - insn_scd, insn_sd, insn_sll, insn_sllv, insn_sra, insn_srl, insn_srlv, - insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, - insn_tlbwi, insn_tlbwr, insn_wait, insn_xor, insn_xori, insn_yield, + insn_mfhi, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, + insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sra, + insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, + insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_xor, + insn_xori, insn_yield, }; struct insn { @@ -273,6 +274,7 @@ I_u2s3u1(_lld) I_u1s2(_lui) I_u2s3u1(_lw) I_u1u2u3(_mfc0) +I_u1(_mfhi) I_u1u2u3(_mtc0) I_u2u1u3(_ori) I_u3u1u2(_or) -- cgit v0.10.2 From 7fa22681c4d6e12cc6aed91056d3e09d47572e6d Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:08 +0100 Subject: MIPS: uasm: Add jalr uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6729/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index c04c9c9..6128cf3 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -79,6 +79,7 @@ static struct insn insn_table_MM[] = { { insn_ext, M(mm_pool32a_op, 0, 0, 0, 0, mm_ext_op), RT | RS | RD | RE }, { insn_j, M(mm_j32_op, 0, 0, 0, 0, 0), JIMM }, { insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM }, + { insn_jalr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RT | RS }, { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS }, { insn_ld, 0, 0 }, { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM }, -- cgit v0.10.2 From 390363ed77c05f4971254bebc96554afb79dd453 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:09 +0100 Subject: MIPS: uasm: Add sltiu uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6730/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 38312d8..abf0845 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -143,6 +143,7 @@ Ip_u2s3u1(_scd); Ip_u2s3u1(_sd); Ip_u2u1u3(_sll); Ip_u3u2u1(_sllv); +Ip_u2u1s3(_sltiu); Ip_u2u1u3(_sra); Ip_u2u1u3(_srl); Ip_u3u2u1(_srlv); diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 6128cf3..e81649a 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -98,6 +98,7 @@ static struct insn insn_table_MM[] = { { insn_sd, 0, 0 }, { insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD }, { insn_sllv, M(mm_pool32a_op, 0, 0, 0, 0, mm_sllv32_op), RT | RS | RD }, + { insn_sltiu, M(mm_sltiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, { insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD }, { insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD }, { insn_srlv, M(mm_pool32a_op, 0, 0, 0, 0, mm_srlv32_op), RT | RS | RD }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 0718492..8231d7d 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -106,6 +106,7 @@ static struct insn insn_table[] = { { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, { insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD }, + { insn_sltiu, M(sltiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, { insn_srlv, M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 29fc432..3a3d8a2 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -52,10 +52,10 @@ enum opcode { insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mfhi, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, - insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sra, - insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, - insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_xor, - insn_xori, insn_yield, + insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sltiu, + insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, + insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, + insn_xor, insn_xori, insn_yield, }; struct insn { @@ -284,6 +284,7 @@ I_u2s3u1(_scd) I_u2s3u1(_sd) I_u2u1u3(_sll) I_u3u2u1(_sllv) +I_u2u1s3(_sltiu) I_u2u1u3(_sra) I_u2u1u3(_srl) I_u3u2u1(_srlv) -- cgit v0.10.2 From e8ef868b470984064c23ce4bf2cd4c0167e1fbe5 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:10 +0100 Subject: MIPS: uasm: Add sltu uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6731/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index abf0845..090f750 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -144,6 +144,7 @@ Ip_u2s3u1(_sd); Ip_u2u1u3(_sll); Ip_u3u2u1(_sllv); Ip_u2u1s3(_sltiu); +Ip_u3u1u2(_sltu); Ip_u2u1u3(_sra); Ip_u2u1u3(_srl); Ip_u3u2u1(_srlv); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index a7f6a16..c78d235 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -261,6 +261,7 @@ enum mm_32a_minor_op { mm_and_op = 0x250, mm_or32_op = 0x290, mm_xor32_op = 0x310, + mm_sltu_op = 0x390, }; /* diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index e81649a..260ca1b 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -99,6 +99,7 @@ static struct insn insn_table_MM[] = { { insn_sll, M(mm_pool32a_op, 0, 0, 0, 0, mm_sll32_op), RT | RS | RD }, { insn_sllv, M(mm_pool32a_op, 0, 0, 0, 0, mm_sllv32_op), RT | RS | RD }, { insn_sltiu, M(mm_sltiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, + { insn_sltu, M(mm_pool32a_op, 0, 0, 0, 0, mm_sltu_op), RT | RS | RD }, { insn_sra, M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD }, { insn_srl, M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD }, { insn_srlv, M(mm_pool32a_op, 0, 0, 0, 0, mm_srlv32_op), RT | RS | RD }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 8231d7d..ad1701c 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -107,6 +107,7 @@ static struct insn insn_table[] = { { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, { insn_sllv, M(spec_op, 0, 0, 0, 0, sllv_op), RS | RT | RD }, { insn_sltiu, M(sltiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, + { insn_sltu, M(spec_op, 0, 0, 0, 0, sltu_op), RS | RT | RD }, { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, { insn_srlv, M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 3a3d8a2..e0738fa 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -53,7 +53,7 @@ enum opcode { insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mfhi, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sltiu, - insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, + insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_xor, insn_xori, insn_yield, }; @@ -285,6 +285,7 @@ I_u2s3u1(_sd) I_u2u1u3(_sll) I_u3u2u1(_sllv) I_u2u1s3(_sltiu) +I_u3u1u2(_sltu) I_u2u1u3(_sra) I_u2u1u3(_srl) I_u3u2u1(_srlv) -- cgit v0.10.2 From ab9e4fa092db6c4beea8fde67261959520675456 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:11 +0100 Subject: MIPS: uasm: Add wsbh uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6732/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 090f750..d754ddc 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -157,6 +157,7 @@ Ip_0(_tlbr); Ip_0(_tlbwi); Ip_0(_tlbwr); Ip_u1(_wait); +Ip_u2u1(_wsbh); Ip_u3u1u2(_xor); Ip_u2u1u3(_xori); Ip_u2u1(_yield); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index c78d235..aa37373 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -206,6 +206,16 @@ enum lx_func { }; /* + * BSHFL opcodes + */ +enum bshfl_func { + wsbh_op = 0x2, + dshd_op = 0x5, + seb_op = 0x10, + seh_op = 0x18, +}; + +/* * (microMIPS) Major opcodes. */ enum mm_major_op { @@ -258,6 +268,7 @@ enum mm_32a_minor_op { mm_lwxs_op = 0x118, mm_addu32_op = 0x150, mm_subu32_op = 0x1d0, + mm_wsbh_op = 0x1ec, mm_and_op = 0x250, mm_or32_op = 0x290, mm_xor32_op = 0x310, diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 260ca1b..071a4c1 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -112,6 +112,7 @@ static struct insn insn_table_MM[] = { { insn_tlbwi, M(mm_pool32a_op, 0, 0, 0, mm_tlbwi_op, mm_pool32axf_op), 0 }, { insn_tlbwr, M(mm_pool32a_op, 0, 0, 0, mm_tlbwr_op, mm_pool32axf_op), 0 }, { insn_wait, M(mm_pool32a_op, 0, 0, 0, mm_wait_op, mm_pool32axf_op), SCIMM }, + { insn_wsbh, M(mm_pool32a_op, 0, 0, 0, mm_wsbh_op, mm_pool32axf_op), RT | RS }, { insn_xor, M(mm_pool32a_op, 0, 0, 0, 0, mm_xor32_op), RT | RS | RD }, { insn_xori, M(mm_xori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, { insn_dins, 0, 0 }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index ad1701c..c50d3b4 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -120,6 +120,7 @@ static struct insn insn_table[] = { { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 }, { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, { insn_wait, M(cop0_op, cop_op, 0, 0, 0, wait_op), SCIMM }, + { insn_wsbh, M(spec3_op, 0, 0, 0, wsbh_op, bshfl_op), RT | RD }, { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, { insn_yield, M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index e0738fa..678e41a 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -55,7 +55,7 @@ enum opcode { insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, - insn_xor, insn_xori, insn_yield, + insn_wsbh, insn_xor, insn_xori, insn_yield, }; struct insn { @@ -298,6 +298,7 @@ I_0(_tlbr) I_0(_tlbwi) I_0(_tlbwr) I_u1(_wait); +I_u2u1(_wsbh) I_u3u1u2(_xor) I_u2u1u3(_xori) I_u2u1(_yield) -- cgit v0.10.2 From d6b3314b49e12e8c349deb4ca28e7028db00728f Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:12 +0100 Subject: MIPS: uasm: Add lh uam instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6733/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index d754ddc..a096581 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -125,6 +125,7 @@ Ip_u2u1(_jalr); Ip_u1(_jr); Ip_u2s3u1(_ld); Ip_u3u1u2(_ldx); +Ip_u2s3u1(_lh); Ip_u2s3u1(_ll); Ip_u2s3u1(_lld); Ip_u1s2(_lui); diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 071a4c1..99d63d9 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -82,6 +82,7 @@ static struct insn insn_table_MM[] = { { insn_jalr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RT | RS }, { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS }, { insn_ld, 0, 0 }, + { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RS | RS | SIMM }, { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM }, { insn_lld, 0, 0 }, { insn_lui, M(mm_pool32i_op, mm_lui_op, 0, 0, 0, 0), RS | SIMM }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index c50d3b4..cb75d45 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -88,6 +88,7 @@ static struct insn insn_table[] = { { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, + { insn_lh, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 678e41a..6ffb601 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -50,12 +50,12 @@ enum opcode { insn_divu, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, - insn_ldx, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, - insn_mfhi, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, - insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sltiu, - insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, - insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, - insn_wsbh, insn_xor, insn_xori, insn_yield, + insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, + insn_mfc0, insn_mfhi, insn_mtc0, insn_or, insn_ori, insn_pref, + insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, + insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, + insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, + insn_tlbwr, insn_wait, insn_wsbh, insn_xor, insn_xori, insn_yield, }; struct insn { @@ -269,6 +269,7 @@ I_u1(_jal) I_u2u1(_jalr) I_u1(_jr) I_u2s3u1(_ld) +I_u2s3u1(_lh) I_u2s3u1(_ll) I_u2s3u1(_lld) I_u1s2(_lui) -- cgit v0.10.2 From a8e897ad00d3cfd0ab9029978f0c3f8ecd6fba61 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:13 +0100 Subject: MIPS: uasm: Add mul uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6736/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index a096581..95954ba 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -134,6 +134,7 @@ Ip_u3u1u2(_lwx); Ip_u1u2u3(_mfc0); Ip_u1(_mfhi); Ip_u1u2u3(_mtc0); +Ip_u3u1u2(_mul); Ip_u3u1u2(_or); Ip_u2u1u3(_ori); Ip_u2s3u1(_pref); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index aa37373..6793383 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -269,6 +269,7 @@ enum mm_32a_minor_op { mm_addu32_op = 0x150, mm_subu32_op = 0x1d0, mm_wsbh_op = 0x1ec, + mm_mul_op = 0x210, mm_and_op = 0x250, mm_or32_op = 0x290, mm_xor32_op = 0x310, diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 99d63d9..9d42f10 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -90,6 +90,7 @@ static struct insn insn_table_MM[] = { { insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD }, { insn_mfhi, M(mm_pool32a_op, 0, 0, 0, mm_mfhi32_op, mm_pool32axf_op), RS }, { insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD }, + { insn_mul, M(mm_pool32a_op, 0, 0, 0, 0, mm_mul_op), RT | RS | RD }, { insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD }, { insn_ori, M(mm_ori32_op, 0, 0, 0, 0, 0), RT | RS | UIMM }, { insn_pref, M(mm_pool32c_op, 0, 0, (mm_pref_func << 1), 0, 0), RT | RS | SIMM }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index cb75d45..9dd1516 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -97,6 +97,7 @@ static struct insn insn_table[] = { { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mfhi, M(spec_op, 0, 0, 0, 0, mfhi_op), RD }, { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, + { insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD}, { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD }, { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 6ffb601..1c8bed3 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -51,7 +51,7 @@ enum opcode { insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, - insn_mfc0, insn_mfhi, insn_mtc0, insn_or, insn_ori, insn_pref, + insn_mfc0, insn_mfhi, insn_mtc0, insn_mul, insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, @@ -277,6 +277,7 @@ I_u2s3u1(_lw) I_u1u2u3(_mfc0) I_u1(_mfhi) I_u1u2u3(_mtc0) +I_u3u1u2(_mul) I_u2u1u3(_ori) I_u3u1u2(_or) I_0(_rfe) -- cgit v0.10.2 From 16d21a812f6bfcbfa84ccc19d38abe797c71b73e Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Mon, 14 Apr 2014 15:42:31 +0100 Subject: MIPS: uasm: Add mflo uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 95954ba..719a884 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -133,6 +133,7 @@ Ip_u2s3u1(_lw); Ip_u3u1u2(_lwx); Ip_u1u2u3(_mfc0); Ip_u1(_mfhi); +Ip_u1(_mflo); Ip_u1u2u3(_mtc0); Ip_u3u1u2(_mul); Ip_u3u1u2(_or); diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 6793383..4b71602 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h @@ -316,6 +316,7 @@ enum mm_32axf_minor_op { mm_mfhi32_op = 0x035, mm_jalr_op = 0x03c, mm_tlbr_op = 0x04d, + mm_mflo32_op = 0x075, mm_jalrhb_op = 0x07c, mm_tlbwi_op = 0x08d, mm_tlbwr_op = 0x0cd, diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 9d42f10..1c390a1 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -89,6 +89,7 @@ static struct insn insn_table_MM[] = { { insn_lw, M(mm_lw32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, { insn_mfc0, M(mm_pool32a_op, 0, 0, 0, mm_mfc0_op, mm_pool32axf_op), RT | RS | RD }, { insn_mfhi, M(mm_pool32a_op, 0, 0, 0, mm_mfhi32_op, mm_pool32axf_op), RS }, + { insn_mflo, M(mm_pool32a_op, 0, 0, 0, mm_mflo32_op, mm_pool32axf_op), RS }, { insn_mtc0, M(mm_pool32a_op, 0, 0, 0, mm_mtc0_op, mm_pool32axf_op), RT | RS | RD }, { insn_mul, M(mm_pool32a_op, 0, 0, 0, 0, mm_mul_op), RT | RS | RD }, { insn_or, M(mm_pool32a_op, 0, 0, 0, 0, mm_or32_op), RT | RS | RD }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 9dd1516..4f9114b 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -96,6 +96,7 @@ static struct insn insn_table[] = { { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD }, { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mfhi, M(spec_op, 0, 0, 0, 0, mfhi_op), RD }, + { insn_mflo, M(spec_op, 0, 0, 0, 0, mflo_op), RD }, { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mul, M(spec2_op, 0, 0, 0, 0, mul_op), RS | RT | RD}, { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 1c8bed3..8cf1fb21c 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -51,11 +51,12 @@ enum opcode { insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, - insn_mfc0, insn_mfhi, insn_mtc0, insn_mul, insn_or, insn_ori, insn_pref, - insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, insn_sllv, - insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu, - insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, - insn_tlbwr, insn_wait, insn_wsbh, insn_xor, insn_xori, insn_yield, + insn_mfc0, insn_mfhi, insn_mflo, insn_mtc0, insn_mul, insn_or, + insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, + insn_sll, insn_sllv, insn_sltiu, insn_sltu, insn_sra, insn_srl, + insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, + insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, insn_xor, + insn_xori, insn_yield, }; struct insn { @@ -276,6 +277,7 @@ I_u1s2(_lui) I_u2s3u1(_lw) I_u1u2u3(_mfc0) I_u1(_mfhi) +I_u1(_mflo) I_u1u2u3(_mtc0) I_u3u1u2(_mul) I_u2u1u3(_ori) -- cgit v0.10.2 From 8248881835da58fa075299926c2994d12b56895b Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 16 Apr 2014 13:49:57 +0100 Subject: MIPS: uasm: Add lb uasm instruction It will be used later on by bpf-jit [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 719a884..f8d63b3 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -123,6 +123,7 @@ Ip_u1(_j); Ip_u1(_jal); Ip_u2u1(_jalr); Ip_u1(_jr); +Ip_u2s3u1(_lb); Ip_u2s3u1(_ld); Ip_u3u1u2(_ldx); Ip_u2s3u1(_lh); diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 1c390a1..775c280 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c @@ -81,6 +81,7 @@ static struct insn insn_table_MM[] = { { insn_jal, M(mm_jal32_op, 0, 0, 0, 0, 0), JIMM }, { insn_jalr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RT | RS }, { insn_jr, M(mm_pool32a_op, 0, 0, 0, mm_jalr_op, mm_pool32axf_op), RS }, + { insn_lb, M(mm_lb32_op, 0, 0, 0, 0, 0), RT | RS | SIMM }, { insn_ld, 0, 0 }, { insn_lh, M(mm_lh32_op, 0, 0, 0, 0, 0), RS | RS | SIMM }, { insn_ll, M(mm_pool32c_op, 0, 0, (mm_ll_func << 1), 0, 0), RS | RT | SIMM }, diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 4f9114b..38792c2 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c @@ -86,6 +86,7 @@ static struct insn insn_table[] = { { insn_jalr, M(spec_op, 0, 0, 0, 0, jalr_op), RS | RD }, { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, + { insn_lb, M(lb_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD }, { insn_lh, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 8cf1fb21c..0051580 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c @@ -49,14 +49,14 @@ enum opcode { insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, insn_divu, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, - insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_ld, - insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, - insn_mfc0, insn_mfhi, insn_mflo, insn_mtc0, insn_mul, insn_or, - insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, - insn_sll, insn_sllv, insn_sltiu, insn_sltu, insn_sra, insn_srl, - insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, - insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, insn_xor, - insn_xori, insn_yield, + insn_ext, insn_ins, insn_j, insn_jal, insn_jalr, insn_jr, insn_lb, + insn_ld, insn_ldx, insn_lh, insn_ll, insn_lld, insn_lui, insn_lw, + insn_lwx, insn_mfc0, insn_mfhi, insn_mflo, insn_mtc0, insn_mul, + insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, + insn_sd, insn_sll, insn_sllv, insn_sltiu, insn_sltu, insn_sra, + insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, + insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, + insn_xor, insn_xori, insn_yield, }; struct insn { @@ -269,6 +269,7 @@ I_u1(_j) I_u1(_jal) I_u2u1(_jalr) I_u1(_jr) +I_u2s3u1(_lb) I_u2s3u1(_ld) I_u2s3u1(_lh) I_u2s3u1(_ll) -- cgit v0.10.2 From c6610de353da5ca6eee5b8960e838a87a90ead0c Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Tue, 8 Apr 2014 12:47:14 +0100 Subject: MIPS: net: Add BPF JIT This adds initial support for BPF-JIT on MIPS Tested on mips32 LE/BE and mips64 BE/n64 using dhcp, ping and various tcpdump filters. Benchmarking: Assuming the remote MIPS target uses 192.168.154.181 as its IP address, and the local host uses 192.168.154.136, the following results can be obtained using the following tcpdump filter (catches no frames) and a simple 'time ping -f -c 1000000' command. [root@(none) ~]# tcpdump -p -n -s 0 -i eth0 net 10.0.0.0/24 -d (000) ldh [12] (001) jeq #0x800 jt 2 jf 8 (002) ld [26] (003) and #0xffffff00 (004) jeq #0xa000000 jt 16 jf 5 (005) ld [30] (006) and #0xffffff00 (007) jeq #0xa000000 jt 16 jf 17 (008) jeq #0x806 jt 10 jf 9 (009) jeq #0x8035 jt 10 jf 17 (010) ld [28] (011) and #0xffffff00 (012) jeq #0xa000000 jt 16 jf 13 (013) ld [38] (014) and #0xffffff00 (015) jeq #0xa000000 jt 16 jf 17 (016) ret #65535 - BPF-JIT Disabled real 1m38.005s user 0m1.510s sys 0m6.710s - BPF-JIT Enabled real 1m35.215s user 0m1.200s sys 0m4.140s [ralf@linux-mips.org: Resolved conflict.] Signed-off-by: Markos Chandras diff --git a/arch/mips/Kbuild b/arch/mips/Kbuild index cc39966..dd29533 100644 --- a/arch/mips/Kbuild +++ b/arch/mips/Kbuild @@ -16,6 +16,7 @@ obj- := $(platform-) obj-y += kernel/ obj-y += mm/ +obj-y += net/ ifdef CONFIG_KVM obj-y += kvm/ diff --git a/arch/mips/net/Makefile b/arch/mips/net/Makefile new file mode 100644 index 0000000..ae74b3a --- /dev/null +++ b/arch/mips/net/Makefile @@ -0,0 +1,3 @@ +# MIPS networking code + +obj-$(CONFIG_BPF_JIT) += bpf_jit.o diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c new file mode 100644 index 0000000..98e9d23 --- /dev/null +++ b/arch/mips/net/bpf_jit.c @@ -0,0 +1,1399 @@ +/* + * Just-In-Time compiler for BPF filters on MIPS + * + * Copyright (c) 2014 Imagination Technologies Ltd. + * Author: Markos Chandras + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bpf_jit.h" + +/* ABI + * + * s0 1st scratch register + * s1 2nd scratch register + * s2 offset register + * s3 BPF register A + * s4 BPF register X + * s5 *skb + * s6 *scratch memory + * + * On entry (*bpf_func)(*skb, *filter) + * a0 = MIPS_R_A0 = skb; + * a1 = MIPS_R_A1 = filter; + * + * Stack + * ... + * M[15] + * M[14] + * M[13] + * ... + * M[0] <-- r_M + * saved reg k-1 + * saved reg k-2 + * ... + * saved reg 0 <-- r_sp + * + * + * Packet layout + * + * <--------------------- len ------------------------> + * <--skb-len(r_skb_hl)-->< ----- skb->data_len ------> + * ---------------------------------------------------- + * | skb->data | + * ---------------------------------------------------- + */ + +#define RSIZE (sizeof(unsigned long)) +#define ptr typeof(unsigned long) + +/* ABI specific return values */ +#ifdef CONFIG_32BIT /* O32 */ +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define r_err MIPS_R_V1 +#define r_val MIPS_R_V0 +#else /* CONFIG_CPU_LITTLE_ENDIAN */ +#define r_err MIPS_R_V0 +#define r_val MIPS_R_V1 +#endif +#else /* N64 */ +#define r_err MIPS_R_V0 +#define r_val MIPS_R_V0 +#endif + +#define r_ret MIPS_R_V0 + +/* + * Use 2 scratch registers to avoid pipeline interlocks. + * There is no overhead during epilogue and prologue since + * any of the $s0-$s6 registers will only be preserved if + * they are going to actually be used. + */ +#define r_s0 MIPS_R_S0 /* scratch reg 1 */ +#define r_s1 MIPS_R_S1 /* scratch reg 2 */ +#define r_off MIPS_R_S2 +#define r_A MIPS_R_S3 +#define r_X MIPS_R_S4 +#define r_skb MIPS_R_S5 +#define r_M MIPS_R_S6 +#define r_tmp_imm MIPS_R_T6 /* No need to preserve this */ +#define r_tmp MIPS_R_T7 /* No need to preserve this */ +#define r_zero MIPS_R_ZERO +#define r_sp MIPS_R_SP +#define r_ra MIPS_R_RA + +#define SCRATCH_OFF(k) (4 * (k)) + +/* JIT flags */ +#define SEEN_CALL (1 << BPF_MEMWORDS) +#define SEEN_SREG_SFT (BPF_MEMWORDS + 1) +#define SEEN_SREG_BASE (1 << SEEN_SREG_SFT) +#define SEEN_SREG(x) (SEEN_SREG_BASE << (x)) +#define SEEN_S0 SEEN_SREG(0) +#define SEEN_S1 SEEN_SREG(1) +#define SEEN_OFF SEEN_SREG(2) +#define SEEN_A SEEN_SREG(3) +#define SEEN_X SEEN_SREG(4) +#define SEEN_SKB SEEN_SREG(5) +#define SEEN_MEM SEEN_SREG(6) + +/* Arguments used by JIT */ +#define ARGS_USED_BY_JIT 2 /* only applicable to 64-bit */ + +#define FLAG_NEED_X_RESET (1 << 0) + +#define SBIT(x) (1 << (x)) /* Signed version of BIT() */ + +/** + * struct jit_ctx - JIT context + * @skf: The sk_filter + * @prologue_bytes: Number of bytes for prologue + * @idx: Instruction index + * @flags: JIT flags + * @offsets: Instruction offsets + * @target: Memory location for the compiled filter + */ +struct jit_ctx { + const struct sk_filter *skf; + unsigned int prologue_bytes; + u32 idx; + u32 flags; + u32 *offsets; + u32 *target; +}; + + +static inline int optimize_div(u32 *k) +{ + /* power of 2 divides can be implemented with right shift */ + if (!(*k & (*k-1))) { + *k = ilog2(*k); + return 1; + } + + return 0; +} + +/* Simply emit the instruction if the JIT memory space has been allocated */ +#define emit_instr(ctx, func, ...) \ +do { \ + if ((ctx)->target != NULL) { \ + u32 *p = &(ctx)->target[ctx->idx]; \ + uasm_i_##func(&p, ##__VA_ARGS__); \ + } \ + (ctx)->idx++; \ +} while (0) + +/* Determine if immediate is within the 16-bit signed range */ +static inline bool is_range16(s32 imm) +{ + if (imm >= SBIT(15) || imm < -SBIT(15)) + return true; + return false; +} + +static inline void emit_addu(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, addu, dst, src1, src2); +} + +static inline void emit_nop(struct jit_ctx *ctx) +{ + emit_instr(ctx, nop); +} + +/* Load a u32 immediate to a register */ +static inline void emit_load_imm(unsigned int dst, u32 imm, struct jit_ctx *ctx) +{ + if (ctx->target != NULL) { + /* addiu can only handle s16 */ + if (is_range16(imm)) { + u32 *p = &ctx->target[ctx->idx]; + uasm_i_lui(&p, r_tmp_imm, (s32)imm >> 16); + p = &ctx->target[ctx->idx + 1]; + uasm_i_ori(&p, dst, r_tmp_imm, imm & 0xffff); + } else { + u32 *p = &ctx->target[ctx->idx]; + uasm_i_addiu(&p, dst, r_zero, imm); + } + } + ctx->idx++; + + if (is_range16(imm)) + ctx->idx++; +} + +static inline void emit_or(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, or, dst, src1, src2); +} + +static inline void emit_ori(unsigned int dst, unsigned src, u32 imm, + struct jit_ctx *ctx) +{ + if (imm >= BIT(16)) { + emit_load_imm(r_tmp, imm, ctx); + emit_or(dst, src, r_tmp, ctx); + } else { + emit_instr(ctx, ori, dst, src, imm); + } +} + + +static inline void emit_daddu(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, daddu, dst, src1, src2); +} + +static inline void emit_daddiu(unsigned int dst, unsigned int src, + int imm, struct jit_ctx *ctx) +{ + /* + * Only used for stack, so the imm is relatively small + * and it fits in 15-bits + */ + emit_instr(ctx, daddiu, dst, src, imm); +} + +static inline void emit_addiu(unsigned int dst, unsigned int src, + u32 imm, struct jit_ctx *ctx) +{ + if (is_range16(imm)) { + emit_load_imm(r_tmp, imm, ctx); + emit_addu(dst, r_tmp, src, ctx); + } else { + emit_instr(ctx, addiu, dst, src, imm); + } +} + +static inline void emit_and(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, and, dst, src1, src2); +} + +static inline void emit_andi(unsigned int dst, unsigned int src, + u32 imm, struct jit_ctx *ctx) +{ + /* If imm does not fit in u16 then load it to register */ + if (imm >= BIT(16)) { + emit_load_imm(r_tmp, imm, ctx); + emit_and(dst, src, r_tmp, ctx); + } else { + emit_instr(ctx, andi, dst, src, imm); + } +} + +static inline void emit_xor(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, xor, dst, src1, src2); +} + +static inline void emit_xori(ptr dst, ptr src, u32 imm, struct jit_ctx *ctx) +{ + /* If imm does not fit in u16 then load it to register */ + if (imm >= BIT(16)) { + emit_load_imm(r_tmp, imm, ctx); + emit_xor(dst, src, r_tmp, ctx); + } else { + emit_instr(ctx, xori, dst, src, imm); + } +} + +static inline void emit_stack_offset(int offset, struct jit_ctx *ctx) +{ + if (config_enabled(CONFIG_64BIT)) + emit_instr(ctx, daddiu, r_sp, r_sp, offset); + else + emit_instr(ctx, addiu, r_sp, r_sp, offset); + +} + +static inline void emit_subu(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, subu, dst, src1, src2); +} + +static inline void emit_neg(unsigned int reg, struct jit_ctx *ctx) +{ + emit_subu(reg, r_zero, reg, ctx); +} + +static inline void emit_sllv(unsigned int dst, unsigned int src, + unsigned int sa, struct jit_ctx *ctx) +{ + emit_instr(ctx, sllv, dst, src, sa); +} + +static inline void emit_sll(unsigned int dst, unsigned int src, + unsigned int sa, struct jit_ctx *ctx) +{ + /* sa is 5-bits long */ + BUG_ON(sa >= BIT(5)); + emit_instr(ctx, sll, dst, src, sa); +} + +static inline void emit_srlv(unsigned int dst, unsigned int src, + unsigned int sa, struct jit_ctx *ctx) +{ + emit_instr(ctx, srlv, dst, src, sa); +} + +static inline void emit_srl(unsigned int dst, unsigned int src, + unsigned int sa, struct jit_ctx *ctx) +{ + /* sa is 5-bits long */ + BUG_ON(sa >= BIT(5)); + emit_instr(ctx, srl, dst, src, sa); +} + +static inline void emit_sltu(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, sltu, dst, src1, src2); +} + +static inline void emit_sltiu(unsigned dst, unsigned int src, + unsigned int imm, struct jit_ctx *ctx) +{ + /* 16 bit immediate */ + if (is_range16((s32)imm)) { + emit_load_imm(r_tmp, imm, ctx); + emit_sltu(dst, src, r_tmp, ctx); + } else { + emit_instr(ctx, sltiu, dst, src, imm); + } + +} + +/* Store register on the stack */ +static inline void emit_store_stack_reg(ptr reg, ptr base, + unsigned int offset, + struct jit_ctx *ctx) +{ + if (config_enabled(CONFIG_64BIT)) + emit_instr(ctx, sd, reg, offset, base); + else + emit_instr(ctx, sw, reg, offset, base); +} + +static inline void emit_store(ptr reg, ptr base, unsigned int offset, + struct jit_ctx *ctx) +{ + emit_instr(ctx, sw, reg, offset, base); +} + +static inline void emit_load_stack_reg(ptr reg, ptr base, + unsigned int offset, + struct jit_ctx *ctx) +{ + if (config_enabled(CONFIG_64BIT)) + emit_instr(ctx, ld, reg, offset, base); + else + emit_instr(ctx, lw, reg, offset, base); +} + +static inline void emit_load(unsigned int reg, unsigned int base, + unsigned int offset, struct jit_ctx *ctx) +{ + emit_instr(ctx, lw, reg, offset, base); +} + +static inline void emit_load_byte(unsigned int reg, unsigned int base, + unsigned int offset, struct jit_ctx *ctx) +{ + emit_instr(ctx, lb, reg, offset, base); +} + +static inline void emit_half_load(unsigned int reg, unsigned int base, + unsigned int offset, struct jit_ctx *ctx) +{ + emit_instr(ctx, lh, reg, offset, base); +} + +static inline void emit_mul(unsigned int dst, unsigned int src1, + unsigned int src2, struct jit_ctx *ctx) +{ + emit_instr(ctx, mul, dst, src1, src2); +} + +static inline void emit_div(unsigned int dst, unsigned int src, + struct jit_ctx *ctx) +{ + if (ctx->target != NULL) { + u32 *p = &ctx->target[ctx->idx]; + uasm_i_divu(&p, dst, src); + p = &ctx->target[ctx->idx + 1]; + uasm_i_mfhi(&p, dst); + } + ctx->idx += 2; /* 2 insts */ +} + +static inline void emit_mod(unsigned int dst, unsigned int src, + struct jit_ctx *ctx) +{ + if (ctx->target != NULL) { + u32 *p = &ctx->target[ctx->idx]; + uasm_i_divu(&p, dst, src); + p = &ctx->target[ctx->idx + 1]; + uasm_i_mflo(&p, dst); + } + ctx->idx += 2; /* 2 insts */ +} + +static inline void emit_dsll(unsigned int dst, unsigned int src, + unsigned int sa, struct jit_ctx *ctx) +{ + emit_instr(ctx, dsll, dst, src, sa); +} + +static inline void emit_dsrl32(unsigned int dst, unsigned int src, + unsigned int sa, struct jit_ctx *ctx) +{ + emit_instr(ctx, dsrl32, dst, src, sa); +} + +static inline void emit_wsbh(unsigned int dst, unsigned int src, + struct jit_ctx *ctx) +{ + emit_instr(ctx, wsbh, dst, src); +} + +/* load a function pointer to register */ +static inline void emit_load_func(unsigned int reg, ptr imm, + struct jit_ctx *ctx) +{ + if (config_enabled(CONFIG_64BIT)) { + /* At this point imm is always 64-bit */ + emit_load_imm(r_tmp, (u64)imm >> 32, ctx); + emit_dsll(r_tmp_imm, r_tmp, 16, ctx); /* left shift by 16 */ + emit_ori(r_tmp, r_tmp_imm, (imm >> 16) & 0xffff, ctx); + emit_dsll(r_tmp_imm, r_tmp, 16, ctx); /* left shift by 16 */ + emit_ori(reg, r_tmp_imm, imm & 0xffff, ctx); + } else { + emit_load_imm(reg, imm, ctx); + } +} + +/* Move to real MIPS register */ +static inline void emit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx) +{ + if (config_enabled(CONFIG_64BIT)) + emit_daddu(dst, src, r_zero, ctx); + else + emit_addu(dst, src, r_zero, ctx); +} + +/* Move to JIT (32-bit) register */ +static inline void emit_jit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx) +{ + emit_addu(dst, src, r_zero, ctx); +} + +/* Compute the immediate value for PC-relative branches. */ +static inline u32 b_imm(unsigned int tgt, struct jit_ctx *ctx) +{ + if (ctx->target == NULL) + return 0; + + /* + * We want a pc-relative branch. We only do forward branches + * so tgt is always after pc. tgt is the instruction offset + * we want to jump to. + + * Branch on MIPS: + * I: target_offset <- sign_extend(offset) + * I+1: PC += target_offset (delay slot) + * + * ctx->idx currently points to the branch instruction + * but the offset is added to the delay slot so we need + * to subtract 4. + */ + return ctx->offsets[tgt] - + (ctx->idx * 4 - ctx->prologue_bytes) - 4; +} + +static inline void emit_bcond(int cond, unsigned int reg1, unsigned int reg2, + unsigned int imm, struct jit_ctx *ctx) +{ + if (ctx->target != NULL) { + u32 *p = &ctx->target[ctx->idx]; + + switch (cond) { + case MIPS_COND_EQ: + uasm_i_beq(&p, reg1, reg2, imm); + break; + case MIPS_COND_NE: + uasm_i_bne(&p, reg1, reg2, imm); + break; + case MIPS_COND_ALL: + uasm_i_b(&p, imm); + break; + default: + pr_warn("%s: Unhandled branch conditional: %d\n", + __func__, cond); + } + } + ctx->idx++; +} + +static inline void emit_b(unsigned int imm, struct jit_ctx *ctx) +{ + emit_bcond(MIPS_COND_ALL, r_zero, r_zero, imm, ctx); +} + +static inline void emit_jalr(unsigned int link, unsigned int reg, + struct jit_ctx *ctx) +{ + emit_instr(ctx, jalr, link, reg); +} + +static inline void emit_jr(unsigned int reg, struct jit_ctx *ctx) +{ + emit_instr(ctx, jr, reg); +} + +static inline u16 align_sp(unsigned int num) +{ + /* Double word alignment for 32-bit, quadword for 64-bit */ + unsigned int align = config_enabled(CONFIG_64BIT) ? 16 : 8; + num = (num + (align - 1)) & -align; + return num; +} + +static inline void update_on_xread(struct jit_ctx *ctx) +{ + if (!(ctx->flags & SEEN_X)) + ctx->flags |= FLAG_NEED_X_RESET; + + ctx->flags |= SEEN_X; +} + +static bool is_load_to_a(u16 inst) +{ + switch (inst) { + case BPF_S_LD_W_LEN: + case BPF_S_LD_W_ABS: + case BPF_S_LD_H_ABS: + case BPF_S_LD_B_ABS: + case BPF_S_ANC_CPU: + case BPF_S_ANC_IFINDEX: + case BPF_S_ANC_MARK: + case BPF_S_ANC_PROTOCOL: + case BPF_S_ANC_RXHASH: + case BPF_S_ANC_VLAN_TAG: + case BPF_S_ANC_VLAN_TAG_PRESENT: + case BPF_S_ANC_QUEUE: + return true; + default: + return false; + } +} + +static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset) +{ + int i = 0, real_off = 0; + u32 sflags, tmp_flags; + + /* Adjust the stack pointer */ + emit_stack_offset(-align_sp(offset), ctx); + + if (ctx->flags & SEEN_CALL) { + /* Argument save area */ + if (config_enabled(CONFIG_64BIT)) + /* Bottom of current frame */ + real_off = align_sp(offset) - RSIZE; + else + /* Top of previous frame */ + real_off = align_sp(offset) + RSIZE; + emit_store_stack_reg(MIPS_R_A0, r_sp, real_off, ctx); + emit_store_stack_reg(MIPS_R_A1, r_sp, real_off + RSIZE, ctx); + + real_off = 0; + } + + tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT; + /* sflags is essentially a bitmap */ + while (tmp_flags) { + if ((sflags >> i) & 0x1) { + emit_store_stack_reg(MIPS_R_S0 + i, r_sp, real_off, + ctx); + real_off += RSIZE; + } + i++; + tmp_flags >>= 1; + } + + /* save return address */ + if (ctx->flags & SEEN_CALL) { + emit_store_stack_reg(r_ra, r_sp, real_off, ctx); + real_off += RSIZE; + } + + /* Setup r_M leaving the alignment gap if necessary */ + if (ctx->flags & SEEN_MEM) { + if (real_off % (RSIZE * 2)) + real_off += RSIZE; + emit_addiu(r_M, r_sp, real_off, ctx); + } +} + +static void restore_bpf_jit_regs(struct jit_ctx *ctx, + unsigned int offset) +{ + int i, real_off = 0; + u32 sflags, tmp_flags; + + if (ctx->flags & SEEN_CALL) { + if (config_enabled(CONFIG_64BIT)) + /* Bottom of current frame */ + real_off = align_sp(offset) - RSIZE; + else + /* Top of previous frame */ + real_off = align_sp(offset) + RSIZE; + emit_load_stack_reg(MIPS_R_A0, r_sp, real_off, ctx); + emit_load_stack_reg(MIPS_R_A1, r_sp, real_off + RSIZE, ctx); + + real_off = 0; + } + + tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT; + /* sflags is a bitmap */ + i = 0; + while (tmp_flags) { + if ((sflags >> i) & 0x1) { + emit_load_stack_reg(MIPS_R_S0 + i, r_sp, real_off, + ctx); + real_off += RSIZE; + } + i++; + tmp_flags >>= 1; + } + + /* restore return address */ + if (ctx->flags & SEEN_CALL) + emit_load_stack_reg(r_ra, r_sp, real_off, ctx); + + /* Restore the sp and discard the scrach memory */ + emit_stack_offset(align_sp(offset), ctx); +} + +static unsigned int get_stack_depth(struct jit_ctx *ctx) +{ + int sp_off = 0; + + + /* How may s* regs do we need to preserved? */ + sp_off += hweight32(ctx->flags >> SEEN_SREG_SFT) * RSIZE; + + if (ctx->flags & SEEN_MEM) + sp_off += 4 * BPF_MEMWORDS; /* BPF_MEMWORDS are 32-bit */ + + if (ctx->flags & SEEN_CALL) + /* + * The JIT code make calls to external functions using 2 + * arguments. Therefore, for o32 we don't need to allocate + * space because we don't care if the argumetns are lost + * across calls. We do need however to preserve incoming + * arguments but the space is already allocated for us by + * the caller. On the other hand, for n64, we need to allocate + * this space ourselves. We need to preserve $ra as well. + */ + sp_off += config_enabled(CONFIG_64BIT) ? + (ARGS_USED_BY_JIT + 1) * RSIZE : RSIZE; + + /* + * Subtract the bytes for the last registers since we only care about + * the location on the stack pointer. + */ + return sp_off - RSIZE; +} + +static void build_prologue(struct jit_ctx *ctx) +{ + u16 first_inst = ctx->skf->insns[0].code; + int sp_off; + + /* Calculate the total offset for the stack pointer */ + sp_off = get_stack_depth(ctx); + save_bpf_jit_regs(ctx, sp_off); + + if (ctx->flags & SEEN_SKB) + emit_reg_move(r_skb, MIPS_R_A0, ctx); + + if (ctx->flags & FLAG_NEED_X_RESET) + emit_jit_reg_move(r_X, r_zero, ctx); + + /* Do not leak kernel data to userspace */ + if ((first_inst != BPF_S_RET_K) && !(is_load_to_a(first_inst))) + emit_jit_reg_move(r_A, r_zero, ctx); +} + +static void build_epilogue(struct jit_ctx *ctx) +{ + unsigned int sp_off; + + /* Calculate the total offset for the stack pointer */ + + sp_off = get_stack_depth(ctx); + restore_bpf_jit_regs(ctx, sp_off); + + /* Return */ + emit_jr(r_ra, ctx); + emit_nop(ctx); +} + +static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset) +{ + u8 ret; + int err; + + err = skb_copy_bits(skb, offset, &ret, 1); + + return (u64)err << 32 | ret; +} + +static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset) +{ + u16 ret; + int err; + + err = skb_copy_bits(skb, offset, &ret, 2); + + return (u64)err << 32 | ntohs(ret); +} + +static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset) +{ + u32 ret; + int err; + + err = skb_copy_bits(skb, offset, &ret, 4); + + return (u64)err << 32 | ntohl(ret); +} + +#define PKT_TYPE_MAX 7 +static int pkt_type_offset(void) +{ + struct sk_buff skb_probe = { + .pkt_type = ~0, + }; + char *ct = (char *)&skb_probe; + unsigned int off; + + for (off = 0; off < sizeof(struct sk_buff); off++) { + if (ct[off] == PKT_TYPE_MAX) + return off; + } + pr_err_once("Please fix pkt_type_offset(), as pkt_type couldn't be found\n"); + return -1; +} + +static int build_body(struct jit_ctx *ctx) +{ + void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w}; + const struct sk_filter *prog = ctx->skf; + const struct sock_filter *inst; + unsigned int i, off, load_order, condt; + u32 k, b_off __maybe_unused; + + for (i = 0; i < prog->len; i++) { + inst = &(prog->insns[i]); + pr_debug("%s: code->0x%02x, jt->0x%x, jf->0x%x, k->0x%x\n", + __func__, inst->code, inst->jt, inst->jf, inst->k); + k = inst->k; + + if (ctx->target == NULL) + ctx->offsets[i] = ctx->idx * 4; + + switch (inst->code) { + case BPF_S_LD_IMM: + /* A <- k ==> li r_A, k */ + ctx->flags |= SEEN_A; + emit_load_imm(r_A, k, ctx); + break; + case BPF_S_LD_W_LEN: + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4); + /* A <- len ==> lw r_A, offset(skb) */ + ctx->flags |= SEEN_SKB | SEEN_A; + off = offsetof(struct sk_buff, len); + emit_load(r_A, r_skb, off, ctx); + break; + case BPF_S_LD_MEM: + /* A <- M[k] ==> lw r_A, offset(M) */ + ctx->flags |= SEEN_MEM | SEEN_A; + emit_load(r_A, r_M, SCRATCH_OFF(k), ctx); + break; + case BPF_S_LD_W_ABS: + /* A <- P[k:4] */ + load_order = 2; + goto load; + case BPF_S_LD_H_ABS: + /* A <- P[k:2] */ + load_order = 1; + goto load; + case BPF_S_LD_B_ABS: + /* A <- P[k:1] */ + load_order = 0; +load: + emit_load_imm(r_off, k, ctx); +load_common: + ctx->flags |= SEEN_CALL | SEEN_OFF | SEEN_S0 | + SEEN_SKB | SEEN_A; + + emit_load_func(r_s0, (ptr)load_func[load_order], + ctx); + emit_reg_move(MIPS_R_A0, r_skb, ctx); + emit_jalr(MIPS_R_RA, r_s0, ctx); + /* Load second argument to delay slot */ + emit_reg_move(MIPS_R_A1, r_off, ctx); + /* Check the error value */ + if (config_enabled(CONFIG_64BIT)) { + /* Get error code from the top 32-bits */ + emit_dsrl32(r_s0, r_val, 0, ctx); + /* Branch to 3 instructions ahead */ + emit_bcond(MIPS_COND_NE, r_s0, r_zero, 3 << 2, + ctx); + } else { + /* Branch to 3 instructions ahead */ + emit_bcond(MIPS_COND_NE, r_err, r_zero, 3 << 2, + ctx); + } + emit_nop(ctx); + /* We are good */ + emit_b(b_imm(i + 1, ctx), ctx); + emit_jit_reg_move(r_A, r_val, ctx); + /* Return with error */ + emit_b(b_imm(prog->len, ctx), ctx); + emit_reg_move(r_ret, r_zero, ctx); + break; + case BPF_S_LD_W_IND: + /* A <- P[X + k:4] */ + load_order = 2; + goto load_ind; + case BPF_S_LD_H_IND: + /* A <- P[X + k:2] */ + load_order = 1; + goto load_ind; + case BPF_S_LD_B_IND: + /* A <- P[X + k:1] */ + load_order = 0; +load_ind: + update_on_xread(ctx); + ctx->flags |= SEEN_OFF | SEEN_X; + emit_addiu(r_off, r_X, k, ctx); + goto load_common; + case BPF_S_LDX_IMM: + /* X <- k */ + ctx->flags |= SEEN_X; + emit_load_imm(r_X, k, ctx); + break; + case BPF_S_LDX_MEM: + /* X <- M[k] */ + ctx->flags |= SEEN_X | SEEN_MEM; + emit_load(r_X, r_M, SCRATCH_OFF(k), ctx); + break; + case BPF_S_LDX_W_LEN: + /* X <- len */ + ctx->flags |= SEEN_X | SEEN_SKB; + off = offsetof(struct sk_buff, len); + emit_load(r_X, r_skb, off, ctx); + break; + case BPF_S_LDX_B_MSH: + /* X <- 4 * (P[k:1] & 0xf) */ + ctx->flags |= SEEN_X | SEEN_CALL | SEEN_S0 | SEEN_SKB; + /* Load offset to a1 */ + emit_load_func(r_s0, (ptr)jit_get_skb_b, ctx); + /* + * This may emit two instructions so it may not fit + * in the delay slot. So use a0 in the delay slot. + */ + emit_load_imm(MIPS_R_A1, k, ctx); + emit_jalr(MIPS_R_RA, r_s0, ctx); + emit_reg_move(MIPS_R_A0, r_skb, ctx); /* delay slot */ + /* Check the error value */ + if (config_enabled(CONFIG_64BIT)) { + /* Top 32-bits of $v0 on 64-bit */ + emit_dsrl32(r_s0, r_val, 0, ctx); + emit_bcond(MIPS_COND_NE, r_s0, r_zero, + 3 << 2, ctx); + } else { + emit_bcond(MIPS_COND_NE, r_err, r_zero, + 3 << 2, ctx); + } + /* No need for delay slot */ + /* We are good */ + /* X <- P[1:K] & 0xf */ + emit_andi(r_X, r_val, 0xf, ctx); + /* X << 2 */ + emit_b(b_imm(i + 1, ctx), ctx); + emit_sll(r_X, r_X, 2, ctx); /* delay slot */ + /* Return with error */ + emit_b(b_imm(prog->len, ctx), ctx); + emit_load_imm(r_ret, 0, ctx); /* delay slot */ + break; + case BPF_S_ST: + /* M[k] <- A */ + ctx->flags |= SEEN_MEM | SEEN_A; + emit_store(r_A, r_M, SCRATCH_OFF(k), ctx); + break; + case BPF_S_STX: + /* M[k] <- X */ + ctx->flags |= SEEN_MEM | SEEN_X; + emit_store(r_X, r_M, SCRATCH_OFF(k), ctx); + break; + case BPF_S_ALU_ADD_K: + /* A += K */ + ctx->flags |= SEEN_A; + emit_addiu(r_A, r_A, k, ctx); + break; + case BPF_S_ALU_ADD_X: + /* A += X */ + ctx->flags |= SEEN_A | SEEN_X; + emit_addu(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_SUB_K: + /* A -= K */ + ctx->flags |= SEEN_A; + emit_addiu(r_A, r_A, -k, ctx); + break; + case BPF_S_ALU_SUB_X: + /* A -= X */ + ctx->flags |= SEEN_A | SEEN_X; + emit_subu(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_MUL_K: + /* A *= K */ + /* Load K to scratch register before MUL */ + ctx->flags |= SEEN_A | SEEN_S0; + emit_load_imm(r_s0, k, ctx); + emit_mul(r_A, r_A, r_s0, ctx); + break; + case BPF_S_ALU_MUL_X: + /* A *= X */ + update_on_xread(ctx); + ctx->flags |= SEEN_A | SEEN_X; + emit_mul(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_DIV_K: + /* A /= k */ + if (k == 1) + break; + if (optimize_div(&k)) { + ctx->flags |= SEEN_A; + emit_srl(r_A, r_A, k, ctx); + break; + } + ctx->flags |= SEEN_A | SEEN_S0; + emit_load_imm(r_s0, k, ctx); + emit_div(r_A, r_s0, ctx); + break; + case BPF_S_ALU_MOD_K: + /* A %= k */ + if (k == 1 || optimize_div(&k)) { + ctx->flags |= SEEN_A; + emit_jit_reg_move(r_A, r_zero, ctx); + } else { + ctx->flags |= SEEN_A | SEEN_S0; + emit_load_imm(r_s0, k, ctx); + emit_mod(r_A, r_s0, ctx); + } + break; + case BPF_S_ALU_DIV_X: + /* A /= X */ + update_on_xread(ctx); + ctx->flags |= SEEN_X | SEEN_A; + /* Check if r_X is zero */ + emit_bcond(MIPS_COND_EQ, r_X, r_zero, + b_imm(prog->len, ctx), ctx); + emit_load_imm(r_val, 0, ctx); /* delay slot */ + emit_div(r_A, r_X, ctx); + break; + case BPF_S_ALU_MOD_X: + /* A %= X */ + update_on_xread(ctx); + ctx->flags |= SEEN_X | SEEN_A; + /* Check if r_X is zero */ + emit_bcond(MIPS_COND_EQ, r_X, r_zero, + b_imm(prog->len, ctx), ctx); + emit_load_imm(r_val, 0, ctx); /* delay slot */ + emit_mod(r_A, r_X, ctx); + break; + case BPF_S_ALU_OR_K: + /* A |= K */ + ctx->flags |= SEEN_A; + emit_ori(r_A, r_A, k, ctx); + break; + case BPF_S_ALU_OR_X: + /* A |= X */ + update_on_xread(ctx); + ctx->flags |= SEEN_A; + emit_ori(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_XOR_K: + /* A ^= k */ + ctx->flags |= SEEN_A; + emit_xori(r_A, r_A, k, ctx); + break; + case BPF_S_ANC_ALU_XOR_X: + case BPF_S_ALU_XOR_X: + /* A ^= X */ + update_on_xread(ctx); + ctx->flags |= SEEN_A; + emit_xor(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_AND_K: + /* A &= K */ + ctx->flags |= SEEN_A; + emit_andi(r_A, r_A, k, ctx); + break; + case BPF_S_ALU_AND_X: + /* A &= X */ + update_on_xread(ctx); + ctx->flags |= SEEN_A | SEEN_X; + emit_and(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_LSH_K: + /* A <<= K */ + ctx->flags |= SEEN_A; + emit_sll(r_A, r_A, k, ctx); + break; + case BPF_S_ALU_LSH_X: + /* A <<= X */ + ctx->flags |= SEEN_A | SEEN_X; + update_on_xread(ctx); + emit_sllv(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_RSH_K: + /* A >>= K */ + ctx->flags |= SEEN_A; + emit_srl(r_A, r_A, k, ctx); + break; + case BPF_S_ALU_RSH_X: + ctx->flags |= SEEN_A | SEEN_X; + update_on_xread(ctx); + emit_srlv(r_A, r_A, r_X, ctx); + break; + case BPF_S_ALU_NEG: + /* A = -A */ + ctx->flags |= SEEN_A; + emit_neg(r_A, ctx); + break; + case BPF_S_JMP_JA: + /* pc += K */ + emit_b(b_imm(i + k + 1, ctx), ctx); + emit_nop(ctx); + break; + case BPF_S_JMP_JEQ_K: + /* pc += ( A == K ) ? pc->jt : pc->jf */ + condt = MIPS_COND_EQ | MIPS_COND_K; + goto jmp_cmp; + case BPF_S_JMP_JEQ_X: + ctx->flags |= SEEN_X; + /* pc += ( A == X ) ? pc->jt : pc->jf */ + condt = MIPS_COND_EQ | MIPS_COND_X; + goto jmp_cmp; + case BPF_S_JMP_JGE_K: + /* pc += ( A >= K ) ? pc->jt : pc->jf */ + condt = MIPS_COND_GE | MIPS_COND_K; + goto jmp_cmp; + case BPF_S_JMP_JGE_X: + ctx->flags |= SEEN_X; + /* pc += ( A >= X ) ? pc->jt : pc->jf */ + condt = MIPS_COND_GE | MIPS_COND_X; + goto jmp_cmp; + case BPF_S_JMP_JGT_K: + /* pc += ( A > K ) ? pc->jt : pc->jf */ + condt = MIPS_COND_GT | MIPS_COND_K; + goto jmp_cmp; + case BPF_S_JMP_JGT_X: + ctx->flags |= SEEN_X; + /* pc += ( A > X ) ? pc->jt : pc->jf */ + condt = MIPS_COND_GT | MIPS_COND_X; +jmp_cmp: + /* Greater or Equal */ + if ((condt & MIPS_COND_GE) || + (condt & MIPS_COND_GT)) { + if (condt & MIPS_COND_K) { /* K */ + ctx->flags |= SEEN_S0 | SEEN_A; + emit_sltiu(r_s0, r_A, k, ctx); + } else { /* X */ + ctx->flags |= SEEN_S0 | SEEN_A | + SEEN_X; + emit_sltu(r_s0, r_A, r_X, ctx); + } + /* A < (K|X) ? r_scrach = 1 */ + b_off = b_imm(i + inst->jf + 1, ctx); + emit_bcond(MIPS_COND_GT, r_s0, r_zero, b_off, + ctx); + emit_nop(ctx); + /* A > (K|X) ? scratch = 0 */ + if (condt & MIPS_COND_GT) { + /* Checking for equality */ + ctx->flags |= SEEN_S0 | SEEN_A | SEEN_X; + if (condt & MIPS_COND_K) + emit_load_imm(r_s0, k, ctx); + else + emit_jit_reg_move(r_s0, r_X, + ctx); + b_off = b_imm(i + inst->jf + 1, ctx); + emit_bcond(MIPS_COND_EQ, r_A, r_s0, + b_off, ctx); + emit_nop(ctx); + /* Finally, A > K|X */ + b_off = b_imm(i + inst->jt + 1, ctx); + emit_b(b_off, ctx); + emit_nop(ctx); + } else { + /* A >= (K|X) so jump */ + b_off = b_imm(i + inst->jt + 1, ctx); + emit_b(b_off, ctx); + emit_nop(ctx); + } + } else { + /* A == K|X */ + if (condt & MIPS_COND_K) { /* K */ + ctx->flags |= SEEN_S0 | SEEN_A; + emit_load_imm(r_s0, k, ctx); + /* jump true */ + b_off = b_imm(i + inst->jt + 1, ctx); + emit_bcond(MIPS_COND_EQ, r_A, r_s0, + b_off, ctx); + emit_nop(ctx); + /* jump false */ + b_off = b_imm(i + inst->jf + 1, + ctx); + emit_bcond(MIPS_COND_NE, r_A, r_s0, + b_off, ctx); + emit_nop(ctx); + } else { /* X */ + /* jump true */ + ctx->flags |= SEEN_A | SEEN_X; + b_off = b_imm(i + inst->jt + 1, + ctx); + emit_bcond(MIPS_COND_EQ, r_A, r_X, + b_off, ctx); + emit_nop(ctx); + /* jump false */ + b_off = b_imm(i + inst->jf + 1, ctx); + emit_bcond(MIPS_COND_NE, r_A, r_X, + b_off, ctx); + emit_nop(ctx); + } + } + break; + case BPF_S_JMP_JSET_K: + ctx->flags |= SEEN_S0 | SEEN_S1 | SEEN_A; + /* pc += (A & K) ? pc -> jt : pc -> jf */ + emit_load_imm(r_s1, k, ctx); + emit_and(r_s0, r_A, r_s1, ctx); + /* jump true */ + b_off = b_imm(i + inst->jt + 1, ctx); + emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off, ctx); + emit_nop(ctx); + /* jump false */ + b_off = b_imm(i + inst->jf + 1, ctx); + emit_b(b_off, ctx); + emit_nop(ctx); + break; + case BPF_S_JMP_JSET_X: + ctx->flags |= SEEN_S0 | SEEN_X | SEEN_A; + /* pc += (A & X) ? pc -> jt : pc -> jf */ + emit_and(r_s0, r_A, r_X, ctx); + /* jump true */ + b_off = b_imm(i + inst->jt + 1, ctx); + emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off, ctx); + emit_nop(ctx); + /* jump false */ + b_off = b_imm(i + inst->jf + 1, ctx); + emit_b(b_off, ctx); + emit_nop(ctx); + break; + case BPF_S_RET_A: + ctx->flags |= SEEN_A; + if (i != prog->len - 1) + /* + * If this is not the last instruction + * then jump to the epilogue + */ + emit_b(b_imm(prog->len, ctx), ctx); + emit_reg_move(r_ret, r_A, ctx); /* delay slot */ + break; + case BPF_S_RET_K: + /* + * It can emit two instructions so it does not fit on + * the delay slot. + */ + emit_load_imm(r_ret, k, ctx); + if (i != prog->len - 1) { + /* + * If this is not the last instruction + * then jump to the epilogue + */ + emit_b(b_imm(prog->len, ctx), ctx); + emit_nop(ctx); + } + break; + case BPF_S_MISC_TAX: + /* X = A */ + ctx->flags |= SEEN_X | SEEN_A; + emit_jit_reg_move(r_X, r_A, ctx); + break; + case BPF_S_MISC_TXA: + /* A = X */ + ctx->flags |= SEEN_A | SEEN_X; + update_on_xread(ctx); + emit_jit_reg_move(r_A, r_X, ctx); + break; + /* AUX */ + case BPF_S_ANC_PROTOCOL: + /* A = ntohs(skb->protocol */ + ctx->flags |= SEEN_SKB | SEEN_OFF | SEEN_A; + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, + protocol) != 2); + off = offsetof(struct sk_buff, protocol); + emit_half_load(r_A, r_skb, off, ctx); +#ifdef CONFIG_CPU_LITTLE_ENDIAN + /* This needs little endian fixup */ + if (!cpu_has_mips_r2) { + /* Get first byte */ + emit_andi(r_tmp_imm, r_A, 0xff, ctx); + /* Shift it */ + emit_sll(r_tmp, r_tmp_imm, 8, ctx); + /* Get second byte */ + emit_srl(r_tmp_imm, r_A, 8, ctx); + emit_andi(r_tmp_imm, r_tmp_imm, 0xff, ctx); + /* Put everyting together in r_A */ + emit_or(r_A, r_tmp, r_tmp_imm, ctx); + } else { + /* R2 and later have the wsbh instruction */ + emit_wsbh(r_A, r_A, ctx); + } +#endif + break; + case BPF_S_ANC_CPU: + ctx->flags |= SEEN_A | SEEN_OFF; + /* A = current_thread_info()->cpu */ + BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, + cpu) != 4); + off = offsetof(struct thread_info, cpu); + /* $28/gp points to the thread_info struct */ + emit_load(r_A, 28, off, ctx); + break; + case BPF_S_ANC_IFINDEX: + /* A = skb->dev->ifindex */ + ctx->flags |= SEEN_SKB | SEEN_A | SEEN_S0; + off = offsetof(struct sk_buff, dev); + emit_load(r_s0, r_skb, off, ctx); + /* error (0) in the delay slot */ + emit_bcond(MIPS_COND_EQ, r_s0, r_zero, + b_imm(prog->len, ctx), ctx); + emit_reg_move(r_ret, r_zero, ctx); + BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, + ifindex) != 4); + off = offsetof(struct net_device, ifindex); + emit_load(r_A, r_s0, off, ctx); + break; + case BPF_S_ANC_MARK: + ctx->flags |= SEEN_SKB | SEEN_A; + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); + off = offsetof(struct sk_buff, mark); + emit_load(r_A, r_skb, off, ctx); + break; + case BPF_S_ANC_RXHASH: + ctx->flags |= SEEN_SKB | SEEN_A; + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4); + off = offsetof(struct sk_buff, hash); + emit_load(r_A, r_skb, off, ctx); + break; + case BPF_S_ANC_VLAN_TAG: + case BPF_S_ANC_VLAN_TAG_PRESENT: + ctx->flags |= SEEN_SKB | SEEN_S0 | SEEN_A; + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, + vlan_tci) != 2); + off = offsetof(struct sk_buff, vlan_tci); + emit_half_load(r_s0, r_skb, off, ctx); + if (inst->code == BPF_S_ANC_VLAN_TAG) + emit_and(r_A, r_s0, VLAN_VID_MASK, ctx); + else + emit_and(r_A, r_s0, VLAN_TAG_PRESENT, ctx); + break; + case BPF_S_ANC_PKTTYPE: + off = pkt_type_offset(); + + if (off < 0) + return -1; + emit_load_byte(r_tmp, r_skb, off, ctx); + /* Keep only the last 3 bits */ + emit_andi(r_A, r_tmp, PKT_TYPE_MAX, ctx); + break; + case BPF_S_ANC_QUEUE: + ctx->flags |= SEEN_SKB | SEEN_A; + BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, + queue_mapping) != 2); + BUILD_BUG_ON(offsetof(struct sk_buff, + queue_mapping) > 0xff); + off = offsetof(struct sk_buff, queue_mapping); + emit_half_load(r_A, r_skb, off, ctx); + break; + default: + pr_warn("%s: Unhandled opcode: 0x%02x\n", __FILE__, + inst->code); + return -1; + } + } + + /* compute offsets only during the first pass */ + if (ctx->target == NULL) + ctx->offsets[i] = ctx->idx * 4; + + return 0; +} + +int bpf_jit_enable __read_mostly; + +void bpf_jit_compile(struct sk_filter *fp) +{ + struct jit_ctx ctx; + unsigned int alloc_size, tmp_idx; + + if (!bpf_jit_enable) + return; + + memset(&ctx, 0, sizeof(ctx)); + + ctx.offsets = kcalloc(fp->len, sizeof(*ctx.offsets), GFP_KERNEL); + if (ctx.offsets == NULL) + return; + + ctx.skf = fp; + + if (build_body(&ctx)) + goto out; + + tmp_idx = ctx.idx; + build_prologue(&ctx); + ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4; + /* just to complete the ctx.idx count */ + build_epilogue(&ctx); + + alloc_size = 4 * ctx.idx; + ctx.target = module_alloc(alloc_size); + if (ctx.target == NULL) + goto out; + + /* Clean it */ + memset(ctx.target, 0, alloc_size); + + ctx.idx = 0; + + /* Generate the actual JIT code */ + build_prologue(&ctx); + build_body(&ctx); + build_epilogue(&ctx); + + /* Update the icache */ + flush_icache_range((ptr)ctx.target, (ptr)(ctx.target + ctx.idx)); + + if (bpf_jit_enable > 1) + /* Dump JIT code */ + bpf_jit_dump(fp->len, alloc_size, 2, ctx.target); + + fp->bpf_func = (void *)ctx.target; + fp->jited = 1; + +out: + kfree(ctx.offsets); +} + +void bpf_jit_free(struct sk_filter *fp) +{ + if (fp->jited) + module_free(NULL, fp->bpf_func); + kfree(fp); +} diff --git a/arch/mips/net/bpf_jit.h b/arch/mips/net/bpf_jit.h new file mode 100644 index 0000000..3a5751b --- /dev/null +++ b/arch/mips/net/bpf_jit.h @@ -0,0 +1,44 @@ +/* + * Just-In-Time compiler for BPF filters on MIPS + * + * Copyright (c) 2014 Imagination Technologies Ltd. + * Author: Markos Chandras + * + * 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_MIPS_OP_H +#define BPF_JIT_MIPS_OP_H + +/* Registers used by JIT */ +#define MIPS_R_ZERO 0 +#define MIPS_R_V0 2 +#define MIPS_R_V1 3 +#define MIPS_R_A0 4 +#define MIPS_R_A1 5 +#define MIPS_R_T6 14 +#define MIPS_R_T7 15 +#define MIPS_R_S0 16 +#define MIPS_R_S1 17 +#define MIPS_R_S2 18 +#define MIPS_R_S3 19 +#define MIPS_R_S4 20 +#define MIPS_R_S5 21 +#define MIPS_R_S6 22 +#define MIPS_R_S7 23 +#define MIPS_R_SP 29 +#define MIPS_R_RA 31 + +/* Conditional codes */ +#define MIPS_COND_EQ 0x1 +#define MIPS_COND_GE (0x1 << 1) +#define MIPS_COND_GT (0x1 << 2) +#define MIPS_COND_NE (0x1 << 3) +#define MIPS_COND_ALL (0x1 << 4) +/* Conditionals on X register or K immediate */ +#define MIPS_COND_X (0x1 << 5) +#define MIPS_COND_K (0x1 << 6) + +#endif /* BPF_JIT_MIPS_OP_H */ -- cgit v0.10.2 From 3f5fdb4bd193091fd30db52c609c4b304151d656 Mon Sep 17 00:00:00 2001 From: Markos Chandras Date: Wed, 9 Apr 2014 17:02:35 +0100 Subject: MIPS: Enable the BPF_JIT symbol for MIPS Signed-off-by: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6743/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2fe8e60..22a69d7 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -12,6 +12,7 @@ config MIPS select HAVE_ARCH_KGDB select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK + select HAVE_BPF_JIT if !CPU_MICROMIPS select ARCH_HAVE_CUSTOM_GPIO_H select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST -- cgit v0.10.2 From a91796a919ceeb80fde7f413cd898bd0f409fec3 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:40 +0530 Subject: MIPS: Support upto 256 CPUs This is needed for two node XLP9xx configurations. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6860/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 22a69d7..c4804bf 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2267,8 +2267,8 @@ config NR_CPUS_DEFAULT_64 bool config NR_CPUS - int "Maximum number of CPUs (2-64)" - range 2 64 + int "Maximum number of CPUs (2-256)" + range 2 256 depends on SMP default "4" if NR_CPUS_DEFAULT_4 default "8" if NR_CPUS_DEFAULT_8 -- cgit v0.10.2 From f9fab7e4edfb2e14b870dcb902976325b21e9f1e Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:41 +0530 Subject: MIPS: Netlogic: Fix uniprocessor compilation The macros in topology.h need CONFIG_SMP, and the uniprocessor compilation fails due to this. Wrap the macros in an ifdef so that uniprocessor works. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6863/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-netlogic/topology.h b/arch/mips/include/asm/mach-netlogic/topology.h index 0da99fa..ceeb1f5 100644 --- a/arch/mips/include/asm/mach-netlogic/topology.h +++ b/arch/mips/include/asm/mach-netlogic/topology.h @@ -10,10 +10,12 @@ #include +#ifdef CONFIG_SMP #define topology_physical_package_id(cpu) cpu_to_node(cpu) #define topology_core_id(cpu) (cpu_logical_map(cpu) / NLM_THREADS_PER_CORE) #define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu]) #define topology_core_cpumask(cpu) cpumask_of_node(cpu_to_node(cpu)) +#endif #include -- cgit v0.10.2 From 3e468567c2d56441079db090b3771bfc9d91cba5 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:42 +0530 Subject: MIPS: Netlogic: Move coremask setup to nlm_node_init This is needed for nlm_node_present(0) to work on uniprocessor compile. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6861/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 997cd9e..7b277cd 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -54,6 +54,8 @@ void nlm_node_init(int node) struct nlm_soc_info *nodep; nodep = nlm_get_node(node); + if (node == 0) + nodep->coremask = 1; /* node 0, boot cpu */ nodep->sysbase = nlm_get_sys_regbase(node); nodep->picbase = nlm_get_pic_regbase(node); nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1)); diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 9a92617..7589238 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -159,10 +159,6 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) */ syscoremask = (1 << hweight32(~fusemask & mask)) - 1; - /* The boot cpu */ - if (n == 0) - nodep->coremask = 1; - pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask); for (core = 0; core < nlm_cores_per_node(); core++) { /* we will be on node 0 core 0 */ -- cgit v0.10.2 From 9de10ffb54565b4d427adf1037579617e73cb8bf Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:43 +0530 Subject: MIPS: Netlogic: Warn on invalid irq Warn and return if invalid IRQ is passed to nlm_set_pic_extra_ack. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6862/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 5afc4b7..c100b9a 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -203,6 +203,8 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *)) xirq = nlm_irq_to_xirq(node, irq); pic_data = irq_get_handler_data(xirq); + if (WARN_ON(!pic_data)) + return; pic_data->extra_ack = xack; } -- cgit v0.10.2 From 2e240ddd09d41645e928a19a3ff3290a0f546834 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Fri, 9 May 2014 16:34:54 +0530 Subject: MIPS: Netlogic: Use cpumask_scnprintf for wakeup_mask Use standard function to print cpumask. Also fixup a typo in the same file. Signed-off-by: Jayachandran C Cc: g@linux-mips.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6909/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index d81b443..4fde7ac 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -194,7 +194,7 @@ void __init nlm_smp_setup(void) cpumask_scnprintf(buf, ARRAY_SIZE(buf), cpu_possible_mask); pr_info("Possible CPU mask: %s\n", buf); - /* check with the cores we have worken up */ + /* check with the cores we have woken up */ for (ncore = 0, i = 0; i < NLM_NR_NODES; i++) ncore += hweight32(nlm_get_node(i)->coremask); @@ -209,6 +209,7 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask) { uint32_t core0_thr_mask, core_thr_mask; int threadmode, i, j; + char buf[64]; core0_thr_mask = 0; for (i = 0; i < NLM_THREADS_PER_CORE; i++) @@ -243,8 +244,8 @@ static int nlm_parse_cpumask(cpumask_t *wakeup_mask) return threadmode; unsupp: - panic("Unsupported CPU mask %lx", - (unsigned long)cpumask_bits(wakeup_mask)[0]); + cpumask_scnprintf(buf, ARRAY_SIZE(buf), wakeup_mask); + panic("Unsupported CPU mask %s", buf); return 0; } -- cgit v0.10.2 From a3deecfaa36662ca2e2104be3c305236cf03efcc Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Fri, 9 May 2014 16:35:14 +0530 Subject: MIPS: Netlogic: Reduce size of reset code Update thread wakeup function to use scratch registers for saving SP and RA. Move the register restore code needed for thread 0 to the calling function. This reduces the size of code copied to the reset vector. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6910/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index b231fe1..fda772a 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -197,6 +197,9 @@ FEXPORT(nlm_reset_entry) EXPORT(nlm_boot_siblings) /* core L1D flush before enable threads */ xlp_flush_l1_dcache + /* save ra and sp, will be used later (only for boot cpu) */ + dmtc0 ra, $22, 6 + dmtc0 sp, $22, 7 /* Enable hw threads by writing to MAP_THREADMODE of the core */ li t0, CKSEG1ADDR(RESET_DATA_PHYS) lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ @@ -238,14 +241,12 @@ EXPORT(nlm_boot_siblings) nop /* - * For the boot CPU, we have to restore registers and - * return + * For the boot CPU, we have to restore ra and sp and return, rest + * of the registers will be restored by the caller */ -4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ - li t1, 0xfadebeef - dmtc0 t1, $4, 2 /* restore SP from UserLocal */ - PTR_SUBU sp, t0, PT_SIZE - RESTORE_ALL +4: + dmfc0 ra, $22, 6 + dmfc0 sp, $22, 7 jr ra nop EXPORT(nlm_reset_entry_end) diff --git a/arch/mips/netlogic/common/smpboot.S b/arch/mips/netlogic/common/smpboot.S index 8597657..805355b 100644 --- a/arch/mips/netlogic/common/smpboot.S +++ b/arch/mips/netlogic/common/smpboot.S @@ -54,8 +54,9 @@ .set noat .set arch=xlr /* for mfcr/mtcr, XLR is sufficient */ -FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ - dmtc0 sp, $4, 2 /* SP saved in UserLocal */ +/* Called by the boot cpu to wake up its sibling threads */ +NESTED(xlp_boot_core0_siblings, PT_SIZE, sp) + /* CPU register contents lost when enabling threads, save them first */ SAVE_ALL sync /* find the location to which nlm_boot_siblings was relocated */ @@ -65,9 +66,12 @@ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ dsubu t2, t1 daddu t2, t0 /* call it */ - jr t2 + jalr t2 nop - /* not reached */ + RESTORE_ALL + jr ra + nop +END(xlp_boot_core0_siblings) NESTED(nlm_boot_secondary_cpus, 16, sp) /* Initialize CP0 Status */ -- cgit v0.10.2 From e9126418dd7a86bee32d2dae37df403f7f1e2a13 Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:47 +0530 Subject: MIPS: Netlogic: Enable access to more than 64GB The ELPA bit needs to be set in the PAGEGRAIN register to enable access to >64GB physical address. Update reset.S to do this from every hardware thread. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6866/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index fda772a..13c1bc5 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -74,6 +74,18 @@ .endm /* + * Allow access to physical mem >64G by enabling ELPA in PAGEGRAIN + * register. This is needed before going to C code since the SP can + * in this region. Called from all HW threads. + */ +.macro xlp_early_mmu_init + mfc0 t0, CP0_PAGEMASK, 1 + li t1, (1 << 29) /* ELPA bit */ + or t0, t1 + mtc0 t0, CP0_PAGEMASK, 1 +.endm + +/* * L1D cache has to be flushed before enabling threads in XLP. * On XLP8xx/XLP3xx, we do a low level flush using processor control * registers. On XLPII CPUs, usual cache instructions work. @@ -228,6 +240,8 @@ EXPORT(nlm_boot_siblings) #endif mtc0 t1, CP0_STATUS + xlp_early_mmu_init + /* mark CPU ready */ li t3, CKSEG1ADDR(RESET_DATA_PHYS) ADDIU t1, t3, BOOT_CPU_READY @@ -254,6 +268,7 @@ EXPORT(nlm_reset_entry_end) LEAF(nlm_init_boot_cpu) #ifdef CONFIG_CPU_XLP xlp_config_lsu + xlp_early_mmu_init #endif jr ra nop -- cgit v0.10.2 From 0d57eba02d6f0685e61763502962fcf00fd4e4cc Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Fri, 9 May 2014 16:35:34 +0530 Subject: MIPS: Netlogic: IRQ mapping for some more SoC blocks Add IRQ to IRT (PIC interupt table index) mapping for SATA, GPIO, NAND and SPI interfaces on the XLP SoC. Fix offsets for few blocks and add device IDs for a few blocks. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6911/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h index 1f23dfa..14b2f51 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h @@ -74,6 +74,8 @@ #define XLP_IO_USB_OHCI2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 4) #define XLP_IO_USB_OHCI3_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 5) +#define XLP_IO_SATA_OFFSET(node) XLP_HDR_OFFSET(node, 0, 3, 2) + /* XLP2xx has an updated USB block */ #define XLP2XX_IO_USB_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 4, i) #define XLP2XX_IO_USB_XHCI0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 4, 1) @@ -103,13 +105,11 @@ #define XLP_IO_SYS_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 5) #define XLP_IO_JTAG_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 6) +/* Flash */ #define XLP_IO_NOR_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 0) #define XLP_IO_NAND_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 1) #define XLP_IO_SPI_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 2) -/* SD flash */ -#define XLP_IO_SD_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 3) -#define XLP_IO_MMC_OFFSET(node, slot) \ - ((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ) +#define XLP_IO_MMC_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 3) /* Things have changed drastically in XLP 9XX */ #define XLP9XX_HDR_OFFSET(n, d, f) \ @@ -135,11 +135,11 @@ /* XLP9XX on-chip SATA controller */ #define XLP9XX_IO_SATA_OFFSET(node) XLP9XX_HDR_OFFSET(node, 3, 2) +/* Flash */ #define XLP9XX_IO_NOR_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 0) #define XLP9XX_IO_NAND_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 1) #define XLP9XX_IO_SPI_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 2) -/* SD flash */ -#define XLP9XX_IO_MMCSD_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 3) +#define XLP9XX_IO_MMC_OFFSET(node) XLP9XX_HDR_OFFSET(node, 7, 3) /* PCI config header register id's */ #define XLP_PCI_CFGREG0 0x00 @@ -186,8 +186,10 @@ #define PCI_DEVICE_ID_NLM_NOR 0x1015 #define PCI_DEVICE_ID_NLM_NAND 0x1016 #define PCI_DEVICE_ID_NLM_MMC 0x1018 -#define PCI_DEVICE_ID_NLM_XHCI 0x101d +#define PCI_DEVICE_ID_NLM_SATA 0x101A +#define PCI_DEVICE_ID_NLM_XHCI 0x101D +#define PCI_DEVICE_ID_XLP9XX_MMC 0x9018 #define PCI_DEVICE_ID_XLP9XX_SATA 0x901A #define PCI_DEVICE_ID_XLP9XX_XHCI 0x901D diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index 2b0c959..bd7dda0 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -58,6 +58,10 @@ #define PIC_I2C_1_IRQ 31 #define PIC_I2C_2_IRQ 32 #define PIC_I2C_3_IRQ 33 +#define PIC_SPI_IRQ 34 +#define PIC_NAND_IRQ 37 +#define PIC_SATA_IRQ 38 +#define PIC_GPIO_IRQ 39 #define PIC_PCIE_LINK_MSI_IRQ_BASE 44 /* 44 - 47 MSI IRQ */ #define PIC_PCIE_LINK_MSI_IRQ(i) (44 + (i)) diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 7b277cd..9f9814d 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -66,31 +66,39 @@ void nlm_node_init(int node) spin_lock_init(&nodep->piclock); } -int nlm_irq_to_irt(int irq) +static int xlp9xx_irq_to_irt(int irq) +{ + switch (irq) { + case PIC_GPIO_IRQ: + return 12; + case PIC_9XX_XHCI_0_IRQ: + return 114; + case PIC_9XX_XHCI_1_IRQ: + return 115; + case PIC_UART_0_IRQ: + return 133; + case PIC_UART_1_IRQ: + return 134; + case PIC_SATA_IRQ: + return 143; + case PIC_SPI_IRQ: + return 152; + case PIC_MMC_IRQ: + return 153; + case PIC_PCIE_LINK_LEGACY_IRQ(0): + case PIC_PCIE_LINK_LEGACY_IRQ(1): + case PIC_PCIE_LINK_LEGACY_IRQ(2): + case PIC_PCIE_LINK_LEGACY_IRQ(3): + return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE; + } + return -1; +} + +static int xlp_irq_to_irt(int irq) { uint64_t pcibase; int devoff, irt; - /* bypass for 9xx */ - if (cpu_is_xlp9xx()) { - switch (irq) { - case PIC_9XX_XHCI_0_IRQ: - return 114; - case PIC_9XX_XHCI_1_IRQ: - return 115; - case PIC_UART_0_IRQ: - return 133; - case PIC_UART_1_IRQ: - return 134; - case PIC_PCIE_LINK_LEGACY_IRQ(0): - case PIC_PCIE_LINK_LEGACY_IRQ(1): - case PIC_PCIE_LINK_LEGACY_IRQ(2): - case PIC_PCIE_LINK_LEGACY_IRQ(3): - return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE; - } - return -1; - } - devoff = 0; switch (irq) { case PIC_UART_0_IRQ: @@ -100,7 +108,7 @@ int nlm_irq_to_irt(int irq) devoff = XLP_IO_UART1_OFFSET(0); break; case PIC_MMC_IRQ: - devoff = XLP_IO_SD_OFFSET(0); + devoff = XLP_IO_MMC_OFFSET(0); break; case PIC_I2C_0_IRQ: /* I2C will be fixed up */ case PIC_I2C_1_IRQ: @@ -111,6 +119,18 @@ int nlm_irq_to_irt(int irq) else devoff = XLP_IO_I2C0_OFFSET(0); break; + case PIC_SATA_IRQ: + devoff = XLP_IO_SATA_OFFSET(0); + break; + case PIC_GPIO_IRQ: + devoff = XLP_IO_GPIO_OFFSET(0); + break; + case PIC_NAND_IRQ: + devoff = XLP_IO_NAND_OFFSET(0); + break; + case PIC_SPI_IRQ: + devoff = XLP_IO_SPI_OFFSET(0); + break; default: if (cpu_is_xlpii()) { switch (irq) { @@ -166,18 +186,26 @@ int nlm_irq_to_irt(int irq) /* HW bug, PCI IRT entries are bad on early silicon, fix */ irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE); - } else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && - irq <= PIC_PCIE_LINK_MSI_IRQ(3)) { - irt = -2; - } else if (irq >= PIC_PCIE_MSIX_IRQ(0) && - irq <= PIC_PCIE_MSIX_IRQ(3)) { - irt = -2; } else { irt = -1; } return irt; } +int nlm_irq_to_irt(int irq) +{ + /* return -2 for irqs without 1-1 mapping */ + if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && irq <= PIC_PCIE_LINK_MSI_IRQ(3)) + return -2; + if (irq >= PIC_PCIE_MSIX_IRQ(0) && irq <= PIC_PCIE_MSIX_IRQ(3)) + return -2; + + if (cpu_is_xlp9xx()) + return xlp9xx_irq_to_irt(irq); + else + return xlp_irq_to_irt(irq); +} + unsigned int nlm_get_core_frequency(int node, int core) { unsigned int pll_divf, pll_divr, dfs_div, ext_div; -- cgit v0.10.2 From 5874743ea8479b780799927f25580ef134547f0f Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:49 +0530 Subject: MIPS: Netlogic: Use PRID_IMP_MASK macro Use PRID_IMP_MASK macro instead of 0xff00 to extract the processor type. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6868/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h index de9aada..38af905 100644 --- a/arch/mips/include/asm/netlogic/mips-extns.h +++ b/arch/mips/include/asm/netlogic/mips-extns.h @@ -146,9 +146,9 @@ static inline int hard_smp_processor_id(void) static inline int nlm_nodeid(void) { - uint32_t prid = read_c0_prid(); + uint32_t prid = read_c0_prid() & PRID_IMP_MASK; - if ((prid & 0xff00) == PRID_IMP_NETLOGIC_XLP9XX) + if (prid == PRID_IMP_NETLOGIC_XLP9XX) return (__read_32bit_c0_register($15, 1) >> 7) & 0x7; else return (__read_32bit_c0_register($15, 1) >> 5) & 0x3; diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index bd7dda0..a11b289 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -99,7 +99,7 @@ void *xlp_dt_init(void *fdtp); static inline int cpu_is_xlpii(void) { - int chip = read_c0_prid() & 0xff00; + int chip = read_c0_prid() & PRID_IMP_MASK; return chip == PRID_IMP_NETLOGIC_XLP2XX || chip == PRID_IMP_NETLOGIC_XLP9XX; @@ -107,7 +107,7 @@ static inline int cpu_is_xlpii(void) static inline int cpu_is_xlp9xx(void) { - int chip = read_c0_prid() & 0xff00; + int chip = read_c0_prid() & PRID_IMP_MASK; return chip == PRID_IMP_NETLOGIC_XLP9XX; } diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index 13c1bc5..5b60b46 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -92,7 +93,7 @@ */ .macro xlp_flush_l1_dcache mfc0 t0, CP0_EBASE, 0 - andi t0, t0, 0xff00 + andi t0, t0, PRID_IMP_MASK slt t1, t0, 0x1200 beqz t1, 15f nop @@ -171,7 +172,7 @@ FEXPORT(nlm_reset_entry) 1: /* Entry point on core wakeup */ mfc0 t0, CP0_EBASE, 0 /* processor ID */ - andi t0, 0xff00 + andi t0, PRID_IMP_MASK li t1, 0x1500 /* XLP 9xx */ beq t0, t1, 2f /* does not need to set coherent */ nop diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c index 5754097..0b36ac8 100644 --- a/arch/mips/netlogic/xlp/dt.c +++ b/arch/mips/netlogic/xlp/dt.c @@ -48,7 +48,7 @@ static void *xlp_fdt_blob; void __init *xlp_dt_init(void *fdtp) { if (!fdtp) { - switch (current_cpu_data.processor_id & 0xff00) { + switch (current_cpu_data.processor_id & PRID_IMP_MASK) { #ifdef CONFIG_DT_XLP_GVP case PRID_IMP_NETLOGIC_XLP9XX: fdtp = __dtb_xlp_gvp_begin; diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 8c60a2d..1ddb62b 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -121,7 +121,7 @@ void __init plat_mem_setup(void) const char *get_system_type(void) { - switch (read_c0_prid() & 0xff00) { + switch (read_c0_prid() & PRID_IMP_MASK) { case PRID_IMP_NETLOGIC_XLP9XX: case PRID_IMP_NETLOGIC_XLP2XX: return "Broadcom XLPII Series"; diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 7589238..f4823ad 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -139,7 +139,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) } else { fusemask = nlm_read_sys_reg(nodep->sysbase, SYS_EFUSE_DEVICE_CFG_STATUS0); - switch (read_c0_prid() & 0xff00) { + switch (read_c0_prid() & PRID_IMP_MASK) { case PRID_IMP_NETLOGIC_XLP3XX: mask = 0xf; break; -- cgit v0.10.2 From 77bef0e4b532341d2d21e4ef28111de7c239432e Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:50 +0530 Subject: MIPS: Netlogic: Fix XLP9XX pic entry Add the compatible property to the PIC entry. Also fix up the nodename to use the correct address. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6869/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/dts/xlp_gvp.dts b/arch/mips/netlogic/dts/xlp_gvp.dts index 047d27f..bb4ecd1 100644 --- a/arch/mips/netlogic/dts/xlp_gvp.dts +++ b/arch/mips/netlogic/dts/xlp_gvp.dts @@ -26,11 +26,12 @@ interrupt-parent = <&pic>; interrupts = <17>; }; - pic: pic@4000 { - interrupt-controller; + pic: pic@110000 { + compatible = "netlogic,xlp-pic"; #address-cells = <0>; #interrupt-cells = <1>; reg = <0 0x110000 0x200>; + interrupt-controller; }; nor_flash@1,0 { -- cgit v0.10.2 From c065909e47aea3575e51304e7411b46df22b20ca Mon Sep 17 00:00:00 2001 From: Ganesan Ramalingam Date: Tue, 29 Apr 2014 20:07:51 +0530 Subject: MIPS: Netlogic: PIC freq calculation for XLP 9XX/2XX Update PIC frequency calculation for XLP9XX and 2XX processors using the correct PLL registers. This should work for all possible board configurations. Signed-off-by: Ganesan Ramalingam Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6876/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h index 14b2f51..805bfd2 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/iomap.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/iomap.h @@ -120,6 +120,8 @@ #define XLP9XX_IO_UART_OFFSET(node) XLP9XX_HDR_OFFSET(node, 2, 2) #define XLP9XX_IO_SYS_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 0) #define XLP9XX_IO_FUSE_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 1) +#define XLP9XX_IO_CLOCK_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 2) +#define XLP9XX_IO_POWER_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 3) #define XLP9XX_IO_JTAG_OFFSET(node) XLP9XX_HDR_OFFSET(node, 6, 4) #define XLP9XX_IO_PCIE_OFFSET(node, i) XLP9XX_HDR_OFFSET(node, 1, i) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h index d9b107f..bcb136d 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h @@ -147,6 +147,28 @@ #define SYS_SYS_PLL_MEM_REQ 0x2a3 #define SYS_PLL_MEM_STAT 0x2a4 +/* PLL registers XLP9XX */ +#define SYS_9XX_DMC_PLL_CTRL0 0x140 +#define SYS_9XX_DMC_PLL_CTRL1 0x141 +#define SYS_9XX_DMC_PLL_CTRL2 0x142 +#define SYS_9XX_DMC_PLL_CTRL3 0x143 +#define SYS_9XX_PLL_CTRL0 0x144 +#define SYS_9XX_PLL_CTRL1 0x145 +#define SYS_9XX_PLL_CTRL2 0x146 +#define SYS_9XX_PLL_CTRL3 0x147 + +#define SYS_9XX_PLL_CTRL0_DEVX(x) (0x148 + (x) * 4) +#define SYS_9XX_PLL_CTRL1_DEVX(x) (0x149 + (x) * 4) +#define SYS_9XX_PLL_CTRL2_DEVX(x) (0x14a + (x) * 4) +#define SYS_9XX_PLL_CTRL3_DEVX(x) (0x14b + (x) * 4) + +#define SYS_9XX_CPU_PLL_CHG_CTRL 0x188 +#define SYS_9XX_PLL_CHG_CTRL 0x189 +#define SYS_9XX_CLK_DEV_DIS 0x18a +#define SYS_9XX_CLK_DEV_SEL 0x18b +#define SYS_9XX_CLK_DEV_DIV 0x18d +#define SYS_9XX_CLK_DEV_CHG 0x18f + /* Registers changed on 9XX */ #define SYS_9XX_POWER_ON_RESET_CFG 0x00 #define SYS_9XX_CHIP_RESET 0x01 @@ -170,6 +192,11 @@ #define nlm_get_fuse_regbase(node) \ (nlm_get_fuse_pcibase(node) + XLP_IO_PCI_HDRSZ) +#define nlm_get_clock_pcibase(node) \ + nlm_pcicfg_base(XLP9XX_IO_CLOCK_OFFSET(node)) +#define nlm_get_clock_regbase(node) \ + (nlm_get_clock_pcibase(node) + XLP_IO_PCI_HDRSZ) + unsigned int nlm_get_pic_frequency(int node); #endif #endif diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c index 13391b8..0c0a1a6 100644 --- a/arch/mips/netlogic/common/time.c +++ b/arch/mips/netlogic/common/time.c @@ -82,6 +82,7 @@ static struct clocksource csrc_pic = { static void nlm_init_pic_timer(void) { uint64_t picbase = nlm_get_node(0)->picbase; + u32 picfreq; nlm_pic_set_timer(picbase, PIC_CLOCK_TIMER, ~0ULL, 0, 0); if (current_cpu_data.cputype == CPU_XLR) { @@ -92,7 +93,9 @@ static void nlm_init_pic_timer(void) csrc_pic.read = nlm_get_pic_timer; } csrc_pic.rating = 1000; - clocksource_register_hz(&csrc_pic, pic_timer_freq()); + picfreq = pic_timer_freq(); + clocksource_register_hz(&csrc_pic, picfreq); + pr_info("PIC clock source added, frequency %d\n", picfreq); } void __init plat_time_init(void) diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 9f9814d..59f1303 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -234,21 +234,28 @@ unsigned int nlm_get_core_frequency(int node, int core) return (unsigned int)num; } -/* Calculate Frequency to the PIC from PLL. - * freq_out = ( ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13 ) / - * ((2^ctrl0[7:5]) * Table(ctrl0[26:24])) +/* + * Calculate PIC frequency from PLL registers. + * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) / + * ((2^ctrl0[7:5]) * Table(ctrl0[26:24])) */ -static unsigned int nlm_2xx_get_pic_frequency(int node) +static unsigned int nlm_xlp2_get_pic_frequency(int node) { - u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div; + u32 ctrl_val0, ctrl_val2, vco_post_div, pll_post_div, cpu_xlp9xx; u32 mdiv, fdiv, pll_out_freq_den, reg_select, ref_div, pic_div; - u64 ref_clk, sysbase, pll_out_freq_num, ref_clk_select; + u64 sysbase, pll_out_freq_num, ref_clk_select, clockbase, ref_clk; sysbase = nlm_get_node(node)->sysbase; + clockbase = nlm_get_clock_regbase(node); + cpu_xlp9xx = cpu_is_xlp9xx(); /* Find ref_clk_base */ - ref_clk_select = - (nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG) >> 18) & 0x3; + if (cpu_xlp9xx) + ref_clk_select = (nlm_read_sys_reg(sysbase, + SYS_9XX_POWER_ON_RESET_CFG) >> 18) & 0x3; + else + ref_clk_select = (nlm_read_sys_reg(sysbase, + SYS_POWER_ON_RESET_CFG) >> 18) & 0x3; switch (ref_clk_select) { case 0: ref_clk = 200000000ULL; @@ -269,30 +276,70 @@ static unsigned int nlm_2xx_get_pic_frequency(int node) } /* Find the clock source PLL device for PIC */ - reg_select = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_SEL) >> 22) & 0x3; - switch (reg_select) { - case 0: - ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0); - ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2); - break; - case 1: - ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(0)); - ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(0)); - break; - case 2: - ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(1)); - ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(1)); - break; - case 3: - ctrl_val0 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL0_DEVX(2)); - ctrl_val2 = nlm_read_sys_reg(sysbase, SYS_PLL_CTRL2_DEVX(2)); - break; + if (cpu_xlp9xx) { + reg_select = nlm_read_sys_reg(clockbase, + SYS_9XX_CLK_DEV_SEL) & 0x3; + switch (reg_select) { + case 0: + ctrl_val0 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL0); + ctrl_val2 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL2); + break; + case 1: + ctrl_val0 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL0_DEVX(0)); + ctrl_val2 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL2_DEVX(0)); + break; + case 2: + ctrl_val0 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL0_DEVX(1)); + ctrl_val2 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL2_DEVX(1)); + break; + case 3: + ctrl_val0 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL0_DEVX(2)); + ctrl_val2 = nlm_read_sys_reg(clockbase, + SYS_9XX_PLL_CTRL2_DEVX(2)); + break; + } + } else { + reg_select = (nlm_read_sys_reg(sysbase, + SYS_CLK_DEV_SEL) >> 22) & 0x3; + switch (reg_select) { + case 0: + ctrl_val0 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL0); + ctrl_val2 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL2); + break; + case 1: + ctrl_val0 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL0_DEVX(0)); + ctrl_val2 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL2_DEVX(0)); + break; + case 2: + ctrl_val0 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL0_DEVX(1)); + ctrl_val2 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL2_DEVX(1)); + break; + case 3: + ctrl_val0 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL0_DEVX(2)); + ctrl_val2 = nlm_read_sys_reg(sysbase, + SYS_PLL_CTRL2_DEVX(2)); + break; + } } vco_post_div = (ctrl_val0 >> 5) & 0x7; pll_post_div = (ctrl_val0 >> 24) & 0x7; mdiv = ctrl_val2 & 0xff; - fdiv = (ctrl_val2 >> 8) & 0xfff; + fdiv = (ctrl_val2 >> 8) & 0x1fff; /* Find PLL post divider value */ switch (pll_post_div) { @@ -322,7 +369,12 @@ static unsigned int nlm_2xx_get_pic_frequency(int node) do_div(pll_out_freq_num, pll_out_freq_den); /* PIC post divider, which happens after PLL */ - pic_div = (nlm_read_sys_reg(sysbase, SYS_CLK_DEV_DIV) >> 22) & 0x3; + if (cpu_xlp9xx) + pic_div = nlm_read_sys_reg(clockbase, + SYS_9XX_CLK_DEV_DIV) & 0x3; + else + pic_div = (nlm_read_sys_reg(sysbase, + SYS_CLK_DEV_DIV) >> 22) & 0x3; do_div(pll_out_freq_num, 1 << pic_div); return pll_out_freq_num; @@ -330,12 +382,8 @@ static unsigned int nlm_2xx_get_pic_frequency(int node) unsigned int nlm_get_pic_frequency(int node) { - /* TODO Has to calculate freq as like 2xx */ - if (cpu_is_xlp9xx()) - return 250000000; - if (cpu_is_xlpii()) - return nlm_2xx_get_pic_frequency(node); + return nlm_xlp2_get_pic_frequency(node); else return 133333333; } -- cgit v0.10.2 From edf3ed5e69bcf3f60087099eccab34be0ebcf60a Mon Sep 17 00:00:00 2001 From: Jayachandran C Date: Tue, 29 Apr 2014 20:07:52 +0530 Subject: MIPS: Netlogic: Update XLP9XX/2XX core freq calculation Calculate XLP 9XX and 2XX core frequency from the per-core PLL. This should give the correct value for all board configurations. Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6870/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/netlogic/xlp-hal/sys.h b/arch/mips/include/asm/netlogic/xlp-hal/sys.h index bcb136d..bc7bddf 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/sys.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/sys.h @@ -118,6 +118,10 @@ #define SYS_SCRTCH3 0x4c /* PLL registers XLP2XX */ +#define SYS_CPU_PLL_CTRL0(core) (0x1c0 + (core * 4)) +#define SYS_CPU_PLL_CTRL1(core) (0x1c1 + (core * 4)) +#define SYS_CPU_PLL_CTRL2(core) (0x1c2 + (core * 4)) +#define SYS_CPU_PLL_CTRL3(core) (0x1c3 + (core * 4)) #define SYS_PLL_CTRL0 0x240 #define SYS_PLL_CTRL1 0x241 #define SYS_PLL_CTRL2 0x242 @@ -148,6 +152,10 @@ #define SYS_PLL_MEM_STAT 0x2a4 /* PLL registers XLP9XX */ +#define SYS_9XX_CPU_PLL_CTRL0(core) (0xc0 + (core * 4)) +#define SYS_9XX_CPU_PLL_CTRL1(core) (0xc1 + (core * 4)) +#define SYS_9XX_CPU_PLL_CTRL2(core) (0xc2 + (core * 4)) +#define SYS_9XX_CPU_PLL_CTRL3(core) (0xc3 + (core * 4)) #define SYS_9XX_DMC_PLL_CTRL0 0x140 #define SYS_9XX_DMC_PLL_CTRL1 0x141 #define SYS_9XX_DMC_PLL_CTRL2 0x142 diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 59f1303..bc24beb 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c @@ -206,34 +206,81 @@ int nlm_irq_to_irt(int irq) return xlp_irq_to_irt(irq); } -unsigned int nlm_get_core_frequency(int node, int core) +static unsigned int nlm_xlp2_get_core_frequency(int node, int core) +{ + unsigned int pll_post_div, ctrl_val0, ctrl_val1, denom; + uint64_t num, sysbase, clockbase; + + if (cpu_is_xlp9xx()) { + clockbase = nlm_get_clock_regbase(node); + ctrl_val0 = nlm_read_sys_reg(clockbase, + SYS_9XX_CPU_PLL_CTRL0(core)); + ctrl_val1 = nlm_read_sys_reg(clockbase, + SYS_9XX_CPU_PLL_CTRL1(core)); + } else { + sysbase = nlm_get_node(node)->sysbase; + ctrl_val0 = nlm_read_sys_reg(sysbase, + SYS_CPU_PLL_CTRL0(core)); + ctrl_val1 = nlm_read_sys_reg(sysbase, + SYS_CPU_PLL_CTRL1(core)); + } + + /* Find PLL post divider value */ + switch ((ctrl_val0 >> 24) & 0x7) { + case 1: + pll_post_div = 2; + break; + case 3: + pll_post_div = 4; + break; + case 7: + pll_post_div = 8; + break; + case 6: + pll_post_div = 16; + break; + case 0: + default: + pll_post_div = 1; + break; + } + + num = 1000000ULL * (400 * 3 + 100 * (ctrl_val1 & 0x3f)); + denom = 3 * pll_post_div; + do_div(num, denom); + + return (unsigned int)num; +} + +static unsigned int nlm_xlp_get_core_frequency(int node, int core) { unsigned int pll_divf, pll_divr, dfs_div, ext_div; unsigned int rstval, dfsval, denom; uint64_t num, sysbase; sysbase = nlm_get_node(node)->sysbase; - if (cpu_is_xlp9xx()) - rstval = nlm_read_sys_reg(sysbase, SYS_9XX_POWER_ON_RESET_CFG); - else - rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); - if (cpu_is_xlpii()) { - num = 1000000ULL * (400 * 3 + 100 * (rstval >> 26)); - denom = 3; - } else { - dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); - pll_divf = ((rstval >> 10) & 0x7f) + 1; - pll_divr = ((rstval >> 8) & 0x3) + 1; - ext_div = ((rstval >> 30) & 0x3) + 1; - dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; - - num = 800000000ULL * pll_divf; - denom = 3 * pll_divr * ext_div * dfs_div; - } + rstval = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG); + dfsval = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIV_VALUE); + pll_divf = ((rstval >> 10) & 0x7f) + 1; + pll_divr = ((rstval >> 8) & 0x3) + 1; + ext_div = ((rstval >> 30) & 0x3) + 1; + dfs_div = ((dfsval >> (core * 4)) & 0xf) + 1; + + num = 800000000ULL * pll_divf; + denom = 3 * pll_divr * ext_div * dfs_div; do_div(num, denom); + return (unsigned int)num; } +unsigned int nlm_get_core_frequency(int node, int core) +{ + if (cpu_is_xlpii()) + return nlm_xlp2_get_core_frequency(node, core); + else + return nlm_xlp_get_core_frequency(node, core); +} + /* * Calculate PIC frequency from PLL registers. * freq_out = (ref_freq/2 * (6 + ctrl2[7:0]) + ctrl2[20:8]/2^13) / -- cgit v0.10.2 From 1c98398662c9b4e2f03f64344f83dd6cb14e0420 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Tue, 29 Apr 2014 20:07:53 +0530 Subject: MIPS: Netlogic: Add support for XLP5XX Add support for the XLP5XX processor which is an 8 core variant of the XLP9XX. Add XLP5XX cases to code which earlier handled XLP9XX. Signed-off-by: Yonghong Song Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6871/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index 39826a7..129d087 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -201,6 +201,7 @@ #define PRID_IMP_NETLOGIC_XLP3XX 0x1100 #define PRID_IMP_NETLOGIC_XLP2XX 0x1200 #define PRID_IMP_NETLOGIC_XLP9XX 0x1500 +#define PRID_IMP_NETLOGIC_XLP5XX 0x1300 /* * Particular Revision values for bits 7:0 of the PRId register. diff --git a/arch/mips/include/asm/netlogic/mips-extns.h b/arch/mips/include/asm/netlogic/mips-extns.h index 38af905..06f1f75 100644 --- a/arch/mips/include/asm/netlogic/mips-extns.h +++ b/arch/mips/include/asm/netlogic/mips-extns.h @@ -148,7 +148,8 @@ static inline int nlm_nodeid(void) { uint32_t prid = read_c0_prid() & PRID_IMP_MASK; - if (prid == PRID_IMP_NETLOGIC_XLP9XX) + if ((prid == PRID_IMP_NETLOGIC_XLP9XX) || + (prid == PRID_IMP_NETLOGIC_XLP5XX)) return (__read_32bit_c0_register($15, 1) >> 7) & 0x7; else return (__read_32bit_c0_register($15, 1) >> 5) & 0x3; diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index a11b289..62d1987 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -102,14 +102,16 @@ static inline int cpu_is_xlpii(void) int chip = read_c0_prid() & PRID_IMP_MASK; return chip == PRID_IMP_NETLOGIC_XLP2XX || - chip == PRID_IMP_NETLOGIC_XLP9XX; + chip == PRID_IMP_NETLOGIC_XLP9XX || + chip == PRID_IMP_NETLOGIC_XLP5XX; } static inline int cpu_is_xlp9xx(void) { int chip = read_c0_prid() & PRID_IMP_MASK; - return chip == PRID_IMP_NETLOGIC_XLP9XX; + return chip == PRID_IMP_NETLOGIC_XLP9XX || + chip == PRID_IMP_NETLOGIC_XLP5XX; } #endif /* !__ASSEMBLY__ */ #endif /* _ASM_NLM_XLP_H */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e8638c5..f34000b 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1059,6 +1059,7 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) switch (c->processor_id & PRID_IMP_MASK) { case PRID_IMP_NETLOGIC_XLP2XX: case PRID_IMP_NETLOGIC_XLP9XX: + case PRID_IMP_NETLOGIC_XLP5XX: c->cputype = CPU_XLP; __cpu_name[cpu] = "Broadcom XLPII"; break; diff --git a/arch/mips/netlogic/common/reset.S b/arch/mips/netlogic/common/reset.S index 5b60b46..701c4bc 100644 --- a/arch/mips/netlogic/common/reset.S +++ b/arch/mips/netlogic/common/reset.S @@ -177,6 +177,10 @@ FEXPORT(nlm_reset_entry) beq t0, t1, 2f /* does not need to set coherent */ nop + li t1, 0x1300 /* XLP 5xx */ + beq t0, t1, 2f /* does not need to set coherent */ + nop + /* set bit in SYS coherent register for the core */ mfc0 t0, CP0_EBASE, 1 mfc0 t1, CP0_EBASE, 1 diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c index 0b36ac8..bba993a 100644 --- a/arch/mips/netlogic/xlp/dt.c +++ b/arch/mips/netlogic/xlp/dt.c @@ -51,6 +51,7 @@ void __init *xlp_dt_init(void *fdtp) switch (current_cpu_data.processor_id & PRID_IMP_MASK) { #ifdef CONFIG_DT_XLP_GVP case PRID_IMP_NETLOGIC_XLP9XX: + case PRID_IMP_NETLOGIC_XLP5XX: fdtp = __dtb_xlp_gvp_begin; break; #endif diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c index 1ddb62b..4fdd9fd 100644 --- a/arch/mips/netlogic/xlp/setup.c +++ b/arch/mips/netlogic/xlp/setup.c @@ -123,6 +123,7 @@ const char *get_system_type(void) { switch (read_c0_prid() & PRID_IMP_MASK) { case PRID_IMP_NETLOGIC_XLP9XX: + case PRID_IMP_NETLOGIC_XLP5XX: case PRID_IMP_NETLOGIC_XLP2XX: return "Broadcom XLPII Series"; default: diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index f4823ad..e5f44d2 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c @@ -135,7 +135,15 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) if (cpu_is_xlp9xx()) { fusebase = nlm_get_fuse_regbase(n); fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6); - mask = 0xfffff; + switch (read_c0_prid() & PRID_IMP_MASK) { + case PRID_IMP_NETLOGIC_XLP5XX: + mask = 0xff; + break; + case PRID_IMP_NETLOGIC_XLP9XX: + default: + mask = 0xfffff; + break; + } } else { fusemask = nlm_read_sys_reg(nodep->sysbase, SYS_EFUSE_DEVICE_CFG_STATUS0); -- cgit v0.10.2 From d66f3f0e10b49df8d0cc0d8eb5bf2ef9863a33cf Mon Sep 17 00:00:00 2001 From: Ganesan Ramalingam Date: Fri, 9 May 2014 16:35:49 +0530 Subject: MIPS: Add MSI support for XLP9XX In XLP9XX, the interrupt routing table for MSI-X has been moved to the PCIe controller's config space from PIC. There are also 32 MSI-X interrupts available per link on XLP9XX. Update XLP MSI/MSI-X code to handle this. Signed-off-by: Ganesan Ramalingam Signed-off-by: Jayachandran C Cc: g@linux-mips.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6912/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h index d4deb87..91540f4 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h @@ -69,6 +69,20 @@ #define PCIE_9XX_BYTE_SWAP_IO_BASE 0x25e #define PCIE_9XX_BYTE_SWAP_IO_LIM 0x25f +#define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE 0x264 +#define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT 0x265 +#define PCIE_9XX_MSI_STATUS 0x283 +#define PCIE_9XX_MSI_EN 0x284 +/* 128 MSIX vectors available in 9xx */ +#define PCIE_9XX_MSIX_STATUS0 0x286 +#define PCIE_9XX_MSIX_STATUSX(n) (n + 0x286) +#define PCIE_9XX_MSIX_VEC 0x296 +#define PCIE_9XX_MSIX_VECX(n) (n + 0x296) +#define PCIE_9XX_INT_STATUS0 0x397 +#define PCIE_9XX_INT_STATUS1 0x398 +#define PCIE_9XX_INT_EN0 0x399 +#define PCIE_9XX_INT_EN1 0x39a + /* other */ #define PCIE_NLINKS 4 diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index f10bf3b..41cefe9 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h @@ -199,6 +199,10 @@ #define PIC_IRT_PCIE_LINK_3_INDEX 81 #define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX) +#define PIC_9XX_IRT_PCIE_LINK_0_INDEX 191 +#define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \ + ((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX) + #define PIC_CLOCK_TIMER 7 #if !defined(LOCORE) && !defined(__ASSEMBLY__) diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index 62d1987..a862b93 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h @@ -70,8 +70,9 @@ #define PIC_PCIE_MSIX_IRQ_BASE 48 /* 48 - 51 MSI-X IRQ */ #define PIC_PCIE_MSIX_IRQ(i) (48 + (i)) -#define NLM_MSIX_VEC_BASE 96 /* 96 - 127 - MSIX mapped */ -#define NLM_MSI_VEC_BASE 128 /* 128 -255 - MSI mapped */ +/* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */ +#define NLM_MSIX_VEC_BASE 96 /* 96 - 223 - MSIX mapped */ +#define NLM_MSI_VEC_BASE 224 /* 224 -351 - MSI mapped */ #define NLM_PIC_INDIRECT_VEC_BASE 512 #define NLM_GPIO_VEC_BASE 768 diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c index afd8405..1ef3ed6 100644 --- a/arch/mips/pci/msi-xlp.c +++ b/arch/mips/pci/msi-xlp.c @@ -56,8 +56,8 @@ #include #define XLP_MSIVEC_PER_LINK 32 -#define XLP_MSIXVEC_TOTAL 32 -#define XLP_MSIXVEC_PER_LINK 8 +#define XLP_MSIXVEC_TOTAL (cpu_is_xlp9xx() ? 128 : 32) +#define XLP_MSIXVEC_PER_LINK (cpu_is_xlp9xx() ? 32 : 8) /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */ static inline int nlm_link_msiirq(int link, int msivec) @@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec) return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec; } +/* get the link MSI vector from irq number */ static inline int nlm_irq_msivec(int irq) { - return irq % XLP_MSIVEC_PER_LINK; + return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK; } +/* get the link from the irq number */ static inline int nlm_irq_msilink(int irq) { - return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) / - XLP_MSIVEC_PER_LINK; + int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS; + + return ((irq - NLM_MSI_VEC_BASE) % total_msivec) / + XLP_MSIVEC_PER_LINK; } /* - * Only 32 MSI-X vectors are possible because there are only 32 PIC - * interrupts for MSI. We split them statically and use 8 MSI-X vectors - * per link - this keeps the allocation and lookup simple. + * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because + * there are only 32 PIC interrupts for MSI. We split them statically + * and use 8 MSI-X vectors per link - this keeps the allocation and + * lookup simple. + * On XLP 9xx, there are 32 vectors per link, and the interrupts are + * not routed thru PIC, so we can use all 128 MSI-X vectors. */ static inline int nlm_link_msixirq(int link, int bit) { return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit; } +/* get the link MSI vector from irq number */ static inline int nlm_irq_msixvec(int irq) { - return irq % XLP_MSIXVEC_TOTAL; /* works when given xirq */ + return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL; } -static inline int nlm_irq_msixlink(int irq) +/* get the link from MSIX vec */ +static inline int nlm_irq_msixlink(int msixvec) { - return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK; + return msixvec / XLP_MSIXVEC_PER_LINK; } /* @@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d) vec = nlm_irq_msivec(d->irq); spin_lock_irqsave(&md->msi_lock, flags); md->msi_enabled_mask |= 1u << vec; - nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); + if (cpu_is_xlp9xx()) + nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, + md->msi_enabled_mask); + else + nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); spin_unlock_irqrestore(&md->msi_lock, flags); } @@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d) vec = nlm_irq_msivec(d->irq); spin_lock_irqsave(&md->msi_lock, flags); md->msi_enabled_mask &= ~(1u << vec); - nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); + if (cpu_is_xlp9xx()) + nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, + md->msi_enabled_mask); + else + nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); spin_unlock_irqrestore(&md->msi_lock, flags); } @@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d) xlp_msi_disable(d); /* Ack MSI on bridge */ - nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); + if (cpu_is_xlp9xx()) + nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec); + else + nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); /* Ack at eirr and PIC */ ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); - nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); + if (cpu_is_xlp9xx()) + nlm_pic_ack(md->node->picbase, + PIC_9XX_IRT_PCIE_LINK_INDEX(link)); + else + nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); } static struct irq_chip xlp_msi_chip = { @@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = { }; /* - * The MSI-X interrupt handling is different from MSI, there are 32 - * MSI-X interrupts generated by the PIC and each of these correspond - * to a MSI-X vector (0-31) that can be assigned. + * XLP8XX/4XX/3XX/2XX: + * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X + * interrupts generated by the PIC and each of these correspond to a MSI-X + * vector (0-31) that can be assigned. * - * We divide the MSI-X vectors to 8 per link and do a per-link - * allocation + * We divide the MSI-X vectors to 8 per link and do a per-link allocation + * + * XLP9XX: + * 32 MSI-X vectors are available per link, and the interrupts are not routed + * thru the PIC. PIC ack not needed. * * Enable and disable done using standard MSI functions. */ static void xlp_msix_mask_ack(struct irq_data *d) { - struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + struct xlp_msi_data *md; int link, msixvec; + uint32_t status_reg, bit; msixvec = nlm_irq_msixvec(d->irq); - link = nlm_irq_msixlink(d->irq); + link = nlm_irq_msixlink(msixvec); mask_msi_irq(d); + md = irq_data_get_irq_handler_data(d); /* Ack MSI on bridge */ - nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec); + if (cpu_is_xlp9xx()) { + status_reg = PCIE_9XX_MSIX_STATUSX(link); + bit = msixvec % XLP_MSIXVEC_PER_LINK; + } else { + status_reg = PCIE_MSIX_STATUS; + bit = msixvec; + } + nlm_write_reg(md->lnkbase, status_reg, 1u << bit); /* Ack at eirr and PIC */ ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); - nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec)); + if (!cpu_is_xlp9xx()) + nlm_pic_ack(md->node->picbase, + PIC_IRT_PCIE_MSIX_INDEX(msixvec)); } static struct irq_chip xlp_msix_chip = { @@ -225,10 +264,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr) { u32 val; - val = nlm_read_reg(lnkbase, PCIE_INT_EN0); - if ((val & 0x200) == 0) { - val |= 0x200; /* MSI Interrupt enable */ - nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + if (cpu_is_xlp9xx()) { + val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); + } + } else { + val = nlm_read_reg(lnkbase, PCIE_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; + nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + } } val = nlm_read_reg(lnkbase, 0x1); /* CMD */ @@ -275,9 +322,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link, spin_lock_irqsave(&md->msi_lock, flags); if (md->msi_alloc_mask == 0) { - /* switch the link IRQ to MSI range */ xlp_config_link_msi(lnkbase, lirq, msiaddr); - irt = PIC_IRT_PCIE_LINK_INDEX(link); + /* switch the link IRQ to MSI range */ + if (cpu_is_xlp9xx()) + irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link); + else + irt = PIC_IRT_PCIE_LINK_INDEX(link); nlm_setup_pic_irq(node, lirq, lirq, irt); nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, node * nlm_threads_per_node(), 1 /*en */); @@ -319,10 +369,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) val |= 0x80000000U; nlm_write_reg(lnkbase, 0x2C, val); } - val = nlm_read_reg(lnkbase, PCIE_INT_EN0); - if ((val & 0x200) == 0) { - val |= 0x200; /* MSI Interrupt enable */ - nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + + if (cpu_is_xlp9xx()) { + val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); + } + } else { + val = nlm_read_reg(lnkbase, PCIE_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + } } val = nlm_read_reg(lnkbase, 0x1); /* CMD */ @@ -337,10 +396,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) val |= (1 << 8) | lirq; nlm_write_pci_reg(lnkbase, 0xf, val); - /* MSI-X addresses */ - nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8); - nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, - (msixaddr + MSI_ADDR_SZ) >> 8); + if (cpu_is_xlp9xx()) { + /* MSI-X addresses */ + nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE, + msixaddr >> 8); + nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT, + (msixaddr + MSI_ADDR_SZ) >> 8); + } else { + /* MSI-X addresses */ + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, + msixaddr >> 8); + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, + (msixaddr + MSI_ADDR_SZ) >> 8); + } } /* @@ -377,6 +445,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link, xirq += t; msixvec = nlm_irq_msixvec(xirq); + msg.address_hi = msixaddr >> 32; msg.address_lo = msixaddr & 0xffffffff; msg.data = 0xc00 | msixvec; @@ -417,7 +486,7 @@ void __init xlp_init_node_msi_irqs(int node, int link) { struct nlm_soc_info *nodep; struct xlp_msi_data *md; - int irq, i, irt, msixvec; + int irq, i, irt, msixvec, val; pr_info("[%d %d] Init node PCI IRT\n", node, link); nodep = nlm_get_node(node); @@ -438,19 +507,28 @@ void __init xlp_init_node_msi_irqs(int node, int link) irq_set_handler_data(i, md); } - for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) { - /* Initialize MSI-X irts to generate one interrupt per link */ - msixvec = link * XLP_MSIXVEC_PER_LINK + i; - irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); - nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link), - node * nlm_threads_per_node(), 1 /* enable */); + for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) { + if (cpu_is_xlp9xx()) { + val = ((node * nlm_threads_per_node()) << 7 | + PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0); + nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i + + (link * XLP_MSIXVEC_PER_LINK)), val); + } else { + /* Initialize MSI-X irts to generate one interrupt + * per link + */ + msixvec = link * XLP_MSIXVEC_PER_LINK + i; + irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); + nlm_pic_init_irt(nodep->picbase, irt, + PIC_PCIE_MSIX_IRQ(link), + node * nlm_threads_per_node(), 1); + } /* Initialize MSI-X extended irq space for the link */ irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); irq_set_handler_data(irq, md); } - } void nlm_dispatch_msi(int node, int lirq) @@ -462,7 +540,11 @@ void nlm_dispatch_msi(int node, int lirq) link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); md = irq_get_handler_data(irqbase); - status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & + if (cpu_is_xlp9xx()) + status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) & + md->msi_enabled_mask; + else + status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & md->msi_enabled_mask; while (status) { i = __ffs(status); @@ -480,10 +562,14 @@ void nlm_dispatch_msix(int node, int lirq) link = lirq - PIC_PCIE_MSIX_IRQ_BASE; irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); md = irq_get_handler_data(irqbase); - status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); + if (cpu_is_xlp9xx()) + status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link)); + else + status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); /* narrow it down to the MSI-x vectors for our link */ - status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & + if (!cpu_is_xlp9xx()) + status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & ((1 << XLP_MSIXVEC_PER_LINK) - 1); while (status) { -- cgit v0.10.2 From a951440971d0f5fa910bb6d0df1a502fa88d5087 Mon Sep 17 00:00:00 2001 From: Ganesan Ramalingam Date: Tue, 29 Apr 2014 20:07:55 +0530 Subject: MIPS: Netlogic: Support for XLP3XX on-chip SATA XLP3XX includes an on-chip SATA controller with 4 ports. The controller needs glue logic initialization and PCI fixup before it can be used with the standard AHCI driver. Signed-off-by: Ganesan Ramalingam Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6872/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile index ed9a93c..0cb53af 100644 --- a/arch/mips/netlogic/xlp/Makefile +++ b/arch/mips/netlogic/xlp/Makefile @@ -2,3 +2,4 @@ obj-y += setup.o nlm_hal.o cop2-ex.o dt.o obj-$(CONFIG_SMP) += wakeup.o obj-$(CONFIG_USB) += usb-init.o obj-$(CONFIG_USB) += usb-init-xlp2.o +obj-$(CONFIG_SATA_AHCI) += ahci-init.o diff --git a/arch/mips/netlogic/xlp/ahci-init.c b/arch/mips/netlogic/xlp/ahci-init.c new file mode 100644 index 0000000..a9d0fae --- /dev/null +++ b/arch/mips/netlogic/xlp/ahci-init.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2003-2014 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define SATA_CTL 0x0 +#define SATA_STATUS 0x1 /* Status Reg */ +#define SATA_INT 0x2 /* Interrupt Reg */ +#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */ +#define SATA_CR_REG_TIMER 0x4 /* PHY Conrol Timer Reg */ +#define SATA_CORE_ID 0x5 /* Core ID Reg */ +#define SATA_AXI_SLAVE_OPT1 0x6 /* AXI Slave Options Reg */ +#define SATA_PHY_LOS_LEV 0x7 /* PHY LOS Level Reg */ +#define SATA_PHY_MULTI 0x8 /* PHY Multiplier Reg */ +#define SATA_PHY_CLK_SEL 0x9 /* Clock Select Reg */ +#define SATA_PHY_AMP1_GEN1 0xa /* PHY Transmit Amplitude Reg 1 */ +#define SATA_PHY_AMP1_GEN2 0xb /* PHY Transmit Amplitude Reg 2 */ +#define SATA_PHY_AMP1_GEN3 0xc /* PHY Transmit Amplitude Reg 3 */ +#define SATA_PHY_PRE1 0xd /* PHY Transmit Preemphasis Reg 1 */ +#define SATA_PHY_PRE2 0xe /* PHY Transmit Preemphasis Reg 2 */ +#define SATA_PHY_PRE3 0xf /* PHY Transmit Preemphasis Reg 3 */ +#define SATA_SPDMODE 0x10 /* Speed Mode Reg */ +#define SATA_REFCLK 0x11 /* Reference Clock Control Reg */ +#define SATA_BYTE_SWAP_DIS 0x12 /* byte swap disable */ + +/*SATA_CTL Bits */ +#define SATA_RST_N BIT(0) +#define PHY0_RESET_N BIT(16) +#define PHY1_RESET_N BIT(17) +#define PHY2_RESET_N BIT(18) +#define PHY3_RESET_N BIT(19) +#define M_CSYSREQ BIT(2) +#define S_CSYSREQ BIT(3) + +/*SATA_STATUS Bits */ +#define P0_PHY_READY BIT(4) +#define P1_PHY_READY BIT(5) +#define P2_PHY_READY BIT(6) +#define P3_PHY_READY BIT(7) + +#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r) +#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v) +#define nlm_get_sata_pcibase(node) \ + nlm_pcicfg_base(XLP_IO_SATA_OFFSET(node)) +/* SATA device specific configuration registers are starts at 0x900 offset */ +#define nlm_get_sata_regbase(node) \ + (nlm_get_sata_pcibase(node) + 0x900) + +static void sata_clear_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit) +{ + uint32_t reg_val; + + reg_val = nlm_read_sata_reg(regbase, off); + nlm_write_sata_reg(regbase, off, (reg_val & ~bit)); +} + +static void sata_set_glue_reg(uint64_t regbase, uint32_t off, uint32_t bit) +{ + uint32_t reg_val; + + reg_val = nlm_read_sata_reg(regbase, off); + nlm_write_sata_reg(regbase, off, (reg_val | bit)); +} + +static void nlm_sata_firmware_init(int node) +{ + uint32_t reg_val; + uint64_t regbase; + int i; + + pr_info("XLP AHCI Initialization started.\n"); + regbase = nlm_get_sata_regbase(node); + + /* Reset SATA */ + sata_clear_glue_reg(regbase, SATA_CTL, SATA_RST_N); + /* Reset PHY */ + sata_clear_glue_reg(regbase, SATA_CTL, + (PHY3_RESET_N | PHY2_RESET_N + | PHY1_RESET_N | PHY0_RESET_N)); + + /* Set SATA */ + sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N); + /* Set PHY */ + sata_set_glue_reg(regbase, SATA_CTL, + (PHY3_RESET_N | PHY2_RESET_N + | PHY1_RESET_N | PHY0_RESET_N)); + + pr_debug("Waiting for PHYs to come up.\n"); + i = 0; + do { + reg_val = nlm_read_sata_reg(regbase, SATA_STATUS); + i++; + } while (((reg_val & 0xF0) != 0xF0) && (i < 10000)); + + for (i = 0; i < 4; i++) { + if (reg_val & (P0_PHY_READY << i)) + pr_info("PHY%d is up.\n", i); + else + pr_info("PHY%d is down.\n", i); + } + + pr_info("XLP AHCI init done.\n"); +} + +static int __init nlm_ahci_init(void) +{ + int node = 0; + int chip = read_c0_prid() & PRID_REV_MASK; + + if (chip == PRID_IMP_NETLOGIC_XLP3XX) + nlm_sata_firmware_init(node); + return 0; +} + +static void nlm_sata_intr_ack(struct irq_data *data) +{ + uint32_t val = 0; + uint64_t regbase; + + regbase = nlm_get_sata_regbase(nlm_nodeid()); + val = nlm_read_sata_reg(regbase, SATA_INT); + sata_set_glue_reg(regbase, SATA_INT, val); +} + +static void nlm_sata_fixup_bar(struct pci_dev *dev) +{ + /* + * The AHCI resource is in BAR 0, move it to + * BAR 5, where it is expected + */ + dev->resource[5] = dev->resource[0]; + memset(&dev->resource[0], 0, sizeof(dev->resource[0])); +} + +static void nlm_sata_fixup_final(struct pci_dev *dev) +{ + uint32_t val; + uint64_t regbase; + int node = 0; /* XLP3XX does not support multi-node */ + + regbase = nlm_get_sata_regbase(node); + + /* clear pending interrupts and then enable them */ + val = nlm_read_sata_reg(regbase, SATA_INT); + sata_set_glue_reg(regbase, SATA_INT, val); + + /* Mask the core interrupt. If all the interrupts + * are enabled there are spurious interrupt flow + * happening, to avoid only enable core interrupt + * mask. + */ + sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1); + + dev->irq = PIC_SATA_IRQ; + nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack); +} + +arch_initcall(nlm_ahci_init); + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA, + nlm_sata_fixup_bar); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_SATA, + nlm_sata_fixup_final); -- cgit v0.10.2 From fedfcb1137d2426e2e7a8ff40aa0ac4ec44793a9 Mon Sep 17 00:00:00 2001 From: Ganesan Ramalingam Date: Fri, 9 May 2014 16:36:25 +0530 Subject: MIPS: Netlogic: XLP9XX on-chip SATA support The XLP9XX SoC has an on-chip SATA controller with two ports. Add ahci-init-xlp2.c to initialize the controller, setup the glue logic registers, fixup PCI quirks and setup interrupt ack logic. Signed-off-by: Ganesan Ramalingam Signed-off-by: Jayachandran C Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6913/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/netlogic/xlp/Makefile b/arch/mips/netlogic/xlp/Makefile index 0cb53af..be358a8 100644 --- a/arch/mips/netlogic/xlp/Makefile +++ b/arch/mips/netlogic/xlp/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_SMP) += wakeup.o obj-$(CONFIG_USB) += usb-init.o obj-$(CONFIG_USB) += usb-init-xlp2.o obj-$(CONFIG_SATA_AHCI) += ahci-init.o +obj-$(CONFIG_SATA_AHCI) += ahci-init-xlp2.o diff --git a/arch/mips/netlogic/xlp/ahci-init-xlp2.c b/arch/mips/netlogic/xlp/ahci-init-xlp2.c new file mode 100644 index 0000000..c83dbf3 --- /dev/null +++ b/arch/mips/netlogic/xlp/ahci-init-xlp2.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2003-2014 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define SATA_CTL 0x0 +#define SATA_STATUS 0x1 /* Status Reg */ +#define SATA_INT 0x2 /* Interrupt Reg */ +#define SATA_INT_MASK 0x3 /* Interrupt Mask Reg */ +#define SATA_BIU_TIMEOUT 0x4 +#define AXIWRSPERRLOG 0x5 +#define AXIRDSPERRLOG 0x6 +#define BiuTimeoutLow 0x7 +#define BiuTimeoutHi 0x8 +#define BiuSlvErLow 0x9 +#define BiuSlvErHi 0xa +#define IO_CONFIG_SWAP_DIS 0xb +#define CR_REG_TIMER 0xc +#define CORE_ID 0xd +#define AXI_SLAVE_OPT1 0xe +#define PHY_MEM_ACCESS 0xf +#define PHY0_CNTRL 0x10 +#define PHY0_STAT 0x11 +#define PHY0_RX_ALIGN 0x12 +#define PHY0_RX_EQ_LO 0x13 +#define PHY0_RX_EQ_HI 0x14 +#define PHY0_BIST_LOOP 0x15 +#define PHY1_CNTRL 0x16 +#define PHY1_STAT 0x17 +#define PHY1_RX_ALIGN 0x18 +#define PHY1_RX_EQ_LO 0x19 +#define PHY1_RX_EQ_HI 0x1a +#define PHY1_BIST_LOOP 0x1b +#define RdExBase 0x1c +#define RdExLimit 0x1d +#define CacheAllocBase 0x1e +#define CacheAllocLimit 0x1f +#define BiuSlaveCmdGstNum 0x20 + +/*SATA_CTL Bits */ +#define SATA_RST_N BIT(0) /* Active low reset sata_core phy */ +#define SataCtlReserve0 BIT(1) +#define M_CSYSREQ BIT(2) /* AXI master low power, not used */ +#define S_CSYSREQ BIT(3) /* AXI slave low power, not used */ +#define P0_CP_DET BIT(8) /* Reserved, bring in from pad */ +#define P0_MP_SW BIT(9) /* Mech Switch */ +#define P0_DISABLE BIT(10) /* disable p0 */ +#define P0_ACT_LED_EN BIT(11) /* Active LED enable */ +#define P0_IRST_HARD_SYNTH BIT(12) /* PHY hard synth reset */ +#define P0_IRST_HARD_TXRX BIT(13) /* PHY lane hard reset */ +#define P0_IRST_POR BIT(14) /* PHY power on reset*/ +#define P0_IPDTXL BIT(15) /* PHY Tx lane dis/power down */ +#define P0_IPDRXL BIT(16) /* PHY Rx lane dis/power down */ +#define P0_IPDIPDMSYNTH BIT(17) /* PHY synthesizer dis/porwer down */ +#define P0_CP_POD_EN BIT(18) /* CP_POD enable */ +#define P0_AT_BYPASS BIT(19) /* P0 address translation by pass */ +#define P1_CP_DET BIT(20) /* Reserved,Cold Detect */ +#define P1_MP_SW BIT(21) /* Mech Switch */ +#define P1_DISABLE BIT(22) /* disable p1 */ +#define P1_ACT_LED_EN BIT(23) /* Active LED enable */ +#define P1_IRST_HARD_SYNTH BIT(24) /* PHY hard synth reset */ +#define P1_IRST_HARD_TXRX BIT(25) /* PHY lane hard reset */ +#define P1_IRST_POR BIT(26) /* PHY power on reset*/ +#define P1_IPDTXL BIT(27) /* PHY Tx lane dis/porwer down */ +#define P1_IPDRXL BIT(28) /* PHY Rx lane dis/porwer down */ +#define P1_IPDIPDMSYNTH BIT(29) /* PHY synthesizer dis/porwer down */ +#define P1_CP_POD_EN BIT(30) +#define P1_AT_BYPASS BIT(31) /* P1 address translation by pass */ + +/* Status register */ +#define M_CACTIVE BIT(0) /* m_cactive, not used */ +#define S_CACTIVE BIT(1) /* s_cactive, not used */ +#define P0_PHY_READY BIT(8) /* phy is ready */ +#define P0_CP_POD BIT(9) /* Cold PowerOn */ +#define P0_SLUMBER BIT(10) /* power mode slumber */ +#define P0_PATIAL BIT(11) /* power mode patial */ +#define P0_PHY_SIG_DET BIT(12) /* phy dignal detect */ +#define P0_PHY_CALI BIT(13) /* phy calibration done */ +#define P1_PHY_READY BIT(16) /* phy is ready */ +#define P1_CP_POD BIT(17) /* Cold PowerOn */ +#define P1_SLUMBER BIT(18) /* power mode slumber */ +#define P1_PATIAL BIT(19) /* power mode patial */ +#define P1_PHY_SIG_DET BIT(20) /* phy dignal detect */ +#define P1_PHY_CALI BIT(21) /* phy calibration done */ + +/* SATA CR_REG_TIMER bits */ +#define CR_TIME_SCALE (0x1000 << 0) + +/* SATA PHY specific registers start and end address */ +#define RXCDRCALFOSC0 0x0065 +#define CALDUTY 0x006e +#define RXDPIF 0x8065 +#define PPMDRIFTMAX_HI 0x80A4 + +#define nlm_read_sata_reg(b, r) nlm_read_reg(b, r) +#define nlm_write_sata_reg(b, r, v) nlm_write_reg(b, r, v) +#define nlm_get_sata_pcibase(node) \ + nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node)) +#define nlm_get_sata_regbase(node) \ + (nlm_get_sata_pcibase(node) + 0x100) + +/* SATA PHY config for register block 1 0x0065 .. 0x006e */ +static const u8 sata_phy_config1[] = { + 0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00 +}; + +/* SATA PHY config for register block 2 0x0x8065 .. 0x0x80A4 */ +static const u8 sata_phy_config2[] = { + 0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18, + 0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF, + 0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD, + 0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, + 0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5, + 0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05, + 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04, +}; + +const int sata_phy_debug = 0; /* set to verify PHY writes */ + +static void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit) +{ + u32 reg_val; + + reg_val = nlm_read_sata_reg(regbase, off); + nlm_write_sata_reg(regbase, off, (reg_val & ~bit)); +} + +static void sata_set_glue_reg(u64 regbase, u32 off, u32 bit) +{ + u32 reg_val; + + reg_val = nlm_read_sata_reg(regbase, off); + nlm_write_sata_reg(regbase, off, (reg_val | bit)); +} + +static void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data) +{ + nlm_write_sata_reg(regbase, PHY_MEM_ACCESS, + (1u << 31) | (physel << 24) | (data << 16) | addr); + udelay(850); +} + +static u8 read_phy_reg(u64 regbase, u32 addr, u32 physel) +{ + u32 val; + + nlm_write_sata_reg(regbase, PHY_MEM_ACCESS, + (0 << 31) | (physel << 24) | (0 << 16) | addr); + udelay(850); + val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS); + return (val >> 16) & 0xff; +} + +static void config_sata_phy(u64 regbase) +{ + u32 port, i, reg; + + for (port = 0; port < 2; port++) { + for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++) + write_phy_reg(regbase, reg, port, sata_phy_config1[i]); + + for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++) + write_phy_reg(regbase, reg, port, sata_phy_config2[i]); + } +} + +static void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata) +{ + u8 data; + + data = read_phy_reg(regbase, addr, physel); + pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n", + addr, physel, data, data == xdata ? "TRUE" : "FALSE"); +} + +static void verify_sata_phy_config(u64 regbase) +{ + u32 port, i, reg; + + for (port = 0; port < 2; port++) { + for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++) + check_phy_register(regbase, reg, port, + sata_phy_config1[i]); + + for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++) + check_phy_register(regbase, reg, port, + sata_phy_config2[i]); + } +} + +static void nlm_sata_firmware_init(int node) +{ + u32 reg_val; + u64 regbase; + int n; + + pr_info("Initializing XLP9XX On-chip AHCI...\n"); + regbase = nlm_get_sata_regbase(node); + + /* Reset port0 */ + sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR); + sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX); + sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH); + sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL); + sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL); + sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH); + + /* port1 */ + sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR); + sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX); + sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH); + sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL); + sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL); + sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH); + udelay(300); + + /* Set PHY */ + sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL); + sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL); + sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH); + sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL); + sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL); + sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH); + + udelay(1000); + sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR); + udelay(1000); + sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR); + udelay(1000); + + /* setup PHY */ + config_sata_phy(regbase); + if (sata_phy_debug) + verify_sata_phy_config(regbase); + + udelay(1000); + sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX); + sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH); + sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX); + sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH); + udelay(300); + + /* Override reset in serial PHY mode */ + sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE); + /* Set reset SATA */ + sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N); + sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ); + sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ); + + pr_debug("Waiting for PHYs to come up.\n"); + n = 10000; + do { + reg_val = nlm_read_sata_reg(regbase, SATA_STATUS); + if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY)) + break; + udelay(10); + } while (--n > 0); + + if (reg_val & P0_PHY_READY) + pr_info("PHY0 is up.\n"); + else + pr_info("PHY0 is down.\n"); + if (reg_val & P1_PHY_READY) + pr_info("PHY1 is up.\n"); + else + pr_info("PHY1 is down.\n"); + + pr_info("XLP AHCI Init Done.\n"); +} + +static int __init nlm_ahci_init(void) +{ + int node; + + if (!cpu_is_xlp9xx()) + return 0; + for (node = 0; node < NLM_NR_NODES; node++) + if (nlm_node_present(node)) + nlm_sata_firmware_init(node); + return 0; +} + +static void nlm_sata_intr_ack(struct irq_data *data) +{ + u64 regbase; + u32 val; + int node; + + node = data->irq / NLM_IRQS_PER_NODE; + regbase = nlm_get_sata_regbase(node); + val = nlm_read_sata_reg(regbase, SATA_INT); + sata_set_glue_reg(regbase, SATA_INT, val); +} + +static void nlm_sata_fixup_bar(struct pci_dev *dev) +{ + dev->resource[5] = dev->resource[0]; + memset(&dev->resource[0], 0, sizeof(dev->resource[0])); +} + +static void nlm_sata_fixup_final(struct pci_dev *dev) +{ + u32 val; + u64 regbase; + int node; + + /* Find end bridge function to find node */ + node = xlp_socdev_to_node(dev); + regbase = nlm_get_sata_regbase(node); + + /* clear pending interrupts and then enable them */ + val = nlm_read_sata_reg(regbase, SATA_INT); + sata_set_glue_reg(regbase, SATA_INT, val); + + /* Enable only the core interrupt */ + sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1); + + dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ); + nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack); +} + +arch_initcall(nlm_ahci_init); + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA, + nlm_sata_fixup_bar); + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA, + nlm_sata_fixup_final); -- cgit v0.10.2 From 06947aaaf9bf7da0b29e211ee1a44f3ca91c08fa Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 6 Apr 2014 21:31:29 +0100 Subject: MIPS: Implement random_get_entropy with CP0 Random Update to commit 9c9b415c50bc298ac61412dff856eae2f54889ee [MIPS: Reimplement get_cycles().] On systems were for whatever reasons we can't use the cycle counter, fall back to the c0_random register as an entropy source. It has however a very small range that makes it suitable for random_get_entropy only and not get_cycles. This optimised version compiles to 8 instructions in the fast path even in the worst case of all the conditions to check being variable (including a MFC0 move delay slot that is only required for very old processors): 828: 8cf90000 lw t9,0(a3) 828: R_MIPS_LO16 jiffies 82c: 40057800 mfc0 a1,c0_prid 830: 3c0200ff lui v0,0xff 834: 00a21024 and v0,a1,v0 838: 1040007d beqz v0,a30 83c: 3c030000 lui v1,0x0 83c: R_MIPS_HI16 cpu_data 840: 40024800 mfc0 v0,c0_count 844: 00000000 nop 848: 00409021 move s2,v0 84c: 8ce20000 lw v0,0(a3) 84c: R_MIPS_LO16 jiffies On most targets the sequence will be shorter and on some it will reduce to a single `MFC0 ,c0_count', as all MIPS architecture (i.e. non-legacy MIPS) processors require the CP0 Count register to be present. The only known exception that reports MIPS architecture compliance, but contrary to that lacks CP0 Count is the Ingenic JZ4740 thingy. For broken platforms like that this code requires cpu_has_counter to be hardcoded to 0 (i.e. no variable setting is permitted) so as not to penalise all the other good platforms out there. The asm barrier is required so that the compiler does not pull any potentially costly (cold cache!) `cpu_data' variable access into the fast path. Signed-off-by: Ralf Baechle Signed-off-by: Maciej W. Rozycki Cc: Theodore Ts'o Cc: John Crispin Cc: Andrew McGregor Cc: Dave Taht Cc: Felix Fietkau Cc: Simon Kelley Cc: Jim Gettys Cc: David Daney Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6702/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h index c542475..b05bb70 100644 --- a/arch/mips/include/asm/timex.h +++ b/arch/mips/include/asm/timex.h @@ -4,12 +4,16 @@ * for more details. * * Copyright (C) 1998, 1999, 2003 by Ralf Baechle + * Copyright (C) 2014 by Maciej W. Rozycki */ #ifndef _ASM_TIMEX_H #define _ASM_TIMEX_H #ifdef __KERNEL__ +#include + +#include #include #include #include @@ -45,29 +49,54 @@ typedef unsigned int cycles_t; * However for now the implementaton of this function doesn't get these * fine details right. */ -static inline cycles_t get_cycles(void) +static inline int can_use_mips_counter(unsigned int prid) { - switch (boot_cpu_type()) { - case CPU_R4400PC: - case CPU_R4400SC: - case CPU_R4400MC: - if ((read_c0_prid() & 0xff) >= 0x0050) - return read_c0_count(); - break; + int comp = (prid & PRID_COMP_MASK) != PRID_COMP_LEGACY; - case CPU_R4000PC: - case CPU_R4000SC: - case CPU_R4000MC: - break; + if (__builtin_constant_p(cpu_has_counter) && !cpu_has_counter) + return 0; + else if (__builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r) + return 1; + else if (likely(!__builtin_constant_p(cpu_has_mips_r) && comp)) + return 1; + /* Make sure we don't peek at cpu_data[0].options in the fast path! */ + if (!__builtin_constant_p(cpu_has_counter)) + asm volatile("" : "=m" (cpu_data[0].options)); + if (likely(cpu_has_counter && + prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0)))) + return 1; + else + return 0; +} - default: - if (cpu_has_counter) - return read_c0_count(); - break; - } +static inline cycles_t get_cycles(void) +{ + if (can_use_mips_counter(read_c0_prid())) + return read_c0_count(); + else + return 0; /* no usable counter */ +} + +/* + * Like get_cycles - but where c0_count is not available we desperately + * use c0_random in an attempt to get at least a little bit of entropy. + * + * R6000 and R6000A neither have a count register nor a random register. + * That leaves no entropy source in the CPU itself. + */ +static inline unsigned long random_get_entropy(void) +{ + unsigned int prid = read_c0_prid(); + unsigned int imp = prid & PRID_IMP_MASK; - return 0; /* no usable counter */ + if (can_use_mips_counter(prid)) + return read_c0_count(); + else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A)) + return read_c0_random(); + else + return 0; /* no usable register */ } +#define random_get_entropy random_get_entropy #endif /* __KERNEL__ */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f34000b..b1b580d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1026,6 +1026,7 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) decode_configs(c); /* JZRISC does not implement the CP0 counter. */ c->options &= ~MIPS_CPU_COUNTER; + BUG_ON(!__builtin_constant_p(cpu_has_counter) || cpu_has_counter); switch (c->processor_id & PRID_IMP_MASK) { case PRID_IMP_JZRISC: c->cputype = CPU_JZRISC; -- cgit v0.10.2 From e496453d3e15ae3e153a03116cb6070e00ec63ee Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 6 Apr 2014 21:42:49 +0100 Subject: MIPS: __delay ABI-dependent subtraction simplification This small update to the previous fix to __delay removes a conditional around the ABI-dependent subtraction operation within an inline asm in favor to the standard LONG_SUBU macro. No change in code produced. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6703/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c index 705cfb7..21d27c6 100644 --- a/arch/mips/lib/delay.c +++ b/arch/mips/lib/delay.c @@ -11,7 +11,9 @@ #include #include #include +#include +#include #include #include @@ -27,11 +29,7 @@ void __delay(unsigned long loops) " .set noreorder \n" " .align 3 \n" "1: bnez %0, 1b \n" -#if BITS_PER_LONG == 32 - " subu %0, %1 \n" -#else - " dsubu %0, %1 \n" -#endif + " " __stringify(LONG_SUBU) " %0, %1 \n" " .set reorder \n" : "=r" (loops) : GCC_DADDI_IMM_ASM() (1), "0" (loops)); -- cgit v0.10.2 From 81d10bad0a5c5d82b1b5fea70fc84f71492e9235 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 6 Apr 2014 21:46:05 +0100 Subject: MIPS: DEC: Only select the R4k clock event/source on R4k systems R3k systems have no R4k timer so there's no point in pulling code that's going to be dead. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6704/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c4804bf..4e49591 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -174,9 +174,9 @@ config MACH_DECSTATION bool "DECstations" select BOOT_ELF32 select CEVT_DS1287 - select CEVT_R4K + select CEVT_R4K if CPU_R4X00 select CSRC_IOASIC - select CSRC_R4K + select CSRC_R4K if CPU_R4X00 select CPU_DADDI_WORKAROUNDS if 64BIT select CPU_R4000_WORKAROUNDS if 64BIT select CPU_R4400_WORKAROUNDS if 64BIT -- cgit v0.10.2 From 76ad023b8925d8b849a9377b77bcfa9a49f57082 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 6 Apr 2014 22:06:28 +0100 Subject: MIPS: DEC: Remove the Halt button interrupt on R4k systems On R4k DECstations the Halt button is wired to the NMI processor input rather than an ordinary interrupt input such as on R3k DECstations. This is possible with a different design of the CPU daughtercard that routes the Halt button line from the baseboard connector. Additionally the interrupt input has been reused for a different purpose on the KN04 and KN05 R4k CPU daughtercards so it is better kept masked. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6705/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c index 56e6e2c..41bbffd 100644 --- a/arch/mips/dec/setup.c +++ b/arch/mips/dec/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -748,6 +749,10 @@ void __init arch_init_irq(void) cpu_fpu_mask = 0; dec_interrupt[DEC_IRQ_FPU] = -1; } + /* Free the halt interrupt unused on R4k systems. */ + if (current_cpu_type() == CPU_R4000SC || + current_cpu_type() == CPU_R4400SC) + dec_interrupt[DEC_IRQ_HALT] = -1; /* Register board interrupts: FPU and cascade. */ if (dec_interrupt[DEC_IRQ_FPU] >= 0) -- cgit v0.10.2 From 643c5705bc9d30b64ca320715eb210b853d1f27e Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 7 May 2014 12:20:56 +0100 Subject: MIPS: Define some more PIIX4 registers & values This patch simply adds definitions for some I/O registers in the PIIX4 PM device, and the magic data for a special cycle which must occur on the PCI bus in order for the PIIX4 to enter a suspend state. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6903/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mips-boards/piix4.h b/arch/mips/include/asm/mips-boards/piix4.h index 9cf5404..9e340be 100644 --- a/arch/mips/include/asm/mips-boards/piix4.h +++ b/arch/mips/include/asm/mips-boards/piix4.h @@ -55,4 +55,16 @@ #define PIIX4_FUNC3_PMREGMISC 0x80 #define PIIX4_FUNC3_PMREGMISC_EN (1 << 0) +/* Power Management IO Space */ +#define PIIX4_FUNC3IO_PMSTS 0x00 +#define PIIX4_FUNC3IO_PMSTS_PWRBTN_STS (1 << 8) +#define PIIX4_FUNC3IO_PMCNTRL 0x04 +#define PIIX4_FUNC3IO_PMCNTRL_SUS_EN (1 << 13) +#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP (0x7 << 10) +#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF (0x0 << 10) +#define PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_STR (0x1 << 10) + +/* Data for magic special PCI cycle */ +#define PIIX4_SUSPEND_MAGIC 0x00120002 + #endif /* __ASM_MIPS_BOARDS_PIIX4_H */ -- cgit v0.10.2 From b6911bba598f5d611f7fdbb87b5af7f1712dbe9d Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 7 May 2014 12:20:57 +0100 Subject: MIPS: Malta: add suspend state entry code This patch introduces code which will enter a suspend state via the PIIX4. This can only be done when PCI support is enabled since it requires access to PCI I/O space and the generation of a special cycle on the PCI bus. In cases where PCI is disabled the mips_pm_suspend function will simply always return an error. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6905/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 4e49591..2f2020f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1671,6 +1671,12 @@ config SYS_HAS_CPU_XLR config SYS_HAS_CPU_XLP bool +config MIPS_MALTA_PM + depends on MIPS_MALTA + depends on PCI + bool + default y + # # CPU may reorder R->R, R->W, W->R, W->W # Reordering beyond LL and SC is handled in WEAK_REORDERING_BEYOND_LLSC diff --git a/arch/mips/include/asm/mach-malta/malta-pm.h b/arch/mips/include/asm/mach-malta/malta-pm.h new file mode 100644 index 0000000..c2c2e20 --- /dev/null +++ b/arch/mips/include/asm/mach-malta/malta-pm.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 Imagination Technologies + * Author: Paul Burton + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __ASM_MIPS_MACH_MALTA_PM_H__ +#define __ASM_MIPS_MACH_MALTA_PM_H__ + +#include + +#ifdef CONFIG_MIPS_MALTA_PM + +/** + * mips_pm_suspend - enter a suspend state + * @state: the state to enter, one of PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_* + * + * Enters a suspend state via the Malta's PIIX4. If the state to be entered + * is one which loses context (eg. SOFF) then this function will never + * return. + */ +extern int mips_pm_suspend(unsigned state); + +#else /* !CONFIG_MIPS_MALTA_PM */ + +static inline int mips_pm_suspend(unsigned state) +{ + return -EINVAL; +} + +#endif /* !CONFIG_MIPS_MALTA_PM */ + +#endif /* __ASM_MIPS_MACH_MALTA_PM_H__ */ diff --git a/arch/mips/mti-malta/Makefile b/arch/mips/mti-malta/Makefile index a851601..b9510ea 100644 --- a/arch/mips/mti-malta/Makefile +++ b/arch/mips/mti-malta/Makefile @@ -8,3 +8,5 @@ obj-y := malta-amon.o malta-display.o malta-init.o \ malta-int.o malta-memory.o malta-platform.o \ malta-reset.o malta-setup.o malta-time.o + +obj-$(CONFIG_MIPS_MALTA_PM) += malta-pm.o diff --git a/arch/mips/mti-malta/malta-pm.c b/arch/mips/mti-malta/malta-pm.c new file mode 100644 index 0000000..c1e456c --- /dev/null +++ b/arch/mips/mti-malta/malta-pm.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2014 Imagination Technologies + * Author: Paul Burton + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + +#include + +static struct pci_bus *pm_pci_bus; +static resource_size_t pm_io_offset; + +int mips_pm_suspend(unsigned state) +{ + int spec_devid; + u16 sts; + + if (!pm_pci_bus || !pm_io_offset) + return -ENODEV; + + /* Ensure the power button status is clear */ + while (1) { + sts = inw(pm_io_offset + PIIX4_FUNC3IO_PMSTS); + if (!(sts & PIIX4_FUNC3IO_PMSTS_PWRBTN_STS)) + break; + outw(sts, pm_io_offset + PIIX4_FUNC3IO_PMSTS); + } + + /* Enable entry to suspend */ + outw(state | PIIX4_FUNC3IO_PMCNTRL_SUS_EN, + pm_io_offset + PIIX4_FUNC3IO_PMCNTRL); + + /* If the special cycle occurs too soon this doesn't work... */ + mdelay(10); + + /* + * The PIIX4 will enter the suspend state only after seeing a special + * cycle with the correct magic data on the PCI bus. Generate that + * cycle now. + */ + spec_devid = PCI_DEVID(0, PCI_DEVFN(0x1f, 0x7)); + pci_bus_write_config_dword(pm_pci_bus, spec_devid, 0, + PIIX4_SUSPEND_MAGIC); + + /* Give the system some time to power down */ + mdelay(1000); + + return 0; +} + +static int __init malta_pm_setup(void) +{ + struct pci_dev *dev; + int res, io_region = PCI_BRIDGE_RESOURCES; + + /* Find a reference to the PCI bus */ + pm_pci_bus = pci_find_next_bus(NULL); + if (!pm_pci_bus) { + pr_warn("malta-pm: failed to find reference to PCI bus\n"); + return -ENODEV; + } + + /* Find the PIIX4 PM device */ + dev = pci_get_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, + PCI_ANY_ID, NULL); + if (!dev) { + pr_warn("malta-pm: failed to find PIIX4 PM\n"); + return -ENODEV; + } + + /* Request access to the PIIX4 PM IO registers */ + res = pci_request_region(dev, io_region, "PIIX4 PM IO registers"); + if (res) { + pr_warn("malta-pm: failed to request PM IO registers (%d)\n", + res); + pci_dev_put(dev); + return -ENODEV; + } + + /* Find the offset to the PIIX4 PM IO registers */ + pm_io_offset = pci_resource_start(dev, io_region); + + pci_dev_put(dev); + return 0; +} + +late_initcall(malta_pm_setup); -- cgit v0.10.2 From 9e53481eea26891011ef7aa28e7990769fb6cf50 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 7 May 2014 12:20:58 +0100 Subject: MIPS: Malta: Let PIIX4 respond to PCI special cycles This patch enables the PIIX4 to respond to special cycles on the PCI bus. One such special cycle must be used in order to enter a suspend state, and if response to it is not enabled then the suspend state will never be entered. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6904/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c index 2f9e52a..40e920c 100644 --- a/arch/mips/pci/fixup-malta.c +++ b/arch/mips/pci/fixup-malta.c @@ -68,6 +68,7 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev) { unsigned char reg_val; u32 reg_val32; + u16 reg_val16; /* PIIX PIRQC[A:D] irq mappings */ static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = { 0, 0, 0, 3, @@ -107,6 +108,11 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev) pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, ®_val); reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT; pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val); + + /* Enable response to special cycles */ + pci_read_config_word(pdev, PCI_COMMAND, ®_val16); + pci_write_config_word(pdev, PCI_COMMAND, + reg_val16 | PCI_COMMAND_SPECIAL); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, -- cgit v0.10.2 From 37e5c835bbbce4fde11cccc30dfe6c7b853ea964 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 7 May 2014 12:20:59 +0100 Subject: MIPS: Malta: hang on halt When the system is halted it makes little sense to reset it. Instead, hang by executing an infinite loop. [ralf@linux-mips.org: Remove printk from mips_machine_halt() - this is not the place to communicate with the user.] Suggested-by: Maciej W. Rozycki Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6906/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c index d627d4b..199ed280 100644 --- a/arch/mips/mti-malta/malta-reset.c +++ b/arch/mips/mti-malta/malta-reset.c @@ -24,17 +24,19 @@ static void mips_machine_restart(char *command) static void mips_machine_halt(void) { - unsigned int __iomem *softres_reg = - ioremap(SOFTRES_REG, sizeof(unsigned int)); + while (true); +} - __raw_writel(GORESET, softres_reg); +static void mips_machine_power_off(void) +{ + mips_machine_restart(NULL); } static int __init mips_reboot_setup(void) { _machine_restart = mips_machine_restart; _machine_halt = mips_machine_halt; - pm_power_off = mips_machine_halt; + pm_power_off = mips_machine_power_off; return 0; } -- cgit v0.10.2 From dadaa1c2c0eddc09d11d7494b040c3f331ecd98f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 7 May 2014 12:22:12 +0100 Subject: MIPS: Malta: support powering down This patch powers down the Malta in response to a power off command (eg. poweroff or shutdown -P). It may then be powered back up by pressing the "ON/NMI" button (S4) on the board. In cases where the power off state cannot be entered (eg. because the required PCI support is disabled) the current reset behaviour will be used as a fallback. Signed-off-by: Paul Burton Tested-by: James Hogan Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6907/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mti-malta/malta-reset.c b/arch/mips/mti-malta/malta-reset.c index 199ed280..2fd2cc2 100644 --- a/arch/mips/mti-malta/malta-reset.c +++ b/arch/mips/mti-malta/malta-reset.c @@ -10,6 +10,7 @@ #include #include +#include #define SOFTRES_REG 0x1f000500 #define GORESET 0x42 @@ -29,6 +30,9 @@ static void mips_machine_halt(void) static void mips_machine_power_off(void) { + mips_pm_suspend(PIIX4_FUNC3IO_PMCNTRL_SUS_TYP_SOFF); + + pr_info("Failed to power down, resetting\n"); mips_machine_restart(NULL); } -- cgit v0.10.2 From a36d8225bceba4b7be47ade34d175945f85cffbc Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:04 +0200 Subject: MIPS: OCTEON: Enable use of FPU Some versions of the assembler will not assemble CFC1 for OCTEON, so override the ISA for these. Add r4k_fpu.o to handle low level FPU initialization. Modify octeon_switch.S to save the FPU registers. And include r4k_switch.S to pick up more FPU support. Get rid of "#define cpu_has_fpu 0" Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7006/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h index 94ed063..cf80228 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h +++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h @@ -22,7 +22,6 @@ #define cpu_has_3k_cache 0 #define cpu_has_4k_cache 0 #define cpu_has_tx39_cache 0 -#define cpu_has_fpu 0 #define cpu_has_counter 1 #define cpu_has_watch 1 #define cpu_has_divec 1 diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index a61d108..008a2fe 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_CPU_R4K_FPU) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o -obj-$(CONFIG_CPU_CAVIUM_OCTEON) += octeon_switch.o +obj-$(CONFIG_CPU_CAVIUM_OCTEON) += r4k_fpu.o octeon_switch.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP_UP) += smp-up.o diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index 84888d9..e198d9b 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c @@ -562,7 +562,11 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, case cop1_op: preempt_disable(); if (is_fpu_owner()) - asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); + asm volatile( + ".set push\n" + "\t.set mips1\n" + "\tcfc1\t%0,$31\n" + "\t.set pop" : "=r" (fcr31)); else fcr31 = current->thread.fpu.fcr31; preempt_enable(); diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S index 029e002..f654768 100644 --- a/arch/mips/kernel/octeon_switch.S +++ b/arch/mips/kernel/octeon_switch.S @@ -10,24 +10,12 @@ * Copyright (C) 2000 MIPS Technologies, Inc. * written by Carsten Langgaard, carstenl@mips.com */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * Offset to the current process status flags, the first 32 bytes of the - * stack are not used. - */ -#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) +#define USE_ALTERNATE_RESUME_IMPL 1 + .set push + .set arch=mips64r2 +#include "r4k_switch.S" + .set pop /* * task_struct *resume(task_struct *prev, task_struct *next, * struct thread_info *next_ti, int usedfpu) @@ -40,6 +28,61 @@ cpu_save_nonscratch a0 LONG_S ra, THREAD_REG31(a0) + /* + * check if we need to save FPU registers + */ + PTR_L t3, TASK_THREAD_INFO(a0) + LONG_L t0, TI_FLAGS(t3) + li t1, _TIF_USEDFPU + and t2, t0, t1 + beqz t2, 1f + nor t1, zero, t1 + + and t0, t0, t1 + LONG_S t0, TI_FLAGS(t3) + + /* + * clear saved user stack CU1 bit + */ + LONG_L t0, ST_OFF(t3) + li t1, ~ST0_CU1 + and t0, t0, t1 + LONG_S t0, ST_OFF(t3) + + .set push + .set arch=mips64r2 + fpu_save_double a0 t0 t1 # c0_status passed in t0 + # clobbers t1 + .set pop +1: + + /* check if we need to save COP2 registers */ + PTR_L t2, TASK_THREAD_INFO(a0) + LONG_L t0, ST_OFF(t2) + bbit0 t0, 30, 1f + + /* Disable COP2 in the stored process state */ + li t1, ST0_CU2 + xor t0, t1 + LONG_S t0, ST_OFF(t2) + + /* Enable COP2 so we can save it */ + mfc0 t0, CP0_STATUS + or t0, t1 + mtc0 t0, CP0_STATUS + + /* Save COP2 */ + daddu a0, THREAD_CP2 + jal octeon_cop2_save + dsubu a0, THREAD_CP2 + + /* Disable COP2 now that we are done */ + mfc0 t0, CP0_STATUS + li t1, ST0_CU2 + xor t0, t1 + mtc0 t0, CP0_STATUS + +1: #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 /* Check if we need to store CVMSEG state */ mfc0 t0, $11,7 /* CvmMemCtl */ @@ -85,12 +128,7 @@ move $28, a2 cpu_restore_nonscratch a1 -#if (_THREAD_SIZE - 32) < 0x8000 - PTR_ADDIU t0, $28, _THREAD_SIZE - 32 -#else - PTR_LI t0, _THREAD_SIZE - 32 - PTR_ADDU t0, $28 -#endif + PTR_ADDU t0, $28, _THREAD_SIZE - 32 set_saved_sp t0, t1, t2 mfc0 t1, CP0_STATUS /* Do we really need this? */ diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index 547c522..81ca3f7 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S @@ -28,6 +28,7 @@ */ #define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) +#ifndef USE_ALTERNATE_RESUME_IMPL /* * task_struct *resume(task_struct *prev, task_struct *next, * struct thread_info *next_ti, s32 fp_save) @@ -99,6 +100,8 @@ jr ra END(resume) +#endif /* USE_ALTERNATE_RESUME_IMPL */ + /* * Save a thread's fp context. */ diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index cdfed28..736c17a 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -584,7 +584,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, if (insn.i_format.rs == bc_op) { preempt_disable(); if (is_fpu_owner()) - asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); + asm volatile( + ".set push\n" + "\t.set mips1\n" + "\tcfc1\t%0,$31\n" + "\t.set pop" : "=r" (fcr31)); else fcr31 = current->thread.fpu.fcr31; preempt_enable(); -- cgit v0.10.2 From 6e5111636d0ad6deb65a8280fdcd49e4753e5aec Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:05 +0200 Subject: MIPS: Move system level config items from CPU_CAVIUM_OCTEON to CAVIUM_OCTEON_SOC They are a property of the SoC not the CPU itself. Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7009/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2f2020f..78b558f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -732,6 +732,11 @@ config CAVIUM_OCTEON_SOC select ZONE_DMA32 select HOLES_IN_ZONE select ARCH_REQUIRE_GPIOLIB + select LIBFDT + select USE_OF + select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_SMP + select NR_CPUS_DEFAULT_16 help This option supports all of the Octeon reference boards from Cavium Networks. It builds a kernel that dynamically determines the Octeon @@ -1410,16 +1415,11 @@ config CPU_SB1 config CPU_CAVIUM_OCTEON bool "Cavium Octeon processor" depends on SYS_HAS_CPU_CAVIUM_OCTEON - select ARCH_SPARSEMEM_ENABLE select CPU_HAS_PREFETCH select CPU_SUPPORTS_64BIT_KERNEL - select SYS_SUPPORTS_SMP - select NR_CPUS_DEFAULT_16 select WEAK_ORDERING select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HUGEPAGES - select LIBFDT - select USE_OF select USB_EHCI_BIG_ENDIAN_MMIO select MIPS_L1_CACHE_SHIFT_7 help -- cgit v0.10.2 From 8a837cdb0a51c4b45aca8966cf11af99b397c97d Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:06 +0200 Subject: MIPS: OCTEON: Move CAVIUM_OCTEON_CVMSEG_SIZE to CPU_CAVIUM_OCTEON CVMSEG is related to the CPU core not the SoC system. So needs to be configurable there. Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7013/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig index 227705d..6028666 100644 --- a/arch/mips/cavium-octeon/Kconfig +++ b/arch/mips/cavium-octeon/Kconfig @@ -10,6 +10,17 @@ config CAVIUM_CN63XXP1 non-CN63XXP1 hardware, so it is recommended to select "n" unless it is known the workarounds are needed. +config CAVIUM_OCTEON_CVMSEG_SIZE + int "Number of L1 cache lines reserved for CVMSEG memory" + range 0 54 + default 1 + help + CVMSEG LM is a segment that accesses portions of the dcache as a + local memory; the larger CVMSEG is, the smaller the cache is. + This selects the size of CVMSEG LM, which is in cache blocks. The + legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is + between zero and 6192 bytes). + endif # CPU_CAVIUM_OCTEON if CAVIUM_OCTEON_SOC @@ -23,17 +34,6 @@ config CAVIUM_OCTEON_2ND_KERNEL with this option to be run at the same time as one built without this option. -config CAVIUM_OCTEON_CVMSEG_SIZE - int "Number of L1 cache lines reserved for CVMSEG memory" - range 0 54 - default 1 - help - CVMSEG LM is a segment that accesses portions of the dcache as a - local memory; the larger CVMSEG is, the smaller the cache is. - This selects the size of CVMSEG LM, which is in cache blocks. The - legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is - between zero and 6192 bytes). - config CAVIUM_OCTEON_LOCK_L2 bool "Lock often used kernel code in the L2" default "y" @@ -86,7 +86,6 @@ config SWIOTLB select IOMMU_HELPER select NEED_SG_DMA_LENGTH - config OCTEON_ILM tristate "Module to measure interrupt latency using Octeon CIU Timer" help -- cgit v0.10.2 From a68d09a156b2a543117bb98df4c8c4cd1b857124 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:07 +0200 Subject: MIPS: Don't use RI/XI with 32-bit kernels on 64-bit CPUs The TLB handlers cannot handle this case, so disable it for now. Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7007/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index f75dd70..c7d8c99 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -110,9 +110,15 @@ #ifndef cpu_has_smartmips #define cpu_has_smartmips (cpu_data[0].ases & MIPS_ASE_SMARTMIPS) #endif + #ifndef cpu_has_rixi -#define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI) +# ifdef CONFIG_64BIT +# define cpu_has_rixi (cpu_data[0].options & MIPS_CPU_RIXI) +# else /* CONFIG_32BIT */ +# define cpu_has_rixi ((cpu_data[0].options & MIPS_CPU_RIXI) && !cpu_has_64bits) +# endif #endif + #ifndef cpu_has_mmips # ifdef CONFIG_SYS_SUPPORTS_MICROMIPS # define cpu_has_mmips (cpu_data[0].options & MIPS_CPU_MICROMIPS) @@ -120,6 +126,7 @@ # define cpu_has_mmips 0 # endif #endif + #ifndef cpu_has_vtag_icache #define cpu_has_vtag_icache (cpu_data[0].icache.flags & MIPS_CACHE_VTAG) #endif -- cgit v0.10.2 From 35d0470668cca234e49ed35342b3f9a0eec8355c Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:08 +0200 Subject: MIPS: Don't build fast TLB refill handler with 32-bit kernels The fast handler only supports 64-bit kernels. Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7010/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index f99ec587..af91f3e 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1250,13 +1250,17 @@ static void build_r4000_tlb_refill_handler(void) unsigned int final_len; struct mips_huge_tlb_info htlb_info __maybe_unused; enum vmalloc64_mode vmalloc_mode __maybe_unused; - +#ifdef CONFIG_64BIT + bool is64bit = true; +#else + bool is64bit = false; +#endif memset(tlb_handler, 0, sizeof(tlb_handler)); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); memset(final_handler, 0, sizeof(final_handler)); - if ((scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) { + if (is64bit && (scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) { htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1, scratch_reg); vmalloc_mode = refill_scratch; -- cgit v0.10.2 From 18a8cd63c0d800bbc8b91f03054fcb13d308f6ec Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:09 +0200 Subject: MIPS: Add minimal support for OCTEON3 to c-r4k.c These are needed to boot a generic mips64r2 kernel on OCTEONIII. Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7003/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h index fe8d1b6..0b8bd28 100644 --- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h @@ -523,6 +523,8 @@ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, ) __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, ) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, ) __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, ) diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 587a148..f2e8302 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -109,18 +109,34 @@ static inline void r4k_blast_dcache_page_dc64(unsigned long addr) blast_dcache64_page(addr); } +static inline void r4k_blast_dcache_page_dc128(unsigned long addr) +{ + blast_dcache128_page(addr); +} + static void r4k_blast_dcache_page_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); - if (dc_lsize == 0) + switch (dc_lsize) { + case 0: r4k_blast_dcache_page = (void *)cache_noop; - else if (dc_lsize == 16) + break; + case 16: r4k_blast_dcache_page = blast_dcache16_page; - else if (dc_lsize == 32) + break; + case 32: r4k_blast_dcache_page = r4k_blast_dcache_page_dc32; - else if (dc_lsize == 64) + break; + case 64: r4k_blast_dcache_page = r4k_blast_dcache_page_dc64; + break; + case 128: + r4k_blast_dcache_page = r4k_blast_dcache_page_dc128; + break; + default: + break; + } } #ifndef CONFIG_EVA @@ -159,6 +175,8 @@ static void r4k_blast_dcache_page_indexed_setup(void) r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed; else if (dc_lsize == 64) r4k_blast_dcache_page_indexed = blast_dcache64_page_indexed; + else if (dc_lsize == 128) + r4k_blast_dcache_page_indexed = blast_dcache128_page_indexed; } void (* r4k_blast_dcache)(void); @@ -176,6 +194,8 @@ static void r4k_blast_dcache_setup(void) r4k_blast_dcache = blast_dcache32; else if (dc_lsize == 64) r4k_blast_dcache = blast_dcache64; + else if (dc_lsize == 128) + r4k_blast_dcache = blast_dcache128; } /* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */ @@ -265,6 +285,8 @@ static void r4k_blast_icache_page_setup(void) r4k_blast_icache_page = blast_icache32_page; else if (ic_lsize == 64) r4k_blast_icache_page = blast_icache64_page; + else if (ic_lsize == 128) + r4k_blast_icache_page = blast_icache128_page; } #ifndef CONFIG_EVA @@ -338,6 +360,8 @@ static void r4k_blast_icache_setup(void) r4k_blast_icache = blast_icache32; } else if (ic_lsize == 64) r4k_blast_icache = blast_icache64; + else if (ic_lsize == 128) + r4k_blast_icache = blast_icache128; } static void (* r4k_blast_scache_page)(unsigned long addr); @@ -1094,6 +1118,21 @@ static void probe_pcache(void) c->dcache.waybit = 0; break; + case CPU_CAVIUM_OCTEON3: + /* For now lie about the number of ways. */ + c->icache.linesz = 128; + c->icache.sets = 16; + c->icache.ways = 8; + c->icache.flags |= MIPS_CACHE_VTAG; + icache_size = c->icache.sets * c->icache.ways * c->icache.linesz; + + c->dcache.linesz = 128; + c->dcache.ways = 8; + c->dcache.sets = 8; + dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz; + c->options |= MIPS_CPU_PREFETCH; + break; + default: if (!(config & MIPS_CONF_M)) panic("Don't know how to probe P-caches on this cpu."); @@ -1414,6 +1453,7 @@ static void setup_scache(void) loongson3_sc_init(); return; + case CPU_CAVIUM_OCTEON3: case CPU_XLP: /* don't need to worry about L2, fully coherent */ return; -- cgit v0.10.2 From 45b585c8dcdc469bb40b58cc2801acd7a2332525 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:10 +0200 Subject: MIPS: Add function get_ebase_cpunum This returns the CPUNum from the low order Ebase bits. Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7012/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index fb2d174..98e9754 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -1792,6 +1792,15 @@ __BUILD_SET_C0(brcm_cmt_ctrl) __BUILD_SET_C0(brcm_config) __BUILD_SET_C0(brcm_mode) +/* + * Return low 10 bits of ebase. + * Note that under KVM (MIPSVZ) this returns vcpu id. + */ +static inline unsigned int get_ebase_cpunum(void) +{ + return read_c0_ebase() & 0x3ff; +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_MIPSREGS_H */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index b1b580d..d74f957 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -423,7 +423,7 @@ static void decode_configs(struct cpuinfo_mips *c) #ifndef CONFIG_MIPS_CPS if (cpu_has_mips_r2) { - c->core = read_c0_ebase() & 0x3ff; + c->core = get_ebase_cpunum(); if (cpu_has_mipsmt) c->core >>= fls(core_nvpes()) - 1; } -- cgit v0.10.2 From cd3f5389489146297eb2c11e4f9d1c4e8aaeb59f Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 28 May 2014 23:52:11 +0200 Subject: MIPS: OCTEON: Add OCTEON3 to __get_cpu_type Otherwise __builtin_unreachable might be called. Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: David Daney Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7014/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h index e3308b4..b4e2bd8 100644 --- a/arch/mips/include/asm/cpu-type.h +++ b/arch/mips/include/asm/cpu-type.h @@ -163,6 +163,7 @@ static inline int __pure __get_cpu_type(const int cpu_type) case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: + case CPU_CAVIUM_OCTEON3: #endif #if defined(CONFIG_SYS_HAS_CPU_BMIPS32_3300) || \ -- cgit v0.10.2 From 90dfdc7ceb577c0d7b7635def3c62039a091e50d Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:12 +0200 Subject: MIPS: Add functions for hypervisor call Introduce kvm_hypercall[0-3]. Define three new hypercalls for MIPS: GET_CLOCK_FREQ, EXIT_VM, and CONSOLE_OUTPUT. [andreas.herrmann: * Properly define hypercalls and HC numbers for MIPS in kvm_para.h header files] Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7005/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/kvm_para.h b/arch/mips/include/asm/kvm_para.h new file mode 100644 index 0000000..5a9aa91 --- /dev/null +++ b/arch/mips/include/asm/kvm_para.h @@ -0,0 +1,109 @@ +#ifndef _ASM_MIPS_KVM_PARA_H +#define _ASM_MIPS_KVM_PARA_H + +#include + +#define KVM_HYPERCALL ".word 0x42000028" + +/* + * Hypercalls for KVM. + * + * Hypercall number is passed in v0. + * Return value will be placed in v0. + * Up to 3 arguments are passed in a0, a1, and a2. + */ +static inline unsigned long kvm_hypercall0(unsigned long num) +{ + register unsigned long n asm("v0"); + register unsigned long r asm("v0"); + + n = num; + __asm__ __volatile__( + KVM_HYPERCALL + : "=r" (r) : "r" (n) : "memory" + ); + + return r; +} + +static inline unsigned long kvm_hypercall1(unsigned long num, + unsigned long arg0) +{ + register unsigned long n asm("v0"); + register unsigned long r asm("v0"); + register unsigned long a0 asm("a0"); + + n = num; + a0 = arg0; + __asm__ __volatile__( + KVM_HYPERCALL + : "=r" (r) : "r" (n), "r" (a0) : "memory" + ); + + return r; +} + +static inline unsigned long kvm_hypercall2(unsigned long num, + unsigned long arg0, unsigned long arg1) +{ + register unsigned long n asm("v0"); + register unsigned long r asm("v0"); + register unsigned long a0 asm("a0"); + register unsigned long a1 asm("a1"); + + n = num; + a0 = arg0; + a1 = arg1; + __asm__ __volatile__( + KVM_HYPERCALL + : "=r" (r) : "r" (n), "r" (a0), "r" (a1) : "memory" + ); + + return r; +} + +static inline unsigned long kvm_hypercall3(unsigned long num, + unsigned long arg0, unsigned long arg1, unsigned long arg2) +{ + register unsigned long n asm("v0"); + register unsigned long r asm("v0"); + register unsigned long a0 asm("a0"); + register unsigned long a1 asm("a1"); + register unsigned long a2 asm("a2"); + + n = num; + a0 = arg0; + a1 = arg1; + a2 = arg2; + __asm__ __volatile__( + KVM_HYPERCALL + : "=r" (r) : "r" (n), "r" (a0), "r" (a1), "r" (a2) : "memory" + ); + + return r; +} + +static inline bool kvm_check_and_clear_guest_paused(void) +{ + return false; +} + +static inline unsigned int kvm_arch_para_features(void) +{ + return 0; +} + +#ifdef CONFIG_MIPS_PARAVIRT +static inline bool kvm_para_available(void) +{ + return true; +} +#else +static inline bool kvm_para_available(void) +{ + return false; +} +#endif + + +#endif /* _ASM_MIPS_KVM_PARA_H */ diff --git a/arch/mips/include/uapi/asm/kvm_para.h b/arch/mips/include/uapi/asm/kvm_para.h index 14fab8f..7e16d7c 100644 --- a/arch/mips/include/uapi/asm/kvm_para.h +++ b/arch/mips/include/uapi/asm/kvm_para.h @@ -1 +1,5 @@ -#include +#ifndef _UAPI_ASM_MIPS_KVM_PARA_H +#define _UAPI_ASM_MIPS_KVM_PARA_H + + +#endif /* _UAPI_ASM_MIPS_KVM_PARA_H */ diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h index 2841f86..bf6cd7d 100644 --- a/include/uapi/linux/kvm_para.h +++ b/include/uapi/linux/kvm_para.h @@ -20,6 +20,9 @@ #define KVM_HC_FEATURES 3 #define KVM_HC_PPC_MAP_MAGIC_PAGE 4 #define KVM_HC_KICK_CPU 5 +#define KVM_HC_MIPS_GET_CLOCK_FREQ 6 +#define KVM_HC_MIPS_EXIT_VM 7 +#define KVM_HC_MIPS_CONSOLE_OUTPUT 8 /* * hypercalls use architecture specific -- cgit v0.10.2 From 18280edafef1b8ffc920743eddaf6cf6612b1509 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:13 +0200 Subject: MIPS: Add code for new system 'paravirt' For para-virtualized guests running under KVM or other equivalent hypervisor. Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7004/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mach-paravirt/cpu-feature-overrides.h b/arch/mips/include/asm/mach-paravirt/cpu-feature-overrides.h new file mode 100644 index 0000000..725e1ed --- /dev/null +++ b/arch/mips/include/asm/mach-paravirt/cpu-feature-overrides.h @@ -0,0 +1,36 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ +#ifndef __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H + +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_tx39_cache 0 +#define cpu_has_counter 1 +#define cpu_has_llsc 1 +/* + * We Disable LL/SC on non SMP systems as it is faster to disable + * interrupts for atomic access than a LL/SC. + */ +#ifdef CONFIG_SMP +# define kernel_uses_llsc 1 +#else +# define kernel_uses_llsc 0 +#endif + +#ifdef CONFIG_CPU_CAVIUM_OCTEON +#define cpu_dcache_line_size() 128 +#define cpu_icache_line_size() 128 +#define cpu_has_octeon_cache 1 +#define cpu_has_4k_cache 0 +#else +#define cpu_has_octeon_cache 0 +#define cpu_has_4k_cache 1 +#endif + +#endif /* __ASM_MACH_PARAVIRT_CPU_FEATURE_OVERRIDES_H */ diff --git a/arch/mips/include/asm/mach-paravirt/irq.h b/arch/mips/include/asm/mach-paravirt/irq.h new file mode 100644 index 0000000..9b4d35e --- /dev/null +++ b/arch/mips/include/asm/mach-paravirt/irq.h @@ -0,0 +1,19 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ +#ifndef __ASM_MACH_PARAVIRT_IRQ_H__ +#define __ASM_MACH_PARAVIRT_IRQ_H__ + +#define NR_IRQS 64 +#define MIPS_CPU_IRQ_BASE 1 + +#define MIPS_IRQ_PCIA (MIPS_CPU_IRQ_BASE + 8) + +#define MIPS_IRQ_MBOX0 (MIPS_CPU_IRQ_BASE + 32) +#define MIPS_IRQ_MBOX1 (MIPS_CPU_IRQ_BASE + 33) + +#endif /* __ASM_MACH_PARAVIRT_IRQ_H__ */ diff --git a/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h b/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h new file mode 100644 index 0000000..2f82bfa --- /dev/null +++ b/arch/mips/include/asm/mach-paravirt/kernel-entry-init.h @@ -0,0 +1,50 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc + */ +#ifndef __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H +#define __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H + +#define CP0_EBASE $15, 1 + + .macro kernel_entry_setup + mfc0 t0, CP0_EBASE + andi t0, t0, 0x3ff # CPUNum + beqz t0, 1f + # CPUs other than zero goto smp_bootstrap + j smp_bootstrap + +1: + .endm + +/* + * Do SMP slave processor setup necessary before we can safely execute + * C code. + */ + .macro smp_slave_setup + mfc0 t0, CP0_EBASE + andi t0, t0, 0x3ff # CPUNum + slti t1, t0, NR_CPUS + bnez t1, 1f +2: + di + wait + b 2b # Unknown CPU, loop forever. +1: + PTR_LA t1, paravirt_smp_sp + PTR_SLL t0, PTR_SCALESHIFT + PTR_ADDU t1, t1, t0 +3: + PTR_L sp, 0(t1) + beqz sp, 3b # Spin until told to proceed. + + PTR_LA t1, paravirt_smp_gp + PTR_ADDU t1, t1, t0 + sync + PTR_L gp, 0(t1) + .endm + +#endif /* __ASM_MACH_PARAVIRT_KERNEL_ENTRY_H */ diff --git a/arch/mips/include/asm/mach-paravirt/war.h b/arch/mips/include/asm/mach-paravirt/war.h new file mode 100644 index 0000000..36d3afb --- /dev/null +++ b/arch/mips/include/asm/mach-paravirt/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + * Copyright (C) 2013 Cavium Networks + */ +#ifndef __ASM_MIPS_MACH_PARAVIRT_WAR_H +#define __ASM_MIPS_MACH_PARAVIRT_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_PARAVIRT_WAR_H */ diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index af91f3e..e80e10b 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -1250,17 +1250,13 @@ static void build_r4000_tlb_refill_handler(void) unsigned int final_len; struct mips_huge_tlb_info htlb_info __maybe_unused; enum vmalloc64_mode vmalloc_mode __maybe_unused; -#ifdef CONFIG_64BIT - bool is64bit = true; -#else - bool is64bit = false; -#endif + memset(tlb_handler, 0, sizeof(tlb_handler)); memset(labels, 0, sizeof(labels)); memset(relocs, 0, sizeof(relocs)); memset(final_handler, 0, sizeof(final_handler)); - if (is64bit && (scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) { + if (IS_ENABLED(CONFIG_64BIT) && (scratch_reg >= 0 || scratchpad_available()) && use_bbit_insns()) { htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1, scratch_reg); vmalloc_mode = refill_scratch; diff --git a/arch/mips/paravirt/Makefile b/arch/mips/paravirt/Makefile new file mode 100644 index 0000000..5023af7 --- /dev/null +++ b/arch/mips/paravirt/Makefile @@ -0,0 +1,14 @@ +# +# Makefile for MIPS para-virtualized specific kernel interface routines +# under Linux. +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2013 Cavium, Inc. +# + +obj-y := setup.o serial.o paravirt-irq.o + +obj-$(CONFIG_SMP) += paravirt-smp.o diff --git a/arch/mips/paravirt/Platform b/arch/mips/paravirt/Platform new file mode 100644 index 0000000..7e76ef2 --- /dev/null +++ b/arch/mips/paravirt/Platform @@ -0,0 +1,8 @@ +# +# Generic para-virtualized guest. +# +platform-$(CONFIG_MIPS_PARAVIRT) += paravirt/ +cflags-$(CONFIG_MIPS_PARAVIRT) += \ + -I$(srctree)/arch/mips/include/asm/mach-paravirt + +load-$(CONFIG_MIPS_PARAVIRT) = 0xffffffff80010000 diff --git a/arch/mips/paravirt/paravirt-irq.c b/arch/mips/paravirt/paravirt-irq.c new file mode 100644 index 0000000..8987b06 --- /dev/null +++ b/arch/mips/paravirt/paravirt-irq.c @@ -0,0 +1,368 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ + +#include +#include +#include +#include + +#include + +#define MBOX_BITS_PER_CPU 2 + +static int cpunum_for_cpu(int cpu) +{ +#ifdef CONFIG_SMP + return cpu_logical_map(cpu); +#else + return get_ebase_cpunum(); +#endif +} + +struct core_chip_data { + struct mutex core_irq_mutex; + bool current_en; + bool desired_en; + u8 bit; +}; + +static struct core_chip_data irq_core_chip_data[8]; + +static void irq_core_ack(struct irq_data *data) +{ + struct core_chip_data *cd = irq_data_get_irq_chip_data(data); + unsigned int bit = cd->bit; + + /* + * We don't need to disable IRQs to make these atomic since + * they are already disabled earlier in the low level + * interrupt code. + */ + clear_c0_status(0x100 << bit); + /* The two user interrupts must be cleared manually. */ + if (bit < 2) + clear_c0_cause(0x100 << bit); +} + +static void irq_core_eoi(struct irq_data *data) +{ + struct core_chip_data *cd = irq_data_get_irq_chip_data(data); + + /* + * We don't need to disable IRQs to make these atomic since + * they are already disabled earlier in the low level + * interrupt code. + */ + set_c0_status(0x100 << cd->bit); +} + +static void irq_core_set_enable_local(void *arg) +{ + struct irq_data *data = arg; + struct core_chip_data *cd = irq_data_get_irq_chip_data(data); + unsigned int mask = 0x100 << cd->bit; + + /* + * Interrupts are already disabled, so these are atomic. + */ + if (cd->desired_en) + set_c0_status(mask); + else + clear_c0_status(mask); + +} + +static void irq_core_disable(struct irq_data *data) +{ + struct core_chip_data *cd = irq_data_get_irq_chip_data(data); + cd->desired_en = false; +} + +static void irq_core_enable(struct irq_data *data) +{ + struct core_chip_data *cd = irq_data_get_irq_chip_data(data); + cd->desired_en = true; +} + +static void irq_core_bus_lock(struct irq_data *data) +{ + struct core_chip_data *cd = irq_data_get_irq_chip_data(data); + + mutex_lock(&cd->core_irq_mutex); +} + +static void irq_core_bus_sync_unlock(struct irq_data *data) +{ + struct core_chip_data *cd = irq_data_get_irq_chip_data(data); + + if (cd->desired_en != cd->current_en) { + on_each_cpu(irq_core_set_enable_local, data, 1); + cd->current_en = cd->desired_en; + } + + mutex_unlock(&cd->core_irq_mutex); +} + +static struct irq_chip irq_chip_core = { + .name = "Core", + .irq_enable = irq_core_enable, + .irq_disable = irq_core_disable, + .irq_ack = irq_core_ack, + .irq_eoi = irq_core_eoi, + .irq_bus_lock = irq_core_bus_lock, + .irq_bus_sync_unlock = irq_core_bus_sync_unlock, + + .irq_cpu_online = irq_core_eoi, + .irq_cpu_offline = irq_core_ack, + .flags = IRQCHIP_ONOFFLINE_ENABLED, +}; + +static void __init irq_init_core(void) +{ + int i; + int irq; + struct core_chip_data *cd; + + /* Start with a clean slate */ + clear_c0_status(ST0_IM); + clear_c0_cause(CAUSEF_IP0 | CAUSEF_IP1); + + for (i = 0; i < ARRAY_SIZE(irq_core_chip_data); i++) { + cd = irq_core_chip_data + i; + cd->current_en = false; + cd->desired_en = false; + cd->bit = i; + mutex_init(&cd->core_irq_mutex); + + irq = MIPS_CPU_IRQ_BASE + i; + + switch (i) { + case 0: /* SW0 */ + case 1: /* SW1 */ + case 5: /* IP5 */ + case 6: /* IP6 */ + case 7: /* IP7 */ + irq_set_chip_data(irq, cd); + irq_set_chip_and_handler(irq, &irq_chip_core, + handle_percpu_irq); + break; + default: + break; + } + } +} + +static void __iomem *mips_irq_chip; +#define MIPS_IRQ_CHIP_NUM_BITS 0 +#define MIPS_IRQ_CHIP_REGS 8 + +static int mips_irq_cpu_stride; +static int mips_irq_chip_reg_raw; +static int mips_irq_chip_reg_src; +static int mips_irq_chip_reg_en; +static int mips_irq_chip_reg_raw_w1s; +static int mips_irq_chip_reg_raw_w1c; +static int mips_irq_chip_reg_en_w1s; +static int mips_irq_chip_reg_en_w1c; + +static void irq_pci_enable(struct irq_data *data) +{ + u32 mask = 1u << data->irq; + + __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s); +} + +static void irq_pci_disable(struct irq_data *data) +{ + u32 mask = 1u << data->irq; + + __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c); +} + +static void irq_pci_ack(struct irq_data *data) +{ +} + +static void irq_pci_mask(struct irq_data *data) +{ + u32 mask = 1u << data->irq; + + __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c); +} + +static void irq_pci_unmask(struct irq_data *data) +{ + u32 mask = 1u << data->irq; + + __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s); +} + +static struct irq_chip irq_chip_pci = { + .name = "PCI", + .irq_enable = irq_pci_enable, + .irq_disable = irq_pci_disable, + .irq_ack = irq_pci_ack, + .irq_mask = irq_pci_mask, + .irq_unmask = irq_pci_unmask, +}; + +static void irq_mbox_all(struct irq_data *data, void __iomem *base) +{ + int cpu; + unsigned int mbox = data->irq - MIPS_IRQ_MBOX0; + u32 mask; + + WARN_ON(mbox >= MBOX_BITS_PER_CPU); + + for_each_online_cpu(cpu) { + unsigned int cpuid = cpunum_for_cpu(cpu); + mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox); + __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride)); + } +} + +static void irq_mbox_enable(struct irq_data *data) +{ + irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32)); +} + +static void irq_mbox_disable(struct irq_data *data) +{ + irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32)); +} + +static void irq_mbox_ack(struct irq_data *data) +{ + u32 mask; + unsigned int mbox = data->irq - MIPS_IRQ_MBOX0; + + WARN_ON(mbox >= MBOX_BITS_PER_CPU); + + mask = 1 << (get_ebase_cpunum() * MBOX_BITS_PER_CPU + mbox); + __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1c + sizeof(u32)); +} + +void irq_mbox_ipi(int cpu, unsigned int actions) +{ + unsigned int cpuid = cpunum_for_cpu(cpu); + u32 mask; + + WARN_ON(actions >= (1 << MBOX_BITS_PER_CPU)); + + mask = actions << (cpuid * MBOX_BITS_PER_CPU); + __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1s + sizeof(u32)); +} + +static void irq_mbox_cpu_onoffline(struct irq_data *data, void __iomem *base) +{ + unsigned int mbox = data->irq - MIPS_IRQ_MBOX0; + unsigned int cpuid = get_ebase_cpunum(); + u32 mask; + + WARN_ON(mbox >= MBOX_BITS_PER_CPU); + + mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox); + __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride)); + +} + +static void irq_mbox_cpu_online(struct irq_data *data) +{ + irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32)); +} + +static void irq_mbox_cpu_offline(struct irq_data *data) +{ + irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32)); +} + +static struct irq_chip irq_chip_mbox = { + .name = "MBOX", + .irq_enable = irq_mbox_enable, + .irq_disable = irq_mbox_disable, + .irq_ack = irq_mbox_ack, + .irq_cpu_online = irq_mbox_cpu_online, + .irq_cpu_offline = irq_mbox_cpu_offline, + .flags = IRQCHIP_ONOFFLINE_ENABLED, +}; + +static void __init irq_pci_init(void) +{ + int i, stride; + u32 num_bits; + + mips_irq_chip = ioremap(0x1e010000, 4096); + + num_bits = __raw_readl(mips_irq_chip + MIPS_IRQ_CHIP_NUM_BITS); + stride = 8 * (1 + ((num_bits - 1) / 64)); + + + pr_notice("mips_irq_chip: %u bits, reg stride: %d\n", num_bits, stride); + mips_irq_chip_reg_raw = MIPS_IRQ_CHIP_REGS + 0 * stride; + mips_irq_chip_reg_raw_w1s = MIPS_IRQ_CHIP_REGS + 1 * stride; + mips_irq_chip_reg_raw_w1c = MIPS_IRQ_CHIP_REGS + 2 * stride; + mips_irq_chip_reg_src = MIPS_IRQ_CHIP_REGS + 3 * stride; + mips_irq_chip_reg_en = MIPS_IRQ_CHIP_REGS + 4 * stride; + mips_irq_chip_reg_en_w1s = MIPS_IRQ_CHIP_REGS + 5 * stride; + mips_irq_chip_reg_en_w1c = MIPS_IRQ_CHIP_REGS + 6 * stride; + mips_irq_cpu_stride = stride * 4; + + for (i = 0; i < 4; i++) + irq_set_chip_and_handler(i + MIPS_IRQ_PCIA, &irq_chip_pci, handle_level_irq); + + for (i = 0; i < 2; i++) + irq_set_chip_and_handler(i + MIPS_IRQ_MBOX0, &irq_chip_mbox, handle_percpu_irq); + + + set_c0_status(STATUSF_IP2); +} + +static void irq_pci_dispatch(void) +{ + unsigned int cpuid = get_ebase_cpunum(); + u32 en; + + en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src + + (cpuid * mips_irq_cpu_stride)); + + if (!en) { + en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src + (cpuid * mips_irq_cpu_stride) + sizeof(u32)); + en = (en >> (2 * cpuid)) & 3; + + if (!en) + spurious_interrupt(); + else + do_IRQ(__ffs(en) + MIPS_IRQ_MBOX0); /* MBOX type */ + } else { + do_IRQ(__ffs(en)); + } +} + + +void __init arch_init_irq(void) +{ + irq_init_core(); + irq_pci_init(); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; + int ip; + + if (unlikely(!pending)) { + spurious_interrupt(); + return; + } + + ip = ffs(pending) - 1 - STATUSB_IP0; + if (ip == 2) + irq_pci_dispatch(); + else + do_IRQ(MIPS_CPU_IRQ_BASE + ip); +} diff --git a/arch/mips/paravirt/paravirt-smp.c b/arch/mips/paravirt/paravirt-smp.c new file mode 100644 index 0000000..73a123e --- /dev/null +++ b/arch/mips/paravirt/paravirt-smp.c @@ -0,0 +1,148 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Writing the sp releases the CPU, so writes must be ordered, gp + * first, then sp. + */ +unsigned long paravirt_smp_sp[NR_CPUS]; +unsigned long paravirt_smp_gp[NR_CPUS]; + +static int numcpus = 1; + +static int __init set_numcpus(char *str) +{ + int newval; + + if (get_option(&str, &newval)) { + if (newval < 1 || newval >= NR_CPUS) + goto bad; + numcpus = newval; + return 0; + } +bad: + return -EINVAL; +} +early_param("numcpus", set_numcpus); + + +static void paravirt_smp_setup(void) +{ + int id; + unsigned int cpunum = get_ebase_cpunum(); + + if (WARN_ON(cpunum >= NR_CPUS)) + return; + + /* The present CPUs are initially just the boot cpu (CPU 0). */ + for (id = 0; id < NR_CPUS; id++) { + set_cpu_possible(id, id == 0); + set_cpu_present(id, id == 0); + } + __cpu_number_map[cpunum] = 0; + __cpu_logical_map[0] = cpunum; + + for (id = 0; id < numcpus; id++) { + set_cpu_possible(id, true); + set_cpu_present(id, true); + __cpu_number_map[id] = id; + __cpu_logical_map[id] = id; + } +} + +void irq_mbox_ipi(int cpu, unsigned int actions); +static void paravirt_send_ipi_single(int cpu, unsigned int action) +{ + irq_mbox_ipi(cpu, action); +} + +static void paravirt_send_ipi_mask(const struct cpumask *mask, unsigned int action) +{ + unsigned int cpu; + + for_each_cpu_mask(cpu, *mask) + paravirt_send_ipi_single(cpu, action); +} + +static void paravirt_init_secondary(void) +{ + unsigned int sr; + + sr = set_c0_status(ST0_BEV); + write_c0_ebase((u32)ebase); + + sr |= STATUSF_IP2; /* Interrupt controller on IP2 */ + write_c0_status(sr); + + irq_cpu_online(); +} + +static void paravirt_smp_finish(void) +{ + /* to generate the first CPU timer interrupt */ + write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ); + local_irq_enable(); +} + +static void paravirt_cpus_done(void) +{ +} + +static void paravirt_boot_secondary(int cpu, struct task_struct *idle) +{ + paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle); + smp_wmb(); + paravirt_smp_sp[cpu] = __KSTK_TOS(idle); +} + +static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id) +{ + scheduler_ipi(); + return IRQ_HANDLED; +} + +static irqreturn_t paravirt_function_interrupt(int irq, void *dev_id) +{ + smp_call_function_interrupt(); + return IRQ_HANDLED; +} + +static void paravirt_prepare_cpus(unsigned int max_cpus) +{ + if (request_irq(MIPS_IRQ_MBOX0, paravirt_reched_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "Scheduler", + paravirt_reched_interrupt)) { + panic("Cannot request_irq for SchedulerIPI"); + } + if (request_irq(MIPS_IRQ_MBOX1, paravirt_function_interrupt, + IRQF_PERCPU | IRQF_NO_THREAD, "SMP-Call", + paravirt_function_interrupt)) { + panic("Cannot request_irq for SMP-Call"); + } +} + +struct plat_smp_ops paravirt_smp_ops = { + .send_ipi_single = paravirt_send_ipi_single, + .send_ipi_mask = paravirt_send_ipi_mask, + .init_secondary = paravirt_init_secondary, + .smp_finish = paravirt_smp_finish, + .cpus_done = paravirt_cpus_done, + .boot_secondary = paravirt_boot_secondary, + .smp_setup = paravirt_smp_setup, + .prepare_cpus = paravirt_prepare_cpus, +}; diff --git a/arch/mips/paravirt/serial.c b/arch/mips/paravirt/serial.c new file mode 100644 index 0000000..02b665c --- /dev/null +++ b/arch/mips/paravirt/serial.c @@ -0,0 +1,40 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ + +#include +#include +#include + +/* + * Emit one character to the boot console. + */ +int prom_putchar(char c) +{ + kvm_hypercall3(KVM_HC_MIPS_CONSOLE_OUTPUT, 0 /* port 0 */, + (unsigned long)&c, 1 /* len == 1 */); + + return 1; +} + +#ifdef CONFIG_VIRTIO_CONSOLE +static int paravirt_put_chars(u32 vtermno, const char *buf, int count) +{ + kvm_hypercall3(KVM_HC_MIPS_CONSOLE_OUTPUT, vtermno, + (unsigned long)buf, count); + + return count; +} + +static int __init paravirt_cons_init(void) +{ + virtio_cons_early_init(paravirt_put_chars); + return 0; +} +core_initcall(paravirt_cons_init); + +#endif diff --git a/arch/mips/paravirt/setup.c b/arch/mips/paravirt/setup.c new file mode 100644 index 0000000..cb8448b --- /dev/null +++ b/arch/mips/paravirt/setup.c @@ -0,0 +1,67 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ + +#include +#include + +#include +#include +#include +#include + +extern struct plat_smp_ops paravirt_smp_ops; + +const char *get_system_type(void) +{ + return "MIPS Para-Virtualized Guest"; +} + +void __init plat_time_init(void) +{ + mips_hpt_frequency = kvm_hypercall0(KVM_HC_MIPS_GET_CLOCK_FREQ); + + preset_lpj = mips_hpt_frequency / (2 * HZ); +} + +static void pv_machine_halt(void) +{ + kvm_hypercall0(KVM_HC_MIPS_EXIT_VM); +} + +/* + * Early entry point for arch setup + */ +void __init prom_init(void) +{ + int i; + int argc = fw_arg0; + char **argv = (char **)fw_arg1; + +#ifdef CONFIG_32BIT + set_io_port_base(KSEG1ADDR(0x1e000000)); +#else /* CONFIG_64BIT */ + set_io_port_base(PHYS_TO_XKSEG_UNCACHED(0x1e000000)); +#endif + + for (i = 0; i < argc; i++) { + strlcat(arcs_cmdline, argv[i], COMMAND_LINE_SIZE); + if (i < argc - 1) + strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE); + } + _machine_halt = pv_machine_halt; + register_smp_ops(¶virt_smp_ops); +} + +void __init plat_mem_setup(void) +{ + /* Do nothing, the "mem=???" parser handles our memory. */ +} + +void __init prom_free_prom_memory(void) +{ +} -- cgit v0.10.2 From ae6e7e635c2c9aa5aa5c03f5ac39e9d84fc0ee09 Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:14 +0200 Subject: MIPS: paravirt: Add pci controller for virtio Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7011/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 78b558f..e41f32b 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -825,6 +825,7 @@ source "arch/mips/cavium-octeon/Kconfig" source "arch/mips/loongson/Kconfig" source "arch/mips/loongson1/Kconfig" source "arch/mips/netlogic/Kconfig" +source "arch/mips/paravirt/Kconfig" endmenu diff --git a/arch/mips/paravirt/Kconfig b/arch/mips/paravirt/Kconfig new file mode 100644 index 0000000..ecae586 --- /dev/null +++ b/arch/mips/paravirt/Kconfig @@ -0,0 +1,6 @@ +if MIPS_PARAVIRT + +config MIPS_PCI_VIRTIO + def_bool y + +endif # MIPS_PARAVIRT diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index d61138a..ff8a553 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o - +obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o # # These are still pretty much in the old state, watch, go blind. # diff --git a/arch/mips/pci/pci-virtio-guest.c b/arch/mips/pci/pci-virtio-guest.c new file mode 100644 index 0000000..40a078b --- /dev/null +++ b/arch/mips/pci/pci-virtio-guest.c @@ -0,0 +1,131 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define PCI_CONFIG_ADDRESS 0xcf8 +#define PCI_CONFIG_DATA 0xcfc + +union pci_config_address { + struct { + __BITFIELD_FIELD(unsigned enable_bit : 1, /* 31 */ + __BITFIELD_FIELD(unsigned reserved : 7, /* 30 .. 24 */ + __BITFIELD_FIELD(unsigned bus_number : 8, /* 23 .. 16 */ + __BITFIELD_FIELD(unsigned devfn_number : 8, /* 15 .. 8 */ + __BITFIELD_FIELD(unsigned register_number : 8, /* 7 .. 0 */ + ))))); + }; + u32 w; +}; + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return ((pin + slot) % 4)+ MIPS_IRQ_PCIA; +} + +static void pci_virtio_guest_write_config_addr(struct pci_bus *bus, + unsigned int devfn, int reg) +{ + union pci_config_address pca = { .w = 0 }; + + pca.register_number = reg; + pca.devfn_number = devfn; + pca.bus_number = bus->number; + pca.enable_bit = 1; + + outl(pca.w, PCI_CONFIG_ADDRESS); +} + +static int pci_virtio_guest_write_config(struct pci_bus *bus, + unsigned int devfn, int reg, int size, u32 val) +{ + pci_virtio_guest_write_config_addr(bus, devfn, reg); + + switch (size) { + case 1: + outb(val, PCI_CONFIG_DATA + (reg & 3)); + break; + case 2: + outw(val, PCI_CONFIG_DATA + (reg & 2)); + break; + case 4: + outl(val, PCI_CONFIG_DATA); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_virtio_guest_read_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 *val) +{ + pci_virtio_guest_write_config_addr(bus, devfn, reg); + + switch (size) { + case 1: + *val = inb(PCI_CONFIG_DATA + (reg & 3)); + break; + case 2: + *val = inw(PCI_CONFIG_DATA + (reg & 2)); + break; + case 4: + *val = inl(PCI_CONFIG_DATA); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_virtio_guest_ops = { + .read = pci_virtio_guest_read_config, + .write = pci_virtio_guest_write_config, +}; + +static struct resource pci_virtio_guest_mem_resource = { + .name = "Virtio MEM", + .flags = IORESOURCE_MEM, + .start = 0x10000000, + .end = 0x1dffffff +}; + +static struct resource pci_virtio_guest_io_resource = { + .name = "Virtio IO", + .flags = IORESOURCE_IO, + .start = 0, + .end = 0xffff +}; + +static struct pci_controller pci_virtio_guest_controller = { + .pci_ops = &pci_virtio_guest_ops, + .mem_resource = &pci_virtio_guest_mem_resource, + .io_resource = &pci_virtio_guest_io_resource, +}; + +static int __init pci_virtio_guest_setup(void) +{ + pr_err("pci_virtio_guest_setup\n"); + + /* Virtio comes pre-assigned */ + pci_set_flags(PCI_PROBE_ONLY); + + pci_virtio_guest_controller.io_map_base = mips_io_port_base; + register_pci_controller(&pci_virtio_guest_controller); + return 0; +} +arch_initcall(pci_virtio_guest_setup); -- cgit v0.10.2 From 9bc463be7d4529488b10c8a04461a7ad3cfeacba Mon Sep 17 00:00:00 2001 From: David Daney Date: Wed, 28 May 2014 23:52:15 +0200 Subject: MIPS: Enable build for new system 'paravirt' Signed-off-by: David Daney Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7015/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms index 6e23912..f5e18bf 100644 --- a/arch/mips/Kbuild.platforms +++ b/arch/mips/Kbuild.platforms @@ -18,6 +18,7 @@ platforms += loongson1 platforms += mti-malta platforms += mti-sead3 platforms += netlogic +platforms += paravirt platforms += pmcs-msp71xx platforms += pnx833x platforms += ralink diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index e41f32b..f6521e4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -805,6 +805,25 @@ config NLM_XLP_BOARD This board is based on Netlogic XLP Processor. Say Y here if you have a XLP based board. +config MIPS_PARAVIRT + bool "Para-Virtualized guest system" + select CEVT_R4K + select CSRC_R4K + select DMA_COHERENT + select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_SMP + select NR_CPUS_DEFAULT_4 + select SYS_HAS_EARLY_PRINTK + select SYS_HAS_CPU_MIPS32_R2 + select SYS_HAS_CPU_MIPS64_R2 + select SYS_HAS_CPU_CAVIUM_OCTEON + select HW_HAS_PCI + select SWAP_IO_SPACE + help + This option supports guest running under ???? + endchoice source "arch/mips/alchemy/Kconfig" -- cgit v0.10.2 From a1eace4ba53546bc7a6670b1c380cd5c1287ae8b Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Wed, 28 May 2014 23:52:16 +0200 Subject: MIPS: Add minimal defconfig for mips_paravirt Signed-off-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: David Daney Cc: James Hogan Cc: kvm@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/7008/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/configs/mips_paravirt_defconfig b/arch/mips/configs/mips_paravirt_defconfig new file mode 100644 index 0000000..84cfcb4 --- /dev/null +++ b/arch/mips/configs/mips_paravirt_defconfig @@ -0,0 +1,103 @@ +CONFIG_MIPS_PARAVIRT=y +CONFIG_CPU_MIPS64_R2=y +CONFIG_64BIT=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_SMP=y +CONFIG_HZ_1000=y +CONFIG_PREEMPT=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PCI=y +CONFIG_MIPS32_COMPAT=y +CONFIG_MIPS32_O32=y +CONFIG_MIPS32_N32=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_LRO is not set +CONFIG_IPV6=y +# CONFIG_WIRELESS is not set +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_FW_LOADER is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_VIRTIO_BLK=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_NETDEVICES=y +CONFIG_VIRTIO_NET=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_PHYLIB=y +CONFIG_MARVELL_PHY=y +CONFIG_BROADCOM_PHY=y +CONFIG_BCM87XX_PHY=y +# CONFIG_WLAN is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_NFS_V4=y +CONFIG_NFS_V4_1=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_UTF8=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_FTRACE is not set +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set -- cgit v0.10.2 From 5e888e8fb55cf3da870b85d04fef6bfe0d57c974 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 22 Apr 2014 12:51:13 +0200 Subject: mips: Update the email address of Geert Uytterhoeven All my Sony addresses are defunct. Signed-off-by: Geert Uytterhoeven Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6817/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/nile4.h b/arch/mips/include/asm/nile4.h index 2e2436d..99e97f8 100644 --- a/arch/mips/include/asm/nile4.h +++ b/arch/mips/include/asm/nile4.h @@ -1,7 +1,7 @@ /* * asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions * - * Copyright (C) 2000 Geert Uytterhoeven + * Copyright (C) 2000 Geert Uytterhoeven * Sony Software Development Center Europe (SDCE), Brussels * * This file is based on the following documentation: diff --git a/arch/mips/paravirt/paravirt-smp.c b/arch/mips/paravirt/paravirt-smp.c index 73a123e..0164b0c 100644 --- a/arch/mips/paravirt/paravirt-smp.c +++ b/arch/mips/paravirt/paravirt-smp.c @@ -99,10 +99,6 @@ static void paravirt_smp_finish(void) local_irq_enable(); } -static void paravirt_cpus_done(void) -{ -} - static void paravirt_boot_secondary(int cpu, struct task_struct *idle) { paravirt_smp_gp[cpu] = (unsigned long)task_thread_info(idle); @@ -141,7 +137,6 @@ struct plat_smp_ops paravirt_smp_ops = { .send_ipi_mask = paravirt_send_ipi_mask, .init_secondary = paravirt_init_secondary, .smp_finish = paravirt_smp_finish, - .cpus_done = paravirt_cpus_done, .boot_secondary = paravirt_boot_secondary, .smp_setup = paravirt_smp_setup, .prepare_cpus = paravirt_prepare_cpus, diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 3d27800..50034f9 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -7,7 +7,7 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven + * Geert Uytterhoeven * * 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 diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c index 02d64f77..d35dc9c 100644 --- a/arch/mips/pci/ops-tx3927.c +++ b/arch/mips/pci/ops-tx3927.c @@ -11,7 +11,7 @@ * Define the pci_ops for TX3927. * * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven + * Geert Uytterhoeven * * 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 -- cgit v0.10.2 From 1d61ff6a1aefa59e9c8fd09da1c03735c60edd2b Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Thu, 24 Apr 2014 12:03:00 -0500 Subject: MIPS: Fix MSA toolchain support detection. The '-mmsa' option is not supported by all current compilers. Change the detection to instead pass the option directly to the assembler. Signed-off-by: Steven J. Hill Reviewed-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6835/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 60a359c..78bab83 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -120,7 +120,7 @@ cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \ -fno-omit-frame-pointer ifeq ($(CONFIG_CPU_HAS_MSA),y) -toolchain-msa := $(call cc-option-yn,-mhard-float -mfp64 -mmsa) +toolchain-msa := $(call cc-option-yn,-mhard-float -mfp64 -Wa$(comma)-mmsa) cflags-$(toolchain-msa) += -DTOOLCHAIN_SUPPORTS_MSA endif -- cgit v0.10.2 From 25198235c705be46a3863b9a0b22f1aee90e47a0 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Fri, 11 Apr 2014 10:11:31 -0500 Subject: MIPS: Fix 'write_msa_##' inline macro. The 'write_msa_##' macro incorrectly uses the 'cfcmsa' instruction, which should be the 'ctcmsa' instruction. Signed-off-by: Steven J. Hill Reviewed-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6750/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h index a2aba6c..baddc5f 100644 --- a/arch/mips/include/asm/msa.h +++ b/arch/mips/include/asm/msa.h @@ -84,7 +84,7 @@ static inline void write_msa_##name(unsigned int val) \ __asm__ __volatile__( \ " .set push\n" \ " .set msa\n" \ - " cfcmsa $" #cs ", %0\n" \ + " ctcmsa $" #cs ", %0\n" \ " .set pop\n" \ : : "r"(val)); \ } -- cgit v0.10.2 From f7a89f1b8eb598ac5da61c9795b3d847baa73d12 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Sat, 19 Apr 2014 19:26:28 -0700 Subject: MIPS: Call find_vma with the mmap_sem held Performing vma lookups without taking the mm->mmap_sem is asking for trouble. While doing the search, the vma in question can be modified or even removed before returning to the caller. Take the lock (exclusively) in order to avoid races while iterating through the vmacache and/or rbtree. Updates two functions: - process_fpemu_return() - cteon_flush_cache_sigtramp() Signed-off-by: Davidlohr Bueso Tested-by: Andreas Herrmann Cc: linux-mips@linux-mips.org Cc: akpm@linux-foundation.org Cc: zeus@gnu.org Cc: aswin@hp.com Cc: davidlohr@hp.com Cc: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org Patchwork: http://patchwork.linux-mips.org/patch/6811/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 8119ac2..d57fc10 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -712,10 +712,12 @@ int process_fpemu_return(int sig, void __user *fault_addr) si.si_addr = fault_addr; si.si_signo = sig; if (sig == SIGSEGV) { + down_read(¤t->mm->mmap_sem); if (find_vma(current->mm, (unsigned long)fault_addr)) si.si_code = SEGV_ACCERR; else si.si_code = SEGV_MAPERR; + up_read(¤t->mm->mmap_sem); } else { si.si_code = BUS_ADRERR; } diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index f41a5c5..05b1d7c 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -137,8 +137,10 @@ static void octeon_flush_cache_sigtramp(unsigned long addr) { struct vm_area_struct *vma; + down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm, addr); octeon_flush_icache_all_cores(vma); + up_read(¤t->mm->mmap_sem); } -- cgit v0.10.2 From b4f16c938eed87aac733972e735c5bea700948aa Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 3 Jun 2014 13:05:55 +0200 Subject: MIPS: BFP: Simplify code slightly. This keeps the if condition slightly simpler - it's going to become ore complication. Signed-off-by: Ralf Baechle diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c index 98e9d23..a67b975 100644 --- a/arch/mips/net/bpf_jit.c +++ b/arch/mips/net/bpf_jit.c @@ -1240,7 +1240,10 @@ jmp_cmp: emit_half_load(r_A, r_skb, off, ctx); #ifdef CONFIG_CPU_LITTLE_ENDIAN /* This needs little endian fixup */ - if (!cpu_has_mips_r2) { + if (cpu_has_mips_r2) { + /* R2 and later have the wsbh instruction */ + emit_wsbh(r_A, r_A, ctx); + } else { /* Get first byte */ emit_andi(r_tmp_imm, r_A, 0xff, ctx); /* Shift it */ @@ -1250,9 +1253,6 @@ jmp_cmp: emit_andi(r_tmp_imm, r_tmp_imm, 0xff, ctx); /* Put everyting together in r_A */ emit_or(r_A, r_tmp, r_tmp_imm, ctx); - } else { - /* R2 and later have the wsbh instruction */ - emit_wsbh(r_A, r_A, ctx); } #endif break; -- cgit v0.10.2 From 8ca635bfc0e4488d167cea322c7e098689f37080 Mon Sep 17 00:00:00 2001 From: Daniel Walter Date: Tue, 3 Jun 2014 16:21:05 +0100 Subject: MIPS: Replace obsolete strict_strto call with kstrto Signed-off-by: Daniel Walter Cc: linux-kernel@vger.kernel.org Cc: richard@nod.at Cc: akpm@linux-foundation.org Signed-off-by: Ralf Baechle diff --git a/arch/mips/alchemy/board-xxs1500.c b/arch/mips/alchemy/board-xxs1500.c index bd55136..3fb814b 100644 --- a/arch/mips/alchemy/board-xxs1500.c +++ b/arch/mips/alchemy/board-xxs1500.c @@ -49,7 +49,7 @@ void __init prom_init(void) prom_init_cmdline(); memsize_str = prom_getenv("memsize"); - if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize)) + if (!memsize_str || kstrtoul(memsize_str, 0, &memsize)) memsize = 0x04000000; add_memory_region(0, memsize, BOOT_MEM_RAM); diff --git a/arch/mips/alchemy/devboards/pm.c b/arch/mips/alchemy/devboards/pm.c index b86bff3..61e90fe 100644 --- a/arch/mips/alchemy/devboards/pm.c +++ b/arch/mips/alchemy/devboards/pm.c @@ -158,7 +158,7 @@ static ssize_t db1x_pmattr_store(struct kobject *kobj, int tmp; if (ATTRCMP(timer_timeout)) { - tmp = strict_strtoul(instr, 0, &l); + tmp = kstrtoul(instr, 0, &l); if (tmp) return tmp; @@ -181,7 +181,7 @@ static ssize_t db1x_pmattr_store(struct kobject *kobj, } } else if (ATTRCMP(wakemsk)) { - tmp = strict_strtoul(instr, 0, &l); + tmp = kstrtoul(instr, 0, &l); if (tmp) return tmp; -- cgit v0.10.2 From 8e9ecbc5e21bf82693e52ec75b1f45c1245a9bea Mon Sep 17 00:00:00 2001 From: Daniel Walter Date: Tue, 3 Jun 2014 16:22:08 +0100 Subject: MIPS: Replace calls to obsolete strict_strto call with kstrto* equivalents. Signed-off-by: Daniel Walter Cc: linux-kernel@vger.kernel.org Cc: richard@nod.at Cc: akpm@linux-foundation.org Signed-off-by: Ralf Baechle diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c index 3d5df51..0e046d8 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c @@ -202,17 +202,20 @@ char *tx4927_pcibios_setup(char *str) unsigned long val; if (!strncmp(str, "trdyto=", 7)) { - if (strict_strtoul(str + 7, 0, &val) == 0) + u8 val = 0; + if (kstrtou8(str + 7, 0, &val) == 0) tx4927_pci_opts.trdyto = val; return NULL; } if (!strncmp(str, "retryto=", 8)) { - if (strict_strtoul(str + 8, 0, &val) == 0) + u8 val = 0; + if (kstrtou8(str + 8, 0, &val) == 0) tx4927_pci_opts.retryto = val; return NULL; } if (!strncmp(str, "gbwc=", 5)) { - if (strict_strtoul(str + 5, 0, &val) == 0) + u16 val; + if (kstrtou16(str + 5, 0, &val) == 0) tx4927_pci_opts.gbwc = val; return NULL; } diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index 2b0b83c..dd2cf25 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -309,8 +309,8 @@ static void __init preprocess_cmdline(void) txx9_board_vec = find_board_byname(str + 6); continue; } else if (strncmp(str, "masterclk=", 10) == 0) { - unsigned long val; - if (strict_strtoul(str + 10, 10, &val) == 0) + unsigned int val; + if (kstrtouint(str + 10, 10, &val) == 0) txx9_master_clock = val; continue; } else if (strcmp(str, "icdisable") == 0) { -- cgit v0.10.2 From d96cc3d1ec5dcbb49a5a990d699239d590624799 Mon Sep 17 00:00:00 2001 From: "Steven J. Hill" Date: Tue, 15 Apr 2014 16:06:49 -0500 Subject: MIPS: Add microMIPS MSA support. This patch adds support for the microMIPS implementation of the MSA instructions. Signed-off-by: Steven J. Hill Reviewed-by: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6763/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index f7db79a..935543f 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h @@ -249,13 +249,35 @@ .set pop .endm #else + +#ifdef CONFIG_CPU_MICROMIPS +#define CFC_MSA_INSN 0x587e0056 +#define CTC_MSA_INSN 0x583e0816 +#define LDD_MSA_INSN 0x58000837 +#define STD_MSA_INSN 0x5800083f +#define COPY_UW_MSA_INSN 0x58f00056 +#define COPY_UD_MSA_INSN 0x58f80056 +#define INSERT_W_MSA_INSN 0x59300816 +#define INSERT_D_MSA_INSN 0x59380816 +#else +#define CFC_MSA_INSN 0x787e0059 +#define CTC_MSA_INSN 0x783e0819 +#define LDD_MSA_INSN 0x78000823 +#define STD_MSA_INSN 0x78000827 +#define COPY_UW_MSA_INSN 0x78f00059 +#define COPY_UD_MSA_INSN 0x78f80059 +#define INSERT_W_MSA_INSN 0x79300819 +#define INSERT_D_MSA_INSN 0x79380819 +#endif + /* * Temporary until all toolchains in use include MSA support. */ .macro cfcmsa rd, cs .set push .set noat - .word 0x787e0059 | (\cs << 11) + .insn + .word CFC_MSA_INSN | (\cs << 11) move \rd, $1 .set pop .endm @@ -264,7 +286,7 @@ .set push .set noat move $1, \rs - .word 0x783e0819 | (\cd << 6) + .word CTC_MSA_INSN | (\cd << 6) .set pop .endm @@ -272,7 +294,7 @@ .set push .set noat add $1, \base, \off - .word 0x78000823 | (\wd << 6) + .word LDD_MSA_INSN | (\wd << 6) .set pop .endm @@ -280,14 +302,15 @@ .set push .set noat add $1, \base, \off - .word 0x78000827 | (\wd << 6) + .word STD_MSA_INSN | (\wd << 6) .set pop .endm .macro copy_u_w rd, ws, n .set push .set noat - .word 0x78f00059 | (\n << 16) | (\ws << 11) + .insn + .word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11) /* move triggers an assembler bug... */ or \rd, $1, zero .set pop @@ -296,7 +319,8 @@ .macro copy_u_d rd, ws, n .set push .set noat - .word 0x78f80059 | (\n << 16) | (\ws << 11) + .insn + .word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11) /* move triggers an assembler bug... */ or \rd, $1, zero .set pop @@ -307,7 +331,7 @@ .set noat /* move triggers an assembler bug... */ or $1, \rs, zero - .word 0x79300819 | (\n << 16) | (\wd << 6) + .word INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6) .set pop .endm @@ -316,7 +340,7 @@ .set noat /* move triggers an assembler bug... */ or $1, \rs, zero - .word 0x79380819 | (\n << 16) | (\wd << 6) + .word INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6) .set pop .endm #endif diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h index a2aba6c..52450a0 100644 --- a/arch/mips/include/asm/msa.h +++ b/arch/mips/include/asm/msa.h @@ -96,6 +96,13 @@ static inline void write_msa_##name(unsigned int val) \ * allow compilation with toolchains that do not support MSA. Once all * toolchains in use support MSA these can be removed. */ +#ifdef CONFIG_CPU_MICROMIPS +#define CFC_MSA_INSN 0x587e0056 +#define CTC_MSA_INSN 0x583e0816 +#else +#define CFC_MSA_INSN 0x787e0059 +#define CTC_MSA_INSN 0x783e0819 +#endif #define __BUILD_MSA_CTL_REG(name, cs) \ static inline unsigned int read_msa_##name(void) \ @@ -104,7 +111,8 @@ static inline unsigned int read_msa_##name(void) \ __asm__ __volatile__( \ " .set push\n" \ " .set noat\n" \ - " .word 0x787e0059 | (" #cs " << 11)\n" \ + " .insn\n" \ + " .word #CFC_MSA_INSN | (" #cs " << 11)\n" \ " move %0, $1\n" \ " .set pop\n" \ : "=r"(reg)); \ @@ -117,7 +125,8 @@ static inline void write_msa_##name(unsigned int val) \ " .set push\n" \ " .set noat\n" \ " move $1, %0\n" \ - " .word 0x783e0819 | (" #cs " << 6)\n" \ + " .insn\n" \ + " .word #CTC_MSA_INSN | (" #cs " << 6)\n" \ " .set pop\n" \ : : "r"(val)); \ } -- cgit v0.10.2 From ebff05b9c64974a3dfdce61b1a8fcc15ca864863 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 6 Apr 2014 23:04:00 +0100 Subject: DEC: Add self as the maintainer Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6707/ Signed-off-by: Ralf Baechle diff --git a/MAINTAINERS b/MAINTAINERS index 6846c7c..bb36478 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2687,6 +2687,15 @@ S: Orphan F: Documentation/networking/decnet.txt F: net/decnet/ +DECSTATION PLATFORM SUPPORT +M: "Maciej W. Rozycki" +L: linux-mips@linux-mips.org +W: http://www.linux-mips.org/wiki/DECstation +S: Maintained +F: arch/mips/dec/ +F: arch/mips/include/asm/dec/ +F: arch/mips/include/asm/mach-dec/ + DEFXX FDDI NETWORK DRIVER M: "Maciej W. Rozycki" S: Maintained -- cgit v0.10.2 From fd28b9ac8e8944b04ace0fceb7222edd4e42b00a Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sun, 6 Apr 2014 22:42:48 +0100 Subject: DEC: Document the R4k MB ASIC mini interrupt controller There's an alternative 5-line mini interrupt controller in the R4k MB ASIC used on the KN04 and KN05 CPU daughtercards. The controller is cascaded from the CPU interrupt input that would be used for the Halt button on the corresponding R3k systems. This change documents the findings so far. Signed-off-by: Maciej W. Rozycki Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/6706/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/dec/kn05.h b/arch/mips/include/asm/dec/kn05.h index 56d22dc..8e14f67 100644 --- a/arch/mips/include/asm/dec/kn05.h +++ b/arch/mips/include/asm/dec/kn05.h @@ -49,12 +49,20 @@ #define KN4K_RES_15 (15*IOASIC_SLOT_SIZE) /* unused? */ /* + * MB ASIC interrupt bits. + */ +#define KN4K_MB_INR_MB 4 /* ??? */ +#define KN4K_MB_INR_MT 3 /* memory, I/O bus read/write errors */ +#define KN4K_MB_INR_RES_2 2 /* unused */ +#define KN4K_MB_INR_RTC 1 /* RTC */ +#define KN4K_MB_INR_TC 0 /* I/O ASIC cascade */ + +/* * Bits for the MB interrupt register. * The register appears read-only. */ -#define KN4K_MB_INT_TC (1<<0) /* TURBOchannel? */ -#define KN4K_MB_INT_RTC (1<<1) /* RTC? */ -#define KN4K_MB_INT_MT (1<<3) /* I/O ASIC cascade */ +#define KN4K_MB_INT_IRQ (0x1f<<0) /* CPU Int[4:0] status. */ +#define KN4K_MB_INT_IRQ_N(n) (1<<(n)) /* Individual status bits. */ /* * Bits for the MB control & status register. @@ -70,6 +78,7 @@ #define KN4K_MB_CSR_NC (1<<14) /* ??? */ #define KN4K_MB_CSR_EE (1<<15) /* (bus) Exception Enable? */ #define KN4K_MB_CSR_MSK (0x1f<<16) /* CPU Int[4:0] mask */ +#define KN4K_MB_CSR_MSK_N(n) (1<<((n)+16)) /* Individual mask bits. */ #define KN4K_MB_CSR_FW (1<<21) /* ??? */ #define KN4K_MB_CSR_W (1<<31) /* ??? */ -- cgit v0.10.2 From a53825ef4e9b2f42a21ad2b903f4d0ce691a5d63 Mon Sep 17 00:00:00 2001 From: Eunbong Song Date: Tue, 22 Apr 2014 06:16:15 +0000 Subject: MIPS: Octeon: Add twsi interrupt initialization for OCTEON 3XXX, 5XXX, 63XX In octeon_3xxx.dts file, there is a definiton for twsi/twsi2 interrupts. But there is no code for initialization of this interrupts. This patch adds code for initialization of twsi interrupts. Signed-off-by: Eunbong Song Cc: linux-kernel@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/6816/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 3aa5b46..1b82ac6 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -1260,11 +1260,13 @@ static void __init octeon_irq_init_ciu(void) for (i = 0; i < 4; i++) octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40); + octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_TWSI, 0, 45); octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46); for (i = 0; i < 4; i++) octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52); octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56); + octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_TWSI2, 0, 59); /* CIU_1 */ for (i = 0; i < 16; i++) diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h index 60fc4c3..cceae32 100644 --- a/arch/mips/include/asm/mach-cavium-octeon/irq.h +++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h @@ -35,6 +35,8 @@ enum octeon_irq { OCTEON_IRQ_PCI_MSI2, OCTEON_IRQ_PCI_MSI3, + OCTEON_IRQ_TWSI, + OCTEON_IRQ_TWSI2, OCTEON_IRQ_RML, OCTEON_IRQ_TIMER0, OCTEON_IRQ_TIMER1, -- cgit v0.10.2 From 1d421ca9d7edbac1eb118631ee039d50ab54771e Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Wed, 4 Jun 2014 12:00:37 +0200 Subject: MIPS: IP22/IP28: Improve GIO support - added interrupt support for GIO devices - improved detection of GIO cards on Indigo2 - added more known GIO cards Signed-off-by: Thomas Bogendoerfer Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/7055/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/gio_device.h b/arch/mips/include/asm/gio_device.h index 0878701..4be1a57 100644 --- a/arch/mips/include/asm/gio_device.h +++ b/arch/mips/include/asm/gio_device.h @@ -50,7 +50,7 @@ static inline void gio_device_free(struct gio_device *dev) extern int gio_register_driver(struct gio_driver *); extern void gio_unregister_driver(struct gio_driver *); -#define gio_get_drvdata(_dev) drv_get_drvdata(&(_dev)->dev) -#define gio_set_drvdata(_dev, data) drv_set_drvdata(&(_dev)->dev, (data)) +#define gio_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) +#define gio_set_drvdata(_dev, data) dev_set_drvdata(&(_dev)->dev, (data)) extern void gio_set_master(struct gio_device *); diff --git a/arch/mips/include/asm/sgi/ip22.h b/arch/mips/include/asm/sgi/ip22.h index 8db1a35..87ec9ea 100644 --- a/arch/mips/include/asm/sgi/ip22.h +++ b/arch/mips/include/asm/sgi/ip22.h @@ -69,6 +69,8 @@ #define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ #define SGI_KEYBD_IRQ SGINT_LOCAL2 + 4 /* keyboard */ #define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ +#define SGI_GIOEXP0_IRQ (SGINT_LOCAL2 + 6) /* Indy GIO EXP0 */ +#define SGI_GIOEXP1_IRQ (SGINT_LOCAL2 + 7) /* Indy GIO EXP1 */ #define ip22_is_fullhouse() (sgioc->sysid & SGIOC_SYSID_FULLHOUSE) diff --git a/arch/mips/sgi-ip22/ip22-gio.c b/arch/mips/sgi-ip22/ip22-gio.c index ab0e379..8e52446 100644 --- a/arch/mips/sgi-ip22/ip22-gio.c +++ b/arch/mips/sgi-ip22/ip22-gio.c @@ -19,6 +19,9 @@ static struct { } gio_name_table[] = { { .name = "SGI Impact", .id = 0x10 }, { .name = "Phobos G160", .id = 0x35 }, + { .name = "Phobos G130", .id = 0x36 }, + { .name = "Phobos G100", .id = 0x37 }, + { .name = "Set Engineering GFE", .id = 0x38 }, /* fake IDs */ { .name = "SGI Newport", .id = 0x7e }, { .name = "SGI GR2/GR3", .id = 0x7f }, @@ -293,7 +296,16 @@ static int ip22_gio_id(unsigned long addr, u32 *res) * data matches */ ptr8 = (void *)CKSEG1ADDR(addr + 3); - get_dbe(tmp8, ptr8); + if (get_dbe(tmp8, ptr8)) { + /* + * 32bit access worked, but 8bit doesn't + * so we don't see phantom reads on + * a pipelined bus, but a real card which + * doesn't support 8 bit reads + */ + *res = tmp32; + return 1; + } ptr16 = (void *)CKSEG1ADDR(addr + 2); get_dbe(tmp16, ptr16); if (tmp8 == (tmp16 & 0xff) && @@ -324,7 +336,7 @@ static int ip22_is_gr2(unsigned long addr) } -static void ip22_check_gio(int slotno, unsigned long addr) +static void ip22_check_gio(int slotno, unsigned long addr, int irq) { const char *name = "Unknown"; struct gio_device *gio_dev; @@ -338,9 +350,9 @@ static void ip22_check_gio(int slotno, unsigned long addr) else { if (!ip22_gio_id(addr, &tmp)) { /* - * no GIO signature at start address of slot, but - * Newport doesn't have one, so let's check usea - * status register + * no GIO signature at start address of slot + * since Newport doesn't have one, we check if + * user status register is readable */ if (ip22_gio_id(addr + NEWPORT_USTATUS_OFFS, &tmp)) tmp = 0x7e; @@ -369,6 +381,7 @@ static void ip22_check_gio(int slotno, unsigned long addr) gio_dev->resource.start = addr; gio_dev->resource.end = addr + 0x3fffff; gio_dev->resource.flags = IORESOURCE_MEM; + gio_dev->irq = irq; dev_set_name(&gio_dev->dev, "%d", slotno); gio_device_register(gio_dev); } else @@ -408,16 +421,17 @@ int __init ip22_gio_init(void) request_resource(&iomem_resource, &gio_bus_resource); printk(KERN_INFO "GIO: Probing bus...\n"); - if (ip22_is_fullhouse() || - !get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) { - /* Indigo2 and ChallengeS */ - ip22_check_gio(0, GIO_SLOT_GFX_BASE); - ip22_check_gio(1, GIO_SLOT_EXP0_BASE); + if (ip22_is_fullhouse()) { + /* Indigo2 */ + ip22_check_gio(0, GIO_SLOT_GFX_BASE, SGI_GIO_1_IRQ); + ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIO_1_IRQ); } else { - /* Indy */ - ip22_check_gio(0, GIO_SLOT_GFX_BASE); - ip22_check_gio(1, GIO_SLOT_EXP0_BASE); - ip22_check_gio(2, GIO_SLOT_EXP1_BASE); + /* Indy/Challenge S */ + if (get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1])) + ip22_check_gio(0, GIO_SLOT_GFX_BASE, + SGI_GIO_0_IRQ); + ip22_check_gio(1, GIO_SLOT_EXP0_BASE, SGI_GIOEXP0_IRQ); + ip22_check_gio(2, GIO_SLOT_EXP1_BASE, SGI_GIOEXP1_IRQ); } } else device_unregister(&gio_bus); diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index 58b40ae..c66889f 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c @@ -119,9 +119,14 @@ static void indy_local0_irqdispatch(void) } else irq = lc0msk_to_irqnr[mask]; - /* if irq == 0, then the interrupt has already been cleared */ + /* + * workaround for INT2 bug; if irq == 0, INT2 has seen a fifo full + * irq, but failed to latch it into status register + */ if (irq) do_IRQ(irq); + else + do_IRQ(SGINT_LOCAL0 + 0); } static void indy_local1_irqdispatch(void) -- cgit v0.10.2