~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/kernel/phys2virt.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-only */
  2 /*
  3  *  Copyright (C) 1994-2002 Russell King
  4  *  Copyright (c) 2003, 2020 ARM Limited
  5  *  All Rights Reserved
  6  */
  7 
  8 #include <linux/init.h>
  9 #include <linux/linkage.h>
 10 #include <asm/assembler.h>
 11 #include <asm/page.h>
 12 
 13 #ifdef __ARMEB__
 14 #define LOW_OFFSET      0x4
 15 #define HIGH_OFFSET     0x0
 16 #else
 17 #define LOW_OFFSET      0x0
 18 #define HIGH_OFFSET     0x4
 19 #endif
 20 
 21 /*
 22  * __fixup_pv_table - patch the stub instructions with the delta between
 23  *                    PHYS_OFFSET and PAGE_OFFSET, which is assumed to be
 24  *                    2 MiB aligned.
 25  *
 26  * Called from head.S, which expects the following registers to be preserved:
 27  *   r1 = machine no, r2 = atags or dtb,
 28  *   r8 = phys_offset, r9 = cpuid, r10 = procinfo
 29  */
 30         __HEAD
 31 ENTRY(__fixup_pv_table)
 32         mov     r0, r8, lsr #PAGE_SHIFT @ convert to PFN
 33         str_l   r0, __pv_phys_pfn_offset, r3
 34 
 35         adr_l   r0, __pv_offset
 36         subs    r3, r8, #PAGE_OFFSET    @ PHYS_OFFSET - PAGE_OFFSET
 37         mvn     ip, #0
 38         strcc   ip, [r0, #HIGH_OFFSET]  @ save to __pv_offset high bits
 39         str     r3, [r0, #LOW_OFFSET]   @ save to __pv_offset low bits
 40 
 41         mov     r0, r3, lsr #21         @ constant for add/sub instructions
 42         teq     r3, r0, lsl #21         @ must be 2 MiB aligned
 43         bne     0f
 44 
 45         adr_l   r4, __pv_table_begin
 46         adr_l   r5, __pv_table_end
 47         b       __fixup_a_pv_table
 48 
 49 0:      mov     r0, r0                  @ deadloop on error
 50         b       0b
 51 ENDPROC(__fixup_pv_table)
 52 
 53         .text
 54 __fixup_a_pv_table:
 55         adr_l   r6, __pv_offset
 56         ldr     r0, [r6, #HIGH_OFFSET]  @ pv_offset high word
 57         ldr     r6, [r6, #LOW_OFFSET]   @ pv_offset low word
 58         cmn     r0, #1
 59 #ifdef CONFIG_THUMB2_KERNEL
 60         @
 61         @ The Thumb-2 versions of the patchable sequences are
 62         @
 63         @ phys-to-virt:                 movw    <reg>, #offset<31:21>
 64         @                               lsl     <reg>, #21
 65         @                               sub     <VA>, <PA>, <reg>
 66         @
 67         @ virt-to-phys (non-LPAE):      movw    <reg>, #offset<31:21>
 68         @                               lsl     <reg>, #21
 69         @                               add     <PA>, <VA>, <reg>
 70         @
 71         @ virt-to-phys (LPAE):          movw    <reg>, #offset<31:21>
 72         @                               lsl     <reg>, #21
 73         @                               adds    <PAlo>, <VA>, <reg>
 74         @                               mov     <PAhi>, #offset<39:32>
 75         @                               adc     <PAhi>, <PAhi>, #0
 76         @
 77         @ In the non-LPAE case, all patchable instructions are MOVW
 78         @ instructions, where we need to patch in the offset into the
 79         @ second halfword of the opcode (the 16-bit immediate is encoded
 80         @ as imm4:i:imm3:imm8)
 81         @
 82         @       15       11 10  9           4 3    0  15  14  12 11 8 7    0
 83         @      +-----------+---+-------------+------++---+------+----+------+
 84         @ MOVW | 1 1 1 1 0 | i | 1 0 0 1 0 0 | imm4 || 0 | imm3 | Rd | imm8 |
 85         @      +-----------+---+-------------+------++---+------+----+------+
 86         @
 87         @ In the LPAE case, we also need to patch in the high word of the
 88         @ offset into the immediate field of the MOV instruction, or patch it
 89         @ to a MVN instruction if the offset is negative. In this case, we
 90         @ need to inspect the first halfword of the opcode, to check whether
 91         @ it is MOVW or MOV/MVN, and to perform the MOV to MVN patching if
 92         @ needed. The encoding of the immediate is rather complex for values
 93         @ of i:imm3 != 0b0000, but fortunately, we never need more than 8 lower
 94         @ order bits, which can be patched into imm8 directly (and i:imm3
 95         @ cleared)
 96         @
 97         @      15       11 10  9        5         0  15  14  12 11 8 7    0
 98         @     +-----------+---+---------------------++---+------+----+------+
 99         @ MOV | 1 1 1 1 0 | i | 0 0 0 1 0 0 1 1 1 1 || 0 | imm3 | Rd | imm8 |
100         @ MVN | 1 1 1 1 0 | i | 0 0 0 1 1 0 1 1 1 1 || 0 | imm3 | Rd | imm8 |
101         @     +-----------+---+---------------------++---+------+----+------+
102         @
103         moveq   r0, #0x200000           @ set bit 21, mov to mvn instruction
104         lsrs    r3, r6, #29             @ isolate top 3 bits of displacement
105         ubfx    r6, r6, #21, #8         @ put bits 28:21 into the MOVW imm8 field
106         bfi     r6, r3, #12, #3         @ put bits 31:29 into the MOVW imm3 field
107         b       .Lnext
108 .Lloop: add     r7, r4
109         adds    r4, #4                  @ clears Z flag
110 #ifdef CONFIG_ARM_LPAE
111         ldrh    ip, [r7]
112 ARM_BE8(rev16   ip, ip)
113         tst     ip, #0x200              @ MOVW has bit 9 set, MVN has it clear
114         bne     0f                      @ skip to MOVW handling (Z flag is clear)
115         bic     ip, #0x20               @ clear bit 5 (MVN -> MOV)
116         orr     ip, ip, r0, lsr #16     @ MOV -> MVN if offset < 0
117 ARM_BE8(rev16   ip, ip)
118         strh    ip, [r7]
119         @ Z flag is set
120 0:
121 #endif
122         ldrh    ip, [r7, #2]
123 ARM_BE8(rev16   ip, ip)
124         and     ip, #0xf00              @ clear everything except Rd field
125         orreq   ip, r0                  @ Z flag set -> MOV/MVN -> patch in high bits
126         orrne   ip, r6                  @ Z flag clear -> MOVW -> patch in low bits
127 ARM_BE8(rev16   ip, ip)
128         strh    ip, [r7, #2]
129 #else
130 #ifdef CONFIG_CPU_ENDIAN_BE8
131 @ in BE8, we load data in BE, but instructions still in LE
132 #define PV_BIT24        0x00000001
133 #define PV_IMM8_MASK    0xff000000
134 #define PV_IMMR_MSB     0x00080000
135 #else
136 #define PV_BIT24        0x01000000
137 #define PV_IMM8_MASK    0x000000ff
138 #define PV_IMMR_MSB     0x00000800
139 #endif
140 
141         @
142         @ The ARM versions of the patchable sequences are
143         @
144         @ phys-to-virt:                 sub     <VA>, <PA>, #offset<31:24>, lsl #24
145         @                               sub     <VA>, <PA>, #offset<23:16>, lsl #16
146         @
147         @ virt-to-phys (non-LPAE):      add     <PA>, <VA>, #offset<31:24>, lsl #24
148         @                               add     <PA>, <VA>, #offset<23:16>, lsl #16
149         @
150         @ virt-to-phys (LPAE):          movw    <reg>, #offset<31:20>
151         @                               adds    <PAlo>, <VA>, <reg>, lsl #20
152         @                               mov     <PAhi>, #offset<39:32>
153         @                               adc     <PAhi>, <PAhi>, #0
154         @
155         @ In the non-LPAE case, all patchable instructions are ADD or SUB
156         @ instructions, where we need to patch in the offset into the
157         @ immediate field of the opcode, which is emitted with the correct
158         @ rotation value. (The effective value of the immediate is imm12<7:0>
159         @ rotated right by [2 * imm12<11:8>] bits)
160         @
161         @      31   28 27      23 22  20 19  16 15  12 11    0
162         @      +------+-----------------+------+------+-------+
163         @  ADD | cond | 0 0 1 0 1 0 0 0 |  Rn  |  Rd  | imm12 |
164         @  SUB | cond | 0 0 1 0 0 1 0 0 |  Rn  |  Rd  | imm12 |
165         @  MOV | cond | 0 0 1 1 1 0 1 0 |  Rn  |  Rd  | imm12 |
166         @  MVN | cond | 0 0 1 1 1 1 1 0 |  Rn  |  Rd  | imm12 |
167         @      +------+-----------------+------+------+-------+
168         @
169         @ In the LPAE case, we use a MOVW instruction to carry the low offset
170         @ word, and patch in the high word of the offset into the immediate
171         @ field of the subsequent MOV instruction, or patch it to a MVN
172         @ instruction if the offset is negative. We can distinguish MOVW
173         @ instructions based on bits 23:22 of the opcode, and ADD/SUB can be
174         @ distinguished from MOV/MVN (all using the encodings above) using
175         @ bit 24.
176         @
177         @      31   28 27      23 22  20 19  16 15  12 11    0
178         @      +------+-----------------+------+------+-------+
179         @ MOVW | cond | 0 0 1 1 0 0 0 0 | imm4 |  Rd  | imm12 |
180         @      +------+-----------------+------+------+-------+
181         @
182         moveq   r0, #0x400000           @ set bit 22, mov to mvn instruction
183         mov     r3, r6, lsr #16         @ put offset bits 31-16 into r3
184         mov     r6, r6, lsr #24         @ put offset bits 31-24 into r6
185         and     r3, r3, #0xf0           @ only keep offset bits 23-20 in r3
186         b       .Lnext
187 .Lloop: ldr     ip, [r7, r4]
188 #ifdef CONFIG_ARM_LPAE
189         tst     ip, #PV_BIT24           @ ADD/SUB have bit 24 clear
190         beq     1f
191 ARM_BE8(rev     ip, ip)
192         tst     ip, #0xc00000           @ MOVW has bits 23:22 clear
193         bic     ip, ip, #0x400000       @ clear bit 22
194         bfc     ip, #0, #12             @ clear imm12 field of MOV[W] instruction
195         orreq   ip, ip, r6, lsl #4      @ MOVW -> mask in offset bits 31-24
196         orreq   ip, ip, r3, lsr #4      @ MOVW -> mask in offset bits 23-20
197         orrne   ip, ip, r0              @ MOV  -> mask in offset bits 7-0 (or bit 22)
198 ARM_BE8(rev     ip, ip)
199         b       2f
200 1:
201 #endif
202         tst     ip, #PV_IMMR_MSB                @ rotation value >= 16 ?
203         bic     ip, ip, #PV_IMM8_MASK
204         orreq   ip, ip, r6 ARM_BE8(, lsl #24)   @ mask in offset bits 31-24
205         orrne   ip, ip, r3 ARM_BE8(, lsl #24)   @ mask in offset bits 23-20
206 2:
207         str     ip, [r7, r4]
208         add     r4, r4, #4
209 #endif
210 
211 .Lnext:
212         cmp     r4, r5
213         ldrcc   r7, [r4]                @ use branch for delay slot
214         bcc     .Lloop
215         ret     lr
216 ENDPROC(__fixup_a_pv_table)
217 
218 ENTRY(fixup_pv_table)
219         stmfd   sp!, {r4 - r7, lr}
220         mov     r4, r0                  @ r0 = table start
221         add     r5, r0, r1              @ r1 = table size
222         bl      __fixup_a_pv_table
223         ldmfd   sp!, {r4 - r7, pc}
224 ENDPROC(fixup_pv_table)
225 
226         .data
227         .align  2
228         .globl  __pv_phys_pfn_offset
229         .type   __pv_phys_pfn_offset, %object
230 __pv_phys_pfn_offset:
231         .word   0
232         .size   __pv_phys_pfn_offset, . -__pv_phys_pfn_offset
233 
234         .globl  __pv_offset
235         .type   __pv_offset, %object
236 __pv_offset:
237         .quad   0
238         .size   __pv_offset, . -__pv_offset

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php