Skip to content

Commit

Permalink
target/arm: Factor out FWB=0 specific part of combine_cacheattrs()
Browse files Browse the repository at this point in the history
Factor out the part of combine_cacheattrs() that is specific to
handling HCR_EL2.FWB == 0.  This is the part where we combine the
memory type and cacheability attributes.

The "force Outer Shareable for Device or Normal Inner-NC Outer-NC"
logic remains in combine_cacheattrs() because it holds regardless
(this is the equivalent of the pseudocode EffectiveShareability()
function).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220505183950.2781801-3-peter.maydell@linaro.org
  • Loading branch information
pm215 committed May 19, 2022
1 parent 9f225e6 commit 4a0b47c
Showing 1 changed file with 50 additions and 38 deletions.
88 changes: 50 additions & 38 deletions target/arm/helper.c
Expand Up @@ -12578,6 +12578,46 @@ static uint8_t combine_cacheattr_nibble(uint8_t s1, uint8_t s2)
}
}

/*
* Combine the memory type and cacheability attributes of
* s1 and s2 for the HCR_EL2.FWB == 0 case, returning the
* combined attributes in MAIR_EL1 format.
*/
static uint8_t combined_attrs_nofwb(CPUARMState *env,
ARMCacheAttrs s1, ARMCacheAttrs s2)
{
uint8_t s1lo, s2lo, s1hi, s2hi, s2_mair_attrs, ret_attrs;

s2_mair_attrs = convert_stage2_attrs(env, s2.attrs);

s1lo = extract32(s1.attrs, 0, 4);
s2lo = extract32(s2_mair_attrs, 0, 4);
s1hi = extract32(s1.attrs, 4, 4);
s2hi = extract32(s2_mair_attrs, 4, 4);

/* Combine memory type and cacheability attributes */
if (s1hi == 0 || s2hi == 0) {
/* Device has precedence over normal */
if (s1lo == 0 || s2lo == 0) {
/* nGnRnE has precedence over anything */
ret_attrs = 0;
} else if (s1lo == 4 || s2lo == 4) {
/* non-Reordering has precedence over Reordering */
ret_attrs = 4; /* nGnRE */
} else if (s1lo == 8 || s2lo == 8) {
/* non-Gathering has precedence over Gathering */
ret_attrs = 8; /* nGRE */
} else {
ret_attrs = 0xc; /* GRE */
}
} else { /* Normal memory */
/* Outer/inner cacheability combine independently */
ret_attrs = combine_cacheattr_nibble(s1hi, s2hi) << 4
| combine_cacheattr_nibble(s1lo, s2lo);
}
return ret_attrs;
}

/* Combine S1 and S2 cacheability/shareability attributes, per D4.5.4
* and CombineS1S2Desc()
*
Expand All @@ -12588,26 +12628,17 @@ static uint8_t combine_cacheattr_nibble(uint8_t s1, uint8_t s2)
static ARMCacheAttrs combine_cacheattrs(CPUARMState *env,
ARMCacheAttrs s1, ARMCacheAttrs s2)
{
uint8_t s1lo, s2lo, s1hi, s2hi;
ARMCacheAttrs ret;
bool tagged = false;
uint8_t s2_mair_attrs;

assert(s2.is_s2_format && !s1.is_s2_format);
ret.is_s2_format = false;

s2_mair_attrs = convert_stage2_attrs(env, s2.attrs);

if (s1.attrs == 0xf0) {
tagged = true;
s1.attrs = 0xff;
}

s1lo = extract32(s1.attrs, 0, 4);
s2lo = extract32(s2_mair_attrs, 0, 4);
s1hi = extract32(s1.attrs, 4, 4);
s2hi = extract32(s2_mair_attrs, 4, 4);

/* Combine shareability attributes (table D4-43) */
if (s1.shareability == 2 || s2.shareability == 2) {
/* if either are outer-shareable, the result is outer-shareable */
Expand All @@ -12621,37 +12652,18 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env,
}

/* Combine memory type and cacheability attributes */
if (s1hi == 0 || s2hi == 0) {
/* Device has precedence over normal */
if (s1lo == 0 || s2lo == 0) {
/* nGnRnE has precedence over anything */
ret.attrs = 0;
} else if (s1lo == 4 || s2lo == 4) {
/* non-Reordering has precedence over Reordering */
ret.attrs = 4; /* nGnRE */
} else if (s1lo == 8 || s2lo == 8) {
/* non-Gathering has precedence over Gathering */
ret.attrs = 8; /* nGRE */
} else {
ret.attrs = 0xc; /* GRE */
}
ret.attrs = combined_attrs_nofwb(env, s1, s2);

/* Any location for which the resultant memory type is any
* type of Device memory is always treated as Outer Shareable.
*/
/*
* Any location for which the resultant memory type is any
* type of Device memory is always treated as Outer Shareable.
* Any location for which the resultant memory type is Normal
* Inner Non-cacheable, Outer Non-cacheable is always treated
* as Outer Shareable.
* TODO: FEAT_XS adds another value (0x40) also meaning iNCoNC
*/
if ((ret.attrs & 0xf0) == 0 || ret.attrs == 0x44) {
ret.shareability = 2;
} else { /* Normal memory */
/* Outer/inner cacheability combine independently */
ret.attrs = combine_cacheattr_nibble(s1hi, s2hi) << 4
| combine_cacheattr_nibble(s1lo, s2lo);

if (ret.attrs == 0x44) {
/* Any location for which the resultant memory type is Normal
* Inner Non-cacheable, Outer Non-cacheable is always treated
* as Outer Shareable.
*/
ret.shareability = 2;
}
}

/* TODO: CombineS1S2Desc does not consider transient, only WB, RWA. */
Expand Down

0 comments on commit 4a0b47c

Please sign in to comment.