mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
asm: make use regular asserts that will just work on baremetal
Previously had wonky line pointer in asm_main. New interface simpler and more portable. Add tests for ASSERT_EQ_ and family in arm and aarch64, previously on x86_64. ASSERT_EQ_ and family in ARM can now either take =123, =addr or var, before this the = was added on macros so var was not possible. Define the main function directly in assembly, the C driver was useless.
This commit is contained in:
62
README.adoc
62
README.adoc
@@ -11647,7 +11647,7 @@ It is then a big copy paste for most other data instructions.
|
|||||||
Then, modify that program to make the assertion fail:
|
Then, modify that program to make the assertion fail:
|
||||||
|
|
||||||
....
|
....
|
||||||
ASSERT_EQ(%rax, $4)
|
LKMC_ASSERT_EQ(%rax, $4)
|
||||||
....
|
....
|
||||||
|
|
||||||
because 1 + 2 tends to equal 3 instead of 4.
|
because 1 + 2 tends to equal 3 instead of 4.
|
||||||
@@ -11676,10 +11676,16 @@ and notice how the error message gives both:
|
|||||||
Other infrastructure sanity checks that you might want to look into include:
|
Other infrastructure sanity checks that you might want to look into include:
|
||||||
|
|
||||||
* link:userland/arch/empty.S[]
|
* link:userland/arch/empty.S[]
|
||||||
* `FAIL` tests
|
* `LKMC_FAIL` tests
|
||||||
** link:userland/arch/fail.S[]
|
** link:userland/arch/fail.S[]
|
||||||
* `ASSERT_MEMCMP` tests
|
* `LKMC_ASSERT_EQ` tests
|
||||||
|
** link:userland/arch/x86_64/lkmc_assert_eq_fail.S[]
|
||||||
|
** link:userland/arch/arm/lkmc_assert_eq_fail.S[]
|
||||||
|
** link:userland/arch/aarch64/lkmc_assert_eq_fail.S[]
|
||||||
|
* `LKMC_ASSERT_MEMCMP` tests
|
||||||
** link:userland/arch/x86_64/lkmc_assert_memcmp_fail.S[]
|
** link:userland/arch/x86_64/lkmc_assert_memcmp_fail.S[]
|
||||||
|
** link:userland/arch/arm/lkmc_assert_memcmp_fail.S[]
|
||||||
|
** link:userland/arch/aarch64/lkmc_assert_memcmp_fail.S[]
|
||||||
|
|
||||||
=== Assembly registers
|
=== Assembly registers
|
||||||
|
|
||||||
@@ -11799,13 +11805,13 @@ This allows using the C standard library for IO, which is very convenient and po
|
|||||||
|
|
||||||
It also exposes other non-IO functionality that is very convenient such as `memcmp`.
|
It also exposes other non-IO functionality that is very convenient such as `memcmp`.
|
||||||
|
|
||||||
The C standard library infrastructure is implemented in the following files:
|
The C standard library infrastructure is implemented in the common userland / baremetal source files:
|
||||||
|
|
||||||
* link:userland/arch/main.c[]
|
* link:lkmc.c[]
|
||||||
* link:userland/arch/common.h[]
|
* link:lkmc.h[]
|
||||||
* link:userland/arch/x86_64/common_arch.h[]
|
* link:lkmc/aarch64.h[]
|
||||||
* link:userland/arch/arm/common_arch.h[]
|
* link:lkmc/arm.h[]
|
||||||
* link:userland/arch/aarch64/common_arch.h[]
|
* link:lkmc/x86_64.h[]
|
||||||
|
|
||||||
==== Freestanding programs
|
==== Freestanding programs
|
||||||
|
|
||||||
@@ -11914,23 +11920,51 @@ Questions about the C inline assembly examples:
|
|||||||
* x86_64: https://stackoverflow.com/questions/9506353/how-to-invoke-a-system-call-via-sysenter-in-inline-assembly/54956854#54956854
|
* x86_64: https://stackoverflow.com/questions/9506353/how-to-invoke-a-system-call-via-sysenter-in-inline-assembly/54956854#54956854
|
||||||
* ARM: https://stackoverflow.com/questions/21729497/doing-a-syscall-without-libc-using-arm-inline-assembly
|
* ARM: https://stackoverflow.com/questions/21729497/doing-a-syscall-without-libc-using-arm-inline-assembly
|
||||||
|
|
||||||
=== Calling conventions
|
=== Linux calling conventions
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
|
||||||
|
[options="header"]
|
||||||
|
|===
|
||||||
|
|arch |arguments |return value |callee saved registers
|
||||||
|
|
||||||
|
|x86_64
|
||||||
|
|rdi, rsi, rdx, rcx, r8, r9, xmm0–7
|
||||||
|
|rax, rdx
|
||||||
|
|rbx, rbp, r12–r15
|
||||||
|
|
||||||
|
|arm
|
||||||
|
|r0-r3
|
||||||
|
|r0-r3
|
||||||
|
|r4-r11
|
||||||
|
|
||||||
|
|aarch64
|
||||||
|
|x0-x7
|
||||||
|
|x0-x7
|
||||||
|
|x19-x29
|
||||||
|
|
||||||
|
|===
|
||||||
|
|
||||||
==== x86_64 calling convention
|
==== x86_64 calling convention
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
* link:userland/arch/x86_64/common_arch.h[] `ENTRY` and `EXIT`
|
* link:lkmc/x86_64.h[] `ENTRY` and `EXIT`
|
||||||
|
|
||||||
|
Bibliography:
|
||||||
|
|
||||||
|
* https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI
|
||||||
|
* https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call/55207335#55207335
|
||||||
|
|
||||||
==== ARM calling convention
|
==== ARM calling convention
|
||||||
|
|
||||||
Call C standard library functions from assembly and vice versa.
|
Call C standard library functions from assembly and vice versa.
|
||||||
|
|
||||||
* arm
|
* arm
|
||||||
** link:userland/arch/arm/common_arch.h[] `ENTRY` and `EXIT`
|
** link:lkmc/arm.h[] `ENTRY` and `EXIT`
|
||||||
** link:userland/arch/arm/linux/c_from_asm.S[]
|
** link:userland/arch/arm/linux/c_from_asm.S[]
|
||||||
* aarch64
|
* aarch64
|
||||||
** link:userland/arch/aarch64/common_arch.h[] `ENTRY` and `EXIT`
|
** link:lkmc/aarch64.h[] `ENTRY` and `EXIT`
|
||||||
** link:userland/arch/aarch64/c/linux/asm_from_c.c[]
|
** link:userland/arch/aarch64/c/linux/asm_from_c.c[]
|
||||||
|
|
||||||
ARM Architecture Procedure Call Standard (AAPCS) is the name that ARM Holdings gives to the calling convention.
|
ARM Architecture Procedure Call Standard (AAPCS) is the name that ARM Holdings gives to the calling convention.
|
||||||
@@ -12685,7 +12719,7 @@ Guaranteed undefined! Therefore raise illegal instruction signal. Used by GCC `_
|
|||||||
* link:userland/arch/arm/udf.S[]
|
* link:userland/arch/arm/udf.S[]
|
||||||
* link:userland/arch/aarch64/udf.S[]
|
* link:userland/arch/aarch64/udf.S[]
|
||||||
|
|
||||||
Why GNU GAS 2.29 does not have a mnemonic for it in A64 because it is very recent: shows in [[armarm8-db]] but not `ca`.
|
Why GNU GAS 2.29 does not have a mnemonic for it in A64 because it is very recent: shows in <<armarm8-db>> but not `ca`.
|
||||||
|
|
||||||
=== ARM SIMD
|
=== ARM SIMD
|
||||||
|
|
||||||
|
|||||||
@@ -60,25 +60,6 @@ Default: build all examples that have their package dependencies met, e.g.:
|
|||||||
extra_deps=[self.env['common_h']],
|
extra_deps=[self.env['common_h']],
|
||||||
link=False,
|
link=False,
|
||||||
)
|
)
|
||||||
extra_obj_userland_asm = os.path.join(
|
|
||||||
build_dir,
|
|
||||||
'arch',
|
|
||||||
'main' + self.env['obj_ext']
|
|
||||||
)
|
|
||||||
extra_obj_userland_asm_relpath = os.path.join(
|
|
||||||
'arch',
|
|
||||||
'main' + self.env['c_ext']
|
|
||||||
)
|
|
||||||
self._build_one(
|
|
||||||
in_path=os.path.join(
|
|
||||||
self.env['userland_source_dir'],
|
|
||||||
extra_obj_userland_asm_relpath
|
|
||||||
),
|
|
||||||
out_path=extra_obj_userland_asm,
|
|
||||||
cc_flags=cc_flags,
|
|
||||||
extra_deps=[self.env['common_h']],
|
|
||||||
link=False,
|
|
||||||
)
|
|
||||||
with thread_pool.ThreadPool(
|
with thread_pool.ThreadPool(
|
||||||
self._build_one,
|
self._build_one,
|
||||||
nthreads=self.env['nproc'],
|
nthreads=self.env['nproc'],
|
||||||
@@ -94,7 +75,6 @@ Default: build all examples that have their package dependencies met, e.g.:
|
|||||||
my_thread_pool.submit({
|
my_thread_pool.submit({
|
||||||
'cc_flags': cc_flags,
|
'cc_flags': cc_flags,
|
||||||
'extra_objs_lkmc_common': [extra_obj_lkmc_common],
|
'extra_objs_lkmc_common': [extra_obj_lkmc_common],
|
||||||
'extra_objs_userland_asm': [extra_obj_userland_asm],
|
|
||||||
'in_path': in_path,
|
'in_path': in_path,
|
||||||
'out_path': self.resolve_userland_executable(in_path),
|
'out_path': self.resolve_userland_executable(in_path),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1497,8 +1497,6 @@ https://github.com/cirosantilli/linux-kernel-module-cheat#gem5-debug-build
|
|||||||
if link:
|
if link:
|
||||||
if my_path_properties['extra_objs_lkmc_common']:
|
if my_path_properties['extra_objs_lkmc_common']:
|
||||||
extra_objs.extend(extra_objs_lkmc_common)
|
extra_objs.extend(extra_objs_lkmc_common)
|
||||||
if my_path_properties['extra_objs_userland_asm']:
|
|
||||||
extra_objs.extend(extra_objs_userland_asm)
|
|
||||||
if my_path_properties['extra_objs_baremetal_bootloader']:
|
if my_path_properties['extra_objs_baremetal_bootloader']:
|
||||||
extra_objs.extend(extra_objs_baremetal_bootloader)
|
extra_objs.extend(extra_objs_baremetal_bootloader)
|
||||||
if self.need_rebuild([in_path] + extra_objs + extra_deps, out_path):
|
if self.need_rebuild([in_path] + extra_objs + extra_deps, out_path):
|
||||||
@@ -1518,12 +1516,7 @@ https://github.com/cirosantilli/linux-kernel-module-cheat#gem5-debug-build
|
|||||||
if dirpath_relative_root_components_len > 0:
|
if dirpath_relative_root_components_len > 0:
|
||||||
if dirpath_relative_root_components[0] == 'userland':
|
if dirpath_relative_root_components[0] == 'userland':
|
||||||
if dirpath_relative_root_components_len > 1:
|
if dirpath_relative_root_components_len > 1:
|
||||||
if dirpath_relative_root_components[1] == 'arch':
|
if dirpath_relative_root_components[1] == 'libs':
|
||||||
cc_flags.extend([
|
|
||||||
'-I', os.path.join(self.env['userland_source_arch_arch_dir']), LF,
|
|
||||||
'-I', os.path.join(self.env['userland_source_arch_dir']), LF,
|
|
||||||
])
|
|
||||||
elif dirpath_relative_root_components[1] == 'libs':
|
|
||||||
if dirpath_relative_root_components_len > 1:
|
if dirpath_relative_root_components_len > 1:
|
||||||
if self.env['gcc_which'] == 'host':
|
if self.env['gcc_which'] == 'host':
|
||||||
eigen_root = '/'
|
eigen_root = '/'
|
||||||
|
|||||||
50
lkmc.c
50
lkmc.c
@@ -2,10 +2,60 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <lkmc.h>
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_EQ_DEFINE(bits) \
|
||||||
|
LKMC_ASSERT_EQ_DECLARE(bits) \
|
||||||
|
{ \
|
||||||
|
if (val1 != val2) { \
|
||||||
|
printf("%s failed\n", __func__); \
|
||||||
|
printf("val1 0x%" PRIX ## bits "\n", val1); \
|
||||||
|
printf("val2 0x%" PRIX ## bits "\n", val2); \
|
||||||
|
lkmc_assert_fail(line); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
LKMC_ASSERT_EQ_DEFINE(32)
|
||||||
|
LKMC_ASSERT_EQ_DEFINE(64)
|
||||||
|
#undef ASSERT_EQ_DEFINE
|
||||||
|
|
||||||
|
void lkmc_assert_fail(uint32_t line) {
|
||||||
|
printf("error: assertion failed at line: %" PRIu32 "\n", line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lkmc_assert_memcmp(
|
||||||
|
const void *s1,
|
||||||
|
const void *s2,
|
||||||
|
size_t n,
|
||||||
|
uint32_t line
|
||||||
|
) {
|
||||||
|
size_t i;
|
||||||
|
uint8_t *s1b, *s2b;
|
||||||
|
uint8_t b1, b2;
|
||||||
|
|
||||||
|
s1b = (uint8_t *)s1;
|
||||||
|
s2b = (uint8_t *)s2;
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
b1 = s1b[i];
|
||||||
|
b2 = s2b[i];
|
||||||
|
if (b1 != b2) {
|
||||||
|
printf(
|
||||||
|
"%s failed: "
|
||||||
|
"byte1, byte2, index: "
|
||||||
|
"0x%02" PRIX8 " 0x%02" PRIX8 " 0x%zX\n",
|
||||||
|
__func__,
|
||||||
|
b1,
|
||||||
|
b2,
|
||||||
|
i
|
||||||
|
);
|
||||||
|
lkmc_assert_fail(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void lkmc_baremetal_on_exit_callback(int status, void *arg) {
|
void lkmc_baremetal_on_exit_callback(int status, void *arg) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
|
|||||||
267
lkmc.h
267
lkmc.h
@@ -3,17 +3,33 @@
|
|||||||
#ifndef LKMC_H
|
#ifndef LKMC_H
|
||||||
#define LKMC_H
|
#define LKMC_H
|
||||||
|
|
||||||
/* Common C definitions. */
|
|
||||||
#define LKMC_UNUSED(x) (void)x
|
|
||||||
|
|
||||||
#if !defined(__ASSEMBLER__)
|
#if !defined(__ASSEMBLER__)
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_EQ_DECLARE(bits) \
|
||||||
|
void lkmc_assert_eq_ ## bits( \
|
||||||
|
uint ## bits ## _t val1, \
|
||||||
|
uint ## bits ## _t val2, \
|
||||||
|
uint32_t line \
|
||||||
|
)
|
||||||
|
LKMC_ASSERT_EQ_DECLARE(32);
|
||||||
|
LKMC_ASSERT_EQ_DECLARE(64);
|
||||||
|
void lkmc_assert_fail(uint32_t line);
|
||||||
|
void lkmc_assert_memcmp(const void *s1, const void *s2, size_t n, uint32_t line);
|
||||||
void lkmc_baremetal_on_exit_callback(int status, void *arg);
|
void lkmc_baremetal_on_exit_callback(int status, void *arg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Assert that the given branch instruction is taken. */
|
||||||
|
#define LKMC_ASSERT(branch_if_pass) \
|
||||||
|
branch_if_pass 1f; \
|
||||||
|
LKMC_ASSERT_FAIL; \
|
||||||
|
1: \
|
||||||
|
;
|
||||||
|
|
||||||
/* https://stackoverflow.com/questions/1489932/how-to-concatenate-twice-with-the-c-preprocessor-and-expand-a-macro-as-in-arg */
|
/* https://stackoverflow.com/questions/1489932/how-to-concatenate-twice-with-the-c-preprocessor-and-expand-a-macro-as-in-arg */
|
||||||
#define LKMC_CONCAT_EVAL(a,b) a ## b
|
#define LKMC_CONCAT_EVAL(a,b) a ## b
|
||||||
#define LKMC_CONCAT(a,b) LKMC_CONCAT_EVAL(a, b)
|
#define LKMC_CONCAT(a,b) LKMC_CONCAT_EVAL(a, b)
|
||||||
@@ -22,6 +38,9 @@ void lkmc_baremetal_on_exit_callback(int status, void *arg);
|
|||||||
.global name; \
|
.global name; \
|
||||||
name:
|
name:
|
||||||
|
|
||||||
|
/* Common C definitions. */
|
||||||
|
#define LKMC_UNUSED(x) (void)x
|
||||||
|
|
||||||
/* Weak means that if any other file defines it as a non-weak global,
|
/* Weak means that if any other file defines it as a non-weak global,
|
||||||
* that one will take precedence:
|
* that one will take precedence:
|
||||||
* https://stackoverflow.com/questions/274753/how-to-make-weak-linking-work-with-gcc/54601464#54601464
|
* https://stackoverflow.com/questions/274753/how-to-make-weak-linking-work-with-gcc/54601464#54601464
|
||||||
@@ -30,238 +49,14 @@ void lkmc_baremetal_on_exit_callback(int status, void *arg);
|
|||||||
.weak name; \
|
.weak name; \
|
||||||
name:
|
name:
|
||||||
|
|
||||||
/* aarch64 specifics. */
|
#if defined(__x86_64__)
|
||||||
#if defined(__aarch64__)
|
#include <lkmc/x86_64.h>
|
||||||
|
#elif defined(__arm__)
|
||||||
/* LKMC_VECTOR_TABLE
|
#include <lkmc/arm.h>
|
||||||
*
|
#elif defined(__aarch64__)
|
||||||
* Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S
|
#include <lkmc/aarch64.h>
|
||||||
*/
|
#else
|
||||||
|
#error
|
||||||
#define LKMC_VECTOR_SYNC_SP0 (0x1)
|
#endif
|
||||||
#define LKMC_VECTOR_IRQ_SP0 (0x2)
|
|
||||||
#define LKMC_VECTOR_FIQ_SP0 (0x3)
|
|
||||||
#define LKMC_VECTOR_SERR_SP0 (0x4)
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_SYNC_SPX (0x11)
|
|
||||||
#define LKMC_VECTOR_IRQ_SPX (0x12)
|
|
||||||
#define LKMC_VECTOR_FIQ_SPX (0x13)
|
|
||||||
#define LKMC_VECTOR_SERR_SPX (0x14)
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_SYNC_AARCH64 (0x21)
|
|
||||||
#define LKMC_VECTOR_IRQ_AARCH64 (0x22)
|
|
||||||
#define LKMC_VECTOR_FIQ_AARCH64 (0x23)
|
|
||||||
#define LKMC_VECTOR_SERR_AARCH64 (0x24)
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_SYNC_AARCH32 (0x31)
|
|
||||||
#define LKMC_VECTOR_IRQ_AARCH32 (0x32)
|
|
||||||
#define LKMC_VECTOR_FIQ_AARCH32 (0x33)
|
|
||||||
#define LKMC_VECTOR_SERR_AARCH32 (0x34)
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */
|
|
||||||
#define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */
|
|
||||||
#define LKMC_VECTOR_EXC_EXC_ESR_OFFSE (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */
|
|
||||||
#define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */
|
|
||||||
#define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */
|
|
||||||
#define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_FUNC_ALIGN .align 2
|
|
||||||
#define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \
|
|
||||||
stp x29, x30, [sp, -16]!; \
|
|
||||||
stp x27, x28, [sp, -16]!; \
|
|
||||||
stp x25, x26, [sp, -16]!; \
|
|
||||||
stp x23, x24, [sp, -16]!; \
|
|
||||||
stp x21, x22, [sp, -16]!; \
|
|
||||||
stp x19, x20, [sp, -16]!; \
|
|
||||||
stp x17, x18, [sp, -16]!; \
|
|
||||||
stp x15, x16, [sp, -16]!; \
|
|
||||||
stp x13, x14, [sp, -16]!; \
|
|
||||||
stp x11, x12, [sp, -16]!; \
|
|
||||||
stp x9, x10, [sp, -16]!; \
|
|
||||||
stp x7, x8, [sp, -16]!; \
|
|
||||||
stp x5, x6, [sp, -16]!; \
|
|
||||||
stp x3, x4, [sp, -16]!; \
|
|
||||||
stp x1, x2, [sp, -16]!; \
|
|
||||||
mrs x21, spsr_el1; \
|
|
||||||
stp x21, x0, [sp, -16]!; \
|
|
||||||
mrs x21, elr_el1; \
|
|
||||||
stp xzr, x21, [sp, -16]!; \
|
|
||||||
mov x21, exc_type; \
|
|
||||||
mrs x22, esr_el1; \
|
|
||||||
stp x21, x22, [sp, -16]!
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_STORE_TRAPED_SP \
|
|
||||||
mrs x21, sp_el0; \
|
|
||||||
str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_CALL_TRAP_HANDLER \
|
|
||||||
mov x0, sp; \
|
|
||||||
bl lkmc_vector_trap_handler
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_STORE_NESTED_SP \
|
|
||||||
mov x21, sp; \
|
|
||||||
add x21, x21, LKMC_VECTOR_EXC_FRAME_SIZE; \
|
|
||||||
str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_RESTORE_TRAPED_SP \
|
|
||||||
ldr x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]; \
|
|
||||||
msr sp_el0, x21
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_RESTORE_TRAPFRAME \
|
|
||||||
add sp, sp, 16; \
|
|
||||||
ldp x21, x22, [sp], 16; \
|
|
||||||
msr elr_el1, x22; \
|
|
||||||
ldp x21, x0, [sp], 16; \
|
|
||||||
msr spsr_el1, x21; \
|
|
||||||
ldp x1, x2, [sp], 16; \
|
|
||||||
ldp x3, x4, [sp], 16; \
|
|
||||||
ldp x5, x6, [sp], 16; \
|
|
||||||
ldp x7, x8, [sp], 16; \
|
|
||||||
ldp x9, x10, [sp], 16; \
|
|
||||||
ldp x11, x12, [sp], 16; \
|
|
||||||
ldp x13, x14, [sp], 16; \
|
|
||||||
ldp x15, x16, [sp], 16; \
|
|
||||||
ldp x17, x18, [sp], 16; \
|
|
||||||
ldp x19, x20, [sp], 16; \
|
|
||||||
ldp x21, x22, [sp], 16; \
|
|
||||||
ldp x23, x24, [sp], 16; \
|
|
||||||
ldp x25, x26, [sp], 16; \
|
|
||||||
ldp x27, x28, [sp], 16; \
|
|
||||||
ldp x29, x30, [sp], 16; \
|
|
||||||
eret
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_ENTRY(func_name) \
|
|
||||||
.align 7; \
|
|
||||||
b LKMC_VECTOR_SYMBOL_PREFIX ## func_name
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_FUNC(func_name, func_id) \
|
|
||||||
LKMC_VECTOR_FUNC_ALIGN; \
|
|
||||||
LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \
|
|
||||||
LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \
|
|
||||||
LKMC_VECTOR_STORE_TRAPED_SP; \
|
|
||||||
LKMC_VECTOR_CALL_TRAP_HANDLER; \
|
|
||||||
LKMC_VECTOR_RESTORE_TRAPED_SP; \
|
|
||||||
LKMC_VECTOR_RESTORE_TRAPFRAME
|
|
||||||
|
|
||||||
#define LKMC_VECTOR_FUNC_NESTED(func_name, func_id) \
|
|
||||||
LKMC_VECTOR_FUNC_ALIGN; \
|
|
||||||
LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \
|
|
||||||
LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \
|
|
||||||
LKMC_VECTOR_STORE_NESTED_SP; \
|
|
||||||
LKMC_VECTOR_CALL_TRAP_HANDLER; \
|
|
||||||
LKMC_VECTOR_RESTORE_TRAPFRAME
|
|
||||||
|
|
||||||
/* Define the actual vector table. */
|
|
||||||
#define LKMC_VECTOR_TABLE \
|
|
||||||
.align 11; \
|
|
||||||
LKMC_GLOBAL(lkmc_vector_table); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_sp0_sync); \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_sp0_irq); \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_sp0_fiq); \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_sp0_serror); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_spx_sync); \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_spx_irq); \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_spx_fiq); \
|
|
||||||
LKMC_VECTOR_ENTRY(curr_el_spx_serror); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch64_sync); \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch64_irq); \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch64_fiq); \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch64_serror); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch32_sync); \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch32_irq); \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch32_fiq); \
|
|
||||||
LKMC_VECTOR_ENTRY(lower_el_aarch32_serror); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_FUNC(curr_el_sp0_sync, LKMC_VECTOR_SYNC_SP0); \
|
|
||||||
LKMC_VECTOR_FUNC(curr_el_sp0_irq, LKMC_VECTOR_IRQ_SP0); \
|
|
||||||
LKMC_VECTOR_FUNC(curr_el_sp0_fiq, LKMC_VECTOR_FIQ_SP0); \
|
|
||||||
LKMC_VECTOR_FUNC(curr_el_sp0_serror, LKMC_VECTOR_SERR_SP0); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_sync, LKMC_VECTOR_SYNC_SPX); \
|
|
||||||
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_irq, LKMC_VECTOR_IRQ_SPX); \
|
|
||||||
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_fiq, LKMC_VECTOR_FIQ_SPX); \
|
|
||||||
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_serror, LKMC_VECTOR_SERR_SPX); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch64_sync, LKMC_VECTOR_SYNC_AARCH64); \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch64_irq, LKMC_VECTOR_IRQ_AARCH64); \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch64_fiq, LKMC_VECTOR_FIQ_AARCH64); \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch64_serror, LKMC_VECTOR_SERR_AARCH64); \
|
|
||||||
; \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch32_sync, LKMC_VECTOR_SYNC_AARCH32); \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch32_irq, LKMC_VECTOR_IRQ_AARCH32); \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch32_fiq, LKMC_VECTOR_FIQ_AARCH32); \
|
|
||||||
LKMC_VECTOR_FUNC(lower_el_aarch32_serror, LKMC_VECTOR_SERR_AARCH32)
|
|
||||||
|
|
||||||
/* aarch64 C definitions. */
|
|
||||||
#if !defined(__ASSEMBLER__)
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t exc_type;
|
|
||||||
uint64_t exc_esr;
|
|
||||||
uint64_t exc_sp;
|
|
||||||
uint64_t exc_elr;
|
|
||||||
uint64_t exc_spsr;
|
|
||||||
uint64_t x0;
|
|
||||||
uint64_t x1;
|
|
||||||
uint64_t x2;
|
|
||||||
uint64_t x3;
|
|
||||||
uint64_t x4;
|
|
||||||
uint64_t x5;
|
|
||||||
uint64_t x6;
|
|
||||||
uint64_t x7;
|
|
||||||
uint64_t x8;
|
|
||||||
uint64_t x9;
|
|
||||||
uint64_t x10;
|
|
||||||
uint64_t x11;
|
|
||||||
uint64_t x12;
|
|
||||||
uint64_t x13;
|
|
||||||
uint64_t x14;
|
|
||||||
uint64_t x15;
|
|
||||||
uint64_t x16;
|
|
||||||
uint64_t x17;
|
|
||||||
uint64_t x18;
|
|
||||||
uint64_t x19;
|
|
||||||
uint64_t x20;
|
|
||||||
uint64_t x21;
|
|
||||||
uint64_t x22;
|
|
||||||
uint64_t x23;
|
|
||||||
uint64_t x24;
|
|
||||||
uint64_t x25;
|
|
||||||
uint64_t x26;
|
|
||||||
uint64_t x27;
|
|
||||||
uint64_t x28;
|
|
||||||
uint64_t x29;
|
|
||||||
uint64_t x30;
|
|
||||||
} LkmcVectorExceptionFrame;
|
|
||||||
|
|
||||||
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception);
|
|
||||||
|
|
||||||
#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : )
|
|
||||||
|
|
||||||
#define LKMC_SYSREG_SYMBOL_PREFIX lkmc_sysreg_
|
|
||||||
#define LKMC_SYSREG_READ_WRITE(type, name) \
|
|
||||||
type LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read)(void); \
|
|
||||||
void LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write)(type name);
|
|
||||||
#define LKMC_SYSREG_OPS \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint32_t, daif) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint32_t, spsel) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint64_t, cntfrq_el0) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint64_t, cntv_cval_el0) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint64_t, cntv_tval_el0) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint64_t, cntvct_el0) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint64_t, sp_el1) \
|
|
||||||
LKMC_SYSREG_READ_WRITE(uint64_t, vbar_el1)
|
|
||||||
LKMC_SYSREG_OPS
|
|
||||||
#undef LKMC_SYSREG_READ_WRITE
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|||||||
299
lkmc/aarch64.h
Normal file
299
lkmc/aarch64.h
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
#ifndef LKMC_AARCH64_H
|
||||||
|
#define LKMC_AARCH64_H
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_EQ(reg, const) \
|
||||||
|
mov x0, reg; \
|
||||||
|
ldr x1, const; \
|
||||||
|
ldr w2, =__LINE__; \
|
||||||
|
bl lkmc_assert_eq_64; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_EQ_REG(reg1, reg2) \
|
||||||
|
str reg2, [sp, -16]!; \
|
||||||
|
mov x0, reg1; \
|
||||||
|
ldr x1, [sp], 16; \
|
||||||
|
ldr w2, =__LINE__; \
|
||||||
|
bl lkmc_assert_eq_64; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_EQ_REG_32(reg1, reg2) \
|
||||||
|
str reg2, [sp, -4]!; \
|
||||||
|
mov w0, reg1; \
|
||||||
|
ldr w1, [sp], 4; \
|
||||||
|
ldr w2, =__LINE__; \
|
||||||
|
bl lkmc_assert_eq_32; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_FAIL \
|
||||||
|
ldr w0, =__LINE__; \
|
||||||
|
bl lkmc_assert_fail; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_MEMCMP(label1, label2, size) \
|
||||||
|
adr x0, label1; \
|
||||||
|
adr x1, label2; \
|
||||||
|
ldr x2, size; \
|
||||||
|
ldr x3, =__LINE__; \
|
||||||
|
bl lkmc_assert_memcmp; \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */
|
||||||
|
#define LKMC_EPILOGUE \
|
||||||
|
ldp x19, x20, [sp, 0x50]; \
|
||||||
|
ldp x21, x22, [sp, 0x40]; \
|
||||||
|
ldp x23, x24, [sp, 0x30]; \
|
||||||
|
ldp x25, x26, [sp, 0x20]; \
|
||||||
|
ldp x27, x28, [sp, 0x10]; \
|
||||||
|
ldp x29, x30, [sp]; \
|
||||||
|
add sp, sp, 0x60; \
|
||||||
|
mov x0, 0; \
|
||||||
|
ret; \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */
|
||||||
|
#define LKMC_PROLOGUE \
|
||||||
|
.text; \
|
||||||
|
.global main; \
|
||||||
|
main: \
|
||||||
|
sub sp, sp, 0x60; \
|
||||||
|
stp x29, x30, [sp]; \
|
||||||
|
stp x27, x28, [sp, 0x10]; \
|
||||||
|
stp x25, x26, [sp, 0x20]; \
|
||||||
|
stp x23, x24, [sp, 0x30]; \
|
||||||
|
stp x21, x22, [sp, 0x40]; \
|
||||||
|
stp x19, x20, [sp, 0x50]; \
|
||||||
|
main_after_prologue: \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* LKMC_VECTOR_TABLE
|
||||||
|
*
|
||||||
|
* Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_SP0 (0x1)
|
||||||
|
#define LKMC_VECTOR_IRQ_SP0 (0x2)
|
||||||
|
#define LKMC_VECTOR_FIQ_SP0 (0x3)
|
||||||
|
#define LKMC_VECTOR_SERR_SP0 (0x4)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_SPX (0x11)
|
||||||
|
#define LKMC_VECTOR_IRQ_SPX (0x12)
|
||||||
|
#define LKMC_VECTOR_FIQ_SPX (0x13)
|
||||||
|
#define LKMC_VECTOR_SERR_SPX (0x14)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_AARCH64 (0x21)
|
||||||
|
#define LKMC_VECTOR_IRQ_AARCH64 (0x22)
|
||||||
|
#define LKMC_VECTOR_FIQ_AARCH64 (0x23)
|
||||||
|
#define LKMC_VECTOR_SERR_AARCH64 (0x24)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_SYNC_AARCH32 (0x31)
|
||||||
|
#define LKMC_VECTOR_IRQ_AARCH32 (0x32)
|
||||||
|
#define LKMC_VECTOR_FIQ_AARCH32 (0x33)
|
||||||
|
#define LKMC_VECTOR_SERR_AARCH32 (0x34)
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_ESR_OFFSE (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */
|
||||||
|
#define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_FUNC_ALIGN .align 2
|
||||||
|
#define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \
|
||||||
|
stp x29, x30, [sp, -16]!; \
|
||||||
|
stp x27, x28, [sp, -16]!; \
|
||||||
|
stp x25, x26, [sp, -16]!; \
|
||||||
|
stp x23, x24, [sp, -16]!; \
|
||||||
|
stp x21, x22, [sp, -16]!; \
|
||||||
|
stp x19, x20, [sp, -16]!; \
|
||||||
|
stp x17, x18, [sp, -16]!; \
|
||||||
|
stp x15, x16, [sp, -16]!; \
|
||||||
|
stp x13, x14, [sp, -16]!; \
|
||||||
|
stp x11, x12, [sp, -16]!; \
|
||||||
|
stp x9, x10, [sp, -16]!; \
|
||||||
|
stp x7, x8, [sp, -16]!; \
|
||||||
|
stp x5, x6, [sp, -16]!; \
|
||||||
|
stp x3, x4, [sp, -16]!; \
|
||||||
|
stp x1, x2, [sp, -16]!; \
|
||||||
|
mrs x21, spsr_el1; \
|
||||||
|
stp x21, x0, [sp, -16]!; \
|
||||||
|
mrs x21, elr_el1; \
|
||||||
|
stp xzr, x21, [sp, -16]!; \
|
||||||
|
mov x21, exc_type; \
|
||||||
|
mrs x22, esr_el1; \
|
||||||
|
stp x21, x22, [sp, -16]!
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_STORE_TRAPED_SP \
|
||||||
|
mrs x21, sp_el0; \
|
||||||
|
str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_CALL_TRAP_HANDLER \
|
||||||
|
mov x0, sp; \
|
||||||
|
bl lkmc_vector_trap_handler
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_STORE_NESTED_SP \
|
||||||
|
mov x21, sp; \
|
||||||
|
add x21, x21, LKMC_VECTOR_EXC_FRAME_SIZE; \
|
||||||
|
str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_RESTORE_TRAPED_SP \
|
||||||
|
ldr x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]; \
|
||||||
|
msr sp_el0, x21
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_RESTORE_TRAPFRAME \
|
||||||
|
add sp, sp, 16; \
|
||||||
|
ldp x21, x22, [sp], 16; \
|
||||||
|
msr elr_el1, x22; \
|
||||||
|
ldp x21, x0, [sp], 16; \
|
||||||
|
msr spsr_el1, x21; \
|
||||||
|
ldp x1, x2, [sp], 16; \
|
||||||
|
ldp x3, x4, [sp], 16; \
|
||||||
|
ldp x5, x6, [sp], 16; \
|
||||||
|
ldp x7, x8, [sp], 16; \
|
||||||
|
ldp x9, x10, [sp], 16; \
|
||||||
|
ldp x11, x12, [sp], 16; \
|
||||||
|
ldp x13, x14, [sp], 16; \
|
||||||
|
ldp x15, x16, [sp], 16; \
|
||||||
|
ldp x17, x18, [sp], 16; \
|
||||||
|
ldp x19, x20, [sp], 16; \
|
||||||
|
ldp x21, x22, [sp], 16; \
|
||||||
|
ldp x23, x24, [sp], 16; \
|
||||||
|
ldp x25, x26, [sp], 16; \
|
||||||
|
ldp x27, x28, [sp], 16; \
|
||||||
|
ldp x29, x30, [sp], 16; \
|
||||||
|
eret
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_ENTRY(func_name) \
|
||||||
|
.align 7; \
|
||||||
|
b LKMC_VECTOR_SYMBOL_PREFIX ## func_name
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_FUNC(func_name, func_id) \
|
||||||
|
LKMC_VECTOR_FUNC_ALIGN; \
|
||||||
|
LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \
|
||||||
|
LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \
|
||||||
|
LKMC_VECTOR_STORE_TRAPED_SP; \
|
||||||
|
LKMC_VECTOR_CALL_TRAP_HANDLER; \
|
||||||
|
LKMC_VECTOR_RESTORE_TRAPED_SP; \
|
||||||
|
LKMC_VECTOR_RESTORE_TRAPFRAME
|
||||||
|
|
||||||
|
#define LKMC_VECTOR_FUNC_NESTED(func_name, func_id) \
|
||||||
|
LKMC_VECTOR_FUNC_ALIGN; \
|
||||||
|
LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \
|
||||||
|
LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \
|
||||||
|
LKMC_VECTOR_STORE_NESTED_SP; \
|
||||||
|
LKMC_VECTOR_CALL_TRAP_HANDLER; \
|
||||||
|
LKMC_VECTOR_RESTORE_TRAPFRAME
|
||||||
|
|
||||||
|
/* Define the actual vector table. */
|
||||||
|
#define LKMC_VECTOR_TABLE \
|
||||||
|
.align 11; \
|
||||||
|
LKMC_GLOBAL(lkmc_vector_table); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_sp0_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(curr_el_spx_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch64_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_sync); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_irq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_fiq); \
|
||||||
|
LKMC_VECTOR_ENTRY(lower_el_aarch32_serror); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_sync, LKMC_VECTOR_SYNC_SP0); \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_irq, LKMC_VECTOR_IRQ_SP0); \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_fiq, LKMC_VECTOR_FIQ_SP0); \
|
||||||
|
LKMC_VECTOR_FUNC(curr_el_sp0_serror, LKMC_VECTOR_SERR_SP0); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_sync, LKMC_VECTOR_SYNC_SPX); \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_irq, LKMC_VECTOR_IRQ_SPX); \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_fiq, LKMC_VECTOR_FIQ_SPX); \
|
||||||
|
LKMC_VECTOR_FUNC_NESTED(curr_el_spx_serror, LKMC_VECTOR_SERR_SPX); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_sync, LKMC_VECTOR_SYNC_AARCH64); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_irq, LKMC_VECTOR_IRQ_AARCH64); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_fiq, LKMC_VECTOR_FIQ_AARCH64); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch64_serror, LKMC_VECTOR_SERR_AARCH64); \
|
||||||
|
; \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_sync, LKMC_VECTOR_SYNC_AARCH32); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_irq, LKMC_VECTOR_IRQ_AARCH32); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_fiq, LKMC_VECTOR_FIQ_AARCH32); \
|
||||||
|
LKMC_VECTOR_FUNC(lower_el_aarch32_serror, LKMC_VECTOR_SERR_AARCH32)
|
||||||
|
|
||||||
|
/* aarch64 C definitions. */
|
||||||
|
#if !defined(__ASSEMBLER__)
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t exc_type;
|
||||||
|
uint64_t exc_esr;
|
||||||
|
uint64_t exc_sp;
|
||||||
|
uint64_t exc_elr;
|
||||||
|
uint64_t exc_spsr;
|
||||||
|
uint64_t x0;
|
||||||
|
uint64_t x1;
|
||||||
|
uint64_t x2;
|
||||||
|
uint64_t x3;
|
||||||
|
uint64_t x4;
|
||||||
|
uint64_t x5;
|
||||||
|
uint64_t x6;
|
||||||
|
uint64_t x7;
|
||||||
|
uint64_t x8;
|
||||||
|
uint64_t x9;
|
||||||
|
uint64_t x10;
|
||||||
|
uint64_t x11;
|
||||||
|
uint64_t x12;
|
||||||
|
uint64_t x13;
|
||||||
|
uint64_t x14;
|
||||||
|
uint64_t x15;
|
||||||
|
uint64_t x16;
|
||||||
|
uint64_t x17;
|
||||||
|
uint64_t x18;
|
||||||
|
uint64_t x19;
|
||||||
|
uint64_t x20;
|
||||||
|
uint64_t x21;
|
||||||
|
uint64_t x22;
|
||||||
|
uint64_t x23;
|
||||||
|
uint64_t x24;
|
||||||
|
uint64_t x25;
|
||||||
|
uint64_t x26;
|
||||||
|
uint64_t x27;
|
||||||
|
uint64_t x28;
|
||||||
|
uint64_t x29;
|
||||||
|
uint64_t x30;
|
||||||
|
} LkmcVectorExceptionFrame;
|
||||||
|
|
||||||
|
void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception);
|
||||||
|
|
||||||
|
#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : )
|
||||||
|
|
||||||
|
#define LKMC_SYSREG_SYMBOL_PREFIX lkmc_sysreg_
|
||||||
|
#define LKMC_SYSREG_READ_WRITE(type, name) \
|
||||||
|
type LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read)(void); \
|
||||||
|
void LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write)(type name);
|
||||||
|
#define LKMC_SYSREG_OPS \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint32_t, daif) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint32_t, spsel) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntfrq_el0) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntv_cval_el0) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntv_tval_el0) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, cntvct_el0) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, sp_el1) \
|
||||||
|
LKMC_SYSREG_READ_WRITE(uint64_t, vbar_el1)
|
||||||
|
LKMC_SYSREG_OPS
|
||||||
|
#undef LKMC_SYSREG_READ_WRITE
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
53
lkmc/arm.h
Normal file
53
lkmc/arm.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef LKMC_ARM_H
|
||||||
|
#define LKMC_ARM_H
|
||||||
|
|
||||||
|
#if defined(__ASSEMBLER__)
|
||||||
|
.syntax unified
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_EQ(reg, const) \
|
||||||
|
mov r0, reg; \
|
||||||
|
ldr r1, const; \
|
||||||
|
ldr r2, =__LINE__; \
|
||||||
|
bl lkmc_assert_eq_32; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_EQ_REG(reg1, reg2) \
|
||||||
|
str reg2, [sp, -4]!; \
|
||||||
|
mov r0, reg1; \
|
||||||
|
ldr r1, [sp], 4; \
|
||||||
|
ldr r2, =__LINE__; \
|
||||||
|
bl lkmc_assert_eq_32; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_FAIL \
|
||||||
|
ldr r0, =__LINE__; \
|
||||||
|
bl lkmc_assert_fail; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_MEMCMP(label1, label2, size) \
|
||||||
|
ldr r0, =label1; \
|
||||||
|
ldr r1, =label2; \
|
||||||
|
ldr r2, size; \
|
||||||
|
ldr r3, =__LINE__; \
|
||||||
|
bl lkmc_assert_memcmp; \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */
|
||||||
|
#define LKMC_EPILOGUE \
|
||||||
|
add sp, 16; \
|
||||||
|
ldmia sp!, {r4-r12, lr}; \
|
||||||
|
mov r0, 0; \
|
||||||
|
bx lr; \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */
|
||||||
|
#define LKMC_PROLOGUE \
|
||||||
|
.text; \
|
||||||
|
.global main; \
|
||||||
|
main: \
|
||||||
|
stmdb sp!, {r0-r12, lr}; \
|
||||||
|
main_after_prologue: \
|
||||||
|
;
|
||||||
|
|
||||||
|
#endif
|
||||||
62
lkmc/x86_64.h
Normal file
62
lkmc/x86_64.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef LKMC_X86_64_H
|
||||||
|
#define LKMC_X86_64_H
|
||||||
|
|
||||||
|
/* This and other macros may make C function calls, and therefore can destroy
|
||||||
|
* non-callee saved registers. */
|
||||||
|
#define LKMC_ASSERT_EQ(general1, general2) \
|
||||||
|
mov general2, %rdi; \
|
||||||
|
push %rdi; \
|
||||||
|
mov general1, %rdi; \
|
||||||
|
pop %rsi; \
|
||||||
|
mov $__LINE__, %edx; \
|
||||||
|
call lkmc_assert_eq_64; \
|
||||||
|
;
|
||||||
|
|
||||||
|
#define LKMC_ASSERT_FAIL \
|
||||||
|
mov $__LINE__, %edi; \
|
||||||
|
call lkmc_assert_fail; \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Assert that two memory arrays are the same. */
|
||||||
|
#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
|
||||||
|
lea label1(%rip), %rdi; \
|
||||||
|
lea label2(%rip), %rsi; \
|
||||||
|
mov const_size, %rdx; \
|
||||||
|
mov $__LINE__, %ecx; \
|
||||||
|
call lkmc_assert_memcmp; \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Function epilogue.
|
||||||
|
*
|
||||||
|
* https://github.com/cirosantilli/linux-kernel-module-cheat#x86_64-calling-convention
|
||||||
|
*/
|
||||||
|
#define LKMC_EPILOGUE \
|
||||||
|
pop %rbx; \
|
||||||
|
pop %r12; \
|
||||||
|
pop %r13; \
|
||||||
|
pop %r14; \
|
||||||
|
pop %r15; \
|
||||||
|
pop %rbp; \
|
||||||
|
mov $0, %rax; \
|
||||||
|
ret; \
|
||||||
|
;
|
||||||
|
|
||||||
|
/* Function prologue.
|
||||||
|
*
|
||||||
|
* https://github.com/cirosantilli/linux-kernel-module-cheat#x86_64-calling-convention
|
||||||
|
*/
|
||||||
|
#define LKMC_PROLOGUE \
|
||||||
|
.text; \
|
||||||
|
.global main; \
|
||||||
|
main: \
|
||||||
|
push %rbp; \
|
||||||
|
mov %rsp, %rbp; \
|
||||||
|
push %r15; \
|
||||||
|
push %r14; \
|
||||||
|
push %r13; \
|
||||||
|
push %r12; \
|
||||||
|
push %rbx; \
|
||||||
|
main_after_prologue: \
|
||||||
|
;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -36,7 +36,6 @@ class PathProperties:
|
|||||||
'extra_objs_baremetal_bootloader': False,
|
'extra_objs_baremetal_bootloader': False,
|
||||||
# We should get rid of this if we ever properly implement dependency graphs.
|
# We should get rid of this if we ever properly implement dependency graphs.
|
||||||
'extra_objs_lkmc_common': False,
|
'extra_objs_lkmc_common': False,
|
||||||
'extra_objs_userland_asm': False,
|
|
||||||
'interactive': False,
|
'interactive': False,
|
||||||
# The script takes a perceptible amount of time to run. Possibly an infinite loop.
|
# The script takes a perceptible amount of time to run. Possibly an infinite loop.
|
||||||
'more_than_1s': False,
|
'more_than_1s': False,
|
||||||
@@ -209,7 +208,7 @@ freestanding_properties = {
|
|||||||
'-nostdlib', LF,
|
'-nostdlib', LF,
|
||||||
'-static', LF,
|
'-static', LF,
|
||||||
],
|
],
|
||||||
'extra_objs_userland_asm': False,
|
'extra_objs_lkmc_common': False,
|
||||||
}
|
}
|
||||||
# See: https://github.com/cirosantilli/linux-kernel-module-cheat#path-properties
|
# See: https://github.com/cirosantilli/linux-kernel-module-cheat#path-properties
|
||||||
path_properties_tuples = (
|
path_properties_tuples = (
|
||||||
@@ -284,7 +283,7 @@ path_properties_tuples = (
|
|||||||
{
|
{
|
||||||
'arch': (
|
'arch': (
|
||||||
{
|
{
|
||||||
'extra_objs_userland_asm': True,
|
'extra_objs_lkmc_common': True,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'arm': (
|
'arm': (
|
||||||
@@ -311,13 +310,14 @@ path_properties_tuples = (
|
|||||||
{
|
{
|
||||||
'c': (
|
'c': (
|
||||||
{
|
{
|
||||||
'extra_objs_userland_asm': False,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
|
'lkmc_assert_eq_fail.S': {'exit_status': 1},
|
||||||
|
'lkmc_assert_memcmp_fail.S': {'exit_status': 1},
|
||||||
'udf.S': {
|
'udf.S': {
|
||||||
'exit_status': 132,
|
'exit_status': 132,
|
||||||
'receives_signal': True
|
'receives_signal': True
|
||||||
@@ -329,13 +329,14 @@ path_properties_tuples = (
|
|||||||
{
|
{
|
||||||
'c': (
|
'c': (
|
||||||
{
|
{
|
||||||
'extra_objs_userland_asm': False,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
|
'lkmc_assert_eq_fail.S': {'exit_status': 1},
|
||||||
|
'lkmc_assert_memcmp_fail.S': {'exit_status': 1},
|
||||||
'udf.S': {
|
'udf.S': {
|
||||||
'exit_status': 132,
|
'exit_status': 132,
|
||||||
'receives_signal': True
|
'receives_signal': True
|
||||||
@@ -343,16 +344,11 @@ path_properties_tuples = (
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
'fail.S': {'exit_status': 1},
|
'fail.S': {'exit_status': 1},
|
||||||
'main.c': {
|
|
||||||
'extra_objs_userland_asm': False,
|
|
||||||
'no_executable': True
|
|
||||||
},
|
|
||||||
'x86_64': (
|
'x86_64': (
|
||||||
{'allowed_archs': {'x86_64'}},
|
{'allowed_archs': {'x86_64'}},
|
||||||
{
|
{
|
||||||
'c': (
|
'c': (
|
||||||
{
|
{
|
||||||
'extra_objs_userland_asm': False,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'freestanding': freestanding_properties,
|
'freestanding': freestanding_properties,
|
||||||
@@ -383,11 +379,6 @@ path_properties_tuples = (
|
|||||||
),
|
),
|
||||||
'gcc': gnu_extension_properties,
|
'gcc': gnu_extension_properties,
|
||||||
'kernel_modules': {**gnu_extension_properties, **{'requires_kernel_modules': True}},
|
'kernel_modules': {**gnu_extension_properties, **{'requires_kernel_modules': True}},
|
||||||
'lkmc': (
|
|
||||||
{'extra_objs_lkmc_common': True},
|
|
||||||
{
|
|
||||||
}
|
|
||||||
),
|
|
||||||
'libs': (
|
'libs': (
|
||||||
{'requires_dynamic_library': True},
|
{'requires_dynamic_library': True},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
mov x0, 1
|
mov x0, 1
|
||||||
add x1, x0, 2
|
add x1, x0, 2
|
||||||
LKMC_ASSERT_EQ(x1, 3)
|
LKMC_ASSERT_EQ(x1, =3)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Add a bunch of integers in one go.
|
* Add a bunch of integers in one go.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
.data
|
.data
|
||||||
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
|
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
|
||||||
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
|
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
|
||||||
@@ -22,11 +22,11 @@ LKMC_ENTRY
|
|||||||
add v2. ## size, v0. ## size, v1. ## size; \
|
add v2. ## size, v0. ## size, v1. ## size; \
|
||||||
adr x0, output; \
|
adr x0, output; \
|
||||||
st1 {v2. ## size}, [x0]; \
|
st1 {v2. ## size}, [x0]; \
|
||||||
LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10)
|
LKMC_ASSERT_MEMCMP(output, expect_ ## size, =0x10)
|
||||||
|
|
||||||
/* 4x 32-bit */
|
/* 4x 32-bit */
|
||||||
TEST(4s)
|
TEST(4s)
|
||||||
/* 2x 64-bit */
|
/* 2x 64-bit */
|
||||||
TEST(2d)
|
TEST(2d)
|
||||||
#undef TEST
|
#undef TEST
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
.data
|
.data
|
||||||
data_label:
|
data_label:
|
||||||
.word 0x1234678
|
.word 0x1234678
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* This is not possible in v7 because the label is in another section.
|
/* This is not possible in v7 because the label is in another section.
|
||||||
* objdump says that this generates a R_AARCH64_ADR_PRE relocation.
|
* objdump says that this generates a R_AARCH64_ADR_PRE relocation.
|
||||||
* which looks specific to ADR, and therefore makes it more likely
|
* which looks specific to ADR, and therefore makes it more likely
|
||||||
@@ -18,4 +18,4 @@ LKMC_ENTRY
|
|||||||
ldr x1, =data_label
|
ldr x1, =data_label
|
||||||
label:
|
label:
|
||||||
LKMC_ASSERT_EQ_REG(x0, x1)
|
LKMC_ASSERT_EQ_REG(x0, x1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
adrp x0, label
|
adrp x0, label
|
||||||
adr x1, label
|
adr x1, label
|
||||||
label:
|
label:
|
||||||
@@ -10,4 +10,4 @@ label:
|
|||||||
bic x1, x1, 0xFF
|
bic x1, x1, 0xFF
|
||||||
bic x1, x1, 0xF00
|
bic x1, x1, 0xF00
|
||||||
LKMC_ASSERT_EQ_REG(x0, x1)
|
LKMC_ASSERT_EQ_REG(x0, x1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* cbz == 0 */
|
/* cbz == 0 */
|
||||||
mov x0, 0
|
mov x0, 0
|
||||||
cbz x0, 1f
|
cbz x0, 1f
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
1:
|
1:
|
||||||
|
|
||||||
/* cbz != 0 */
|
/* cbz != 0 */
|
||||||
@@ -14,13 +14,13 @@ LKMC_ENTRY
|
|||||||
cbz x0, 1f
|
cbz x0, 1f
|
||||||
b 2f
|
b 2f
|
||||||
1:
|
1:
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
2:
|
2:
|
||||||
|
|
||||||
/* cbnz != 0 */
|
/* cbnz != 0 */
|
||||||
mov x0, 1
|
mov x0, 1
|
||||||
cbnz x0, 1f
|
cbnz x0, 1f
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
1:
|
1:
|
||||||
|
|
||||||
/* cbnz == 0 */
|
/* cbnz == 0 */
|
||||||
@@ -28,6 +28,6 @@ LKMC_ENTRY
|
|||||||
cbnz x0, 1f
|
cbnz x0, 1f
|
||||||
b 2f
|
b 2f
|
||||||
1:
|
1:
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
2:
|
2:
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr x0, =0x1122334455667788
|
ldr x0, =0x1122334455667788
|
||||||
|
|
||||||
ldr x1, =0xFFFFFFFFFFFFFFFF
|
ldr x1, =0xFFFFFFFFFFFFFFFF
|
||||||
bfi x1, x0, 16, 32
|
bfi x1, x0, 16, 32
|
||||||
LKMC_ASSERT_EQ(x1, 0xFFFF55667788FFFF)
|
LKMC_ASSERT_EQ(x1, =0xFFFF55667788FFFF)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cbz-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cbz-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Branch. */
|
/* Branch. */
|
||||||
mov x0, 0x0
|
mov x0, 0x0
|
||||||
cbz x0, ok
|
cbz x0, ok
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
ok:
|
ok:
|
||||||
|
|
||||||
/* Don't branch. */
|
/* Don't branch. */
|
||||||
mov x0, 0x1
|
mov x0, 0x1
|
||||||
cbz x0, ko
|
cbz x0, ko
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
ko:
|
ko:
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
# mycomment
|
# mycomment
|
||||||
|
|
||||||
/* ARMv8 has // instead of @ as for comments. */
|
/* ARMv8 has // instead of @ as for comments. */
|
||||||
@@ -14,4 +14,4 @@ LKMC_ENTRY
|
|||||||
@ mycomment
|
@ mycomment
|
||||||
nop @ mycomment
|
nop @ mycomment
|
||||||
#endif
|
#endif
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */
|
|
||||||
|
|
||||||
#ifndef COMMON_ARCH_H
|
|
||||||
#define COMMON_ARCH_H
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_EQ(reg, const) \
|
|
||||||
mov x0, reg; \
|
|
||||||
ldr x1, =const; \
|
|
||||||
LKMC_ASSERT_EQ_DO(64); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_EQ_DO(bits) \
|
|
||||||
bl lkmc_assert_eq_ ## bits; \
|
|
||||||
cmp x0, 0; \
|
|
||||||
LKMC_ASSERT(beq); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_EQ_REG(reg1, reg2) \
|
|
||||||
str reg2, [sp, -16]!; \
|
|
||||||
mov x0, reg1; \
|
|
||||||
ldr x1, [sp], 16; \
|
|
||||||
LKMC_ASSERT_EQ_DO(64); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_EQ_REG_32(reg1, reg2) \
|
|
||||||
str reg2, [sp, -4]!; \
|
|
||||||
mov w0, reg1; \
|
|
||||||
ldr w1, [sp], 4; \
|
|
||||||
LKMC_ASSERT_EQ_DO(32); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
|
|
||||||
adr x0, label1; \
|
|
||||||
adr x1, label2; \
|
|
||||||
ldr x2, =const_size; \
|
|
||||||
bl lkmc_assert_memcmp; \
|
|
||||||
cmp x0, 0; \
|
|
||||||
LKMC_ASSERT(beq); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ENTRY \
|
|
||||||
.text; \
|
|
||||||
.global asm_main; \
|
|
||||||
asm_main: \
|
|
||||||
sub sp, sp, 0xA0; \
|
|
||||||
stp x29, x30, [sp]; \
|
|
||||||
stp x27, x28, [sp, 0x10]; \
|
|
||||||
stp x25, x26, [sp, 0x20]; \
|
|
||||||
stp x23, x24, [sp, 0x30]; \
|
|
||||||
stp x21, x22, [sp, 0x40]; \
|
|
||||||
stp x19, x20, [sp, 0x50]; \
|
|
||||||
stp x6, x7, [sp, 0x60]; \
|
|
||||||
stp x4, x5, [sp, 0x70]; \
|
|
||||||
stp x2, x3, [sp, 0x80]; \
|
|
||||||
stp x0, x1, [sp, 0x90]; \
|
|
||||||
asm_main_after_prologue: \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_EXIT \
|
|
||||||
mov w0, 0; \
|
|
||||||
mov w1, 0; \
|
|
||||||
b pass; \
|
|
||||||
fail: \
|
|
||||||
ldr x1, [sp, 0x90]; \
|
|
||||||
str w0, [x1]; \
|
|
||||||
mov w0, 1; \
|
|
||||||
pass: \
|
|
||||||
ldp x19, x20, [sp, 0x50]; \
|
|
||||||
ldp x21, x22, [sp, 0x40]; \
|
|
||||||
ldp x23, x24, [sp, 0x30]; \
|
|
||||||
ldp x25, x26, [sp, 0x20]; \
|
|
||||||
ldp x27, x28, [sp, 0x10]; \
|
|
||||||
ldp x29, x30, [sp]; \
|
|
||||||
add sp, sp, 0xA0; \
|
|
||||||
ret; \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_FAIL \
|
|
||||||
ldr w0, =__LINE__; \
|
|
||||||
b fail; \
|
|
||||||
;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cset-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cset-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* Test values. */
|
/* Test values. */
|
||||||
mov x19, 0
|
mov x19, 0
|
||||||
mov x20, 1
|
mov x20, 1
|
||||||
@@ -10,19 +10,19 @@ LKMC_ENTRY
|
|||||||
/* eq is true, set x21 = 1. */
|
/* eq is true, set x21 = 1. */
|
||||||
cmp x19, x19
|
cmp x19, x19
|
||||||
cset x21, eq
|
cset x21, eq
|
||||||
LKMC_ASSERT_EQ(x21, 1)
|
LKMC_ASSERT_EQ(x21, =1)
|
||||||
|
|
||||||
/* eq is false, set x21 = 0. */
|
/* eq is false, set x21 = 0. */
|
||||||
cmp x19, x20
|
cmp x19, x20
|
||||||
cset x21, eq
|
cset x21, eq
|
||||||
LKMC_ASSERT_EQ(x21, 0)
|
LKMC_ASSERT_EQ(x21, =0)
|
||||||
|
|
||||||
/* Same for ne. */
|
/* Same for ne. */
|
||||||
cmp x19, x19
|
cmp x19, x19
|
||||||
cset x21, ne
|
cset x21, ne
|
||||||
LKMC_ASSERT_EQ(x21, 0)
|
LKMC_ASSERT_EQ(x21, =0)
|
||||||
|
|
||||||
cmp x19, x20
|
cmp x19, x20
|
||||||
cset x21, ne
|
cset x21, ne
|
||||||
LKMC_ASSERT_EQ(x21, 1)
|
LKMC_ASSERT_EQ(x21, =1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#advanced-simd-instructions */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#advanced-simd-instructions */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* 1.5 + 2.5 == 4.0
|
/* 1.5 + 2.5 == 4.0
|
||||||
* using 64-bit double immediates.
|
* using 64-bit double immediates.
|
||||||
*/
|
*/
|
||||||
@@ -57,4 +57,4 @@ my_double_sum_expect:
|
|||||||
#if 0
|
#if 0
|
||||||
fmov d0, 1.23456798
|
fmov d0, 1.23456798
|
||||||
#endif
|
#endif
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Add a bunch of floating point numbers in one go.
|
* Add a bunch of floating point numbers in one go.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
.data
|
.data
|
||||||
input0_4s: .float 1.5, 2.5, 3.5, 4.5
|
input0_4s: .float 1.5, 2.5, 3.5, 4.5
|
||||||
input1_4s: .float 5.5, 6.5, 7.5, 8.5
|
input1_4s: .float 5.5, 6.5, 7.5, 8.5
|
||||||
@@ -24,11 +24,11 @@ LKMC_ENTRY
|
|||||||
fadd v2. ## size, v0. ## size, v1. ## size; \
|
fadd v2. ## size, v0. ## size, v1. ## size; \
|
||||||
adr x0, output; \
|
adr x0, output; \
|
||||||
st1 {v2. ## size}, [x0]; \
|
st1 {v2. ## size}, [x0]; \
|
||||||
LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10)
|
LKMC_ASSERT_MEMCMP(output, expect_ ## size, =0x10)
|
||||||
|
|
||||||
/* 4x 32-bit */
|
/* 4x 32-bit */
|
||||||
TEST(4s)
|
TEST(4s)
|
||||||
/* 2x 64-bit */
|
/* 2x 64-bit */
|
||||||
TEST(2d)
|
TEST(2d)
|
||||||
#undef TEST
|
#undef TEST
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
#define ASSERT_DIFF(label1, label2, result) \
|
#define ASSERT_DIFF(label1, label2, result) \
|
||||||
adr x0, label1; \
|
adr x0, label1; \
|
||||||
adr x1, label2; \
|
adr x1, label2; \
|
||||||
sub x0, x1, x0; \
|
sub x0, x1, x0; \
|
||||||
LKMC_ASSERT_EQ(x0, result)
|
LKMC_ASSERT_EQ(x0, =result)
|
||||||
|
|
||||||
ASSERT_DIFF(mybyte, myword, 1)
|
ASSERT_DIFF(mybyte, myword, 1)
|
||||||
ASSERT_DIFF(myword, mylong, 4)
|
ASSERT_DIFF(myword, mylong, 4)
|
||||||
@@ -15,7 +15,7 @@ LKMC_ENTRY
|
|||||||
ASSERT_DIFF(myquad, myocta, 8)
|
ASSERT_DIFF(myquad, myocta, 8)
|
||||||
ASSERT_DIFF(myocta, theend, 16)
|
ASSERT_DIFF(myocta, theend, 16)
|
||||||
#undef ASSERT_DIF
|
#undef ASSERT_DIF
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
mybyte:
|
mybyte:
|
||||||
.byte 0x12
|
.byte 0x12
|
||||||
myword:
|
myword:
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-immediates */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-immediates */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
mov x0, 1
|
mov x0, 1
|
||||||
mov x0, 0x1
|
mov x0, 0x1
|
||||||
mov x0, 1
|
mov x0, 1
|
||||||
mov x0, 0x1
|
mov x0, 0x1
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ld2-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ld2-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
.data
|
.data
|
||||||
u32_interleave: .word \
|
u32_interleave: .word \
|
||||||
0x11111111, 0x55555555, \
|
0x11111111, 0x55555555, \
|
||||||
@@ -22,5 +22,5 @@ LKMC_ENTRY
|
|||||||
add v2.4s, v0.4s, v1.4s
|
add v2.4s, v0.4s, v1.4s
|
||||||
adr x0, u32_interleave_sum
|
adr x0, u32_interleave_sum
|
||||||
st1 {v2.4s}, [x0]
|
st1 {v2.4s}, [x0]
|
||||||
LKMC_ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, 0x10)
|
LKMC_ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, =0x10)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
35
userland/arch/aarch64/lkmc_assert_eq_fail.S
Normal file
35
userland/arch/aarch64/lkmc_assert_eq_fail.S
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
LKMC_PROLOGUE
|
||||||
|
ldr x19, =0x123456789ABCDEF0
|
||||||
|
ldr x20, =0x123456789ABCDEF0
|
||||||
|
ldr x21, =0x000000009ABCDEF0
|
||||||
|
|
||||||
|
/* Passing examples. */
|
||||||
|
|
||||||
|
/* Register immediate. */
|
||||||
|
LKMC_ASSERT_EQ(x19, =0x123456789ABCDEF0)
|
||||||
|
#if 0
|
||||||
|
/* Syntax not supported. */
|
||||||
|
LKMC_ASSERT_EQ(=0x123456789ABCDEF0, x19)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Register register. */
|
||||||
|
LKMC_ASSERT_EQ_REG(x19, x20)
|
||||||
|
LKMC_ASSERT_EQ_REG(x20, x19)
|
||||||
|
LKMC_ASSERT_EQ_REG_32(w19, w21)
|
||||||
|
LKMC_ASSERT_EQ_REG_32(w21, w19)
|
||||||
|
|
||||||
|
/* Register memory. */
|
||||||
|
LKMC_ASSERT_EQ(x19, myvar)
|
||||||
|
#if 0
|
||||||
|
/* Syntax not supported. */
|
||||||
|
LKMC_ASSERT_EQ(myvar, x19)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now let's fail. */
|
||||||
|
LKMC_ASSERT_EQ(x19, =0x123456789ABCDEF1)
|
||||||
|
LKMC_EPILOGUE
|
||||||
|
myvar: .quad 0x123456789ABCDEF0
|
||||||
15
userland/arch/aarch64/lkmc_assert_memcmp_fail.S
Normal file
15
userland/arch/aarch64/lkmc_assert_memcmp_fail.S
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
LKMC_PROLOGUE
|
||||||
|
/* Pass */
|
||||||
|
LKMC_ASSERT_MEMCMP(var0, var1, =0x10)
|
||||||
|
LKMC_ASSERT_MEMCMP(var0, var1, size)
|
||||||
|
/* Fail */
|
||||||
|
LKMC_ASSERT_MEMCMP(var0, var2, =0x10)
|
||||||
|
LKMC_EPILOGUE
|
||||||
|
var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
||||||
|
var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
||||||
|
var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444
|
||||||
|
size: .quad 0x10
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movk-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movk-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
movk x0, 0x4444, lsl 0
|
movk x0, 0x4444, lsl 0
|
||||||
movk x0, 0x3333, lsl 16
|
movk x0, 0x3333, lsl 16
|
||||||
movk x0, 0x2222, lsl 32
|
movk x0, 0x2222, lsl 32
|
||||||
movk x0, 0x1111, lsl 48
|
movk x0, 0x1111, lsl 48
|
||||||
LKMC_ASSERT_EQ(x0, 0x1111222233334444)
|
LKMC_ASSERT_EQ(x0, =0x1111222233334444)
|
||||||
|
|
||||||
/* Set a label (addresses are 48-bit) with immediates:
|
/* Set a label (addresses are 48-bit) with immediates:
|
||||||
*
|
*
|
||||||
@@ -23,4 +23,4 @@ LKMC_ENTRY
|
|||||||
adr x1, label
|
adr x1, label
|
||||||
label:
|
label:
|
||||||
LKMC_ASSERT_EQ_REG(x0, x1)
|
LKMC_ASSERT_EQ_REG(x0, x1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movn-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movn-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr x0, =0x123456789ABCDEF0
|
ldr x0, =0x123456789ABCDEF0
|
||||||
movn x0, 0x8888, lsl 16
|
movn x0, 0x8888, lsl 16
|
||||||
LKMC_ASSERT_EQ(x0, 0xFFFFFFFF7777FFFF)
|
LKMC_ASSERT_EQ(x0, =0xFFFFFFFF7777FFFF)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
#if 0
|
#if 0
|
||||||
/* Unlike v7, we can't use PC like any other register in ARMv8,
|
/* Unlike v7, we can't use PC like any other register in ARMv8,
|
||||||
* since it is not a general purpose register anymore.
|
* since it is not a general purpose register anymore.
|
||||||
@@ -16,7 +16,7 @@ LKMC_ENTRY
|
|||||||
* exception return.
|
* exception return.
|
||||||
*/
|
*/
|
||||||
ldr pc, =10f
|
ldr pc, =10f
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
10:
|
10:
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
@@ -32,7 +32,7 @@ LKMC_ENTRY
|
|||||||
pc_relative_ldr:
|
pc_relative_ldr:
|
||||||
.quad 0x123456789ABCDEF0
|
.quad 0x123456789ABCDEF0
|
||||||
1:
|
1:
|
||||||
LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
|
LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0)
|
||||||
|
|
||||||
/* Just for fun, we can also use relative numbers instead of labels.
|
/* Just for fun, we can also use relative numbers instead of labels.
|
||||||
* https://reverseengineering.stackexchange.com/questions/17666/how-does-the-ldr-instruction-work-on-arm/20567#20567
|
* https://reverseengineering.stackexchange.com/questions/17666/how-does-the-ldr-instruction-work-on-arm/20567#20567
|
||||||
@@ -41,14 +41,14 @@ pc_relative_ldr:
|
|||||||
b 1f
|
b 1f
|
||||||
.quad 0x123456789ABCDEF0
|
.quad 0x123456789ABCDEF0
|
||||||
1:
|
1:
|
||||||
LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
|
LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0)
|
||||||
|
|
||||||
/* Analogous for b with PC. */
|
/* Analogous for b with PC. */
|
||||||
mov x0, 0
|
mov x0, 0
|
||||||
/* Jumps over mov to LKMC_ASSERT_EQ. */
|
/* Jumps over mov to LKMC_ASSERT_EQ. */
|
||||||
b 8
|
b 8
|
||||||
mov x0, 1
|
mov x0, 1
|
||||||
LKMC_ASSERT_EQ(x0, 0)
|
LKMC_ASSERT_EQ(x0, =0)
|
||||||
|
|
||||||
/* Trying to use the old "LDR (immediate)" PC-relative
|
/* Trying to use the old "LDR (immediate)" PC-relative
|
||||||
* syntax does not work.
|
* syntax does not work.
|
||||||
@@ -66,13 +66,13 @@ pc_relative_ldr:
|
|||||||
|
|
||||||
/* You just have to use adr + "STR (register)". */
|
/* You just have to use adr + "STR (register)". */
|
||||||
ldr x0, pc_relative_str
|
ldr x0, pc_relative_str
|
||||||
LKMC_ASSERT_EQ(x0, 0x0)
|
LKMC_ASSERT_EQ(x0, =0x0)
|
||||||
adr x1, pc_relative_str
|
adr x1, pc_relative_str
|
||||||
ldr x0, pc_relative_ldr
|
ldr x0, pc_relative_ldr
|
||||||
str x0, [x1]
|
str x0, [x1]
|
||||||
ldr x0, pc_relative_str
|
ldr x0, pc_relative_str
|
||||||
LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0)
|
LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
.data
|
.data
|
||||||
pc_relative_str:
|
pc_relative_str:
|
||||||
.quad 0x0000000000000000
|
.quad 0x0000000000000000
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* 31 64-bit eXtended general purpose registers. */
|
/* 31 64-bit eXtended general purpose registers. */
|
||||||
mov x0, 0
|
mov x0, 0
|
||||||
@@ -43,5 +43,5 @@ LKMC_ENTRY
|
|||||||
ldr x0, =0x1111222233334444
|
ldr x0, =0x1111222233334444
|
||||||
ldr x1, =0x5555666677778888
|
ldr x1, =0x5555666677778888
|
||||||
mov w0, w1
|
mov w0, w1
|
||||||
LKMC_ASSERT_EQ(x0, 0x0000000077778888)
|
LKMC_ASSERT_EQ(x0, =0x0000000077778888)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-ret-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-ret-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
mov x19, 1
|
mov x19, 1
|
||||||
bl inc
|
bl inc
|
||||||
LKMC_ASSERT_EQ(x19, 2)
|
LKMC_ASSERT_EQ(x19, =2)
|
||||||
bl inc2
|
bl inc2
|
||||||
LKMC_ASSERT_EQ(x19, 3)
|
LKMC_ASSERT_EQ(x19, =3)
|
||||||
bl inc3
|
bl inc3
|
||||||
LKMC_ASSERT_EQ(x19, 4)
|
LKMC_ASSERT_EQ(x19, =4)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|
||||||
/* void inc(uint64_t *i) { (*i)++ } */
|
/* void inc(uint64_t *i) { (*i)++ } */
|
||||||
inc:
|
inc:
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-str-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-str-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr x0, myvar
|
ldr x0, myvar
|
||||||
LKMC_ASSERT_EQ(x0, 0x12346789ABCDEF0)
|
LKMC_ASSERT_EQ(x0, =0x12346789ABCDEF0)
|
||||||
#if 0
|
#if 0
|
||||||
/* Error: invalid addressing mode at operand 2 -- `str x0,myvar' */
|
/* Error: invalid addressing mode at operand 2 -- `str x0,myvar' */
|
||||||
str x0, myvar
|
str x0, myvar
|
||||||
#endif
|
#endif
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
myvar: .quad 0x12346789ABCDEF0
|
myvar: .quad 0x12346789ABCDEF0
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfm-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfm-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr x19, =0x1122334455667788
|
ldr x19, =0x1122334455667788
|
||||||
|
|
||||||
// lsr alias: imms == 63
|
// lsr alias: imms == 63
|
||||||
|
|
||||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||||
ubfm x20, x19, 16, 63
|
ubfm x20, x19, 16, 63
|
||||||
LKMC_ASSERT_EQ(x20, 0x0000112233445566)
|
LKMC_ASSERT_EQ(x20, =0x0000112233445566)
|
||||||
|
|
||||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||||
ubfm x20, x19, 32, 63
|
ubfm x20, x19, 32, 63
|
||||||
LKMC_ASSERT_EQ(x20, 0x0000000011223344)
|
LKMC_ASSERT_EQ(x20, =0x0000000011223344)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfx-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfx-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr x19, =0x1122334455667788
|
ldr x19, =0x1122334455667788
|
||||||
|
|
||||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||||
ubfx x20, x19, 8, 16
|
ubfx x20, x19, 8, 16
|
||||||
LKMC_ASSERT_EQ(x20, 0x0000000000006677)
|
LKMC_ASSERT_EQ(x20, =0x0000000000006677)
|
||||||
|
|
||||||
ldr x20, =0xFFFFFFFFFFFFFFFF
|
ldr x20, =0xFFFFFFFFFFFFFFFF
|
||||||
ubfx x20, x19, 8, 32
|
ubfx x20, x19, 8, 32
|
||||||
LKMC_ASSERT_EQ(x20, 0x0000000044556677)
|
LKMC_ASSERT_EQ(x20, =0x0000000044556677)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-udf-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-udf-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
.long 0
|
.long 0
|
||||||
#if 0
|
#if 0
|
||||||
udf 0
|
udf 0
|
||||||
#endif
|
#endif
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-x31-register */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-x31-register */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* ERROR: can never use the name x31. */
|
/* ERROR: can never use the name x31. */
|
||||||
#if 0
|
#if 0
|
||||||
mov x31, 31
|
mov x31, 31
|
||||||
@@ -11,12 +11,12 @@ LKMC_ENTRY
|
|||||||
/* mov (register) is an alias for ORR, which accepts xzr. */
|
/* mov (register) is an alias for ORR, which accepts xzr. */
|
||||||
mov x19, 1
|
mov x19, 1
|
||||||
mov x19, xzr
|
mov x19, xzr
|
||||||
LKMC_ASSERT_EQ(x19, 0)
|
LKMC_ASSERT_EQ(x19, =0)
|
||||||
|
|
||||||
/* Same encoding as the mov version. */
|
/* Same encoding as the mov version. */
|
||||||
mov x19, 1
|
mov x19, 1
|
||||||
orr x19, xzr, xzr
|
orr x19, xzr, xzr
|
||||||
LKMC_ASSERT_EQ(x19, 0)
|
LKMC_ASSERT_EQ(x19, =0)
|
||||||
|
|
||||||
/* So, orr, which is not an alias, can only take xzr, not sp. */
|
/* So, orr, which is not an alias, can only take xzr, not sp. */
|
||||||
#if 0
|
#if 0
|
||||||
@@ -26,7 +26,7 @@ LKMC_ENTRY
|
|||||||
/* Zero register discards result if written to. */
|
/* Zero register discards result if written to. */
|
||||||
mov x19, 1
|
mov x19, 1
|
||||||
orr xzr, x19, x19
|
orr xzr, x19, x19
|
||||||
LKMC_ASSERT_EQ(xzr, 0)
|
LKMC_ASSERT_EQ(xzr, =0)
|
||||||
|
|
||||||
/* MOV (to/from SP) is an alias for ADD (immediate). */
|
/* MOV (to/from SP) is an alias for ADD (immediate). */
|
||||||
mov x19, sp
|
mov x19, sp
|
||||||
@@ -36,7 +36,7 @@ LKMC_ENTRY
|
|||||||
/* Exact same encoding as above. */
|
/* Exact same encoding as above. */
|
||||||
add x20, sp, 0
|
add x20, sp, 0
|
||||||
mov sp, x19
|
mov sp, x19
|
||||||
LKMC_ASSERT_EQ(x20, 1)
|
LKMC_ASSERT_EQ(x20, =1)
|
||||||
|
|
||||||
/* So, ADD (immediate), which is not an alias, can only take sp, not xzr. */
|
/* So, ADD (immediate), which is not an alias, can only take sp, not xzr. */
|
||||||
#if 0
|
#if 0
|
||||||
@@ -48,4 +48,4 @@ LKMC_ENTRY
|
|||||||
* does not say anything about SP, and so does accept xzr just fine.
|
* does not say anything about SP, and so does accept xzr just fine.
|
||||||
*/
|
*/
|
||||||
add xzr, xzr, xzr
|
add xzr, xzr, xzr
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-data-processing-instructions */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-data-processing-instructions */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Immediate encoding.
|
/* Immediate encoding.
|
||||||
*
|
*
|
||||||
@@ -11,7 +11,7 @@ LKMC_ENTRY
|
|||||||
mov r0, 1
|
mov r0, 1
|
||||||
/* r1 = r0 + 2 */
|
/* r1 = r0 + 2 */
|
||||||
add r1, r0, 2
|
add r1, r0, 2
|
||||||
LKMC_ASSERT_EQ(r1, 3)
|
LKMC_ASSERT_EQ(r1, =3)
|
||||||
|
|
||||||
/* If src == dest, we can omit one of them.
|
/* If src == dest, we can omit one of them.
|
||||||
*
|
*
|
||||||
@@ -19,12 +19,12 @@ LKMC_ENTRY
|
|||||||
*/
|
*/
|
||||||
mov r0, 1
|
mov r0, 1
|
||||||
add r0, 2
|
add r0, 2
|
||||||
LKMC_ASSERT_EQ(r0, 3)
|
LKMC_ASSERT_EQ(r0, =3)
|
||||||
|
|
||||||
/* Same as above but explicit. */
|
/* Same as above but explicit. */
|
||||||
mov r0, 1
|
mov r0, 1
|
||||||
add r0, r0, 2
|
add r0, r0, 2
|
||||||
LKMC_ASSERT_EQ(r0, 3)
|
LKMC_ASSERT_EQ(r0, =3)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* But we cannot omit the register if there is a shift when using .syntx unified:
|
/* But we cannot omit the register if there is a shift when using .syntx unified:
|
||||||
@@ -44,7 +44,7 @@ LKMC_ENTRY
|
|||||||
mov r0, 1
|
mov r0, 1
|
||||||
mov r1, 2
|
mov r1, 2
|
||||||
add r2, r0, r1
|
add r2, r0, r1
|
||||||
LKMC_ASSERT_EQ(r2, 3)
|
LKMC_ASSERT_EQ(r2, =3)
|
||||||
|
|
||||||
/* Register encoding, omit implicit register.
|
/* Register encoding, omit implicit register.
|
||||||
*
|
*
|
||||||
@@ -53,6 +53,6 @@ LKMC_ENTRY
|
|||||||
mov r0, 1
|
mov r0, 1
|
||||||
mov r1, 2
|
mov r1, 2
|
||||||
add r1, r0
|
add r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 3)
|
LKMC_ASSERT_EQ(r1, =3)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-addressing-modes */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-addressing-modes */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Offset mode with immediate. Add 4 to the address register,
|
/* Offset mode with immediate. Add 4 to the address register,
|
||||||
* which ends up * reading myvar6 instead of myvar.
|
* which ends up * reading myvar6 instead of myvar.
|
||||||
*/
|
*/
|
||||||
adr r4, myvar
|
adr r4, myvar
|
||||||
ldr r5, [r4, 4]
|
ldr r5, [r4, 4]
|
||||||
LKMC_ASSERT_EQ(r5, 0x9ABCDEF0)
|
LKMC_ASSERT_EQ(r5, =0x9ABCDEF0)
|
||||||
/* r4 was not modified. */
|
/* r4 was not modified. */
|
||||||
LKMC_ASSERT_EQ(r4, myvar)
|
LKMC_ASSERT_EQ(r4, =myvar)
|
||||||
|
|
||||||
/* Pre-indexed mode: modify register, then use it. */
|
/* Pre-indexed mode: modify register, then use it. */
|
||||||
adr r4, myvar
|
adr r4, myvar
|
||||||
ldr r5, [r4, 4]!
|
ldr r5, [r4, 4]!
|
||||||
LKMC_ASSERT_EQ(r5, 0x9ABCDEF0)
|
LKMC_ASSERT_EQ(r5, =0x9ABCDEF0)
|
||||||
/* r4 was modified. */
|
/* r4 was modified. */
|
||||||
LKMC_ASSERT_EQ(r4, myvar6)
|
LKMC_ASSERT_EQ(r4, =myvar6)
|
||||||
|
|
||||||
/* Post-indexed mode: use register, then modify it. */
|
/* Post-indexed mode: use register, then modify it. */
|
||||||
adr r4, myvar
|
adr r4, myvar
|
||||||
ldr r5, [r4], 4
|
ldr r5, [r4], 4
|
||||||
LKMC_ASSERT_EQ(r5, 0x12345678)
|
LKMC_ASSERT_EQ(r5, =0x12345678)
|
||||||
/* r4 was modified. */
|
/* r4 was modified. */
|
||||||
LKMC_ASSERT_EQ(r4, myvar6)
|
LKMC_ASSERT_EQ(r4, =myvar6)
|
||||||
|
|
||||||
/* Offset in register. */
|
/* Offset in register. */
|
||||||
adr r4, myvar
|
adr r4, myvar
|
||||||
mov r5, 4
|
mov r5, 4
|
||||||
ldr r6, [r4, r5]
|
ldr r6, [r4, r5]
|
||||||
LKMC_ASSERT_EQ(r6, 0x9ABCDEF0)
|
LKMC_ASSERT_EQ(r6, =0x9ABCDEF0)
|
||||||
|
|
||||||
/* Offset in shifted register:
|
/* Offset in shifted register:
|
||||||
* r6 =
|
* r6 =
|
||||||
@@ -42,9 +42,9 @@ LKMC_ENTRY
|
|||||||
adr r4, myvar
|
adr r4, myvar
|
||||||
mov r5, 2
|
mov r5, 2
|
||||||
ldr r6, [r4, r5, lsl 1]
|
ldr r6, [r4, r5, lsl 1]
|
||||||
LKMC_ASSERT_EQ(r6, 0x9ABCDEF0)
|
LKMC_ASSERT_EQ(r6, =0x9ABCDEF0)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
myvar:
|
myvar:
|
||||||
.word 0x12345678
|
.word 0x12345678
|
||||||
myvar6:
|
myvar6:
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
.data
|
.data
|
||||||
data_label:
|
data_label:
|
||||||
.word 0x1234678
|
.word 0x1234678
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
adr r4, label
|
adr r4, label
|
||||||
/* objdump tells us that this uses the literal pool,
|
/* objdump tells us that this uses the literal pool,
|
||||||
* it does not get converted to adr, which is the better
|
* it does not get converted to adr, which is the better
|
||||||
@@ -30,4 +30,4 @@ label:
|
|||||||
*/
|
*/
|
||||||
adr r5, data_label
|
adr r5, data_label
|
||||||
#endif
|
#endif
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bitwise-instructions */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bitwise-instructions */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* 0x00 && 0xFF == 0x00 */
|
/* 0x00 && 0xFF == 0x00 */
|
||||||
mov r0, 0x00
|
mov r0, 0x00
|
||||||
and r0, 0xFF
|
and r0, 0xFF
|
||||||
LKMC_ASSERT_EQ(r0, 0x00)
|
LKMC_ASSERT_EQ(r0, =0x00)
|
||||||
|
|
||||||
/* 0x0F && 0xF0 == 0x00 */
|
/* 0x0F && 0xF0 == 0x00 */
|
||||||
mov r0, 0x0F
|
mov r0, 0x0F
|
||||||
and r0, 0xF0
|
and r0, 0xF0
|
||||||
LKMC_ASSERT_EQ(r0, 0x00)
|
LKMC_ASSERT_EQ(r0, =0x00)
|
||||||
|
|
||||||
/* 0x0F && 0xFF == 0x0F */
|
/* 0x0F && 0xFF == 0x0F */
|
||||||
mov r0, 0x0F
|
mov r0, 0x0F
|
||||||
and r0, 0xFF
|
and r0, 0xFF
|
||||||
LKMC_ASSERT_EQ(r0, 0x0F)
|
LKMC_ASSERT_EQ(r0, =0x0F)
|
||||||
|
|
||||||
/* 0xF0 && 0xFF == 0xF0 */
|
/* 0xF0 && 0xFF == 0xF0 */
|
||||||
mov r0, 0xF0
|
mov r0, 0xF0
|
||||||
and r0, 0xFF
|
and r0, 0xFF
|
||||||
LKMC_ASSERT_EQ(r0, 0xF0)
|
LKMC_ASSERT_EQ(r0, =0xF0)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-b-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-b-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* Jump over the fail. 26-bit PC-relative. */
|
/* Jump over the fail. 26-bit PC-relative. */
|
||||||
b ok
|
b ok
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
ok:
|
ok:
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Smaller*/
|
/* Smaller*/
|
||||||
mov r0, 1
|
mov r0, 1
|
||||||
@@ -25,4 +25,4 @@ LKMC_ENTRY
|
|||||||
LKMC_ASSERT(bgt)
|
LKMC_ASSERT(bgt)
|
||||||
LKMC_ASSERT(bne)
|
LKMC_ASSERT(bne)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr r0, =0x11223344
|
ldr r0, =0x11223344
|
||||||
ldr r1, =0xFFFFFFFF
|
ldr r1, =0xFFFFFFFF
|
||||||
bfi r1, r0, 8, 16
|
bfi r1, r0, 8, 16
|
||||||
LKMC_ASSERT_EQ(r1, 0xFF3344FF)
|
LKMC_ASSERT_EQ(r1, =0xFF3344FF)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bic-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bic-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* 0x0F & ~0x55 == 0x0F & 0xAA == 0x0A */
|
/* 0x0F & ~0x55 == 0x0F & 0xAA == 0x0A */
|
||||||
mov r0, 0x0F
|
mov r0, 0x0F
|
||||||
bic r0, 0x55
|
bic r0, 0x55
|
||||||
LKMC_ASSERT_EQ(r0, 0x0A)
|
LKMC_ASSERT_EQ(r0, =0x0A)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bl-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bl-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
mov r0, 1
|
mov r0, 1
|
||||||
bl inc
|
bl inc
|
||||||
LKMC_ASSERT_EQ(r0, 2)
|
LKMC_ASSERT_EQ(r0, =2)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|
||||||
/* void inc(int *i) { (*i)++ } */
|
/* void inc(int *i) { (*i)++ } */
|
||||||
inc:
|
inc:
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#data-bitwise-instructions */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#data-bitwise-instructions */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr r0, =0x7FFFFFFF
|
ldr r0, =0x7FFFFFFF
|
||||||
clz r1, r0
|
clz r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 1)
|
LKMC_ASSERT_EQ(r1, =1)
|
||||||
|
|
||||||
ldr r0, =0x3FFFFFFF
|
ldr r0, =0x3FFFFFFF
|
||||||
clz r1, r0
|
clz r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 2)
|
LKMC_ASSERT_EQ(r1, =2)
|
||||||
|
|
||||||
ldr r0, =0x1FFFFFFF
|
ldr r0, =0x1FFFFFFF
|
||||||
clz r1, r0
|
clz r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 3)
|
LKMC_ASSERT_EQ(r1, =3)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
# mycomment
|
# mycomment
|
||||||
@ mycomment
|
@ mycomment
|
||||||
/* # only works at the beginning of the line.
|
/* # only works at the beginning of the line.
|
||||||
@@ -11,4 +11,4 @@ LKMC_ENTRY
|
|||||||
nop # mycomment
|
nop # mycomment
|
||||||
#endif
|
#endif
|
||||||
nop @ mycomment
|
nop @ mycomment
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */
|
|
||||||
|
|
||||||
#ifndef COMMON_ARCH_H
|
|
||||||
#define COMMON_ARCH_H
|
|
||||||
|
|
||||||
.syntax unified
|
|
||||||
|
|
||||||
/* Assert that a register equals a constant.
|
|
||||||
* * reg: the register to check
|
|
||||||
* * const: the constant to compare to. Only works for literals or labels, not for registers.
|
|
||||||
* For register / register comparison, use LKMC_ASSERT_EQ_REG.
|
|
||||||
*/
|
|
||||||
#define LKMC_ASSERT_EQ(reg, const) \
|
|
||||||
mov r0, reg; \
|
|
||||||
ldr r1, =const; \
|
|
||||||
LKMC_ASSERT_EQ_DO; \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_EQ_DO \
|
|
||||||
bl lkmc_assert_eq_32; \
|
|
||||||
cmp r0, 0; \
|
|
||||||
LKMC_ASSERT(beq); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_EQ_REG(reg1, reg2) \
|
|
||||||
str reg2, [sp, -4]!; \
|
|
||||||
mov r0, reg1; \
|
|
||||||
ldr r1, [sp], 4; \
|
|
||||||
LKMC_ASSERT_EQ_DO; \
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Assert that two arrays are the same. */
|
|
||||||
#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
|
|
||||||
ldr r0, =label1; \
|
|
||||||
ldr r1, =label2; \
|
|
||||||
ldr r2, =const_size; \
|
|
||||||
bl lkmc_assert_memcmp; \
|
|
||||||
cmp r0, 0; \
|
|
||||||
LKMC_ASSERT(beq); \
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Store all callee saved registers, and LR in case we make further BL calls.
|
|
||||||
*
|
|
||||||
* Also save the input arguments r0-r3 on the stack, so we can access them later on,
|
|
||||||
* despite those registers being overwritten.
|
|
||||||
*/
|
|
||||||
#define LKMC_ENTRY \
|
|
||||||
.text; \
|
|
||||||
.global asm_main; \
|
|
||||||
asm_main: \
|
|
||||||
stmdb sp!, {r0-r12, lr}; \
|
|
||||||
asm_main_after_prologue: \
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Meant to be called at the end of LKMC_ENTRY.*
|
|
||||||
*
|
|
||||||
* Branching to "fail" makes tests fail with exit status 1.
|
|
||||||
*
|
|
||||||
* If LKMC_EXIT is reached, the program ends successfully.
|
|
||||||
*
|
|
||||||
* Restore LR and bx jump to it to return from asm_main.
|
|
||||||
*/
|
|
||||||
#define LKMC_EXIT \
|
|
||||||
mov r0, 0; \
|
|
||||||
mov r1, 0; \
|
|
||||||
b pass; \
|
|
||||||
fail: \
|
|
||||||
ldr r1, [sp]; \
|
|
||||||
str r0, [r1]; \
|
|
||||||
mov r0, 1; \
|
|
||||||
pass: \
|
|
||||||
add sp, 16; \
|
|
||||||
ldmia sp!, {r4-r12, lr}; \
|
|
||||||
bx lr; \
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Always fail. */
|
|
||||||
#define LKMC_FAIL \
|
|
||||||
ldr r0, =__LINE__; \
|
|
||||||
b fail; \
|
|
||||||
;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,16 +1,18 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-conditional-execution */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-conditional-execution */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
LKMC_PROLOGUE
|
||||||
|
mov r4, 0
|
||||||
|
mov r5, 1
|
||||||
|
|
||||||
LKMC_ENTRY
|
|
||||||
mov r0, 0
|
|
||||||
mov r1, 1
|
|
||||||
cmp r0, 1
|
|
||||||
/* Previous cmp failed, skip this operation. */
|
/* Previous cmp failed, skip this operation. */
|
||||||
addeq r1, 1
|
cmp r4, 1
|
||||||
LKMC_ASSERT_EQ(r1, 1)
|
addeq r5, 1
|
||||||
cmp r0, 0
|
LKMC_ASSERT_EQ(r5, =1)
|
||||||
|
|
||||||
/* Previous passed, do this operation. */
|
/* Previous passed, do this operation. */
|
||||||
addeq r1, 1
|
cmp r4, 0
|
||||||
LKMC_ASSERT_EQ(r1, 2)
|
addeq r5, 1
|
||||||
LKMC_EXIT
|
LKMC_ASSERT_EQ(r5, =2)
|
||||||
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
.data
|
.data
|
||||||
mybyte:
|
mybyte:
|
||||||
@@ -14,12 +14,12 @@ myquad:
|
|||||||
myocta:
|
myocta:
|
||||||
.octa 0x123456789ABCDEF0123456789ABCDEF0
|
.octa 0x123456789ABCDEF0123456789ABCDEF0
|
||||||
theend:
|
theend:
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
#define ASSERT_DIFF(label1, label2, result) \
|
#define ASSERT_DIFF(label1, label2, result) \
|
||||||
ldr r0, =label1; \
|
ldr r0, =label1; \
|
||||||
ldr r1, =label2; \
|
ldr r1, =label2; \
|
||||||
sub r0, r1, r0; \
|
sub r0, r1, r0; \
|
||||||
LKMC_ASSERT_EQ(r0, result)
|
LKMC_ASSERT_EQ(r0, =result)
|
||||||
|
|
||||||
ASSERT_DIFF(mybyte, myword, 1)
|
ASSERT_DIFF(mybyte, myword, 1)
|
||||||
ASSERT_DIFF(myword, mylong, 4)
|
ASSERT_DIFF(myword, mylong, 4)
|
||||||
@@ -27,4 +27,4 @@ LKMC_ENTRY
|
|||||||
ASSERT_DIFF(myquad, myocta, 8)
|
ASSERT_DIFF(myquad, myocta, 8)
|
||||||
ASSERT_DIFF(myocta, theend, 16)
|
ASSERT_DIFF(myocta, theend, 16)
|
||||||
#undef ASSERT_DIF
|
#undef ASSERT_DIF
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-gnu-instruction-gas-assembler-immediates */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-gnu-instruction-gas-assembler-immediates */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* This is the default. We hack it in common.h however. */
|
/* This is the default. We hack it in common.h however. */
|
||||||
.syntax divided
|
.syntax divided
|
||||||
/* These fail. */
|
/* These fail. */
|
||||||
@@ -21,4 +21,4 @@ LKMC_ENTRY
|
|||||||
mov r0, 0x1
|
mov r0, 0x1
|
||||||
mov r0, $1
|
mov r0, $1
|
||||||
mov r0, $0x1
|
mov r0, $0x1
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-loop-instruction-over-array */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-loop-instruction-over-array */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
#define NELEM 4
|
#define NELEM 4
|
||||||
#define ELEM_SIZE 4
|
#define ELEM_SIZE 4
|
||||||
@@ -11,7 +11,7 @@ my_array:
|
|||||||
my_array_expect:
|
my_array_expect:
|
||||||
.word 0x11111112, 0x22222223, 0x33333334, 0x44444445
|
.word 0x11111112, 0x22222223, 0x33333334, 0x44444445
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* Increment. */
|
/* Increment. */
|
||||||
ldr r0, =my_array
|
ldr r0, =my_array
|
||||||
mov r1, NELEM
|
mov r1, NELEM
|
||||||
@@ -23,5 +23,5 @@ increment:
|
|||||||
sub r1, 1
|
sub r1, 1
|
||||||
cmp r1, 0
|
cmp r1, 0
|
||||||
bne increment
|
bne increment
|
||||||
LKMC_ASSERT_MEMCMP(my_array, my_array_expect, 0x10)
|
LKMC_ASSERT_MEMCMP(my_array, my_array_expect, =0x10)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-loop-instruction-over-array */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-loop-instruction-over-array */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
#define NELEM 4
|
#define NELEM 4
|
||||||
#define ELEM_SIZE 4
|
#define ELEM_SIZE 4
|
||||||
@@ -11,7 +11,7 @@ my_array_0:
|
|||||||
my_array_1:
|
my_array_1:
|
||||||
.word 0x55555555, 0x66666666, 0x77777777, 0x88888888
|
.word 0x55555555, 0x66666666, 0x77777777, 0x88888888
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Load r5, r6, r7 and r8 starting from the address in r4. Don't change r4 */
|
/* Load r5, r6, r7 and r8 starting from the address in r4. Don't change r4 */
|
||||||
ldr r4, =my_array_0
|
ldr r4, =my_array_0
|
||||||
@@ -20,11 +20,11 @@ LKMC_ENTRY
|
|||||||
ldr r7, =0
|
ldr r7, =0
|
||||||
ldr r8, =0
|
ldr r8, =0
|
||||||
ldmia r4, {r5-r8}
|
ldmia r4, {r5-r8}
|
||||||
LKMC_ASSERT_EQ(r4, my_array_0)
|
LKMC_ASSERT_EQ(r4, =my_array_0)
|
||||||
LKMC_ASSERT_EQ(r5, 0x11111111)
|
LKMC_ASSERT_EQ(r5, =0x11111111)
|
||||||
LKMC_ASSERT_EQ(r6, 0x22222222)
|
LKMC_ASSERT_EQ(r6, =0x22222222)
|
||||||
LKMC_ASSERT_EQ(r7, 0x33333333)
|
LKMC_ASSERT_EQ(r7, =0x33333333)
|
||||||
LKMC_ASSERT_EQ(r8, 0x44444444)
|
LKMC_ASSERT_EQ(r8, =0x44444444)
|
||||||
|
|
||||||
/* Swapping the order of r5 and r6 on the mnemonic makes no difference to load order.
|
/* Swapping the order of r5 and r6 on the mnemonic makes no difference to load order.
|
||||||
*
|
*
|
||||||
@@ -38,8 +38,8 @@ LKMC_ENTRY
|
|||||||
ldr r5, =0
|
ldr r5, =0
|
||||||
ldr r6, =0
|
ldr r6, =0
|
||||||
ldmia r4, {r6,r5}
|
ldmia r4, {r6,r5}
|
||||||
LKMC_ASSERT_EQ(r5, 0x11111111)
|
LKMC_ASSERT_EQ(r5, =0x11111111)
|
||||||
LKMC_ASSERT_EQ(r6, 0x22222222)
|
LKMC_ASSERT_EQ(r6, =0x22222222)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Modify the array */
|
/* Modify the array */
|
||||||
@@ -51,11 +51,11 @@ LKMC_ENTRY
|
|||||||
stmdb r4, {r5-r8}
|
stmdb r4, {r5-r8}
|
||||||
|
|
||||||
/* Verify that my_array_0 changed and is equal to my_array_1. */
|
/* Verify that my_array_0 changed and is equal to my_array_1. */
|
||||||
LKMC_ASSERT_MEMCMP(my_array_0, my_array_1, 0x10)
|
LKMC_ASSERT_MEMCMP(my_array_0, my_array_1, =0x10)
|
||||||
|
|
||||||
/* Load registers and increment r4. */
|
/* Load registers and increment r4. */
|
||||||
ldr r4, =my_array_0
|
ldr r4, =my_array_0
|
||||||
ldmia r4!, {r5-r8}
|
ldmia r4!, {r5-r8}
|
||||||
LKMC_ASSERT_EQ(r4, my_array_1)
|
LKMC_ASSERT_EQ(r4, =my_array_1)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldr-instruction-pseudo-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldr-instruction-pseudo-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Mnemonic for a PC relative load:
|
/* Mnemonic for a PC relative load:
|
||||||
*
|
*
|
||||||
@@ -12,13 +12,13 @@ LKMC_ENTRY
|
|||||||
* ....
|
* ....
|
||||||
*/
|
*/
|
||||||
ldr r0, myvar
|
ldr r0, myvar
|
||||||
LKMC_ASSERT_EQ(r0, 0x12345678)
|
LKMC_ASSERT_EQ(r0, =0x12345678)
|
||||||
|
|
||||||
/* Mnemonic PC relative load with an offset.
|
/* Mnemonic PC relative load with an offset.
|
||||||
* Load myvar2 instead of myvar.
|
* Load myvar2 instead of myvar.
|
||||||
*/
|
*/
|
||||||
ldr r0, myvar + 4
|
ldr r0, myvar + 4
|
||||||
LKMC_ASSERT_EQ(r0, 0x9ABCDEF0)
|
LKMC_ASSERT_EQ(r0, =0x9ABCDEF0)
|
||||||
|
|
||||||
/* First store the address in r0 using a magic =myvar, which creates
|
/* First store the address in r0 using a magic =myvar, which creates
|
||||||
* a new variable containing the address and PC-relative addresses it
|
* a new variable containing the address and PC-relative addresses it
|
||||||
@@ -33,17 +33,17 @@ LKMC_ENTRY
|
|||||||
*/
|
*/
|
||||||
ldr r0, =myvar
|
ldr r0, =myvar
|
||||||
ldr r1, [r0]
|
ldr r1, [r0]
|
||||||
LKMC_ASSERT_EQ(r1, 0x12345678)
|
LKMC_ASSERT_EQ(r1, =0x12345678)
|
||||||
|
|
||||||
/* More efficiently, use r0 as the address to read, and write to r0 itself. */
|
/* More efficiently, use r0 as the address to read, and write to r0 itself. */
|
||||||
ldr r0, =myvar
|
ldr r0, =myvar
|
||||||
ldr r0, [r0]
|
ldr r0, [r0]
|
||||||
LKMC_ASSERT_EQ(r0, 0x12345678)
|
LKMC_ASSERT_EQ(r0, =0x12345678)
|
||||||
|
|
||||||
/* Same as =myvar but store a constant to a register.
|
/* Same as =myvar but store a constant to a register.
|
||||||
* Can also be done with movw and movt. */
|
* Can also be done with movw and movt. */
|
||||||
ldr r0, =0x11112222
|
ldr r0, =0x11112222
|
||||||
LKMC_ASSERT_EQ(r0, 0x11112222)
|
LKMC_ASSERT_EQ(r0, =0x11112222)
|
||||||
|
|
||||||
/* We can also use GAS tolower16 and topper16 and movw and movt
|
/* We can also use GAS tolower16 and topper16 and movw and movt
|
||||||
* to load the address of myvar into r0 with two immediates.
|
* to load the address of myvar into r0 with two immediates.
|
||||||
@@ -56,9 +56,9 @@ LKMC_ENTRY
|
|||||||
movw r0, #:lower16:myvar
|
movw r0, #:lower16:myvar
|
||||||
movt r0, #:upper16:myvar
|
movt r0, #:upper16:myvar
|
||||||
ldr r1, [r0]
|
ldr r1, [r0]
|
||||||
LKMC_ASSERT_EQ(r1, 0x12345678)
|
LKMC_ASSERT_EQ(r1, =0x12345678)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
myvar:
|
myvar:
|
||||||
.word 0x12345678
|
.word 0x12345678
|
||||||
myvar2:
|
myvar2:
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldrh-instruction-and-ldrb */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldrh-instruction-and-ldrb */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr r0, =myvar
|
ldr r0, =myvar
|
||||||
mov r1, 0x0
|
mov r1, 0x0
|
||||||
ldrb r1, [r0]
|
ldrb r1, [r0]
|
||||||
LKMC_ASSERT_EQ(r1, 0x00000078)
|
LKMC_ASSERT_EQ(r1, =0x00000078)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
myvar:
|
myvar:
|
||||||
.word 0x12345678
|
.word 0x12345678
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldrh-instruction-and-ldrb */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldrh-instruction-and-ldrb */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr r0, =myvar
|
ldr r0, =myvar
|
||||||
mov r1, 0x0
|
mov r1, 0x0
|
||||||
ldrh r1, [r0]
|
ldrh r1, [r0]
|
||||||
LKMC_ASSERT_EQ(r1, 0x00005678)
|
LKMC_ASSERT_EQ(r1, =0x00005678)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
myvar:
|
myvar:
|
||||||
.word 0x12345678
|
.word 0x12345678
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#calling-convention */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
.data
|
.data
|
||||||
puts_s:
|
puts_s:
|
||||||
@@ -12,7 +12,7 @@ my_array_0:
|
|||||||
my_array_1:
|
my_array_1:
|
||||||
.word 0x55555555, 0x66666666, 0x77777777, 0x88888888
|
.word 0x55555555, 0x66666666, 0x77777777, 0x88888888
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* puts("hello world") */
|
/* puts("hello world") */
|
||||||
/* r0 is first argument. */
|
/* r0 is first argument. */
|
||||||
ldr r0, =puts_s
|
ldr r0, =puts_s
|
||||||
@@ -49,11 +49,11 @@ LKMC_ENTRY
|
|||||||
ldr r1, =my_array_1
|
ldr r1, =my_array_1
|
||||||
ldr r2, =0x10
|
ldr r2, =0x10
|
||||||
bl memcmp
|
bl memcmp
|
||||||
LKMC_ASSERT_EQ(r0, 0)
|
LKMC_ASSERT_EQ(r0, =0)
|
||||||
|
|
||||||
/* exit(0) */
|
/* exit(0) */
|
||||||
mov r0, 0
|
mov r0, 0
|
||||||
bl exit
|
bl exit
|
||||||
|
|
||||||
/* Never reached, just for the fail symbol. */
|
/* Never reached, just for the fail symbol. */
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
32
userland/arch/arm/lkmc_assert_eq_fail.S
Normal file
32
userland/arch/arm/lkmc_assert_eq_fail.S
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
LKMC_PROLOGUE
|
||||||
|
ldr r4, =0x12345678
|
||||||
|
ldr r5, =0x12345678
|
||||||
|
|
||||||
|
/* Passing examples. */
|
||||||
|
|
||||||
|
/* Register immediate. */
|
||||||
|
LKMC_ASSERT_EQ(r4, =0x12345678)
|
||||||
|
#if 0
|
||||||
|
/* Syntax not supported. */
|
||||||
|
LKMC_ASSERT_EQ(=0x12345678, r4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Register register. */
|
||||||
|
LKMC_ASSERT_EQ_REG(r4, r5)
|
||||||
|
LKMC_ASSERT_EQ_REG(r5, r4)
|
||||||
|
|
||||||
|
/* Register memory. */
|
||||||
|
LKMC_ASSERT_EQ(r4, myvar)
|
||||||
|
#if 0
|
||||||
|
/* Syntax not supported. */
|
||||||
|
LKMC_ASSERT_EQ(myvar, r4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Now let's fail. */
|
||||||
|
LKMC_ASSERT_EQ(r4, =0x12345679)
|
||||||
|
LKMC_EPILOGUE
|
||||||
|
myvar: .quad 0x12345678
|
||||||
15
userland/arch/arm/lkmc_assert_memcmp_fail.S
Normal file
15
userland/arch/arm/lkmc_assert_memcmp_fail.S
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
LKMC_PROLOGUE
|
||||||
|
/* Pass */
|
||||||
|
LKMC_ASSERT_MEMCMP(var0, var1, =0x10)
|
||||||
|
LKMC_ASSERT_MEMCMP(var0, var1, size)
|
||||||
|
/* Fail */
|
||||||
|
LKMC_ASSERT_MEMCMP(var0, var2, =0x10)
|
||||||
|
LKMC_EPILOGUE
|
||||||
|
var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
||||||
|
var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
||||||
|
var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444
|
||||||
|
size: .long 0x10
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-mov-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-mov-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Immediate. */
|
/* Immediate. */
|
||||||
mov r0, 0
|
mov r0, 0
|
||||||
LKMC_ASSERT_EQ(r0, 0)
|
LKMC_ASSERT_EQ(r0, =0)
|
||||||
mov r0, 1
|
mov r0, 1
|
||||||
LKMC_ASSERT_EQ(r0, 1)
|
LKMC_ASSERT_EQ(r0, =1)
|
||||||
|
|
||||||
/* Register. */
|
/* Register. */
|
||||||
mov r0, 0
|
mov r0, 0
|
||||||
mov r1, 1
|
mov r1, 1
|
||||||
mov r1, r0
|
mov r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 0)
|
LKMC_ASSERT_EQ(r1, =0)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-movw-and-movt-instructions */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-movw-and-movt-instructions */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* movt (top) and movw (TODO what is w) set the higher
|
/* movt (top) and movw (TODO what is w) set the higher
|
||||||
* and lower 16 bits of the register.
|
* and lower 16 bits of the register.
|
||||||
@@ -10,7 +10,7 @@ LKMC_ENTRY
|
|||||||
movw r0, 0xFFFF
|
movw r0, 0xFFFF
|
||||||
movt r0, 0x1234
|
movt r0, 0x1234
|
||||||
add r0, 1
|
add r0, 1
|
||||||
LKMC_ASSERT_EQ(r0, 0x12350000)
|
LKMC_ASSERT_EQ(r0, =0x12350000)
|
||||||
|
|
||||||
/* movw also zeroes out the top bits, allowing small 16-bit
|
/* movw also zeroes out the top bits, allowing small 16-bit
|
||||||
* C constants to be assigned in a single instruction.
|
* C constants to be assigned in a single instruction.
|
||||||
@@ -22,6 +22,6 @@ LKMC_ENTRY
|
|||||||
*/
|
*/
|
||||||
ldr r0, =0x12345678
|
ldr r0, =0x12345678
|
||||||
movw r0, 0x1111
|
movw r0, 0x1111
|
||||||
LKMC_ASSERT_EQ(r0, 0x00001111)
|
LKMC_ASSERT_EQ(r0, =0x00001111)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
* Multiplication.
|
* Multiplication.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* 2 * 3 = 6 */
|
/* 2 * 3 = 6 */
|
||||||
mov r0, 0
|
mov r0, 0
|
||||||
mov r1, 2
|
mov r1, 2
|
||||||
mov r2, 3
|
mov r2, 3
|
||||||
mul r1, r2
|
mul r1, r2
|
||||||
LKMC_ASSERT_EQ(r1, 6)
|
LKMC_ASSERT_EQ(r1, =6)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-nop-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-nop-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* Disassembles as:
|
/* Disassembles as:
|
||||||
*
|
*
|
||||||
* ....
|
* ....
|
||||||
@@ -29,4 +29,4 @@ LKMC_ENTRY
|
|||||||
|
|
||||||
/* And there are other nops as well? Disassembles as `and`. */
|
/* And there are other nops as well? Disassembles as `and`. */
|
||||||
and r0, r0, r0
|
and r0, r0, r0
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldmia-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldmia-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Save sp before push. */
|
/* Save sp before push. */
|
||||||
mov r4, sp
|
mov r4, sp
|
||||||
@@ -19,13 +19,13 @@ LKMC_ENTRY
|
|||||||
mov r7, 0
|
mov r7, 0
|
||||||
mov r8, 0
|
mov r8, 0
|
||||||
pop {r7, r8}
|
pop {r7, r8}
|
||||||
LKMC_ASSERT_EQ(r7, 1)
|
LKMC_ASSERT_EQ(r7, =1)
|
||||||
LKMC_ASSERT_EQ(r8, 2)
|
LKMC_ASSERT_EQ(r8, =2)
|
||||||
|
|
||||||
/* Check that stack pointer moved down by 8 bytes
|
/* Check that stack pointer moved down by 8 bytes
|
||||||
* (2 registers x 4 bytes each).
|
* (2 registers x 4 bytes each).
|
||||||
*/
|
*/
|
||||||
sub r4, r5
|
sub r4, r5
|
||||||
LKMC_ASSERT_EQ(r4, 8)
|
LKMC_ASSERT_EQ(r4, =8)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
* Reverse bit order.
|
* Reverse bit order.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
ldr r0, =0b00000001001000110100010101100101
|
ldr r0, =0b00000001001000110100010101100101
|
||||||
rbit r1, r0
|
rbit r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 0b10100110101000101100010010000000)
|
LKMC_ASSERT_EQ(r1, =0b10100110101000101100010010000000)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* 13 general purpose registers. */
|
/* 13 general purpose registers. */
|
||||||
mov r0, 0
|
mov r0, 0
|
||||||
@@ -39,12 +39,12 @@ LKMC_ENTRY
|
|||||||
* https://stackoverflow.com/questions/32304646/arm-assembly-branch-to-address-inside-register-or-memory/54145818#54145818
|
* https://stackoverflow.com/questions/32304646/arm-assembly-branch-to-address-inside-register-or-memory/54145818#54145818
|
||||||
*/
|
*/
|
||||||
ldr pc, =10f
|
ldr pc, =10f
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
10:
|
10:
|
||||||
|
|
||||||
/* Same with r15, which is the same as pc. */
|
/* Same with r15, which is the same as pc. */
|
||||||
ldr r15, =10f
|
ldr r15, =10f
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
10:
|
10:
|
||||||
|
|
||||||
/* Another example with mov reading from pc. */
|
/* Another example with mov reading from pc. */
|
||||||
@@ -60,10 +60,10 @@ pc_addr:
|
|||||||
b 1f
|
b 1f
|
||||||
.word 0x12345678
|
.word 0x12345678
|
||||||
1:
|
1:
|
||||||
LKMC_ASSERT_EQ(r0, 0x12345678)
|
LKMC_ASSERT_EQ(r0, =0x12345678)
|
||||||
|
|
||||||
/* We can also use fp in GNU GAS assembly. */
|
/* We can also use fp in GNU GAS assembly. */
|
||||||
mov r11, 0
|
mov r11, 0
|
||||||
mov fp, 1
|
mov fp, 1
|
||||||
LKMC_ASSERT_EQ(r11, 1)
|
LKMC_ASSERT_EQ(r11, =1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
* Reverse byte order.
|
* Reverse byte order.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* All bytes in register. */
|
/* All bytes in register. */
|
||||||
ldr r0, =0x11223344
|
ldr r0, =0x11223344
|
||||||
rev r1, r0
|
rev r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 0x44332211)
|
LKMC_ASSERT_EQ(r1, =0x44332211)
|
||||||
|
|
||||||
/* Groups of 16-bits. */
|
/* Groups of 16-bits. */
|
||||||
ldr r0, =0x11223344
|
ldr r0, =0x11223344
|
||||||
rev16 r1, r0
|
rev16 r1, r0
|
||||||
LKMC_ASSERT_EQ(r1, 0x22114433)
|
LKMC_ASSERT_EQ(r1, =0x22114433)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-s-suffix */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-s-suffix */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* Result is 0, set beq. */
|
/* Result is 0, set beq. */
|
||||||
movs r0, 0
|
movs r0, 0
|
||||||
@@ -20,7 +20,7 @@ LKMC_ENTRY
|
|||||||
/* movs still moves... */
|
/* movs still moves... */
|
||||||
mov r0, 0
|
mov r0, 0
|
||||||
movs r0, 1
|
movs r0, 1
|
||||||
LKMC_ASSERT_EQ(r0, 1)
|
LKMC_ASSERT_EQ(r0, =1)
|
||||||
|
|
||||||
/* add: the result is 0. */
|
/* add: the result is 0. */
|
||||||
mov r0, 1
|
mov r0, 1
|
||||||
@@ -32,4 +32,4 @@ LKMC_ENTRY
|
|||||||
adds r0, 1
|
adds r0, 1
|
||||||
LKMC_ASSERT(bne)
|
LKMC_ASSERT(bne)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-shift-suffixes */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-shift-suffixes */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* lsr */
|
/* lsr */
|
||||||
ldr r0, =0xFFF00FFF
|
ldr r0, =0xFFF00FFF
|
||||||
@@ -76,4 +76,4 @@ LKMC_ENTRY
|
|||||||
ldr r2, =0x00000120
|
ldr r2, =0x00000120
|
||||||
LKMC_ASSERT_EQ_REG(r1, r2)
|
LKMC_ASSERT_EQ_REG(r1, r2)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#load-and-store-instructions */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#load-and-store-instructions */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
.data;
|
.data;
|
||||||
/* Must be in the .data section, since we want to modify it. */
|
/* Must be in the .data section, since we want to modify it. */
|
||||||
myvar:
|
myvar:
|
||||||
.word 0x12345678
|
.word 0x12345678
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* Sanity check. */
|
/* Sanity check. */
|
||||||
ldr r0, =myvar
|
ldr r0, =myvar
|
||||||
ldr r1, [r0]
|
ldr r1, [r0]
|
||||||
@@ -57,4 +57,4 @@ var_in_same_section:
|
|||||||
str r1, =myvar
|
str r1, =myvar
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
* Subtraction.
|
* Subtraction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* 3 - 2 == 1 , register version.*/
|
/* 3 - 2 == 1 , register version.*/
|
||||||
mov r0, 3
|
mov r0, 3
|
||||||
mov r1, 2
|
mov r1, 2
|
||||||
sub r0, r0, r1
|
sub r0, r0, r1
|
||||||
LKMC_ASSERT_EQ(r0, 1)
|
LKMC_ASSERT_EQ(r0, =1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
.syntax unified
|
.syntax unified
|
||||||
.text
|
.text
|
||||||
.thumb_func
|
.thumb_func
|
||||||
.global asm_main
|
.global main
|
||||||
asm_main:
|
main:
|
||||||
asm_main_after_prologue:
|
main_after_prologue:
|
||||||
|
|
||||||
/* CBZ: cmp and branch if zero instruction. Equivalent to CMP + BEQ.
|
/* CBZ: cmp and branch if zero instruction. Equivalent to CMP + BEQ.
|
||||||
* TODO create an interesting assertion here.
|
* TODO create an interesting assertion here.
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Test. Same as ands, but don't store the result, just update flags.
|
* Test. Same as ands, but don't store the result, just update flags.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
|
||||||
/* 0x0F && 0xF0 == 0x00, so beq. */
|
/* 0x0F && 0xF0 == 0x00, so beq. */
|
||||||
mov r0, 0x0F
|
mov r0, 0x0F
|
||||||
@@ -17,6 +17,6 @@ LKMC_ENTRY
|
|||||||
tst r0, 0x0F
|
tst r0, 0x0F
|
||||||
LKMC_ASSERT(bne)
|
LKMC_ASSERT(bne)
|
||||||
# r0 was not modified.
|
# r0 was not modified.
|
||||||
LKMC_ASSERT_EQ(r0, 0xFF)
|
LKMC_ASSERT_EQ(r0, =0xFF)
|
||||||
|
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-udf-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-udf-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
udf 0
|
udf 0
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#vfp
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#vfp
|
||||||
* Adapted from: https://mindplusplus.wordpress.com/2013/06/27/arm-vfp-vector-programming-part-2-examples/ */
|
* Adapted from: https://mindplusplus.wordpress.com/2013/06/27/arm-vfp-vector-programming-part-2-examples/ */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* Minimal single precision floating point example.
|
/* Minimal single precision floating point example.
|
||||||
* TODO: floating point representation constraints due to 4-byte instruction?
|
* TODO: floating point representation constraints due to 4-byte instruction?
|
||||||
*/
|
*/
|
||||||
@@ -39,7 +39,7 @@ my_float_sum:
|
|||||||
vadd.f32 s2, s0, s1
|
vadd.f32 s2, s0, s1
|
||||||
ldr r0, =my_float_sum
|
ldr r0, =my_float_sum
|
||||||
vstr.f32 s2, [r0]
|
vstr.f32 s2, [r0]
|
||||||
LKMC_ASSERT_MEMCMP(my_float_sum, my_float_sum_expect, 4)
|
LKMC_ASSERT_MEMCMP(my_float_sum, my_float_sum_expect, =4)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* We can't do pseudo vldr as for ldr, fails with:
|
/* We can't do pseudo vldr as for ldr, fails with:
|
||||||
@@ -69,4 +69,4 @@ my_float_sum:
|
|||||||
vmov s1, s0
|
vmov s1, s0
|
||||||
vmov r1, s1
|
vmov r1, s1
|
||||||
LKMC_ASSERT_EQ_REG(r0, r1)
|
LKMC_ASSERT_EQ_REG(r0, r1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vadd-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vadd-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
.bss
|
.bss
|
||||||
output: .skip 16
|
output: .skip 16
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* Integer. */
|
/* Integer. */
|
||||||
.data
|
.data
|
||||||
input0_u: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
|
input0_u: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
|
||||||
@@ -20,7 +20,7 @@ LKMC_ENTRY
|
|||||||
vadd.u ## size q2, q0, q1; \
|
vadd.u ## size q2, q0, q1; \
|
||||||
ldr r0, =output; \
|
ldr r0, =output; \
|
||||||
vst1.u ## size {q2}, [r0]; \
|
vst1.u ## size {q2}, [r0]; \
|
||||||
LKMC_ASSERT_MEMCMP(output, expect_u_ ## size, 0x10)
|
LKMC_ASSERT_MEMCMP(output, expect_u_ ## size, =0x10)
|
||||||
|
|
||||||
/* vadd.u32
|
/* vadd.u32
|
||||||
*
|
*
|
||||||
@@ -54,7 +54,7 @@ LKMC_ENTRY
|
|||||||
vadd.f ## size q2, q0, q1; \
|
vadd.f ## size q2, q0, q1; \
|
||||||
ldr r0, =output; \
|
ldr r0, =output; \
|
||||||
vst1. ## size {q2}, [r0]; \
|
vst1. ## size {q2}, [r0]; \
|
||||||
LKMC_ASSERT_MEMCMP(output, expect_f_ ## size, 0x10)
|
LKMC_ASSERT_MEMCMP(output, expect_f_ ## size, =0x10)
|
||||||
|
|
||||||
/* 4x 32-bit. */
|
/* 4x 32-bit. */
|
||||||
TEST(32)
|
TEST(32)
|
||||||
@@ -68,4 +68,4 @@ LKMC_ENTRY
|
|||||||
TEST(64)
|
TEST(64)
|
||||||
#endif
|
#endif
|
||||||
#undef TEST
|
#undef TEST
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvt-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvt-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* SIMD positive. */
|
/* SIMD positive. */
|
||||||
.data
|
.data
|
||||||
vcvt_positive_0: .float 1.25, 2.5, 3.75, 4.0
|
vcvt_positive_0: .float 1.25, 2.5, 3.75, 4.0
|
||||||
@@ -15,7 +15,7 @@ LKMC_ENTRY
|
|||||||
vcvt.u32.f32 q1, q0
|
vcvt.u32.f32 q1, q0
|
||||||
ldr r0, =vcvt_positive_result
|
ldr r0, =vcvt_positive_result
|
||||||
vst1.32 {q1}, [r0]
|
vst1.32 {q1}, [r0]
|
||||||
LKMC_ASSERT_MEMCMP(vcvt_positive_result, vcvt_positive_expect, 0x10)
|
LKMC_ASSERT_MEMCMP(vcvt_positive_result, vcvt_positive_expect, =0x10)
|
||||||
|
|
||||||
/* SIMD negative. */
|
/* SIMD negative. */
|
||||||
.data
|
.data
|
||||||
@@ -29,7 +29,7 @@ LKMC_ENTRY
|
|||||||
vcvt.s32.f32 q1, q0
|
vcvt.s32.f32 q1, q0
|
||||||
ldr r0, =vcvt_negative_result
|
ldr r0, =vcvt_negative_result
|
||||||
vst1.32 {q1}, [r0]
|
vst1.32 {q1}, [r0]
|
||||||
LKMC_ASSERT_MEMCMP(vcvt_negative_result, vcvt_negative_expect, 0x10)
|
LKMC_ASSERT_MEMCMP(vcvt_negative_result, vcvt_negative_expect, =0x10)
|
||||||
|
|
||||||
/* Floating point. */
|
/* Floating point. */
|
||||||
.data
|
.data
|
||||||
@@ -44,7 +44,7 @@ LKMC_ENTRY
|
|||||||
vcvt.u32.f32 s0, s0
|
vcvt.u32.f32 s0, s0
|
||||||
ldr r0, =vcvt_positive_float_result
|
ldr r0, =vcvt_positive_float_result
|
||||||
vst1.32 {d0}, [r0]
|
vst1.32 {d0}, [r0]
|
||||||
LKMC_ASSERT_MEMCMP(vcvt_positive_float_result, vcvt_positive_float_expect, 0x8)
|
LKMC_ASSERT_MEMCMP(vcvt_positive_float_result, vcvt_positive_float_expect, =0x8)
|
||||||
|
|
||||||
/* Floating point but with immediates.
|
/* Floating point but with immediates.
|
||||||
*
|
*
|
||||||
@@ -85,6 +85,6 @@ LKMC_ENTRY
|
|||||||
LKMC_ASSERT_MEMCMP(
|
LKMC_ASSERT_MEMCMP(
|
||||||
vcvt_positive_double_result,
|
vcvt_positive_double_result,
|
||||||
vcvt_positive_double_expect,
|
vcvt_positive_double_expect,
|
||||||
0x4
|
=0x4
|
||||||
)
|
)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvta-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvta-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
/* SIMD positive. */
|
/* SIMD positive. */
|
||||||
.data
|
.data
|
||||||
vcvta_positive_0: .float 1.25, 2.5, 3.75, 4.0
|
vcvta_positive_0: .float 1.25, 2.5, 3.75, 4.0
|
||||||
@@ -18,7 +18,7 @@ LKMC_ENTRY
|
|||||||
LKMC_ASSERT_MEMCMP(
|
LKMC_ASSERT_MEMCMP(
|
||||||
vcvta_positive_result,
|
vcvta_positive_result,
|
||||||
vcvta_positive_expect,
|
vcvta_positive_expect,
|
||||||
0x10
|
=0x10
|
||||||
)
|
)
|
||||||
|
|
||||||
/* SIMD negative. */
|
/* SIMD negative. */
|
||||||
@@ -36,6 +36,6 @@ LKMC_ENTRY
|
|||||||
LKMC_ASSERT_MEMCMP(
|
LKMC_ASSERT_MEMCMP(
|
||||||
vcvta_negative_result,
|
vcvta_negative_result,
|
||||||
vcvta_negative_expect,
|
vcvta_negative_expect,
|
||||||
0x10
|
=0x10
|
||||||
)
|
)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvtrr-instruction */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvtrr-instruction */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
.data
|
.data
|
||||||
vcvtr_0: .float 1.25, 2.5, 3.75, 4.0
|
vcvtr_0: .float 1.25, 2.5, 3.75, 4.0
|
||||||
vcvtr_expect_zero: .word 1, 2, 3, 4
|
vcvtr_expect_zero: .word 1, 2, 3, 4
|
||||||
@@ -24,7 +24,7 @@ LKMC_ENTRY
|
|||||||
LKMC_ASSERT_MEMCMP(
|
LKMC_ASSERT_MEMCMP(
|
||||||
vcvtr_result_zero,
|
vcvtr_result_zero,
|
||||||
vcvtr_expect_zero,
|
vcvtr_expect_zero,
|
||||||
0x10
|
=0x10
|
||||||
)
|
)
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -40,7 +40,7 @@ LKMC_ENTRY
|
|||||||
LKMC_ASSERT_MEMCMP(
|
LKMC_ASSERT_MEMCMP(
|
||||||
vcvtr_result_plus_infinity,
|
vcvtr_result_plus_infinity,
|
||||||
vcvtr_expect_plus_infinity,
|
vcvtr_expect_plus_infinity,
|
||||||
0x10
|
=0x10
|
||||||
)
|
)
|
||||||
#endif
|
#endif
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */
|
|
||||||
|
|
||||||
#ifndef COMMON_H
|
|
||||||
#define COMMON_H
|
|
||||||
|
|
||||||
/* We define in this header only macros that are the same on all archs. */
|
|
||||||
|
|
||||||
/* common_arch.h contains arch specific macros. */
|
|
||||||
#include "common_arch.h"
|
|
||||||
|
|
||||||
.extern \
|
|
||||||
exit, \
|
|
||||||
printf, \
|
|
||||||
puts \
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Assert that the given branch instruction is taken. */
|
|
||||||
#define LKMC_ASSERT(branch_if_pass) \
|
|
||||||
branch_if_pass 1f; \
|
|
||||||
LKMC_FAIL; \
|
|
||||||
1: \
|
|
||||||
;
|
|
||||||
|
|
||||||
#ifndef LKMC_ASSERT_EQ_REG
|
|
||||||
/* Assert that a register equals another register. */
|
|
||||||
#define LKMC_ASSERT_EQ_REG(reg1, reg2) \
|
|
||||||
cmp reg1, reg2; \
|
|
||||||
LKMC_ASSERT(beq); \
|
|
||||||
;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly
|
* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/* See what happens on test failure with LKMC_FAIL.
|
/* See what happens on test failure with LKMC_ASSERT_FAIL.
|
||||||
* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly
|
* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
LKMC_FAIL
|
LKMC_ASSERT_FAIL
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
/* This is the main entry point for all .S examples.
|
|
||||||
* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
int asm_main(uint32_t *line);
|
|
||||||
|
|
||||||
#define ASSERT_EQ_DEFINE(bits) \
|
|
||||||
int lkmc_assert_eq_ ## bits(uint ## bits ## _t val1, uint ## bits ## _t val2) { \
|
|
||||||
if (val1 != val2) { \
|
|
||||||
printf("%s failed\n", __func__); \
|
|
||||||
printf("val1 0x%" PRIX ## bits "\n", val1); \
|
|
||||||
printf("val2 0x%" PRIX ## bits "\n", val2); \
|
|
||||||
return 1; \
|
|
||||||
} \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
ASSERT_EQ_DEFINE(32)
|
|
||||||
ASSERT_EQ_DEFINE(64)
|
|
||||||
#undef ASSERT_EQ_DEFINE
|
|
||||||
|
|
||||||
int lkmc_assert_memcmp(const void *s1, const void *s2, size_t n) {
|
|
||||||
int ret;
|
|
||||||
size_t i;
|
|
||||||
uint8_t *s1b, *s2b;
|
|
||||||
uint8_t b1, b2;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
s1b = (uint8_t *)s1;
|
|
||||||
s2b = (uint8_t *)s2;
|
|
||||||
for (i = 0; i < n; ++i) {
|
|
||||||
b1 = s1b[i];
|
|
||||||
b2 = s2b[i];
|
|
||||||
if (b1 != b2) {
|
|
||||||
printf(
|
|
||||||
"%s failed: "
|
|
||||||
"byte1, byte2, index: "
|
|
||||||
"0x%02" PRIX8 " 0x%02" PRIX8 " 0x%zX\n",
|
|
||||||
__func__,
|
|
||||||
b1,
|
|
||||||
b2,
|
|
||||||
i
|
|
||||||
);
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
uint32_t ret, line;
|
|
||||||
ret = asm_main(&line);
|
|
||||||
if (ret) {
|
|
||||||
printf("error: asm_main returned %d at line %d\n", ret, line);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
mov $1, %rax
|
mov $1, %rax
|
||||||
add $2, %rax
|
add $2, %rax
|
||||||
LKMC_ASSERT_EQ(%rax, $3)
|
LKMC_ASSERT_EQ(%rax, $3)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* Add a bunch of floating point numbers in one go.
|
* Add a bunch of floating point numbers in one go.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
.bss
|
.bss
|
||||||
output: .skip 16
|
output: .skip 16
|
||||||
.data
|
.data
|
||||||
@@ -28,4 +28,4 @@ LKMC_ENTRY
|
|||||||
/* 2x 64-bit */
|
/* 2x 64-bit */
|
||||||
TEST(d)
|
TEST(d)
|
||||||
#undef TEST
|
#undef TEST
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */
|
|
||||||
|
|
||||||
#ifndef COMMON_ARCH_H
|
|
||||||
#define COMMON_ARCH_H
|
|
||||||
|
|
||||||
/* This and other macros may make C function calls, and therefore can destroy
|
|
||||||
* non-callee saved registers. */
|
|
||||||
#define LKMC_ASSERT_EQ(general1, general2) \
|
|
||||||
mov general2, %rdi; \
|
|
||||||
push %rdi; \
|
|
||||||
mov general1, %rdi; \
|
|
||||||
pop %rsi; \
|
|
||||||
LKMC_ASSERT_EQ_DO(64); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_EQ_DO(bits) \
|
|
||||||
call lkmc_assert_eq_ ## bits; \
|
|
||||||
cmp $0, %rax; \
|
|
||||||
LKMC_ASSERT(je); \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \
|
|
||||||
lea label1(%rip), %rdi; \
|
|
||||||
lea label2(%rip), %rsi; \
|
|
||||||
mov const_size, %rdx; \
|
|
||||||
call lkmc_assert_memcmp; \
|
|
||||||
cmp $0, %rax; \
|
|
||||||
LKMC_ASSERT(je); \
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Program entry point.
|
|
||||||
*
|
|
||||||
* Return with LKMC_EXIT.
|
|
||||||
*
|
|
||||||
* Basically implements an x86_64 prologue:
|
|
||||||
*
|
|
||||||
* - save callee saved registers
|
|
||||||
* x86_64 explained at: https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call/55207335#55207335
|
|
||||||
* - save register arguments for later usage
|
|
||||||
*/
|
|
||||||
#define LKMC_ENTRY \
|
|
||||||
.text; \
|
|
||||||
.global asm_main; \
|
|
||||||
asm_main: \
|
|
||||||
push %rbp; \
|
|
||||||
mov %rsp, %rbp; \
|
|
||||||
push %r15; \
|
|
||||||
push %r14; \
|
|
||||||
push %r13; \
|
|
||||||
push %r12; \
|
|
||||||
push %rbx; \
|
|
||||||
push %rdi; \
|
|
||||||
sub $8, %rsp; \
|
|
||||||
asm_main_after_prologue: \
|
|
||||||
;
|
|
||||||
|
|
||||||
/* Meant to be called at the end of LKMC_ENTRY.*
|
|
||||||
*
|
|
||||||
* Branching to "fail" makes tests fail with exit status 1.
|
|
||||||
*
|
|
||||||
* If LKMC_EXIT is reached, the program ends successfully.
|
|
||||||
*/
|
|
||||||
#define LKMC_EXIT \
|
|
||||||
mov $0, %rax; \
|
|
||||||
jmp pass; \
|
|
||||||
fail: \
|
|
||||||
/* -0x30(%rbp) is argument 1 which we pushed at prologue */ \
|
|
||||||
mov -0x30(%rbp), %rbx; \
|
|
||||||
movl %eax, (%rbx); \
|
|
||||||
mov $1, %rax; \
|
|
||||||
pass: \
|
|
||||||
add $16, %rsp; \
|
|
||||||
pop %rbx; \
|
|
||||||
pop %r12; \
|
|
||||||
pop %r13; \
|
|
||||||
pop %r14; \
|
|
||||||
pop %r15; \
|
|
||||||
pop %rbp; \
|
|
||||||
ret; \
|
|
||||||
;
|
|
||||||
|
|
||||||
#define LKMC_FAIL \
|
|
||||||
mov $__LINE__, %eax; \
|
|
||||||
jmp fail; \
|
|
||||||
;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
#define ASSERT_DIFF(label1, label2, result) \
|
#define ASSERT_DIFF(label1, label2, result) \
|
||||||
lea label2(%rip), %rax; \
|
lea label2(%rip), %rax; \
|
||||||
lea label1(%rip), %rbx; \
|
lea label1(%rip), %rbx; \
|
||||||
@@ -15,7 +15,7 @@ LKMC_ENTRY
|
|||||||
ASSERT_DIFF(myquad, myocta, 8)
|
ASSERT_DIFF(myquad, myocta, 8)
|
||||||
ASSERT_DIFF(myocta, theend, 16)
|
ASSERT_DIFF(myocta, theend, 16)
|
||||||
#undef ASSERT_DIF
|
#undef ASSERT_DIF
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
mybyte:
|
mybyte:
|
||||||
.byte 0x12
|
.byte 0x12
|
||||||
myword:
|
myword:
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
mov $0x123456789ABCDEF0, %r12
|
mov $0x123456789ABCDEF0, %r12
|
||||||
mov $0x123456789ABCDEF0, %r13
|
mov $0x123456789ABCDEF0, %r13
|
||||||
|
|
||||||
|
/* Passing examples. */
|
||||||
|
|
||||||
|
/* Register immediate. */
|
||||||
LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF0)
|
LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF0)
|
||||||
LKMC_ASSERT_EQ(%r12, %r13)
|
|
||||||
LKMC_ASSERT_EQ(%r12, myvar)
|
|
||||||
LKMC_ASSERT_EQ($0x123456789ABCDEF0, %r12)
|
LKMC_ASSERT_EQ($0x123456789ABCDEF0, %r12)
|
||||||
|
|
||||||
|
/* Register register. */
|
||||||
|
LKMC_ASSERT_EQ(%r12, %r13)
|
||||||
LKMC_ASSERT_EQ(%r13, %r12)
|
LKMC_ASSERT_EQ(%r13, %r12)
|
||||||
|
|
||||||
|
/* Register memory. */
|
||||||
|
LKMC_ASSERT_EQ(%r12, myvar)
|
||||||
LKMC_ASSERT_EQ(myvar, %r12)
|
LKMC_ASSERT_EQ(myvar, %r12)
|
||||||
|
|
||||||
|
/* Now let's fail. */
|
||||||
LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF1)
|
LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF1)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
myvar: .quad 0x123456789ABCDEF0
|
myvar: .quad 0x123456789ABCDEF0
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
|
/* Pass */
|
||||||
LKMC_ASSERT_MEMCMP(var0, var1, $0x10)
|
LKMC_ASSERT_MEMCMP(var0, var1, $0x10)
|
||||||
|
LKMC_ASSERT_MEMCMP(var0, var1, size)
|
||||||
|
/* Fail */
|
||||||
LKMC_ASSERT_MEMCMP(var0, var2, $0x10)
|
LKMC_ASSERT_MEMCMP(var0, var2, $0x10)
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
||||||
var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444
|
||||||
var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444
|
var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444
|
||||||
|
size: .quad 0x10
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
* The different variants basically determine if carries get forwarded or not.
|
* The different variants basically determine if carries get forwarded or not.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include <lkmc.h>
|
||||||
|
|
||||||
LKMC_ENTRY
|
LKMC_PROLOGUE
|
||||||
.data
|
.data
|
||||||
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
|
input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4
|
||||||
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
|
input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515
|
||||||
@@ -35,4 +35,4 @@ LKMC_ENTRY
|
|||||||
/* 2x 16-bit */
|
/* 2x 16-bit */
|
||||||
TEST(q)
|
TEST(q)
|
||||||
#undef TEST
|
#undef TEST
|
||||||
LKMC_EXIT
|
LKMC_EPILOGUE
|
||||||
|
|||||||
Reference in New Issue
Block a user