From 6e9538917c5f62c1a1598da9b898702800801b98 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 16 Apr 2006 23:27:21 +0400 Subject: [MIPS] Fix marking buddy of pte global for MIPS32 w/36-bit physical address In case of CONFIG_64BIT_PHYS_ADDR, set_pte() and pte_clear() functions only set _PAGE_GLOBAL bit in the pte_low field of the buddy PTEs, forgetting to propagate ito to pte_high. Thus, the both pages might not really be made global for the CPU (since it AND's the G-bit of the odd / even PTEs together to decide whether they're global or not). Thus, if only a single page is allocated via vmalloc() or ioremap(), it's not really global for CPU (and it must be, since this is kernel mapping), and thus its ASID is compared against the current process' one -- so, we'll get into trouble sooner or later... Also, pte_none() will fail on global pages because _PAGE_GLOBAL bit is set in both pte_low and pte_high, and pte_val() will return u64 value consisting of those fields concateneted. Signed-off-by: Sergei Shtylyov Signed-off-by: Ralf Baechle --- include/asm-mips/pgtable.h | 88 ++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 39 deletions(-) (limited to 'include') diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 702a28f..174a3cd 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -82,10 +82,11 @@ extern void paging_init(void); #define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) #define pmd_page_kernel(pmd) pmd_val(pmd) -#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) -#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) - #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1) + +#define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL)) +#define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) + static inline void set_pte(pte_t *ptep, pte_t pte) { ptep->pte_high = pte.pte_high; @@ -93,27 +94,35 @@ static inline void set_pte(pte_t *ptep, pte_t pte) ptep->pte_low = pte.pte_low; //printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low); - if (pte_val(pte) & _PAGE_GLOBAL) { + if (pte.pte_low & _PAGE_GLOBAL) { pte_t *buddy = ptep_buddy(ptep); /* * Make sure the buddy is global too (if it's !none, * it better already be global) */ - if (pte_none(*buddy)) - buddy->pte_low |= _PAGE_GLOBAL; + if (pte_none(*buddy)) { + buddy->pte_low |= _PAGE_GLOBAL; + buddy->pte_high |= _PAGE_GLOBAL; + } } } #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { + pte_t null = __pte(0); + /* Preserve global status for the pair */ - if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL) - set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL)); - else - set_pte_at(mm, addr, ptep, __pte(0)); + if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) + null.pte_low = null.pte_high = _PAGE_GLOBAL; + + set_pte_at(mm, addr, ptep, null); } #else + +#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL)) +#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) + /* * Certain architectures need to do special things when pte's * within a page table are directly modified. Thus, the following @@ -174,75 +183,76 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; */ static inline int pte_user(pte_t pte) { BUG(); return 0; } #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1) -static inline int pte_read(pte_t pte) { return (pte).pte_low & _PAGE_READ; } -static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_WRITE; } -static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_MODIFIED; } -static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; } -static inline int pte_file(pte_t pte) { return (pte).pte_low & _PAGE_FILE; } +static inline int pte_read(pte_t pte) { return pte.pte_low & _PAGE_READ; } +static inline int pte_write(pte_t pte) { return pte.pte_low & _PAGE_WRITE; } +static inline int pte_dirty(pte_t pte) { return pte.pte_low & _PAGE_MODIFIED; } +static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; } +static inline int pte_file(pte_t pte) { return pte.pte_low & _PAGE_FILE; } + static inline pte_t pte_wrprotect(pte_t pte) { - (pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); - (pte).pte_high &= ~_PAGE_SILENT_WRITE; + pte.pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE); + pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } static inline pte_t pte_rdprotect(pte_t pte) { - (pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ); - (pte).pte_high &= ~_PAGE_SILENT_READ; + pte.pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ); + pte.pte_high &= ~_PAGE_SILENT_READ; return pte; } static inline pte_t pte_mkclean(pte_t pte) { - (pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE); - (pte).pte_high &= ~_PAGE_SILENT_WRITE; + pte.pte_low &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); + pte.pte_high &= ~_PAGE_SILENT_WRITE; return pte; } static inline pte_t pte_mkold(pte_t pte) { - (pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ); - (pte).pte_high &= ~_PAGE_SILENT_READ; + pte.pte_low &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ); + pte.pte_high &= ~_PAGE_SILENT_READ; return pte; } static inline pte_t pte_mkwrite(pte_t pte) { - (pte).pte_low |= _PAGE_WRITE; - if ((pte).pte_low & _PAGE_MODIFIED) { - (pte).pte_low |= _PAGE_SILENT_WRITE; - (pte).pte_high |= _PAGE_SILENT_WRITE; + pte.pte_low |= _PAGE_WRITE; + if (pte.pte_low & _PAGE_MODIFIED) { + pte.pte_low |= _PAGE_SILENT_WRITE; + pte.pte_high |= _PAGE_SILENT_WRITE; } return pte; } static inline pte_t pte_mkread(pte_t pte) { - (pte).pte_low |= _PAGE_READ; - if ((pte).pte_low & _PAGE_ACCESSED) { - (pte).pte_low |= _PAGE_SILENT_READ; - (pte).pte_high |= _PAGE_SILENT_READ; + pte.pte_low |= _PAGE_READ; + if (pte.pte_low & _PAGE_ACCESSED) { + pte.pte_low |= _PAGE_SILENT_READ; + pte.pte_high |= _PAGE_SILENT_READ; } return pte; } static inline pte_t pte_mkdirty(pte_t pte) { - (pte).pte_low |= _PAGE_MODIFIED; - if ((pte).pte_low & _PAGE_WRITE) { - (pte).pte_low |= _PAGE_SILENT_WRITE; - (pte).pte_high |= _PAGE_SILENT_WRITE; + pte.pte_low |= _PAGE_MODIFIED; + if (pte.pte_low & _PAGE_WRITE) { + pte.pte_low |= _PAGE_SILENT_WRITE; + pte.pte_high |= _PAGE_SILENT_WRITE; } return pte; } static inline pte_t pte_mkyoung(pte_t pte) { - (pte).pte_low |= _PAGE_ACCESSED; - if ((pte).pte_low & _PAGE_READ) - (pte).pte_low |= _PAGE_SILENT_READ; - (pte).pte_high |= _PAGE_SILENT_READ; + pte.pte_low |= _PAGE_ACCESSED; + if (pte.pte_low & _PAGE_READ) + pte.pte_low |= _PAGE_SILENT_READ; + pte.pte_high |= _PAGE_SILENT_READ; return pte; } #else -- cgit v1.1 From c620953c32d301c2a7bc73f9f780301e110b7d7c Mon Sep 17 00:00:00 2001 From: Chris Dearman Date: Tue, 2 May 2006 14:08:46 +0100 Subject: [MIPS] Fix detection and handling of the 74K processor. Nothing exciting; Linux just didn't know it yet so this is most adding a value to a case statement. Signed-off-by: Chris Dearman Signed-off-by: Ralf Baechle --- include/asm-mips/cpu.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h index 818b9a9..0117138 100644 --- a/include/asm-mips/cpu.h +++ b/include/asm-mips/cpu.h @@ -87,6 +87,7 @@ #define PRID_IMP_24K 0x9300 #define PRID_IMP_34K 0x9500 #define PRID_IMP_24KE 0x9600 +#define PRID_IMP_74K 0x9700 /* * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE @@ -196,7 +197,8 @@ #define CPU_34K 60 #define CPU_PR4450 61 #define CPU_SB1A 62 -#define CPU_LAST 62 +#define CPU_74K 63 +#define CPU_LAST 63 /* * ISA Level encodings -- cgit v1.1 From 6ee1da94c5fed95bacce3eda8e6d9e69324ecab7 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 3 May 2006 20:42:39 +0100 Subject: [MIPS] Update/fix futex assembly o Implement futex_atomic_op_inuser() operation o Don't use the R10000-ll/sc bug workaround version for every processor. branch likely is deprecated and some historic ll/sc processors don't implement it. In any case it's slow. Signed-off-by: Ralf Baechle --- include/asm-mips/futex.h | 141 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h index a554089..12d118f 100644 --- a/include/asm-mips/futex.h +++ b/include/asm-mips/futex.h @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef CONFIG_SMP #define __FUTEX_SMP_SYNC " sync \n" @@ -16,30 +17,58 @@ #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ { \ - __asm__ __volatile__( \ - " .set push \n" \ - " .set noat \n" \ - " .set mips3 \n" \ - "1: ll %1, (%3) # __futex_atomic_op1 \n" \ - " .set mips0 \n" \ - " " insn " \n" \ - " .set mips3 \n" \ - "2: sc $1, (%3) \n" \ - " beqzl $1, 1b \n" \ - __FUTEX_SMP_SYNC \ - "3: \n" \ - " .set pop \n" \ - " .set mips0 \n" \ - " .section .fixup,\"ax\" \n" \ - "4: li %0, %5 \n" \ - " j 2b \n" \ - " .previous \n" \ - " .section __ex_table,\"a\" \n" \ - " "__UA_ADDR "\t1b, 4b \n" \ - " "__UA_ADDR "\t2b, 4b \n" \ - " .previous \n" \ - : "=r" (ret), "=r" (oldval) \ - : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \ + if (cpu_has_llsc && R10000_LLSC_WAR) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: ll %1, (%3) # __futex_atomic_op \n" \ + " .set mips0 \n" \ + " " insn " \n" \ + " .set mips3 \n" \ + "2: sc $1, (%3) \n" \ + " beqzl $1, 1b \n" \ + __FUTEX_SMP_SYNC \ + "3: \n" \ + " .set pop \n" \ + " .set mips0 \n" \ + " .section .fixup,\"ax\" \n" \ + "4: li %0, %5 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " "__UA_ADDR "\t1b, 4b \n" \ + " "__UA_ADDR "\t2b, 4b \n" \ + " .previous \n" \ + : "=r" (ret), "=r" (oldval) \ + : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \ + } else if (cpu_has_llsc) { \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noat \n" \ + " .set mips3 \n" \ + "1: ll %1, (%3) # __futex_atomic_op \n" \ + " .set mips0 \n" \ + " " insn " \n" \ + " .set mips3 \n" \ + "2: sc $1, (%3) \n" \ + " beqz $1, 1b \n" \ + __FUTEX_SMP_SYNC \ + "3: \n" \ + " .set pop \n" \ + " .set mips0 \n" \ + " .section .fixup,\"ax\" \n" \ + "4: li %0, %5 \n" \ + " j 2b \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " "__UA_ADDR "\t1b, 4b \n" \ + " "__UA_ADDR "\t2b, 4b \n" \ + " .previous \n" \ + : "=r" (ret), "=r" (oldval) \ + : "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT)); \ + } else \ + ret = -ENOSYS; \ } static inline int @@ -102,7 +131,69 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { - return -ENOSYS; + int retval; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + if (cpu_has_llsc && R10000_LLSC_WAR) { + __asm__ __volatile__( + "# futex_atomic_cmpxchg_inatomic \n" + " .set push \n" + " .set noat \n" + " .set mips3 \n" + "1: ll %0, %2 \n" + " bne %0, %z3, 3f \n" + " .set mips0 \n" + " move $1, %z4 \n" + " .set mips3 \n" + "2: sc $1, %1 \n" + " beqzl $1, 1b \n" + __FUTEX_SMP_SYNC + "3: \n" + " .set pop \n" + " .section .fixup,\"ax\" \n" + "4: li %0, %5 \n" + " j 3b \n" + " .previous \n" + " .section __ex_table,\"a\" \n" + " "__UA_ADDR "\t1b, 4b \n" + " "__UA_ADDR "\t2b, 4b \n" + " .previous \n" + : "=&r" (retval), "=R" (*uaddr) + : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) + : "memory"); + } else if (cpu_has_llsc) { + __asm__ __volatile__( + "# futex_atomic_cmpxchg_inatomic \n" + " .set push \n" + " .set noat \n" + " .set mips3 \n" + "1: ll %0, %2 \n" + " bne %0, %z3, 3f \n" + " .set mips0 \n" + " move $1, %z4 \n" + " .set mips3 \n" + "2: sc $1, %1 \n" + " beqz $1, 1b \n" + __FUTEX_SMP_SYNC + "3: \n" + " .set pop \n" + " .section .fixup,\"ax\" \n" + "4: li %0, %5 \n" + " j 3b \n" + " .previous \n" + " .section __ex_table,\"a\" \n" + " "__UA_ADDR "\t1b, 4b \n" + " "__UA_ADDR "\t2b, 4b \n" + " .previous \n" + : "=&r" (retval), "=R" (*uaddr) + : "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT) + : "memory"); + } else + return -ENOSYS; + + return retval; } #endif -- cgit v1.1 From 1c0c1ae4f3d5057d091677d0ef7dbaeb28122ded Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Mon, 8 May 2006 15:28:22 -0400 Subject: [MIPS] Update struct sigcontext member names Rename the 64-bit sc_hi and sc_lo arrays to use the same names as the 32-bit struct sigcontext (sc_mdhi, sc_hi1, et cetera). Signed-off-by: Daniel Jacobowitz Signed-off-by: Ralf Baechle --- include/asm-mips/sigcontext.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-mips/sigcontext.h b/include/asm-mips/sigcontext.h index 8edabb0..cefa657 100644 --- a/include/asm-mips/sigcontext.h +++ b/include/asm-mips/sigcontext.h @@ -55,8 +55,14 @@ struct sigcontext { struct sigcontext { unsigned long sc_regs[32]; unsigned long sc_fpregs[32]; - unsigned long sc_hi[4]; - unsigned long sc_lo[4]; + unsigned long sc_mdhi; + unsigned long sc_hi1; + unsigned long sc_hi2; + unsigned long sc_hi3; + unsigned long sc_mdlo; + unsigned long sc_lo1; + unsigned long sc_lo2; + unsigned long sc_lo3; unsigned long sc_pc; unsigned int sc_fpc_csr; unsigned int sc_used_math; -- cgit v1.1 From 3301edcbd7aab674bd7598e6b97a314b93874ec0 Mon Sep 17 00:00:00 2001 From: Thiemo Seufer Date: Mon, 15 May 2006 18:24:57 +0100 Subject: [MIPS] DSP and MDMX share the same config flag bit. Clarify comment. Signed-off-by: Thiemo Seufer Signed-off-by: Ralf Baechle --- include/asm-mips/mipsregs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h index a2ef579..5af7517f 100644 --- a/include/asm-mips/mipsregs.h +++ b/include/asm-mips/mipsregs.h @@ -291,7 +291,7 @@ #define ST0_DL (_ULCAST_(1) << 24) /* - * Enable the MIPS DSP ASE + * Enable the MIPS MDMX and DSP ASEs */ #define ST0_MX 0x01000000 -- cgit v1.1 From ca30225e9e4c0c74fe781a9fd1d1ad5f85b29c60 Mon Sep 17 00:00:00 2001 From: Thiemo Seufer Date: Mon, 15 May 2006 18:27:03 +0100 Subject: [MIPS] Update/Fix instruction definitions A small bugfix for up to now unused instruction definitions, and a somewhat larger update to cover MIPS32R2 instructions. Signed-off-by: Thiemo Seufer Signed-off-by: Ralf Baechle --- include/asm-mips/inst.h | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/asm-mips/inst.h b/include/asm-mips/inst.h index e0745f4..1ed8d0f 100644 --- a/include/asm-mips/inst.h +++ b/include/asm-mips/inst.h @@ -6,6 +6,7 @@ * for more details. * * Copyright (C) 1996, 2000 by Ralf Baechle + * Copyright (C) 2006 by Thiemo Seufer */ #ifndef _ASM_INST_H #define _ASM_INST_H @@ -21,14 +22,14 @@ enum major_op { cop0_op, cop1_op, cop2_op, cop1x_op, beql_op, bnel_op, blezl_op, bgtzl_op, daddi_op, daddiu_op, ldl_op, ldr_op, - major_1c_op, jalx_op, major_1e_op, major_1f_op, + spec2_op, jalx_op, mdmx_op, spec3_op, lb_op, lh_op, lwl_op, lw_op, lbu_op, lhu_op, lwr_op, lwu_op, sb_op, sh_op, swl_op, sw_op, sdl_op, sdr_op, swr_op, cache_op, ll_op, lwc1_op, lwc2_op, pref_op, lld_op, ldc1_op, ldc2_op, ld_op, - sc_op, swc1_op, swc2_op, rdhwr_op, + sc_op, swc1_op, swc2_op, major_3b_op, scd_op, sdc1_op, sdc2_op, sd_op }; @@ -37,7 +38,7 @@ enum major_op { */ enum spec_op { sll_op, movc_op, srl_op, sra_op, - sllv_op, srlv_op, srav_op, spec1_unused_op, /* Opcode 0x07 is unused */ + sllv_op, pmon_op, srlv_op, srav_op, jr_op, jalr_op, movz_op, movn_op, syscall_op, break_op, spim_op, sync_op, mfhi_op, mthi_op, mflo_op, mtlo_op, @@ -55,6 +56,28 @@ enum spec_op { }; /* + * func field of spec2 opcode. + */ +enum spec2_op { + madd_op, maddu_op, mul_op, spec2_3_unused_op, + msub_op, msubu_op, /* more unused ops */ + clz_op = 0x20, clo_op, + dclz_op = 0x24, dclo_op, + sdbpp_op = 0x3f +}; + +/* + * func field of spec3 opcode. + */ +enum spec3_op { + ext_op, dextm_op, dextu_op, dext_op, + ins_op, dinsm_op, dinsu_op, dins_op, + bshfl_op = 0x20, + dbshfl_op = 0x24, + rdhwr_op = 0x3f +}; + +/* * rt field of bcond opcodes. */ enum rt_op { @@ -151,8 +174,8 @@ enum cop1x_func { * func field for mad opcodes (MIPS IV). */ enum mad_func { - madd_op = 0x08, msub_op = 0x0a, - nmadd_op = 0x0c, nmsub_op = 0x0e + madd_fp_op = 0x08, msub_fp_op = 0x0a, + nmadd_fp_op = 0x0c, nmsub_fp_op = 0x0e }; /* -- cgit v1.1 From 44d921b246923380f26b8010e47ac5dfe48fcec5 Mon Sep 17 00:00:00 2001 From: Kumba Date: Tue, 16 May 2006 22:23:59 -0400 Subject: [MIPS] Treat R14000 like R10000. Signed-off-by: Joshua Kinard Signed-off-by: Ralf Baechle --- include/asm-mips/cpu.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h index 0117138..dff2a0a 100644 --- a/include/asm-mips/cpu.h +++ b/include/asm-mips/cpu.h @@ -51,6 +51,7 @@ #define PRID_IMP_R4300 0x0b00 #define PRID_IMP_VR41XX 0x0c00 #define PRID_IMP_R12000 0x0e00 +#define PRID_IMP_R14000 0x0f00 #define PRID_IMP_R8000 0x1000 #define PRID_IMP_PR4450 0x1200 #define PRID_IMP_R4600 0x2000 @@ -198,7 +199,8 @@ #define CPU_PR4450 61 #define CPU_SB1A 62 #define CPU_74K 63 -#define CPU_LAST 63 +#define CPU_R14000 64 +#define CPU_LAST 64 /* * ISA Level encodings -- cgit v1.1