Эх сурвалжийг харах

Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus

Pull MIPS fixes from Ralf Baechle:
 "These are the fixes for the N32 syscall bugs found by Al, an
  extraneous break that broke detection for R3000 and R3081 processors,
  an endless loop processing signals for kernel task (x86 received the
  same fix a while ago) and a fix for transparent huge page which took
  ages to track down because it was so hard to come up with a workable
  test case."

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus:
  MIPS: Fix endless loop when processing signals for kernel tasks
  MIPS: R3000/R3081: Fix CPU detection.
  MIPS: N32: Fix signalfd4 syscall entry point
  MIPS: N32: Fix preadv(2) and pwritev(2) entry points.
  MIPS: Avoid mcheck by flushing page range in huge_ptep_set_access_flags()
Linus Torvalds 12 жил өмнө
parent
commit
04c5decdc0

+ 11 - 1
arch/mips/include/asm/hugetlb.h

@@ -95,7 +95,17 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 					     pte_t *ptep, pte_t pte,
 					     pte_t *ptep, pte_t pte,
 					     int dirty)
 					     int dirty)
 {
 {
-	return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+	int changed = !pte_same(*ptep, pte);
+
+	if (changed) {
+		set_pte_at(vma->vm_mm, addr, ptep, pte);
+		/*
+		 * There could be some standard sized pages in there,
+		 * get them all.
+		 */
+		flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+	}
+	return changed;
 }
 }
 
 
 static inline pte_t huge_ptep_get(pte_t *ptep)
 static inline pte_t huge_ptep_get(pte_t *ptep)

+ 0 - 1
arch/mips/kernel/cpu-probe.c

@@ -510,7 +510,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
 				c->cputype = CPU_R3000A;
 				c->cputype = CPU_R3000A;
 				__cpu_name[cpu] = "R3000A";
 				__cpu_name[cpu] = "R3000A";
 			}
 			}
-			break;
 		} else {
 		} else {
 			c->cputype = CPU_R3000;
 			c->cputype = CPU_R3000;
 			__cpu_name[cpu] = "R3000";
 			__cpu_name[cpu] = "R3000";

+ 6 - 1
arch/mips/kernel/entry.S

@@ -36,6 +36,11 @@ FEXPORT(ret_from_exception)
 FEXPORT(ret_from_irq)
 FEXPORT(ret_from_irq)
 	LONG_S	s0, TI_REGS($28)
 	LONG_S	s0, TI_REGS($28)
 FEXPORT(__ret_from_irq)
 FEXPORT(__ret_from_irq)
+/*
+ * We can be coming here from a syscall done in the kernel space,
+ * e.g. a failed kernel_execve().
+ */
+resume_userspace_check:
 	LONG_L	t0, PT_STATUS(sp)		# returning to kernel mode?
 	LONG_L	t0, PT_STATUS(sp)		# returning to kernel mode?
 	andi	t0, t0, KU_USER
 	andi	t0, t0, KU_USER
 	beqz	t0, resume_kernel
 	beqz	t0, resume_kernel
@@ -162,7 +167,7 @@ work_notifysig:				# deal with pending signals and
 	move	a0, sp
 	move	a0, sp
 	li	a1, 0
 	li	a1, 0
 	jal	do_notify_resume	# a2 already loaded
 	jal	do_notify_resume	# a2 already loaded
-	j	resume_userspace
+	j	resume_userspace_check
 
 
 FEXPORT(syscall_exit_partial)
 FEXPORT(syscall_exit_partial)
 	local_irq_disable		# make sure need_resched doesn't
 	local_irq_disable		# make sure need_resched doesn't

+ 3 - 3
arch/mips/kernel/scall64-n32.S

@@ -397,14 +397,14 @@ EXPORT(sysn32_call_table)
 	PTR	sys_timerfd_create
 	PTR	sys_timerfd_create
 	PTR	compat_sys_timerfd_gettime	/* 6285 */
 	PTR	compat_sys_timerfd_gettime	/* 6285 */
 	PTR	compat_sys_timerfd_settime
 	PTR	compat_sys_timerfd_settime
-	PTR	sys_signalfd4
+	PTR	compat_sys_signalfd4
 	PTR	sys_eventfd2
 	PTR	sys_eventfd2
 	PTR	sys_epoll_create1
 	PTR	sys_epoll_create1
 	PTR	sys_dup3			/* 6290 */
 	PTR	sys_dup3			/* 6290 */
 	PTR	sys_pipe2
 	PTR	sys_pipe2
 	PTR	sys_inotify_init1
 	PTR	sys_inotify_init1
-	PTR	sys_preadv
-	PTR	sys_pwritev
+	PTR	compat_sys_preadv
+	PTR	compat_sys_pwritev
 	PTR	compat_sys_rt_tgsigqueueinfo	/* 6295 */
 	PTR	compat_sys_rt_tgsigqueueinfo	/* 6295 */
 	PTR	sys_perf_event_open
 	PTR	sys_perf_event_open
 	PTR	sys_accept4
 	PTR	sys_accept4

+ 4 - 14
arch/mips/mm/tlb-r4k.c

@@ -120,18 +120,11 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 
 
 	if (cpu_context(cpu, mm) != 0) {
 	if (cpu_context(cpu, mm) != 0) {
 		unsigned long size, flags;
 		unsigned long size, flags;
-		int huge = is_vm_hugetlb_page(vma);
 
 
 		ENTER_CRITICAL(flags);
 		ENTER_CRITICAL(flags);
-		if (huge) {
-			start = round_down(start, HPAGE_SIZE);
-			end = round_up(end, HPAGE_SIZE);
-			size = (end - start) >> HPAGE_SHIFT;
-		} else {
-			start = round_down(start, PAGE_SIZE << 1);
-			end = round_up(end, PAGE_SIZE << 1);
-			size = (end - start) >> (PAGE_SHIFT + 1);
-		}
+		start = round_down(start, PAGE_SIZE << 1);
+		end = round_up(end, PAGE_SIZE << 1);
+		size = (end - start) >> (PAGE_SHIFT + 1);
 		if (size <= current_cpu_data.tlbsize/2) {
 		if (size <= current_cpu_data.tlbsize/2) {
 			int oldpid = read_c0_entryhi();
 			int oldpid = read_c0_entryhi();
 			int newpid = cpu_asid(cpu, mm);
 			int newpid = cpu_asid(cpu, mm);
@@ -140,10 +133,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 				int idx;
 				int idx;
 
 
 				write_c0_entryhi(start | newpid);
 				write_c0_entryhi(start | newpid);
-				if (huge)
-					start += HPAGE_SIZE;
-				else
-					start += (PAGE_SIZE << 1);
+				start += (PAGE_SIZE << 1);
 				mtc0_tlbw_hazard();
 				mtc0_tlbw_hazard();
 				tlb_probe();
 				tlb_probe();
 				tlb_probe_hazard();
 				tlb_probe_hazard();