diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-16 12:44:40 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-16 12:44:40 -0500 |
| commit | a6d3bd274b85218bf7dda925d14db81e1a8268b3 (patch) | |
| tree | bb18def4472ed572b4844cb682642a4fab4c5b2a | |
| parent | 2409c873be56278ea41c345b453f76813e5c3fed (diff) | |
| parent | 72d0ac048f3ded4022cf1cc72f54073f6fcad72f (diff) | |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64
Pull arm64 fixes from Catalin Marinas:
- Page protection fixes, including proper PAGE_NONE handling
- Timezone vdso sequence counting fix
- Additional compat syscall wiring
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64:
arm64: compat: add syscall table entries for new syscalls
arm64: mm: introduce present, faulting entries for PAGE_NONE
arm64: mm: only wrprotect clean ptes if they are present
arm64: vdso: remove broken, redundant sequence counting for timezones
| -rw-r--r-- | arch/arm64/include/asm/pgtable.h | 36 | ||||
| -rw-r--r-- | arch/arm64/include/asm/unistd32.h | 7 | ||||
| -rw-r--r-- | arch/arm64/kernel/vdso.c | 4 | ||||
| -rw-r--r-- | arch/arm64/kernel/vdso/gettimeofday.S | 2 |
4 files changed, 26 insertions, 23 deletions
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 64b133949502..e333a243bfcc 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
| @@ -24,7 +24,8 @@ | |||
| 24 | /* | 24 | /* |
| 25 | * Software defined PTE bits definition. | 25 | * Software defined PTE bits definition. |
| 26 | */ | 26 | */ |
| 27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) /* pte_present() check */ | 27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) |
| 28 | #define PTE_PROT_NONE (_AT(pteval_t, 1) << 1) /* only when !PTE_VALID */ | ||
| 28 | #define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ | 29 | #define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ |
| 29 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) | 30 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) |
| 30 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) | 31 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) |
| @@ -60,9 +61,12 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
| 60 | 61 | ||
| 61 | extern pgprot_t pgprot_default; | 62 | extern pgprot_t pgprot_default; |
| 62 | 63 | ||
| 63 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) | 64 | #define __pgprot_modify(prot,mask,bits) \ |
| 65 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
| 66 | |||
| 67 | #define _MOD_PROT(p, b) __pgprot_modify(p, 0, b) | ||
| 64 | 68 | ||
| 65 | #define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 69 | #define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE) |
| 66 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 70 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
| 67 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) | 71 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) |
| 68 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 72 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) |
| @@ -72,7 +76,7 @@ extern pgprot_t pgprot_default; | |||
| 72 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) | 76 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) |
| 73 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) | 77 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) |
| 74 | 78 | ||
| 75 | #define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 79 | #define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE) |
| 76 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 80 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
| 77 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) | 81 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) |
| 78 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 82 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) |
| @@ -125,16 +129,15 @@ extern struct page *empty_zero_page; | |||
| 125 | /* | 129 | /* |
| 126 | * The following only work if pte_present(). Undefined behaviour otherwise. | 130 | * The following only work if pte_present(). Undefined behaviour otherwise. |
| 127 | */ | 131 | */ |
| 128 | #define pte_present(pte) (pte_val(pte) & PTE_VALID) | 132 | #define pte_present(pte) (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)) |
| 129 | #define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) | 133 | #define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) |
| 130 | #define pte_young(pte) (pte_val(pte) & PTE_AF) | 134 | #define pte_young(pte) (pte_val(pte) & PTE_AF) |
| 131 | #define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) | 135 | #define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) |
| 132 | #define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) | 136 | #define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) |
| 133 | #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) | 137 | #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) |
| 134 | 138 | ||
| 135 | #define pte_present_exec_user(pte) \ | 139 | #define pte_valid_user(pte) \ |
| 136 | ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \ | 140 | ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) |
| 137 | (PTE_VALID | PTE_USER)) | ||
| 138 | 141 | ||
| 139 | #define PTE_BIT_FUNC(fn,op) \ | 142 | #define PTE_BIT_FUNC(fn,op) \ |
| 140 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | 143 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } |
| @@ -157,10 +160,13 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); | |||
| 157 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | 160 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, |
| 158 | pte_t *ptep, pte_t pte) | 161 | pte_t *ptep, pte_t pte) |
| 159 | { | 162 | { |
| 160 | if (pte_present_exec_user(pte)) | 163 | if (pte_valid_user(pte)) { |
| 161 | __sync_icache_dcache(pte, addr); | 164 | if (pte_exec(pte)) |
| 162 | if (!pte_dirty(pte)) | 165 | __sync_icache_dcache(pte, addr); |
| 163 | pte = pte_wrprotect(pte); | 166 | if (!pte_dirty(pte)) |
| 167 | pte = pte_wrprotect(pte); | ||
| 168 | } | ||
| 169 | |||
| 164 | set_pte(ptep, pte); | 170 | set_pte(ptep, pte); |
| 165 | } | 171 | } |
| 166 | 172 | ||
| @@ -170,9 +176,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
| 170 | #define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) | 176 | #define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) |
| 171 | #define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) | 177 | #define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) |
| 172 | 178 | ||
| 173 | #define __pgprot_modify(prot,mask,bits) \ | ||
| 174 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
| 175 | |||
| 176 | #define __HAVE_ARCH_PTE_SPECIAL | 179 | #define __HAVE_ARCH_PTE_SPECIAL |
| 177 | 180 | ||
| 178 | /* | 181 | /* |
| @@ -264,7 +267,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | |||
| 264 | 267 | ||
| 265 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 268 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
| 266 | { | 269 | { |
| 267 | const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY; | 270 | const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY | |
| 271 | PTE_PROT_NONE | PTE_VALID; | ||
| 268 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); | 272 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); |
| 269 | return pte; | 273 | return pte; |
| 270 | } | 274 | } |
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 58432625fdb3..5ef47ba3ed45 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h | |||
| @@ -395,8 +395,13 @@ __SYSCALL(370, sys_name_to_handle_at) | |||
| 395 | __SYSCALL(371, compat_sys_open_by_handle_at) | 395 | __SYSCALL(371, compat_sys_open_by_handle_at) |
| 396 | __SYSCALL(372, compat_sys_clock_adjtime) | 396 | __SYSCALL(372, compat_sys_clock_adjtime) |
| 397 | __SYSCALL(373, sys_syncfs) | 397 | __SYSCALL(373, sys_syncfs) |
| 398 | __SYSCALL(374, compat_sys_sendmmsg) | ||
| 399 | __SYSCALL(375, sys_setns) | ||
| 400 | __SYSCALL(376, compat_sys_process_vm_readv) | ||
| 401 | __SYSCALL(377, compat_sys_process_vm_writev) | ||
| 402 | __SYSCALL(378, sys_ni_syscall) /* 378 for kcmp */ | ||
| 398 | 403 | ||
| 399 | #define __NR_compat_syscalls 374 | 404 | #define __NR_compat_syscalls 379 |
| 400 | 405 | ||
| 401 | /* | 406 | /* |
| 402 | * Compat syscall numbers used by the AArch64 kernel. | 407 | * Compat syscall numbers used by the AArch64 kernel. |
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index c958cb84d75f..6a389dc1bd49 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c | |||
| @@ -252,10 +252,6 @@ void update_vsyscall(struct timekeeper *tk) | |||
| 252 | 252 | ||
| 253 | void update_vsyscall_tz(void) | 253 | void update_vsyscall_tz(void) |
| 254 | { | 254 | { |
| 255 | ++vdso_data->tb_seq_count; | ||
| 256 | smp_wmb(); | ||
| 257 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; | 255 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; |
| 258 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; | 256 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; |
| 259 | smp_wmb(); | ||
| 260 | ++vdso_data->tb_seq_count; | ||
| 261 | } | 257 | } |
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S index 8bf658d974f9..f0a6d10b5211 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.S +++ b/arch/arm64/kernel/vdso/gettimeofday.S | |||
| @@ -73,8 +73,6 @@ ENTRY(__kernel_gettimeofday) | |||
| 73 | /* If tz is NULL, return 0. */ | 73 | /* If tz is NULL, return 0. */ |
| 74 | cbz x1, 3f | 74 | cbz x1, 3f |
| 75 | ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST] | 75 | ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST] |
| 76 | seqcnt_read w9 | ||
| 77 | seqcnt_check w9, 1b | ||
| 78 | stp w4, w5, [x1, #TZ_MINWEST] | 76 | stp w4, w5, [x1, #TZ_MINWEST] |
| 79 | 3: | 77 | 3: |
| 80 | mov x0, xzr | 78 | mov x0, xzr |
