aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/debug-monitors.c20
-rw-r--r--arch/arm64/kernel/entry.S29
-rw-r--r--arch/arm64/kernel/ptrace.c40
-rw-r--r--arch/arm64/kernel/setup.c5
-rw-r--r--arch/arm64/kernel/smp.c1
5 files changed, 44 insertions, 51 deletions
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,
248int aarch32_break_handler(struct pt_regs *regs) 248int 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
5241:
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, &reg, 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(&reg, 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
717out:
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
206void __init setup_arch(char **cmdline_p) 206void __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