diff options
| -rw-r--r-- | arch/mips/include/asm/pgtable.h | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 9d8106758142..ae8569475264 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h | |||
| @@ -182,8 +182,39 @@ static inline void set_pte(pte_t *ptep, pte_t pteval) | |||
| 182 | * Make sure the buddy is global too (if it's !none, | 182 | * Make sure the buddy is global too (if it's !none, |
| 183 | * it better already be global) | 183 | * it better already be global) |
| 184 | */ | 184 | */ |
| 185 | #ifdef CONFIG_SMP | ||
| 186 | /* | ||
| 187 | * For SMP, multiple CPUs can race, so we need to do | ||
| 188 | * this atomically. | ||
| 189 | */ | ||
| 190 | #ifdef CONFIG_64BIT | ||
| 191 | #define LL_INSN "lld" | ||
| 192 | #define SC_INSN "scd" | ||
| 193 | #else /* CONFIG_32BIT */ | ||
| 194 | #define LL_INSN "ll" | ||
| 195 | #define SC_INSN "sc" | ||
| 196 | #endif | ||
| 197 | unsigned long page_global = _PAGE_GLOBAL; | ||
| 198 | unsigned long tmp; | ||
| 199 | |||
| 200 | __asm__ __volatile__ ( | ||
| 201 | " .set push\n" | ||
| 202 | " .set noreorder\n" | ||
| 203 | "1: " LL_INSN " %[tmp], %[buddy]\n" | ||
| 204 | " bnez %[tmp], 2f\n" | ||
| 205 | " or %[tmp], %[tmp], %[global]\n" | ||
| 206 | " " SC_INSN " %[tmp], %[buddy]\n" | ||
| 207 | " beqz %[tmp], 1b\n" | ||
| 208 | " nop\n" | ||
| 209 | "2:\n" | ||
| 210 | " .set pop" | ||
| 211 | : [buddy] "+m" (buddy->pte), | ||
| 212 | [tmp] "=&r" (tmp) | ||
| 213 | : [global] "r" (page_global)); | ||
| 214 | #else /* !CONFIG_SMP */ | ||
| 185 | if (pte_none(*buddy)) | 215 | if (pte_none(*buddy)) |
| 186 | pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; | 216 | pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL; |
| 217 | #endif /* CONFIG_SMP */ | ||
| 187 | } | 218 | } |
| 188 | #endif | 219 | #endif |
| 189 | } | 220 | } |
