Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 303c6443 authored by Russell King's avatar Russell King Committed by Russell King
Browse files

[ARM] clearpage: provide our own clear_user_highpage()



For similar reasons as copy_user_page(), we want to avoid the
additional kmap_atomic if it's unnecessary.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 063b0a42
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@
struct page;

struct cpu_user_fns {
	void (*cpu_clear_user_page)(void *p, unsigned long user);
	void (*cpu_clear_user_highpage)(struct page *page, unsigned long vaddr);
	void (*cpu_copy_user_highpage)(struct page *to, struct page *from,
			unsigned long vaddr);
};
@@ -119,20 +119,21 @@ struct cpu_user_fns {
#ifdef MULTI_USER
extern struct cpu_user_fns cpu_user;

#define __cpu_clear_user_page		cpu_user.cpu_clear_user_page
#define __cpu_clear_user_highpage	cpu_user.cpu_clear_user_highpage
#define __cpu_copy_user_highpage	cpu_user.cpu_copy_user_highpage

#else

#define __cpu_clear_user_page		__glue(_USER,_clear_user_page)
#define __cpu_clear_user_highpage	__glue(_USER,_clear_user_highpage)
#define __cpu_copy_user_highpage	__glue(_USER,_copy_user_highpage)

extern void __cpu_clear_user_page(void *p, unsigned long user);
extern void __cpu_clear_user_highpage(struct page *page, unsigned long vaddr);
extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
			unsigned long vaddr);
#endif

#define clear_user_page(addr,vaddr,pg)	 __cpu_clear_user_page(addr, vaddr)
#define clear_user_highpage(page,vaddr)		\
	 __cpu_clear_user_highpage(page, vaddr)

#define __HAVE_ARCH_COPY_USER_HIGHPAGE
#define copy_user_highpage(to,from,vaddr,vma)	\
+10 −10
Original line number Diff line number Diff line
@@ -79,12 +79,11 @@ void feroceon_copy_user_highpage(struct page *to, struct page *from,
	kunmap_atomic(kto, KM_USER0);
}

void __attribute__((naked))
feroceon_clear_user_page(void *kaddr, unsigned long vaddr)
void feroceon_clear_user_highpage(struct page *page, unsigned long vaddr)
{
	void *kaddr = kmap_atomic(page, KM_USER0);
	asm("\
	stmfd	sp!, {r4-r7, lr}		\n\
	mov	r1, %0				\n\
	mov	r1, %1				\n\
	mov	r2, #0				\n\
	mov	r3, #0				\n\
	mov	r4, #0				\n\
@@ -93,19 +92,20 @@ feroceon_clear_user_page(void *kaddr, unsigned long vaddr)
	mov	r7, #0				\n\
	mov	ip, #0				\n\
	mov	lr, #0				\n\
1:	stmia	r0, {r2-r7, ip, lr}		\n\
1:	stmia	%0, {r2-r7, ip, lr}		\n\
	subs	r1, r1, #1			\n\
	mcr	p15, 0, r0, c7, c14, 1		@ clean and invalidate D line\n\
	mcr	p15, 0, %0, c7, c14, 1		@ clean and invalidate D line\n\
	add	r0, r0, #32			\n\
	bne	1b				\n\
	mcr	p15, 0, r1, c7, c10, 4		@ drain WB\n\
	ldmfd	sp!, {r4-r7, pc}"
	mcr	p15, 0, r1, c7, c10, 4		@ drain WB"
	:
	: "I" (PAGE_SIZE / 32));
	: "r" (kaddr), "I" (PAGE_SIZE / 32)
	: "r1", "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr");
	kunmap_atomic(kaddr, KM_USER0);
}

struct cpu_user_fns feroceon_user_fns __initdata = {
	.cpu_clear_user_page	= feroceon_clear_user_page,
	.cpu_clear_user_highpage = feroceon_clear_user_highpage,
	.cpu_copy_user_highpage	= feroceon_copy_user_highpage,
};
+7 −6
Original line number Diff line number Diff line
@@ -54,10 +54,10 @@ void v3_copy_user_highpage(struct page *to, struct page *from,
 *
 * FIXME: do we need to handle cache stuff...
 */
void __attribute__((naked)) v3_clear_user_page(void *kaddr, unsigned long vaddr)
void v3_clear_user_highpage(struct page *page, unsigned long vaddr)
{
	void *kaddr = kmap_atomic(page, KM_USER0);
	asm("\n\
	str	lr, [sp, #-4]!\n\
	mov	r1, %1				@ 1\n\
	mov	r2, #0				@ 1\n\
	mov	r3, #0				@ 1\n\
@@ -68,13 +68,14 @@ void __attribute__((naked)) v3_clear_user_page(void *kaddr, unsigned long vaddr)
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	subs	r1, r1, #1			@ 1\n\
	bne	1b				@ 1\n\
	ldr	pc, [sp], #4"
	bne	1b				@ 1"
	:
	: "r" (kaddr), "I" (PAGE_SIZE / 64));
	: "r" (kaddr), "I" (PAGE_SIZE / 64)
	: "r1", "r2", "r3", "ip", "lr");
	kunmap_atomic(kaddr, KM_USER0);
}

struct cpu_user_fns v3_user_fns __initdata = {
	.cpu_clear_user_page	= v3_clear_user_page,
	.cpu_clear_user_highpage = v3_clear_user_highpage,
	.cpu_copy_user_highpage	= v3_copy_user_highpage,
};
+14 −14
Original line number Diff line number Diff line
@@ -91,30 +91,30 @@ void v4_mc_copy_user_highpage(struct page *from, struct page *to,
/*
 * ARMv4 optimised clear_user_page
 */
void __attribute__((naked))
v4_mc_clear_user_page(void *kaddr, unsigned long vaddr)
void v4_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
{
	asm volatile(
	"str	lr, [sp, #-4]!\n\
	void *kaddr = kmap_atomic(page, KM_USER0);
	asm volatile("\
	mov	r1, %0				@ 1\n\
	mov	r2, #0				@ 1\n\
	mov	r3, #0				@ 1\n\
	mov	ip, #0				@ 1\n\
	mov	lr, #0				@ 1\n\
1:	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
1:	mcr	p15, 0, %0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	mcr	p15, 0, %0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	subs	r1, r1, #1			@ 1\n\
	bne	1b				@ 1\n\
	ldr	pc, [sp], #4"
	bne	1b				@ 1"
	:
	: "I" (PAGE_SIZE / 64));
	: "r" (kaddr), "I" (PAGE_SIZE / 64)
	: "r1", "r2", "r3", "ip", "lr");
	kunmap_atomic(kaddr, KM_USER0);
}

struct cpu_user_fns v4_mc_user_fns __initdata = {
	.cpu_clear_user_page	= v4_mc_clear_user_page, 
	.cpu_clear_user_highpage = v4_mc_clear_user_highpage,
	.cpu_copy_user_highpage	= v4_mc_copy_user_highpage,
};
+14 −14
Original line number Diff line number Diff line
@@ -64,31 +64,31 @@ void v4wb_copy_user_highpage(struct page *to, struct page *from,
 *
 * Same story as above.
 */
void __attribute__((naked))
v4wb_clear_user_page(void *kaddr, unsigned long vaddr)
void v4wb_clear_user_highpage(struct page *page, unsigned long vaddr)
{
	void *kaddr = kmap_atomic(page, KM_USER0);
	asm("\
	str	lr, [sp, #-4]!\n\
	mov	r1, %0				@ 1\n\
	mov	r1, %1				@ 1\n\
	mov	r2, #0				@ 1\n\
	mov	r3, #0				@ 1\n\
	mov	ip, #0				@ 1\n\
	mov	lr, #0				@ 1\n\
1:	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
	mcr	p15, 0, r0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	r0!, {r2, r3, ip, lr}		@ 4\n\
1:	mcr	p15, 0, %0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	mcr	p15, 0, %0, c7, c6, 1		@ 1   invalidate D line\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	stmia	%0!, {r2, r3, ip, lr}		@ 4\n\
	subs	r1, r1, #1			@ 1\n\
	bne	1b				@ 1\n\
	mcr	p15, 0, r1, c7, c10, 4		@ 1   drain WB\n\
	ldr	pc, [sp], #4"
	mcr	p15, 0, r1, c7, c10, 4		@ 1   drain WB"
	:
	: "I" (PAGE_SIZE / 64));
	: "r" (kaddr), "I" (PAGE_SIZE / 64)
	: "r1", "r2", "r3", "ip", "lr");
	kunmap_atomic(kaddr, KM_USER0);
}

struct cpu_user_fns v4wb_user_fns __initdata = {
	.cpu_clear_user_page	= v4wb_clear_user_page,
	.cpu_clear_user_highpage = v4wb_clear_user_highpage,
	.cpu_copy_user_highpage	= v4wb_copy_user_highpage,
};
Loading