[PATCH 16/17] arm: add useful headers from the linux kernel

Andrew Jones
2014-01-21T16:22:49Z

We're going to need PSR bit defines and pt_regs. We'll also need
pt_regs offsets in assembly code. This patch adapts the linux
kernel's ptrace.h and asm-offsets to this framework. Even though
lib/arm/asm-offsets.h is a generated file, we still commit it,
as it's unlikely to change. Also adapt cp15.h from the kernel,
since we'll need bit defines from there too.

Signed-off-by: Andrew Jones <drjones@redhat.com>
---
config/config-arm.mak | 20 ++++++++--
lib/arm/asm-offsets.h | 27 +++++++++++++
lib/arm/cp15.h | 36 +++++++++++++++++
lib/arm/ptrace.h | 100 ++++++++++++++++++++++++++++++++++++++++++++++
scripts/arm/asm-offsets.c | 40 +++++++++++++++++++
5 files changed, 219 insertions(+), 4 deletions(-)
create mode 100644 lib/arm/asm-offsets.h
create mode 100644 lib/arm/cp15.h
create mode 100644 lib/arm/ptrace.h
create mode 100644 scripts/arm/asm-offsets.c

diff --git a/config/config-arm.mak b/config/config-arm.mak
index 3480003f0ac13..a863b3e3511c9 100644
--- a/config/config-arm.mak
+++ b/config/config-arm.mak
@@ -32,10 +32,9 @@ CFLAGS += -marm
CFLAGS += -O2
ifeq ($(PROCESSOR), $(ARCH))
# PROCESSOR=ARCH is the default, but there is no 'arm' cpu
- CFLAGS += -mcpu=cortex-a15
-else
- CFLAGS += -mcpu=$(PROCESSOR)
+ PROCESSOR = cortex-a15
endif
+CFLAGS += -mcpu=$(PROCESSOR)

libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name)
start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) )))
@@ -62,6 +61,19 @@ $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding $(includedirs)

$(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o

-arch_clean: libfdt_clean
+arch_clean: libfdt_clean scripts_clean
$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
$(libeabi) $(eabiobjs) $(TEST_DIR)/.*.d lib/arm/.*.d
+
+.PHONY: scripts_clean asm-offsets
+
+scripts_clean:
+ $(RM) scripts/arm/.*.d scripts/arm/*.o \
+ scripts/arm/*.flat scripts/arm/*.elf
+
+asm-offsets: scripts/arm/asm-offsets.flat
+ $(QEMU) -device virtio-testdev -display none -serial stdio \
+ -M virt -cpu $(PROCESSOR) \
+ -kernel $^ > lib/arm/asm-offsets.h || true
+scripts/arm/asm-offsets.elf: $(cstart.o) scripts/arm/asm-offsets.o
+scripts/arm/%.o: CFLAGS += -std=gnu99 -ffreestanding $(includedirs)
diff --git a/lib/arm/asm-offsets.h b/lib/arm/asm-offsets.h
new file mode 100644
index 0000000000000..b43be20ef8377
--- /dev/null
+++ b/lib/arm/asm-offsets.h
@@ -0,0 +1,27 @@
+#ifndef _ARM_ASM_OFFSETS_H_
+#define _ARM_ASM_OFFSETS_H_
+/*
+ * Generated file. Regenerate with 'make asm-offsets'
+ */
+
+#define S_R0 0x0
+#define S_R1 0x4
+#define S_R2 0x8
+#define S_R3 0xc
+#define S_R4 0x10
+#define S_R5 0x14
+#define S_R6 0x18
+#define S_R7 0x1c
+#define S_R8 0x20
+#define S_R9 0x24
+#define S_R10 0x28
+#define S_FP 0x2c
+#define S_IP 0x30
+#define S_SP 0x34
+#define S_LR 0x38
+#define S_PC 0x3c
+#define S_PSR 0x40
+#define S_OLD_R0 0x44
+#define S_FRAME_SIZE 0x48
+
+#endif /* _ARM_ASM_OFFSETS_H_ */
diff --git a/lib/arm/cp15.h b/lib/arm/cp15.h
new file mode 100644
index 0000000000000..6a8a29aadb008
--- /dev/null
+++ b/lib/arm/cp15.h
@@ -0,0 +1,36 @@
+#ifndef _ARM_CP15_H_
+#define _ARM_CP15_H_
+/*
+ * From Linux kernel arch/arm/include/asm/cp15.h
+ *
+ * CR1 bits (CP#15 CR1)
+ */
+#define CR_M (1 << 0) /* MMU enable */
+#define CR_A (1 << 1) /* Alignment abort enable */
+#define CR_C (1 << 2) /* Dcache enable */
+#define CR_W (1 << 3) /* Write buffer enable */
+#define CR_P (1 << 4) /* 32-bit exception handler */
+#define CR_D (1 << 5) /* 32-bit data address range */
+#define CR_L (1 << 6) /* Implementation defined */
+#define CR_B (1 << 7) /* Big endian */
+#define CR_S (1 << 8) /* System MMU protection */
+#define CR_R (1 << 9) /* ROM MMU protection */
+#define CR_F (1 << 10) /* Implementation defined */
+#define CR_Z (1 << 11) /* Implementation defined */
+#define CR_I (1 << 12) /* Icache enable */
+#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */
+#define CR_RR (1 << 14) /* Round Robin cache replacement */
+#define CR_L4 (1 << 15) /* LDR pc can set T bit */
+#define CR_DT (1 << 16)
+#define CR_HA (1 << 17) /* Hardware management of Access Flag */
+#define CR_IT (1 << 18)
+#define CR_ST (1 << 19)
+#define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */
+#define CR_U (1 << 22) /* Unaligned access operation */
+#define CR_XP (1 << 23) /* Extended page tables */
+#define CR_VE (1 << 24) /* Vectored interrupts */
+#define CR_EE (1 << 25) /* Exception (Big) Endian */
+#define CR_TRE (1 << 28) /* TEX remap enable */
+#define CR_AFE (1 << 29) /* Access flag enable */
+#define CR_TE (1 << 30) /* Thumb exception enable */
+#endif
diff --git a/lib/arm/ptrace.h b/lib/arm/ptrace.h
new file mode 100644
index 0000000000000..3c8781508a72e
--- /dev/null
+++ b/lib/arm/ptrace.h
@@ -0,0 +1,100 @@
+#ifndef _ARM_PTRACE_H_
+#define _ARM_PTRACE_H_
+/*
+ * Adapted from Linux kernel headers
+ * arch/arm/include/asm/ptrace.h
+ * arch/arm/include/uapi/asm/ptrace.h
+ */
+
+/*
+ * PSR bits
+ */
+#define USR_MODE 0x00000010
+#define SVC_MODE 0x00000013
+#define FIQ_MODE 0x00000011
+#define IRQ_MODE 0x00000012
+#define ABT_MODE 0x00000017
+#define HYP_MODE 0x0000001a
+#define UND_MODE 0x0000001b
+#define SYSTEM_MODE 0x0000001f
+#define MODE32_BIT 0x00000010
+#define MODE_MASK 0x0000001f
+
+#define PSR_T_BIT 0x00000020 /* >= V4T, but not V7M */
+#define PSR_F_BIT 0x00000040 /* >= V4, but not V7M */
+#define PSR_I_BIT 0x00000080 /* >= V4, but not V7M */
+#define PSR_A_BIT 0x00000100 /* >= V6, but not V7M */
+#define PSR_E_BIT 0x00000200 /* >= V6, but not V7M */
+#define PSR_J_BIT 0x01000000 /* >= V5J, but not V7M */
+#define PSR_Q_BIT 0x08000000 /* >= V5E, including V7M */
+#define PSR_V_BIT 0x10000000
+#define PSR_C_BIT 0x20000000
+#define PSR_Z_BIT 0x40000000
+#define PSR_N_BIT 0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f 0xff000000 /* Flags */
+#define PSR_s 0x00ff0000 /* Status */
+#define PSR_x 0x0000ff00 /* Extension */
+#define PSR_c 0x000000ff /* Control */
+
+/*
+ * ARMv7 groups of PSR bits
+ */
+#define APSR_MASK 0xf80f0000 /* N, Z, C, V, Q and GE flags */
+#define PSR_ISET_MASK 0x01000010 /* ISA state (J, T) mask */
+#define PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
+#define PSR_ENDIAN_MASK 0x00000200 /* Endianness state mask */
+
+#ifndef __ASSEMBLY__
+#include "libcflat.h"
+
+struct pt_regs {
+ unsigned long uregs[18];
+};
+
+#define ARM_cpsr uregs[16]
+#define ARM_pc uregs[15]
+#define ARM_lr uregs[14]
+#define ARM_sp uregs[13]
+#define ARM_ip uregs[12]
+#define ARM_fp uregs[11]
+#define ARM_r10 uregs[10]
+#define ARM_r9 uregs[9]
+#define ARM_r8 uregs[8]
+#define ARM_r7 uregs[7]
+#define ARM_r6 uregs[6]
+#define ARM_r5 uregs[5]
+#define ARM_r4 uregs[4]
+#define ARM_r3 uregs[3]
+#define ARM_r2 uregs[2]
+#define ARM_r1 uregs[1]
+#define ARM_r0 uregs[0]
+#define ARM_ORIG_r0 uregs[17]
+
+#define user_mode(regs) \
+ (((regs)->ARM_cpsr & 0xf) == 0)
+
+#define processor_mode(regs) \
+ ((regs)->ARM_cpsr & MODE_MASK)
+
+#define interrupts_enabled(regs) \
+ (!((regs)->ARM_cpsr & PSR_I_BIT))
+
+#define fast_interrupts_enabled(regs) \
+ (!((regs)->ARM_cpsr & PSR_F_BIT))
+
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, ARM_ORIG_r0))
+
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+ unsigned int offset)
+{
+ if (offset > MAX_REG_OFFSET)
+ return 0;
+ return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ARM_PTRACE_H_ */
diff --git a/scripts/arm/asm-offsets.c b/scripts/arm/asm-offsets.c
new file mode 100644
index 0000000000000..03b22da907d58
--- /dev/null
+++ b/scripts/arm/asm-offsets.c
@@ -0,0 +1,40 @@
+/*
+ * Adapted from arch/arm/kernel/asm-offsets.c
+ */
+#include "libcflat.h"
+#include "arm/ptrace.h"
+
+#define P(sym, val) \
+ printf("#define " #sym "\t0x%x\n", val)
+
+int main(void)
+{
+ printf("#ifndef _ARM_ASM_OFFSETS_H_\n");
+ printf("#define _ARM_ASM_OFFSETS_H_\n");
+ printf("/*\n");
+ printf(" * Generated file. Regenerate with 'make asm-offsets'\n");
+ printf(" */\n");
+ printf("\n");
+ P(S_R0, offsetof(struct pt_regs, ARM_r0));
+ P(S_R1, offsetof(struct pt_regs, ARM_r1));
+ P(S_R2, offsetof(struct pt_regs, ARM_r2));
+ P(S_R3, offsetof(struct pt_regs, ARM_r3));
+ P(S_R4, offsetof(struct pt_regs, ARM_r4));
+ P(S_R5, offsetof(struct pt_regs, ARM_r5));
+ P(S_R6, offsetof(struct pt_regs, ARM_r6));
+ P(S_R7, offsetof(struct pt_regs, ARM_r7));
+ P(S_R8, offsetof(struct pt_regs, ARM_r8));
+ P(S_R9, offsetof(struct pt_regs, ARM_r9));
+ P(S_R10, offsetof(struct pt_regs, ARM_r10));
+ P(S_FP, offsetof(struct pt_regs, ARM_fp));
+ P(S_IP, offsetof(struct pt_regs, ARM_ip));
+ P(S_SP, offsetof(struct pt_regs, ARM_sp));
+ P(S_LR, offsetof(struct pt_regs, ARM_lr));
+ P(S_PC, offsetof(struct pt_regs, ARM_pc));
+ P(S_PSR, offsetof(struct pt_regs, ARM_cpsr));
+ P(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
+ P(S_FRAME_SIZE, sizeof(struct pt_regs));
+ printf("\n");
+ printf("#endif /* _ARM_ASM_OFFSETS_H_ */\n");
+ return 0;
+}
--
1.8.1.4