diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-29 12:57:13 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-29 12:57:13 -0500 |
| commit | d5ff835f88c7c346ba748f389bd4ef5eae619ebc (patch) | |
| tree | 8feddb009e4479fbdad95284d72e4aa3c629038f | |
| parent | 033dbbdec3ab178e5fe063a992b8c90ad08fd18c (diff) | |
| parent | 3676f9ef5481d614f8c5c857f5319755be248268 (diff) | |
Merge tag 'arm64-stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64
Pull ARM64 fixes from Catalin Marinas:
- Remove preempt_count modifications in the arm64 IRQ handling code
since that's already dealt with in generic irq_enter/irq_exit
- PTE_PROT_NONE bit moved higher up to avoid overlapping with the
hardware bits (for PROT_NONE mappings which are pte_present)
- Big-endian fixes for ptrace support
- Asynchronous aborts unmasking while in the kernel
- pgprot_writecombine() change to create Normal NonCacheable memory
rather than Device GRE
* tag 'arm64-stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64:
arm64: Move PTE_PROT_NONE higher up
arm64: Use Normal NonCacheable memory for writecombine
arm64: debug: make aarch32 bkpt checking endian clean
arm64: ptrace: fix compat registes get/set to be endian clean
arm64: Unmask asynchronous aborts when in kernel mode
arm64: dts: Reserve the memory used for secondary CPU release address
arm64: let the core code deal with preempt_count
| -rw-r--r-- | arch/arm64/boot/dts/foundation-v8.dts | 2 | ||||
| -rw-r--r-- | arch/arm64/include/asm/irqflags.h | 3 | ||||
| -rw-r--r-- | arch/arm64/include/asm/pgtable.h | 33 | ||||
| -rw-r--r-- | arch/arm64/kernel/debug-monitors.c | 20 | ||||
| -rw-r--r-- | arch/arm64/kernel/entry.S | 29 | ||||
| -rw-r--r-- | arch/arm64/kernel/ptrace.c | 40 | ||||
| -rw-r--r-- | arch/arm64/kernel/setup.c | 5 | ||||
| -rw-r--r-- | arch/arm64/kernel/smp.c | 1 |
8 files changed, 67 insertions, 66 deletions
diff --git a/arch/arm64/boot/dts/foundation-v8.dts b/arch/arm64/boot/dts/foundation-v8.dts index 84fcc5018284..519c4b2c0687 100644 --- a/arch/arm64/boot/dts/foundation-v8.dts +++ b/arch/arm64/boot/dts/foundation-v8.dts | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | /dts-v1/; | 7 | /dts-v1/; |
| 8 | 8 | ||
| 9 | /memreserve/ 0x80000000 0x00010000; | ||
| 10 | |||
| 9 | / { | 11 | / { |
| 10 | model = "Foundation-v8A"; | 12 | model = "Foundation-v8A"; |
| 11 | compatible = "arm,foundation-aarch64", "arm,vexpress"; | 13 | compatible = "arm,foundation-aarch64", "arm,vexpress"; |
diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h index aa11943b8502..b2fcfbc51ecc 100644 --- a/arch/arm64/include/asm/irqflags.h +++ b/arch/arm64/include/asm/irqflags.h | |||
| @@ -56,6 +56,9 @@ static inline void arch_local_irq_disable(void) | |||
| 56 | #define local_fiq_enable() asm("msr daifclr, #1" : : : "memory") | 56 | #define local_fiq_enable() asm("msr daifclr, #1" : : : "memory") |
| 57 | #define local_fiq_disable() asm("msr daifset, #1" : : : "memory") | 57 | #define local_fiq_disable() asm("msr daifset, #1" : : : "memory") |
| 58 | 58 | ||
| 59 | #define local_async_enable() asm("msr daifclr, #4" : : : "memory") | ||
| 60 | #define local_async_disable() asm("msr daifset, #4" : : : "memory") | ||
| 61 | |||
| 59 | /* | 62 | /* |
| 60 | * Save the current interrupt enable state. | 63 | * Save the current interrupt enable state. |
| 61 | */ | 64 | */ |
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 17bd3af0a117..7f2b60affbb4 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
| @@ -25,10 +25,11 @@ | |||
| 25 | * Software defined PTE bits definition. | 25 | * Software defined PTE bits definition. |
| 26 | */ | 26 | */ |
| 27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) | 27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) |
| 28 | #define PTE_PROT_NONE (_AT(pteval_t, 1) << 2) /* 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) << 3) /* only when !pte_present() */ | ||
| 30 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) | 29 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) |
| 31 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) | 30 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) |
| 31 | /* bit 57 for PMD_SECT_SPLITTING */ | ||
| 32 | #define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */ | ||
| 32 | 33 | ||
| 33 | /* | 34 | /* |
| 34 | * VMALLOC and SPARSEMEM_VMEMMAP ranges. | 35 | * VMALLOC and SPARSEMEM_VMEMMAP ranges. |
| @@ -254,7 +255,7 @@ static inline int has_transparent_hugepage(void) | |||
| 254 | #define pgprot_noncached(prot) \ | 255 | #define pgprot_noncached(prot) \ |
| 255 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE)) | 256 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE)) |
| 256 | #define pgprot_writecombine(prot) \ | 257 | #define pgprot_writecombine(prot) \ |
| 257 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE)) | 258 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) |
| 258 | #define pgprot_dmacoherent(prot) \ | 259 | #define pgprot_dmacoherent(prot) \ |
| 259 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) | 260 | __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) |
| 260 | #define __HAVE_PHYS_MEM_ACCESS_PROT | 261 | #define __HAVE_PHYS_MEM_ACCESS_PROT |
| @@ -357,18 +358,20 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | |||
| 357 | 358 | ||
| 358 | /* | 359 | /* |
| 359 | * Encode and decode a swap entry: | 360 | * Encode and decode a swap entry: |
| 360 | * bits 0, 2: present (must both be zero) | 361 | * bits 0-1: present (must be zero) |
| 361 | * bit 3: PTE_FILE | 362 | * bit 2: PTE_FILE |
| 362 | * bits 4-8: swap type | 363 | * bits 3-8: swap type |
| 363 | * bits 9-63: swap offset | 364 | * bits 9-57: swap offset |
| 364 | */ | 365 | */ |
| 365 | #define __SWP_TYPE_SHIFT 4 | 366 | #define __SWP_TYPE_SHIFT 3 |
| 366 | #define __SWP_TYPE_BITS 6 | 367 | #define __SWP_TYPE_BITS 6 |
| 368 | #define __SWP_OFFSET_BITS 49 | ||
| 367 | #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) | 369 | #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) |
| 368 | #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) | 370 | #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) |
| 371 | #define __SWP_OFFSET_MASK ((1UL << __SWP_OFFSET_BITS) - 1) | ||
| 369 | 372 | ||
| 370 | #define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) | 373 | #define __swp_type(x) (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) |
| 371 | #define __swp_offset(x) ((x).val >> __SWP_OFFSET_SHIFT) | 374 | #define __swp_offset(x) (((x).val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK) |
| 372 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) }) | 375 | #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) }) |
| 373 | 376 | ||
| 374 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) | 377 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) |
| @@ -382,15 +385,15 @@ extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | |||
| 382 | 385 | ||
| 383 | /* | 386 | /* |
| 384 | * Encode and decode a file entry: | 387 | * Encode and decode a file entry: |
| 385 | * bits 0, 2: present (must both be zero) | 388 | * bits 0-1: present (must be zero) |
| 386 | * bit 3: PTE_FILE | 389 | * bit 2: PTE_FILE |
| 387 | * bits 4-63: file offset / PAGE_SIZE | 390 | * bits 3-57: file offset / PAGE_SIZE |
| 388 | */ | 391 | */ |
| 389 | #define pte_file(pte) (pte_val(pte) & PTE_FILE) | 392 | #define pte_file(pte) (pte_val(pte) & PTE_FILE) |
| 390 | #define pte_to_pgoff(x) (pte_val(x) >> 4) | 393 | #define pte_to_pgoff(x) (pte_val(x) >> 3) |
| 391 | #define pgoff_to_pte(x) __pte(((x) << 4) | PTE_FILE) | 394 | #define pgoff_to_pte(x) __pte(((x) << 3) | PTE_FILE) |
| 392 | 395 | ||
| 393 | #define PTE_FILE_MAX_BITS 60 | 396 | #define PTE_FILE_MAX_BITS 55 |
| 394 | 397 | ||
| 395 | extern int kern_addr_valid(unsigned long addr); | 398 | extern int kern_addr_valid(unsigned long addr); |
| 396 | 399 | ||
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 6a0a9b132d7a..4ae68579031d 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c | |||
| @@ -248,7 +248,8 @@ static int brk_handler(unsigned long addr, unsigned int esr, | |||
| 248 | int aarch32_break_handler(struct pt_regs *regs) | 248 | int aarch32_break_handler(struct pt_regs *regs) |
| 249 | { | 249 | { |
| 250 | siginfo_t info; | 250 | siginfo_t info; |
| 251 | unsigned int instr; | 251 | u32 arm_instr; |
| 252 | u16 thumb_instr; | ||
| 252 | bool bp = false; | 253 | bool bp = false; |
| 253 | void __user *pc = (void __user *)instruction_pointer(regs); | 254 | void __user *pc = (void __user *)instruction_pointer(regs); |
| 254 | 255 | ||
| @@ -257,18 +258,21 @@ int aarch32_break_handler(struct pt_regs *regs) | |||
| 257 | 258 | ||
| 258 | if (compat_thumb_mode(regs)) { | 259 | if (compat_thumb_mode(regs)) { |
| 259 | /* get 16-bit Thumb instruction */ | 260 | /* get 16-bit Thumb instruction */ |
| 260 | get_user(instr, (u16 __user *)pc); | 261 | get_user(thumb_instr, (u16 __user *)pc); |
| 261 | if (instr == AARCH32_BREAK_THUMB2_LO) { | 262 | thumb_instr = le16_to_cpu(thumb_instr); |
| 263 | if (thumb_instr == AARCH32_BREAK_THUMB2_LO) { | ||
| 262 | /* get second half of 32-bit Thumb-2 instruction */ | 264 | /* get second half of 32-bit Thumb-2 instruction */ |
| 263 | get_user(instr, (u16 __user *)(pc + 2)); | 265 | get_user(thumb_instr, (u16 __user *)(pc + 2)); |
| 264 | bp = instr == AARCH32_BREAK_THUMB2_HI; | 266 | thumb_instr = le16_to_cpu(thumb_instr); |
| 267 | bp = thumb_instr == AARCH32_BREAK_THUMB2_HI; | ||
| 265 | } else { | 268 | } else { |
| 266 | bp = instr == AARCH32_BREAK_THUMB; | 269 | bp = thumb_instr == AARCH32_BREAK_THUMB; |
| 267 | } | 270 | } |
| 268 | } else { | 271 | } else { |
| 269 | /* 32-bit ARM instruction */ | 272 | /* 32-bit ARM instruction */ |
| 270 | get_user(instr, (u32 __user *)pc); | 273 | get_user(arm_instr, (u32 __user *)pc); |
| 271 | bp = (instr & ~0xf0000000) == AARCH32_BREAK_ARM; | 274 | arm_instr = le32_to_cpu(arm_instr); |
| 275 | bp = (arm_instr & ~0xf0000000) == AARCH32_BREAK_ARM; | ||
| 272 | } | 276 | } |
| 273 | 277 | ||
| 274 | if (!bp) | 278 | if (!bp) |
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index e1166145ca29..4d2c6f3f0c41 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S | |||
| @@ -309,15 +309,12 @@ el1_irq: | |||
| 309 | #ifdef CONFIG_TRACE_IRQFLAGS | 309 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 310 | bl trace_hardirqs_off | 310 | bl trace_hardirqs_off |
| 311 | #endif | 311 | #endif |
| 312 | #ifdef CONFIG_PREEMPT | 312 | |
| 313 | get_thread_info tsk | ||
| 314 | ldr w24, [tsk, #TI_PREEMPT] // get preempt count | ||
| 315 | add w0, w24, #1 // increment it | ||
| 316 | str w0, [tsk, #TI_PREEMPT] | ||
| 317 | #endif | ||
| 318 | irq_handler | 313 | irq_handler |
| 314 | |||
| 319 | #ifdef CONFIG_PREEMPT | 315 | #ifdef CONFIG_PREEMPT |
| 320 | str w24, [tsk, #TI_PREEMPT] // restore preempt count | 316 | get_thread_info tsk |
| 317 | ldr w24, [tsk, #TI_PREEMPT] // restore preempt count | ||
| 321 | cbnz w24, 1f // preempt count != 0 | 318 | cbnz w24, 1f // preempt count != 0 |
| 322 | ldr x0, [tsk, #TI_FLAGS] // get flags | 319 | ldr x0, [tsk, #TI_FLAGS] // get flags |
| 323 | tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? | 320 | tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? |
| @@ -507,22 +504,10 @@ el0_irq_naked: | |||
| 507 | #ifdef CONFIG_TRACE_IRQFLAGS | 504 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 508 | bl trace_hardirqs_off | 505 | bl trace_hardirqs_off |
| 509 | #endif | 506 | #endif |
| 510 | get_thread_info tsk | 507 | |
| 511 | #ifdef CONFIG_PREEMPT | ||
| 512 | ldr w24, [tsk, #TI_PREEMPT] // get preempt count | ||
| 513 | add w23, w24, #1 // increment it | ||
| 514 | str w23, [tsk, #TI_PREEMPT] | ||
| 515 | #endif | ||
| 516 | irq_handler | 508 | irq_handler |
| 517 | #ifdef CONFIG_PREEMPT | 509 | get_thread_info tsk |
| 518 | ldr w0, [tsk, #TI_PREEMPT] | 510 | |
| 519 | str w24, [tsk, #TI_PREEMPT] | ||
| 520 | cmp w0, w23 | ||
| 521 | b.eq 1f | ||
| 522 | mov x1, #0 | ||
| 523 | str x1, [x1] // BUG | ||
| 524 | 1: | ||
| 525 | #endif | ||
| 526 | #ifdef CONFIG_TRACE_IRQFLAGS | 511 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 527 | bl trace_hardirqs_on | 512 | bl trace_hardirqs_on |
| 528 | #endif | 513 | #endif |
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index fecdbf7de82e..6777a2192b83 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c | |||
| @@ -636,28 +636,27 @@ static int compat_gpr_get(struct task_struct *target, | |||
| 636 | 636 | ||
| 637 | for (i = 0; i < num_regs; ++i) { | 637 | for (i = 0; i < num_regs; ++i) { |
| 638 | unsigned int idx = start + i; | 638 | unsigned int idx = start + i; |
| 639 | void *reg; | 639 | compat_ulong_t reg; |
| 640 | 640 | ||
| 641 | switch (idx) { | 641 | switch (idx) { |
| 642 | case 15: | 642 | case 15: |
| 643 | reg = (void *)&task_pt_regs(target)->pc; | 643 | reg = task_pt_regs(target)->pc; |
| 644 | break; | 644 | break; |
| 645 | case 16: | 645 | case 16: |
| 646 | reg = (void *)&task_pt_regs(target)->pstate; | 646 | reg = task_pt_regs(target)->pstate; |
| 647 | break; | 647 | break; |
| 648 | case 17: | 648 | case 17: |
| 649 | reg = (void *)&task_pt_regs(target)->orig_x0; | 649 | reg = task_pt_regs(target)->orig_x0; |
| 650 | break; | 650 | break; |
| 651 | default: | 651 | default: |
| 652 | reg = (void *)&task_pt_regs(target)->regs[idx]; | 652 | reg = task_pt_regs(target)->regs[idx]; |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t)); | 655 | ret = copy_to_user(ubuf, ®, sizeof(reg)); |
| 656 | |||
| 657 | if (ret) | 656 | if (ret) |
| 658 | break; | 657 | break; |
| 659 | else | 658 | |
| 660 | ubuf += sizeof(compat_ulong_t); | 659 | ubuf += sizeof(reg); |
| 661 | } | 660 | } |
| 662 | 661 | ||
| 663 | return ret; | 662 | return ret; |
| @@ -685,28 +684,28 @@ static int compat_gpr_set(struct task_struct *target, | |||
| 685 | 684 | ||
| 686 | for (i = 0; i < num_regs; ++i) { | 685 | for (i = 0; i < num_regs; ++i) { |
| 687 | unsigned int idx = start + i; | 686 | unsigned int idx = start + i; |
| 688 | void *reg; | 687 | compat_ulong_t reg; |
| 688 | |||
| 689 | ret = copy_from_user(®, ubuf, sizeof(reg)); | ||
| 690 | if (ret) | ||
| 691 | return ret; | ||
| 692 | |||
| 693 | ubuf += sizeof(reg); | ||
| 689 | 694 | ||
| 690 | switch (idx) { | 695 | switch (idx) { |
| 691 | case 15: | 696 | case 15: |
| 692 | reg = (void *)&newregs.pc; | 697 | newregs.pc = reg; |
| 693 | break; | 698 | break; |
| 694 | case 16: | 699 | case 16: |
| 695 | reg = (void *)&newregs.pstate; | 700 | newregs.pstate = reg; |
| 696 | break; | 701 | break; |
| 697 | case 17: | 702 | case 17: |
| 698 | reg = (void *)&newregs.orig_x0; | 703 | newregs.orig_x0 = reg; |
| 699 | break; | 704 | break; |
| 700 | default: | 705 | default: |
| 701 | reg = (void *)&newregs.regs[idx]; | 706 | newregs.regs[idx] = reg; |
| 702 | } | 707 | } |
| 703 | 708 | ||
| 704 | ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t)); | ||
| 705 | |||
| 706 | if (ret) | ||
| 707 | goto out; | ||
| 708 | else | ||
| 709 | ubuf += sizeof(compat_ulong_t); | ||
| 710 | } | 709 | } |
| 711 | 710 | ||
| 712 | if (valid_user_regs(&newregs.user_regs)) | 711 | if (valid_user_regs(&newregs.user_regs)) |
| @@ -714,7 +713,6 @@ static int compat_gpr_set(struct task_struct *target, | |||
| 714 | else | 713 | else |
| 715 | ret = -EINVAL; | 714 | ret = -EINVAL; |
| 716 | 715 | ||
| 717 | out: | ||
| 718 | return ret; | 716 | return ret; |
| 719 | } | 717 | } |
| 720 | 718 | ||
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 0bc5e4cbc017..bd9bbd0e44ed 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c | |||
| @@ -205,6 +205,11 @@ u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; | |||
| 205 | 205 | ||
| 206 | void __init setup_arch(char **cmdline_p) | 206 | void __init setup_arch(char **cmdline_p) |
| 207 | { | 207 | { |
| 208 | /* | ||
| 209 | * Unmask asynchronous aborts early to catch possible system errors. | ||
| 210 | */ | ||
| 211 | local_async_enable(); | ||
| 212 | |||
| 208 | setup_processor(); | 213 | setup_processor(); |
| 209 | 214 | ||
| 210 | setup_machine_fdt(__fdt_pointer); | 215 | setup_machine_fdt(__fdt_pointer); |
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a5aeefab03c3..a0c2ca602cf8 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c | |||
| @@ -160,6 +160,7 @@ asmlinkage void secondary_start_kernel(void) | |||
| 160 | 160 | ||
| 161 | local_irq_enable(); | 161 | local_irq_enable(); |
| 162 | local_fiq_enable(); | 162 | local_fiq_enable(); |
| 163 | local_async_enable(); | ||
| 163 | 164 | ||
| 164 | /* | 165 | /* |
| 165 | * OK, it's off to the idle thread for us | 166 | * OK, it's off to the idle thread for us |
