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

Andrew Jones
2014-07-11T08:20:26Z

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 generated/asm-offsets.h to this framework.
It also adapts cp15.h from the kernel, since we'll need bit defines
from there too.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
---
v4: much improved asm-offsets.h generation based on Kbuild
---
config/asm-offsets.mak | 41 +++++++++++++++++++
config/config-arm.mak | 9 ++++-
lib/arm/.gitignore | 1 +
lib/arm/asm-offsets.c | 39 ++++++++++++++++++
lib/arm/asm/asm-offsets.h | 1 +
lib/arm/asm/cp15.h | 37 +++++++++++++++++
lib/arm/asm/ptrace.h | 100 ++++++++++++++++++++++++++++++++++++++++++++++
lib/generated/.gitignore | 1 +
8 files changed, 227 insertions(+), 2 deletions(-)
create mode 100644 config/asm-offsets.mak
create mode 100644 lib/arm/.gitignore
create mode 100644 lib/arm/asm-offsets.c
create mode 100644 lib/arm/asm/asm-offsets.h
create mode 100644 lib/arm/asm/cp15.h
create mode 100644 lib/arm/asm/ptrace.h
create mode 100644 lib/generated/.gitignore

diff --git a/config/asm-offsets.mak b/config/asm-offsets.mak
new file mode 100644
index 0000000000000..b2578a6692f33
--- /dev/null
+++ b/config/asm-offsets.mak
@@ -0,0 +1,41 @@
+#
+# asm-offsets adapted from the kernel, see
+# Kbuild
+# scripts/Kbuild.include
+# scripts/Makefile.build
+#
+# Authors: Andrew Jones <drjones@redhat.com>
+#
+
+define sed-y
+ "/^->/{s:->#\(.*\):/* \1 */:; \
+ s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+ s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+ s:->::; p;}"
+endef
+
+define make_asm_offsets
+ (set -e; \
+ echo "#ifndef __ASM_OFFSETS_H__"; \
+ echo "#define __ASM_OFFSETS_H__"; \
+ echo "/*"; \
+ echo " * Generated file. DO NOT MODIFY."; \
+ echo " *"; \
+ echo " */"; \
+ echo ""; \
+ sed -ne $(sed-y) $<; \
+ echo ""; \
+ echo "#endif" ) > $@
+endef
+
+$(asm-offsets:.h=.s): $(asm-offsets:.h=.c)
+ $(CC) $(CFLAGS) -fverbose-asm -S -o $@ $<
+
+$(asm-offsets): $(asm-offsets:.h=.s)
+ $(call make_asm_offsets)
+ cp -f $(asm-offsets) lib/generated
+
+asm_offsets_clean:
+ $(RM) $(asm-offsets) $(asm-offsets:.h=.s) \
+ $(addprefix lib/generated/,$(notdir $(asm-offsets)))
+
diff --git a/config/config-arm.mak b/config/config-arm.mak
index fb160b6c65e2a..ca47b483e9ce9 100644
--- a/config/config-arm.mak
+++ b/config/config-arm.mak
@@ -30,6 +30,9 @@ CFLAGS += -Wextra
CFLAGS += -O2
CFLAGS += -I lib -I lib/libfdt

+asm-offsets = lib/arm/asm-offsets.h
+include config/asm-offsets.mak
+
cflatobjs += \
lib/alloc.o \
lib/devicetree.o \
@@ -58,7 +61,7 @@ FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libgcc) $(libeabi)
$(libeabi): $(eabiobjs)
$(AR) rcs $@ $^

-arch_clean: libfdt_clean
+arch_clean: libfdt_clean asm_offsets_clean
$(RM) $(TEST_DIR)/*.{o,flat,elf} $(libeabi) $(eabiobjs) \
$(TEST_DIR)/.*.d lib/arm/.*.d

@@ -68,7 +71,9 @@ tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg

cstart.o = $(TEST_DIR)/cstart.o

-test_cases: $(tests-common) $(tests)
+generated_files = $(asm-offsets)
+
+test_cases: $(generated_files) $(tests-common) $(tests)

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

diff --git a/lib/arm/.gitignore b/lib/arm/.gitignore
new file mode 100644
index 0000000000000..84872bf197c67
--- /dev/null
+++ b/lib/arm/.gitignore
@@ -0,0 +1 @@
+asm-offsets.[hs]
diff --git a/lib/arm/asm-offsets.c b/lib/arm/asm-offsets.c
new file mode 100644
index 0000000000000..a9c349d2d427c
--- /dev/null
+++ b/lib/arm/asm-offsets.c
@@ -0,0 +1,39 @@
+/*
+ * Adapted from arch/arm/kernel/asm-offsets.c
+ *
+ * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include "libcflat.h"
+#include "asm/ptrace.h"
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#define OFFSET(sym, str, mem) DEFINE(sym, offsetof(struct str, mem))
+#define COMMENT(x) asm volatile("\n->#" x)
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+ OFFSET(S_R0, pt_regs, ARM_r0);
+ OFFSET(S_R1, pt_regs, ARM_r1);
+ OFFSET(S_R2, pt_regs, ARM_r2);
+ OFFSET(S_R3, pt_regs, ARM_r3);
+ OFFSET(S_R4, pt_regs, ARM_r4);
+ OFFSET(S_R5, pt_regs, ARM_r5);
+ OFFSET(S_R6, pt_regs, ARM_r6);
+ OFFSET(S_R7, pt_regs, ARM_r7);
+ OFFSET(S_R8, pt_regs, ARM_r8);
+ OFFSET(S_R9, pt_regs, ARM_r9);
+ OFFSET(S_R10, pt_regs, ARM_r10);
+ OFFSET(S_FP, pt_regs, ARM_fp);
+ OFFSET(S_IP, pt_regs, ARM_ip);
+ OFFSET(S_SP, pt_regs, ARM_sp);
+ OFFSET(S_LR, pt_regs, ARM_lr);
+ OFFSET(S_PC, pt_regs, ARM_pc);
+ OFFSET(S_PSR, pt_regs, ARM_cpsr);
+ OFFSET(S_OLD_R0, pt_regs, ARM_ORIG_r0);
+ DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
+ return 0;
+}
diff --git a/lib/arm/asm/asm-offsets.h b/lib/arm/asm/asm-offsets.h
new file mode 100644
index 0000000000000..c2ff2ba6ec417
--- /dev/null
+++ b/lib/arm/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include "generated/asm-offsets.h"
diff --git a/lib/arm/asm/cp15.h b/lib/arm/asm/cp15.h
new file mode 100644
index 0000000000000..7690a48f17f1f
--- /dev/null
+++ b/lib/arm/asm/cp15.h
@@ -0,0 +1,37 @@
+#ifndef _ASMARM_CP15_H_
+#define _ASMARM_CP15_H_
+/*
+ * From the 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 /* _ASMARM_CP15_H_ */
diff --git a/lib/arm/asm/ptrace.h b/lib/arm/asm/ptrace.h
new file mode 100644
index 0000000000000..3a4c7532258f6
--- /dev/null
+++ b/lib/arm/asm/ptrace.h
@@ -0,0 +1,100 @@
+#ifndef _ASMARM_PTRACE_H_
+#define _ASMARM_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 /* _ASMARM_PTRACE_H_ */
diff --git a/lib/generated/.gitignore b/lib/generated/.gitignore
new file mode 100644
index 0000000000000..72e8ffc0db8aa
--- /dev/null
+++ b/lib/generated/.gitignore
@@ -0,0 +1 @@
+*
--
1.9.3