1 // Copyright 2017 The Fuchsia Authors
2 //
3 // Use of this source code is governed by a MIT-style
4 // license that can be found in the LICENSE file or at
5 // https://opensource.org/licenses/MIT
6 
7 #pragma once
8 
9 #if defined(__ASSEMBLER__)
10 
11 // This is used in assembly code to specify a code fragment that will get
12 // filled in by the given function, patch_func() when the kernel starts up.
13 // |loc| specifies which code will be patched up, so that a functioning
14 // version of the code may be used before patching takes place.  This is
15 // needed, for example, for memcpy and memset.
16 #define APPLY_CODE_PATCH_FUNC_WITH_DEFAULT(patch_func, loc, size_in_bytes) \
17     /* Add "struct CodePatchInfo" entry to the code_patch_table array. */  \
18     .pushsection code_patch_table,"a",%progbits;                           \
19     .balign 8;                                                             \
20     .quad patch_func; /* apply_func field */                               \
21     .quad loc; /* dest_addr field */                                       \
22     .quad size_in_bytes; /* dest_size field */                             \
23     .popsection
24 
25 // This is used in assembly code to specify a code fragment that will get
26 // filled in by the given function, patch_func(), when the kernel starts
27 // up.  This is used for selecting instructions based on which instructions
28 // the CPU supports.
29 #define APPLY_CODE_PATCH_FUNC(patch_func, size_in_bytes)                  \
30     0:                                                                    \
31     /* Allocate placeholder code.  We fill this with the 1-byte int3 */   \
32     /* instruction (0xcc), which will fault if we accidentally execute */ \
33     /* it before applying the patch. */                                   \
34     .fill size_in_bytes, 1, 0xcc;                                         \
35     APPLY_CODE_PATCH_FUNC_WITH_DEFAULT(patch_func, 0b, size_in_bytes)
36 
37 #else
38 
39 #include <stdint.h>
40 
41 struct CodePatchInfo {
42     void (*apply_func)(const CodePatchInfo* patch);
43     uint8_t* dest_addr; // Destination code address to patch.
44     uint64_t dest_size; // Size of placeholder code.
45 };
46 
47 // CODE_TEMPLATE(kVar, "asm...") assembles the given assembly code and
48 // makes the resulting bytes available in a global variable, kVar.  kVarEnd
49 // specifies the end address of kVar, allowing the size of the code
50 // fragment to be calculated.
51 #define CODE_TEMPLATE(name, asm_code)                              \
52     extern const uint8_t name[];                                   \
53     extern const uint8_t name##End[];                              \
54     __asm__(".pushsection .rodata.code_template,\"a\",%progbits\n" \
55             ".global " #name "\n"                                  \
56             ".global " #name "End\n"                               \
57             #name ":\n"                                            \
58             asm_code "\n"                                          \
59             #name "End:\n"                                         \
60             ".popsection");
61 
62 #endif
63