aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-01-16 12:44:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-01-16 12:44:40 -0500
commita6d3bd274b85218bf7dda925d14db81e1a8268b3 (patch)
treebb18def4472ed572b4844cb682642a4fab4c5b2a
parent2409c873be56278ea41c345b453f76813e5c3fed (diff)
parent72d0ac048f3ded4022cf1cc72f54073f6fcad72f (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.h36
-rw-r--r--arch/arm64/include/asm/unistd32.h7
-rw-r--r--arch/arm64/kernel/vdso.c4
-rw-r--r--arch/arm64/kernel/vdso/gettimeofday.S2
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
61extern pgprot_t pgprot_default; 62extern 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) \
140static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } 143static 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);
157static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, 160static 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
265static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 268static 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
253void update_vsyscall_tz(void) 253void 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]
793: 773:
80 mov x0, xzr 78 mov x0, xzr