Blame view

arch/arm/mm/copypage-fa.c 2.32 KB
28853ac8f   Paulius Zaleckas   ARM: Add support ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  /*
   *  linux/arch/arm/lib/copypage-fa.S
   *
   *  Copyright (C) 2005 Faraday Corp.
   *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
   *
   * Based on copypage-v4wb.S:
   *  Copyright (C) 1995-1999 Russell King
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  #include <linux/init.h>
  #include <linux/highmem.h>
  
  /*
   * Faraday optimised copy_user_page
   */
  static void __naked
  fa_copy_user_page(void *kto, const void *kfrom)
  {
  	asm("\
  	stmfd	sp!, {r4, lr}			@ 2
  \
  	mov	r2, %0				@ 1
  \
  1:	ldmia	r1!, {r3, r4, ip, lr}		@ 4
  \
  	stmia	r0, {r3, r4, ip, lr}		@ 4
  \
  	mcr	p15, 0, r0, c7, c14, 1		@ 1   clean and invalidate D line
  \
  	add	r0, r0, #16			@ 1
  \
  	ldmia	r1!, {r3, r4, ip, lr}		@ 4
  \
  	stmia	r0, {r3, r4, ip, lr}		@ 4
  \
  	mcr	p15, 0, r0, c7, c14, 1		@ 1   clean and invalidate D line
  \
  	add	r0, r0, #16			@ 1
  \
  	subs	r2, r2, #1			@ 1
  \
  	bne	1b				@ 1
  \
  	mcr	p15, 0, r2, c7, c10, 4		@ 1   drain WB
  \
  	ldmfd	sp!, {r4, pc}			@ 3"
  	:
  	: "I" (PAGE_SIZE / 32));
  }
  
  void fa_copy_user_highpage(struct page *to, struct page *from,
a3be63271   Hans Ulli Kroll   ARM: Gemini: fix ...
56
  	unsigned long vaddr, struct vm_area_struct *vma)
28853ac8f   Paulius Zaleckas   ARM: Add support ...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  {
  	void *kto, *kfrom;
  
  	kto = kmap_atomic(to, KM_USER0);
  	kfrom = kmap_atomic(from, KM_USER1);
  	fa_copy_user_page(kto, kfrom);
  	kunmap_atomic(kfrom, KM_USER1);
  	kunmap_atomic(kto, KM_USER0);
  }
  
  /*
   * Faraday optimised clear_user_page
   *
   * Same story as above.
   */
  void fa_clear_user_highpage(struct page *page, unsigned long vaddr)
  {
  	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
  	asm volatile("\
  	mov	r1, %2				@ 1
  \
  	mov	r2, #0				@ 1
  \
  	mov	r3, #0				@ 1
  \
  	mov	ip, #0				@ 1
  \
  	mov	lr, #0				@ 1
  \
  1:	stmia	%0, {r2, r3, ip, lr}		@ 4
  \
  	mcr	p15, 0, %0, c7, c14, 1		@ 1   clean and invalidate D line
  \
  	add	%0, %0, #16			@ 1
  \
  	stmia	%0, {r2, r3, ip, lr}		@ 4
  \
  	mcr	p15, 0, %0, c7, c14, 1		@ 1   clean and invalidate D line
  \
  	add	%0, %0, #16			@ 1
  \
  	subs	r1, r1, #1			@ 1
  \
  	bne	1b				@ 1
  \
  	mcr	p15, 0, r1, c7, c10, 4		@ 1   drain WB"
  	: "=r" (ptr)
  	: "0" (kaddr), "I" (PAGE_SIZE / 32)
  	: "r1", "r2", "r3", "ip", "lr");
  	kunmap_atomic(kaddr, KM_USER0);
  }
  
  struct cpu_user_fns fa_user_fns __initdata = {
  	.cpu_clear_user_highpage = fa_clear_user_highpage,
  	.cpu_copy_user_highpage	= fa_copy_user_highpage,
  };