accel/tcg: Introduce and use MO_ALIGN_TLB_ONLY
For Arm, we need 3 cases: (1) the alignment required when accessing Normal memory, (2) the alignment required when accessing Device memory, and (3) the atomicity of the access. When we added TLB_CHECK_ALIGNED, we assumed that cases 2 and 3 were identical, and thus used memop_atomicity_bits for TLB_CHECK_ALIGNED. This is incorrect for multiple reasons, including that the atomicity of the access is adjusted depending on whether or not we are executing within a serial context. For Arm, what is true is that there is an underlying alignment requirement of the access, and for that access Normal memory will support unalignement. Introduce MO_ALIGN_TLB_ONLY to indicate that the alignment specified in MO_AMASK only applies when the TLB entry has TLB_CHECK_ALIGNED set; otherwise no alignment required. Introduce memop_tlb_alignment_bits with an additional bool argument that specifies whether TLB_CHECK_ALIGNED is set. All other usage of memop_alignment_bits assumes it is not. Remove memop_atomicity_bits as unused; it didn't properly support MO_ATOM_SUBWORD anyway. Update target/arm finalize_memop_atom to set MO_ALIGN_TLB_ONLY when strict alignment isn't otherwise required. Suggested-by: Peter Maydell <peter.maydell@linaro.org> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3171 Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
parent
3728de3192
commit
4dea00368d
7 changed files with 35 additions and 49 deletions
|
|
@ -72,6 +72,16 @@ typedef enum MemOp {
|
|||
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
|
||||
|
|
@ -104,7 +114,7 @@ typedef enum MemOp {
|
|||
* size of the operation, if aligned. This retains the behaviour
|
||||
* from before this field was introduced.
|
||||
*/
|
||||
MO_ATOM_SHIFT = 8,
|
||||
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,
|
||||
|
|
@ -169,16 +179,16 @@ static inline MemOp size_memop(unsigned size)
|
|||
}
|
||||
|
||||
/**
|
||||
* memop_alignment_bits:
|
||||
* memop_tlb_alignment_bits:
|
||||
* @memop: MemOp value
|
||||
*
|
||||
* Extract the alignment size from the memop.
|
||||
* Extract the alignment size for use with TLB_CHECK_ALIGNED.
|
||||
*/
|
||||
static inline unsigned memop_alignment_bits(MemOp memop)
|
||||
static inline unsigned memop_tlb_alignment_bits(MemOp memop, bool tlb_check)
|
||||
{
|
||||
unsigned a = memop & MO_AMASK;
|
||||
|
||||
if (a == MO_UNALN) {
|
||||
if (a == MO_UNALN || (!tlb_check && (memop & MO_ALIGN_TLB_ONLY))) {
|
||||
/* No alignment required. */
|
||||
a = 0;
|
||||
} else if (a == MO_ALIGN) {
|
||||
|
|
@ -191,28 +201,15 @@ static inline unsigned memop_alignment_bits(MemOp memop)
|
|||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
* memop_atomicity_bits:
|
||||
/**
|
||||
* memop_alignment_bits:
|
||||
* @memop: MemOp value
|
||||
*
|
||||
* Extract the atomicity size from the memop.
|
||||
* Extract the alignment size from the memop.
|
||||
*/
|
||||
static inline unsigned memop_atomicity_bits(MemOp memop)
|
||||
static inline unsigned memop_alignment_bits(MemOp memop)
|
||||
{
|
||||
unsigned size = memop & MO_SIZE;
|
||||
|
||||
switch (memop & MO_ATOM_MASK) {
|
||||
case MO_ATOM_NONE:
|
||||
size = MO_8;
|
||||
break;
|
||||
case MO_ATOM_IFALIGN_PAIR:
|
||||
case MO_ATOM_WITHIN16_PAIR:
|
||||
size = size ? size - 1 : 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
return memop_tlb_alignment_bits(memop, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue