- 论坛徽章:
- 0
|
arm上这个pv_stub有什么用?
看着咋定义CONFIG_ARM_PATCH_PHYS_VIRT之后virt_to_phys偏移就加错了,算错了呢,有了解这个的大侠不?
-------------------------------------------------------------------------------------------------------------------------------------------------------
include/asm/memory.h
-------------------------------------------------------------------------------------------------------------------------------------------------------
146/*
147 * Physical vs virtual RAM address space conversion. These are
148 * private definitions which should NOT be used outside memory.h
149 * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
150 */
151#ifndef __virt_to_phys
152#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
153
154/*
155 * Constants used to force the right instruction encodings and shifts
156 * so that all we need to do is modify the 8-bit constant field.
157 */
158#define __PV_BITS_31_24 0x81000000
159
160extern unsigned long __pv_phys_offset;
161#define PHYS_OFFSET __pv_phys_offset
162
163#define __pv_stub(from,to,instr,type) \
164 __asm__("@ __pv_stub\n" \
165 "1: " instr " %0, %1, %2\n" \
166 " .pushsection .pv_table,\"a\"\n" \
167 " .long 1b\n" \
168 " .popsection\n" \
169 : "=r" (to) \
170 : "r" (from), "I" (type))
171
172static inline unsigned long __virt_to_phys(unsigned long x)
173{
174 unsigned long t;
175 __pv_stub(x, t, "add", __PV_BITS_31_24);
176 return t;
177}
178
179static inline unsigned long __phys_to_virt(unsigned long x)
180{
181 unsigned long t;
182 __pv_stub(x, t, "sub", __PV_BITS_31_24);
183 return t;
184}
185#else
186#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
187#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
188#endif
189#endif
190#endif /* __ASSEMBLY__ */
191
192#ifndef PHYS_OFFSET
193#ifdef PLAT_PHYS_OFFSET
194#define PHYS_OFFSET PLAT_PHYS_OFFSET
195#else
196#define PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)
197#endif
198#endif
------------------------------------------------------------------------------------------------------------------------------------------------------
arch/arm/kernel/vmlinux.lds.S
------------------------------------------------------------------------------------------------------------------------------------------------------
197 .init.pv_table : {
198 __pv_table_begin = .;
199 *(.pv_table)
200 __pv_table_end = .;
201 }
------------------------------------------------------------------------------------------------------------------------------------------------------
arch/arm/kernel/module.c
------------------------------------------------------------------------------------------------------------------------------------------------------
319#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
320 s = find_mod_section(hdr, sechdrs, ".pv_table");
321 if (s)
322 fixup_pv_table((void *)s->sh_addr, s->sh_size);
323#endif
------------------------------------------------------------------------------------------------------------------------------------------------------
arch/arm/kernel/head.S
------------------------------------------------------------------------------------------------------------------------------------------------------
541#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
542
543/* __fixup_pv_table - patch the stub instructions with the delta between
544 * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and
545 * can be expressed by an immediate shifter operand. The stub instruction
546 * has a form of '(add|sub) rd, rn, #imm'.
547 */
548 __HEAD
549__fixup_pv_table:
550 adr r0, 1f
551 ldmia r0, {r3-r5, r7}
552 sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET
553 add r4, r4, r3 @ adjust table start address
554 add r5, r5, r3 @ adjust table end address
555 add r7, r7, r3 @ adjust __pv_phys_offset address
556 str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset
557 mov r6, r3, lsr #24 @ constant for add/sub instructions
558 teq r3, r6, lsl #24 @ must be 16MiB aligned
559THUMB( it ne @ cross section branch )
560 bne __error
561 str r6, [r7, #4] @ save to __pv_offset
562 b __fixup_a_pv_table
563ENDPROC(__fixup_pv_table)
564
565 .align
5661: .long .
567 .long __pv_table_begin
568 .long __pv_table_end
5692: .long __pv_phys_offset
570
571 .text
572__fixup_a_pv_table:
573#ifdef CONFIG_THUMB2_KERNEL
574 lsls r6, #24
575 beq 2f
576 clz r7, r6
577 lsr r6, #24
578 lsl r6, r7
579 bic r6, #0x0080
580 lsrs r7, #1
581 orrcs r6, #0x0080
582 orr r6, r6, r7, lsl #12
583 orr r6, #0x4000
584 b 2f
5851: add r7, r3
586 ldrh ip, [r7, #2]
587 and ip, 0x8f00
588 orr ip, r6 @ mask in offset bits 31-24
589 strh ip, [r7, #2]
5902: cmp r4, r5
591 ldrcc r7, [r4], #4 @ use branch for delay slot
592 bcc 1b
593 bx lr
594#else
595 b 2f
5961: ldr ip, [r7, r3]
597 bic ip, ip, #0x000000ff
598 orr ip, ip, r6 @ mask in offset bits 31-24
599 str ip, [r7, r3]
6002: cmp r4, r5
601 ldrcc r7, [r4], #4 @ use branch for delay slot
602 bcc 1b
603 mov pc, lr
604#endif
605ENDPROC(__fixup_a_pv_table)
606
607ENTRY(fixup_pv_table)
608 stmfd sp!, {r4 - r7, lr}
609 ldr r2, 2f @ get address of __pv_phys_offset
610 mov r3, #0 @ no offset
611 mov r4, r0 @ r0 = table start
612 add r5, r0, r1 @ r1 = table size
613 ldr r6, [r2, #4] @ get __pv_offset
614 bl __fixup_a_pv_table
615 ldmfd sp!, {r4 - r7, pc}
616ENDPROC(fixup_pv_table)
617
618 .align
6192: .long __pv_phys_offset
620
621 .data
622 .globl __pv_phys_offset
623 .type __pv_phys_offset, %object
624__pv_phys_offset:
625 .long 0
626 .size __pv_phys_offset, . - __pv_phys_offset
627__pv_offset:
628 .long 0
629#endif |
|