在内核模块中使用 'dccmvac' 时出现汇编程序错误
Assembler error when using 'dccmvac' in a kernel module
当我尝试在 Raspberry Pi 3B+(ARMv8a、AARCH32)的内核模块中编译以下代码时,出现 'bad instruction' 错误。根据 ARMv8a 的 ARM 参考手册,此指令在 AARCH32 的异常级别 0 (EL0) 未定义,但我在内核模块中使用它,所以我不明白这个问题。
__asm(
"mov r9,%0 \n\t"
"mov r10,%1 \n\t"
"mov r1,#0 \n\t
"str r1,[r9] \n\t"
"str r1,[r10] \n\t"
"DCCMVAC r9 \n\t"
"DCCMVAC r10 \n\t"
:
:"r" (firstPtr),
"r" (secondPtr)
:"r1","r9","r10","memory"
);
组装相关消息如下,
/tmp/ccCmW5TY.s: Assembler messages:
/tmp/ccCmW5TY.s:221: Error: bad instruction `dccmvac r9'
/tmp/ccCmW5TY.s:222: Error: bad instruction `dccmvac r10'
DCCMVAC
指令可能无法被 GNU as
识别:
根据 Arm 文档,DCCMVAC
指令是通过在 CP15
协处理器上执行操作来执行的:
MCR{<c>}{<q>} <coproc>, {#}<opc1>, <Rt>, <CRn>, <CRm>{, {#}<opc2>}
with the following values:
coproc opc1 CRn CRm opc2
0b1111 0b000 0b0111 0b1010 0b001
CMSIS_5
项目中有一个实现,格式如下 define/function/macro,在文件 CMSIS/Core_A/Include/cmsis_gcc.h
和 CMSIS/Core_A/Include/cmsis_cp15.h
.
中
我们可以重新使用一些代码来构建示例程序dccmvac.c
:
#include <stdint.h>
#define __ASM __asm
#define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
/** \brief Set DCCMVAC
Data cache clean
*/
__STATIC_FORCEINLINE void __set_DCCMVAC(uint32_t value)
{
__set_CP(15, 0, value, 7, 10, 1);
}
int main()
{
__set_DCCMVAC(0x12345678U);
return 0;
}
/opt/arm/9/gcc-arm-9.2-2019.12-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -c -o dccmvac.o dccmvac.c
/opt/arm/9/gcc-arm-9.2-2019.12-x86_64-arm-none-eabi/bin/arm-none-eabi-objdump -D dccmvac.o
dccmvac.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <main>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e59f3020 ldr r3, [pc, #32] ; 34 <main+0x34>
10: e50b3008 str r3, [fp, #-8]
14: e51b3008 ldr r3, [fp, #-8]
18: ee073f3a mcr 15, 0, r3, cr7, cr10, {1}
1c: e1a00000 nop ; (mov r0, r0)
20: e3a03000 mov r3, #0
24: e1a00003 mov r0, r3
28: e28bd000 add sp, fp, #0
2c: e49db004 pop {fp} ; (ldr fp, [sp], #4)
30: e12fff1e bx lr
34: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
值 0x123456781
在执行 mcr 15, 0, r3, cr7, cr10, {1}
之前被加载到 r3
。
使用 shell-storm
反汇编 0xee073f3a
得到:
0x0000000000000000: EE 07 3F 3A mcr p15, #0, r3, c7, c10, #1
您现在应该拥有在代码中使用 DCCMVAC
指令所需的信息 - 请记住,Arm CMSIS_5
代码是根据 Apache-2.0 许可获得许可的,因此不能只需 copied/pasted 进入 Linux 内核模块 - 您可能应该使用 arch/arm/mm/cache-v7m.S
中定义的 Linux dccmvac
宏,或者编写您自己的等效代码。
当我尝试在 Raspberry Pi 3B+(ARMv8a、AARCH32)的内核模块中编译以下代码时,出现 'bad instruction' 错误。根据 ARMv8a 的 ARM 参考手册,此指令在 AARCH32 的异常级别 0 (EL0) 未定义,但我在内核模块中使用它,所以我不明白这个问题。
__asm(
"mov r9,%0 \n\t"
"mov r10,%1 \n\t"
"mov r1,#0 \n\t
"str r1,[r9] \n\t"
"str r1,[r10] \n\t"
"DCCMVAC r9 \n\t"
"DCCMVAC r10 \n\t"
:
:"r" (firstPtr),
"r" (secondPtr)
:"r1","r9","r10","memory"
);
组装相关消息如下,
/tmp/ccCmW5TY.s: Assembler messages:
/tmp/ccCmW5TY.s:221: Error: bad instruction `dccmvac r9'
/tmp/ccCmW5TY.s:222: Error: bad instruction `dccmvac r10'
DCCMVAC
指令可能无法被 GNU as
识别:
根据 Arm 文档,DCCMVAC
指令是通过在 CP15
协处理器上执行操作来执行的:
MCR{<c>}{<q>} <coproc>, {#}<opc1>, <Rt>, <CRn>, <CRm>{, {#}<opc2>}
with the following values:
coproc opc1 CRn CRm opc2
0b1111 0b000 0b0111 0b1010 0b001
CMSIS_5
项目中有一个实现,格式如下 define/function/macro,在文件 CMSIS/Core_A/Include/cmsis_gcc.h
和 CMSIS/Core_A/Include/cmsis_cp15.h
.
我们可以重新使用一些代码来构建示例程序dccmvac.c
:
#include <stdint.h>
#define __ASM __asm
#define __set_CP(cp, op1, Rt, CRn, CRm, op2) __ASM volatile("MCR p" # cp ", " # op1 ", %0, c" # CRn ", c" # CRm ", " # op2 : : "r" (Rt) : "memory" )
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
/** \brief Set DCCMVAC
Data cache clean
*/
__STATIC_FORCEINLINE void __set_DCCMVAC(uint32_t value)
{
__set_CP(15, 0, value, 7, 10, 1);
}
int main()
{
__set_DCCMVAC(0x12345678U);
return 0;
}
/opt/arm/9/gcc-arm-9.2-2019.12-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -c -o dccmvac.o dccmvac.c
/opt/arm/9/gcc-arm-9.2-2019.12-x86_64-arm-none-eabi/bin/arm-none-eabi-objdump -D dccmvac.o
dccmvac.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <main>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e59f3020 ldr r3, [pc, #32] ; 34 <main+0x34>
10: e50b3008 str r3, [fp, #-8]
14: e51b3008 ldr r3, [fp, #-8]
18: ee073f3a mcr 15, 0, r3, cr7, cr10, {1}
1c: e1a00000 nop ; (mov r0, r0)
20: e3a03000 mov r3, #0
24: e1a00003 mov r0, r3
28: e28bd000 add sp, fp, #0
2c: e49db004 pop {fp} ; (ldr fp, [sp], #4)
30: e12fff1e bx lr
34: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
值 0x123456781
在执行 mcr 15, 0, r3, cr7, cr10, {1}
之前被加载到 r3
。
使用 shell-storm
反汇编 0xee073f3a
得到:
0x0000000000000000: EE 07 3F 3A mcr p15, #0, r3, c7, c10, #1
您现在应该拥有在代码中使用 DCCMVAC
指令所需的信息 - 请记住,Arm CMSIS_5
代码是根据 Apache-2.0 许可获得许可的,因此不能只需 copied/pasted 进入 Linux 内核模块 - 您可能应该使用 arch/arm/mm/cache-v7m.S
中定义的 Linux dccmvac
宏,或者编写您自己的等效代码。