| 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
| 2 | /* |
| 3 | * Definition of TranslationBlock. |
| 4 | * Copyright (c) 2003 Fabrice Bellard |
| 5 | */ |
| 6 | |
| 7 | #ifndef EXEC_TRANSLATION_BLOCK_H |
| 8 | #define EXEC_TRANSLATION_BLOCK_H |
| 9 | |
| 10 | #include "qemu/atomic.h" |
| 11 | #include "qemu/thread.h" |
| 12 | #include "exec/cpu-common.h" |
| 13 | #include "exec/vaddr.h" |
| 14 | #ifdef CONFIG_USER_ONLY |
| 15 | #include "qemu/interval-tree.h" |
| 16 | #include "exec/target_page.h" |
| 17 | #else |
| 18 | #include "system/ram_addr.h" |
| 19 | #endif |
| 20 | |
| 21 | /* |
| 22 | * Page tracking code uses ram addresses in system mode, and virtual |
| 23 | * addresses in userspace mode. Define tb_page_addr_t to be an |
| 24 | * appropriate type. |
| 25 | */ |
| 26 | #if defined(CONFIG_USER_ONLY) |
| 27 | typedef vaddr tb_page_addr_t; |
| 28 | #define TB_PAGE_ADDR_FMT "%" VADDR_PRIx |
| 29 | #else |
| 30 | typedef ram_addr_t tb_page_addr_t; |
| 31 | #define TB_PAGE_ADDR_FMT RAM_ADDR_FMT |
| 32 | #endif |
| 33 | |
| 34 | /* |
| 35 | * Translation Cache-related fields of a TB. |
| 36 | * This struct exists just for convenience; we keep track of TB's in a binary |
| 37 | * search tree, and the only fields needed to compare TB's in the tree are |
| 38 | * @ptr and @size. |
| 39 | * Note: the address of search data can be obtained by adding @size to @ptr. |
| 40 | */ |
| 41 | struct tb_tc { |
| 42 | const void *ptr; /* pointer to the translated code */ |
| 43 | size_t size; |
| 44 | }; |
| 45 | |
| 46 | struct TranslationBlock { |
| 47 | /* |
| 48 | * Guest PC corresponding to this block. This must be the true |
| 49 | * virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and |
| 50 | * targets like Arm, MIPS, HP-PA, which reuse low bits for ISA or |
| 51 | * privilege, must store those bits elsewhere. |
| 52 | * |
| 53 | * If CF_PCREL, the opcodes for the TranslationBlock are written |
| 54 | * such that the TB is associated only with the physical page and |
| 55 | * may be run in any virtual address context. In this case, PC |
| 56 | * must always be taken from ENV in a target-specific manner. |
| 57 | * Unwind information is taken as offsets from the page, to be |
| 58 | * deposited into the "current" PC. |
| 59 | */ |
| 60 | vaddr pc; |
| 61 | |
| 62 | /* |
| 63 | * Target-specific data associated with the TranslationBlock, e.g.: |
| 64 | * x86: the original user, the Code Segment virtual base, |
| 65 | * arm: an extension of tb->flags, |
| 66 | * s390x: instruction data for EXECUTE, |
| 67 | * sparc: the next pc of the instruction queue (for delay slots). |
| 68 | * riscv: an extension of tb->flags, |
| 69 | */ |
| 70 | uint64_t cs_base; |
| 71 | |
| 72 | uint32_t flags; /* flags defining in which context the code was generated */ |
| 73 | uint32_t cflags; /* compile flags */ |
| 74 | |
| 75 | /* Note that TCG_MAX_INSNS is 512; we validate this match elsewhere. */ |
| 76 | #define CF_COUNT_MASK 0x000001ff |
| 77 | #define CF_NO_GOTO_TB 0x00000200 /* Do not chain with goto_tb */ |
| 78 | #define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */ |
| 79 | #define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */ |
| 80 | #define CF_MEMI_ONLY 0x00001000 /* Only instrument memory ops */ |
| 81 | #define CF_USE_ICOUNT 0x00002000 |
| 82 | #define CF_INVALID 0x00004000 /* TB is stale. Set with @jmp_lock held */ |
| 83 | #define CF_PARALLEL 0x00008000 /* Generate code for a parallel context */ |
| 84 | #define CF_NOIRQ 0x00010000 /* Generate an uninterruptible TB */ |
| 85 | #define CF_PCREL 0x00020000 /* Opcodes in TB are PC-relative */ |
| 86 | #define CF_BP_PAGE 0x00040000 /* Breakpoint present in code page */ |
| 87 | #define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */ |
| 88 | #define CF_CLUSTER_SHIFT 24 |
| 89 | |
| 90 | /* |
| 91 | * Above fields used for comparing |
| 92 | */ |
| 93 | |
| 94 | /* size of target code for this block (1 <= size <= TARGET_PAGE_SIZE) */ |
| 95 | uint16_t size; |
| 96 | uint16_t icount; |
| 97 | |
| 98 | struct tb_tc tc; |
| 99 | |
| 100 | /* |
| 101 | * Track tb_page_addr_t intervals that intersect this TB. |
| 102 | * For user-only, the virtual addresses are always contiguous, |
| 103 | * and we use a unified interval tree. For system, we use a |
| 104 | * linked list headed in each PageDesc. Within the list, the lsb |
| 105 | * of the previous pointer tells the index of page_next[], and the |
| 106 | * list is protected by the PageDesc lock(s). |
| 107 | */ |
| 108 | #ifdef CONFIG_USER_ONLY |
| 109 | IntervalTreeNode itree; |
| 110 | #else |
| 111 | uintptr_t page_next[2]; |
| 112 | tb_page_addr_t page_addr[2]; |
| 113 | #endif |
| 114 | |
| 115 | /* jmp_lock placed here to fill a 4-byte hole. Its documentation is below */ |
| 116 | QemuSpin jmp_lock; |
| 117 | |
| 118 | /* The following data are used to directly call another TB from |
| 119 | * the code of this one. This can be done either by emitting direct or |
| 120 | * indirect native jump instructions. These jumps are reset so that the TB |
| 121 | * just continues its execution. The TB can be linked to another one by |
| 122 | * setting one of the jump targets (or patching the jump instruction). Only |
| 123 | * two of such jumps are supported. |
| 124 | */ |
| 125 | #define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */ |
| 126 | uint16_t jmp_reset_offset[2]; /* offset of original jump target */ |
| 127 | uint16_t jmp_insn_offset[2]; /* offset of direct jump insn */ |
| 128 | uintptr_t jmp_target_addr[2]; /* target address */ |
| 129 | |
| 130 | /* |
| 131 | * Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps. |
| 132 | * Each TB can have two outgoing jumps, and therefore can participate |
| 133 | * in two lists. The list entries are kept in jmp_list_next[2]. The least |
| 134 | * significant bit (LSB) of the pointers in these lists is used to encode |
| 135 | * which of the two list entries is to be used in the pointed TB. |
| 136 | * |
| 137 | * List traversals are protected by jmp_lock. The destination TB of each |
| 138 | * outgoing jump is kept in jmp_dest[] so that the appropriate jmp_lock |
| 139 | * can be acquired from any origin TB. |
| 140 | * |
| 141 | * jmp_dest[] are tagged pointers as well. The LSB is set when the TB is |
| 142 | * being invalidated, so that no further outgoing jumps from it can be set. |
| 143 | * |
| 144 | * jmp_lock also protects the CF_INVALID cflag; a jump must not be chained |
| 145 | * to a destination TB that has CF_INVALID set. |
| 146 | */ |
| 147 | uintptr_t jmp_list_head; |
| 148 | uintptr_t jmp_list_next[2]; |
| 149 | uintptr_t jmp_dest[2]; |
| 150 | }; |
| 151 | |
| 152 | /* The alignment given to TranslationBlock during allocation. */ |
| 153 | #define CODE_GEN_ALIGN 16 |
| 154 | |
| 155 | /* Hide the qatomic_read to make code a little easier on the eyes */ |
| 156 | static inline uint32_t tb_cflags(const TranslationBlock *tb) |
| 157 | { |
| 158 | return qatomic_read(&tb->cflags); |
| 159 | } |
| 160 | |
| 161 | bool tcg_cflags_has(CPUState *cpu, uint32_t flags); |
| 162 | void tcg_cflags_set(CPUState *cpu, uint32_t flags); |
| 163 | |
| 164 | static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb) |
| 165 | { |
| 166 | #ifdef CONFIG_USER_ONLY |
| 167 | return tb->itree.start; |
| 168 | #else |
| 169 | return tb->page_addr[0]; |
| 170 | #endif |
| 171 | } |
| 172 | |
| 173 | static inline tb_page_addr_t tb_page_addr1(const TranslationBlock *tb) |
| 174 | { |
| 175 | #ifdef CONFIG_USER_ONLY |
| 176 | tb_page_addr_t next = tb->itree.last & TARGET_PAGE_MASK; |
| 177 | return next == (tb->itree.start & TARGET_PAGE_MASK) ? -1 : next; |
| 178 | #else |
| 179 | return tb->page_addr[1]; |
| 180 | #endif |
| 181 | } |
| 182 | |
| 183 | static inline void tb_set_page_addr0(TranslationBlock *tb, |
| 184 | tb_page_addr_t addr) |
| 185 | { |
| 186 | #ifdef CONFIG_USER_ONLY |
| 187 | tb->itree.start = addr; |
| 188 | /* |
| 189 | * To begin, we record an interval of one byte. When the translation |
| 190 | * loop encounters a second page, the interval will be extended to |
| 191 | * include the first byte of the second page, which is sufficient to |
| 192 | * allow tb_page_addr1() above to work properly. The final corrected |
| 193 | * interval will be set by tb_page_add() from tb->size before the |
| 194 | * node is added to the interval tree. |
| 195 | */ |
| 196 | tb->itree.last = addr; |
| 197 | #else |
| 198 | tb->page_addr[0] = addr; |
| 199 | #endif |
| 200 | } |
| 201 | |
| 202 | static inline void tb_set_page_addr1(TranslationBlock *tb, |
| 203 | tb_page_addr_t addr) |
| 204 | { |
| 205 | #ifdef CONFIG_USER_ONLY |
| 206 | /* Extend the interval to the first byte of the second page. See above. */ |
| 207 | tb->itree.last = addr; |
| 208 | #else |
| 209 | tb->page_addr[1] = addr; |
| 210 | #endif |
| 211 | } |
| 212 | |
| 213 | /* TranslationBlock invalidate API */ |
| 214 | void tb_invalidate_phys_range(CPUState *cpu, tb_page_addr_t start, |
| 215 | tb_page_addr_t last); |
| 216 | |
| 217 | #endif /* EXEC_TRANSLATION_BLOCK_H */ |