1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
/*
* Constants for memory operations
*
* Authors:
* Richard Henderson <rth@twiddle.net>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#ifndef MEMOP_H
#define MEMOP_H
#include "qemu/host-utils.h"
typedef enum MemOp {
MO_8 = 0,
MO_16 = 1,
MO_32 = 2,
MO_64 = 3,
MO_128 = 4,
MO_256 = 5,
MO_512 = 6,
MO_1024 = 7,
MO_SIZE = 0x07, /* Mask for the above. */
MO_SIGN = 0x08, /* Sign-extended, otherwise zero-extended. */
MO_BSWAP = 0x10, /* Host reverse endian. */
#if HOST_BIG_ENDIAN
MO_LE = MO_BSWAP,
MO_BE = 0,
#else
MO_LE = 0,
MO_BE = MO_BSWAP,
#endif
#ifdef COMPILING_PER_TARGET
#ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
#if TARGET_BIG_ENDIAN
MO_TE = MO_BE,
#else
MO_TE = MO_LE,
#endif
#endif
#endif
/*
* MO_UNALN accesses are never checked for alignment.
* MO_ALIGN accesses will result in a call to the CPU's
* do_unaligned_access hook if the guest address is not aligned.
*
* Some architectures (e.g. ARMv8) need the address which is aligned
* to a size more than the size of the memory access.
* Some architectures (e.g. SPARCv9) need an address which is aligned,
* but less strictly than the natural alignment.
*
* MO_ALIGN supposes the alignment size is the size of a memory access.
*
* There are three options:
* - unaligned access permitted (MO_UNALN).
* - an alignment to the size of an access (MO_ALIGN);
* - an alignment to a specified size, which may be more or less than
* the access size (MO_ALIGN_x where 'x' is a size in bytes);
*/
MO_ASHIFT = 5,
MO_AMASK = 0x7 << MO_ASHIFT,
MO_UNALN = 0,
MO_ALIGN_2 = 1 << MO_ASHIFT,
MO_ALIGN_4 = 2 << MO_ASHIFT,
MO_ALIGN_8 = 3 << MO_ASHIFT,
MO_ALIGN_16 = 4 << MO_ASHIFT,
MO_ALIGN_32 = 5 << MO_ASHIFT,
MO_ALIGN_64 = 6 << MO_ASHIFT,
MO_ALIGN = MO_AMASK,
/*
* MO_ALIGN_TLB_ONLY:
* Apply MO_AMASK only along the TCG slow path if TLB_CHECK_ALIGNED
* is set; otherwise unaligned access is permitted.
* This is used by target/arm, where unaligned accesses are
* permitted for pages marked Normal but aligned accesses are
* required for pages marked Device.
*/
MO_ALIGN_TLB_ONLY = 1 << 8,
/*
* MO_ATOM_* describes the atomicity requirements of the operation:
* MO_ATOM_IFALIGN: the operation must be single-copy atomic if it
* is aligned; if unaligned there is no atomicity.
* MO_ATOM_IFALIGN_PAIR: the entire operation may be considered to
* be a pair of half-sized operations which are packed together
* for convenience, with single-copy atomicity on each half if
* the half is aligned.
* This is the atomicity e.g. of Arm pre-FEAT_LSE2 LDP.
* MO_ATOM_WITHIN16: the operation is single-copy atomic, even if it
* is unaligned, so long as it does not cross a 16-byte boundary;
* if it crosses a 16-byte boundary there is no atomicity.
* This is the atomicity e.g. of Arm FEAT_LSE2 LDR.
* MO_ATOM_WITHIN16_PAIR: the entire operation is single-copy atomic,
* if it happens to be within a 16-byte boundary, otherwise it
* devolves to a pair of half-sized MO_ATOM_WITHIN16 operations.
* Depending on alignment, one or both will be single-copy atomic.
* This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
* MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
* by the alignment. E.g. if an 8-byte value is accessed at an
* address which is 0 mod 8, then the whole 8-byte access is
* single-copy atomic; otherwise, if it is accessed at 0 mod 4
* then each 4-byte subobject is single-copy atomic; otherwise
* if it is accessed at 0 mod 2 then the four 2-byte subobjects
* are single-copy atomic.
* This is the atomicity e.g. of IBM Power.
* MO_ATOM_NONE: the operation has no atomicity requirements.
*
* Note the default (i.e. 0) value is single-copy atomic to the
* size of the operation, if aligned. This retains the behaviour
* from before this field was introduced.
*/
MO_ATOM_SHIFT = 9,
MO_ATOM_IFALIGN = 0 << MO_ATOM_SHIFT,
MO_ATOM_IFALIGN_PAIR = 1 << MO_ATOM_SHIFT,
MO_ATOM_WITHIN16 = 2 << MO_ATOM_SHIFT,
MO_ATOM_WITHIN16_PAIR = 3 << MO_ATOM_SHIFT,
MO_ATOM_SUBALIGN = 4 << MO_ATOM_SHIFT,
MO_ATOM_NONE = 5 << MO_ATOM_SHIFT,
MO_ATOM_MASK = 7 << MO_ATOM_SHIFT,
/* Combinations of the above, for ease of use. */
MO_UB = MO_8,
MO_UW = MO_16,
MO_UL = MO_32,
MO_UQ = MO_64,
MO_UO = MO_128,
MO_SB = MO_SIGN | MO_8,
MO_SW = MO_SIGN | MO_16,
MO_SL = MO_SIGN | MO_32,
MO_SQ = MO_SIGN | MO_64,
MO_SO = MO_SIGN | MO_128,
MO_LEUW = MO_LE | MO_UW,
MO_LEUL = MO_LE | MO_UL,
MO_LEUQ = MO_LE | MO_UQ,
MO_LESW = MO_LE | MO_SW,
MO_LESL = MO_LE | MO_SL,
MO_LESQ = MO_LE | MO_SQ,
MO_BEUW = MO_BE | MO_UW,
MO_BEUL = MO_BE | MO_UL,
MO_BEUQ = MO_BE | MO_UQ,
MO_BESW = MO_BE | MO_SW,
MO_BESL = MO_BE | MO_SL,
MO_BESQ = MO_BE | MO_SQ,
#ifdef COMPILING_PER_TARGET
#ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
MO_TEUW = MO_TE | MO_UW,
MO_TEUL = MO_TE | MO_UL,
MO_TEUQ = MO_TE | MO_UQ,
MO_TEUO = MO_TE | MO_UO,
MO_TESW = MO_TE | MO_SW,
MO_TESL = MO_TE | MO_SL,
MO_TESQ = MO_TE | MO_SQ,
#endif
#endif
MO_SSIZE = MO_SIZE | MO_SIGN,
} MemOp;
/* MemOp to size in bytes. */
static inline unsigned memop_size(MemOp op)
{
return 1 << (op & MO_SIZE);
}
/* Size in bytes to MemOp. */
static inline MemOp size_memop(unsigned size)
{
#ifdef CONFIG_DEBUG_TCG
/* Power of 2 up to 1024 */
assert(is_power_of_2(size) && size >= 1 && size <= (1 << MO_SIZE));
#endif
return (MemOp)ctz32(size);
}
/**
* memop_tlb_alignment_bits:
* @memop: MemOp value
*
* Extract the alignment size for use with TLB_CHECK_ALIGNED.
*/
static inline unsigned memop_tlb_alignment_bits(MemOp memop, bool tlb_check)
{
unsigned a = memop & MO_AMASK;
if (a == MO_UNALN || (!tlb_check && (memop & MO_ALIGN_TLB_ONLY))) {
/* No alignment required. */
a = 0;
} else if (a == MO_ALIGN) {
/* A natural alignment requirement. */
a = memop & MO_SIZE;
} else {
/* A specific alignment requirement. */
a = a >> MO_ASHIFT;
}
return a;
}
/**
* memop_alignment_bits:
* @memop: MemOp value
*
* Extract the alignment size from the memop.
*/
static inline unsigned memop_alignment_bits(MemOp memop)
{
return memop_tlb_alignment_bits(memop, false);
}
#endif
|