mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-26 20:12:44 +00:00
arm64: Support more ID register field types
Add MRS_EXACT_IF_DIFFERENT, MRS_HIGHER_OR_ZERO, and MRS_HIGHER. These will be used to handle the cache CTR_EL0 register, and make some ID register values safer. They are: - MRS_EXACT_IF_DIFFERENT: If the field is the same on all CPUs then use this value, otherwise use the safe value. - MRS_HIGHER_OR_ZERO: Use the highest value, or zero if seen, - MRS_HIGHER: Use the highest value. Reviewed by: imp Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D47122
This commit is contained in:
parent
f031499405
commit
f1fb1d5c90
@ -292,7 +292,10 @@ const struct cpu_implementers cpu_implementers[] = {
|
||||
#define MRS_TYPE_MASK 0xf
|
||||
#define MRS_INVALID 0
|
||||
#define MRS_EXACT 1
|
||||
#define MRS_LOWER 2
|
||||
#define MRS_EXACT_IF_DIFFERENT 2
|
||||
#define MRS_LOWER 3
|
||||
#define MRS_HIGHER_OR_ZERO 4
|
||||
#define MRS_HIGHER 5
|
||||
#define MRS_SAFE_SHIFT 4
|
||||
#define MRS_SAFE_MASK (0xfu << MRS_SAFE_SHIFT)
|
||||
#define MRS_SAFE(x) (((x) << MRS_SAFE_SHIFT) & MRS_SAFE_MASK)
|
||||
@ -2175,19 +2178,41 @@ static uint64_t
|
||||
update_special_reg_field(uint64_t user_reg, u_int type, uint64_t value,
|
||||
u_int width, u_int shift, bool sign)
|
||||
{
|
||||
uint64_t cur, mask, new_val;
|
||||
|
||||
mask = ((1ul << width) - 1) << shift;
|
||||
cur = user_reg & mask;
|
||||
new_val = value & mask;
|
||||
|
||||
switch (type & MRS_TYPE_MASK) {
|
||||
case MRS_EXACT_IF_DIFFERENT:
|
||||
if (mrs_field_cmp(cur, new_val, shift, width, sign) != 0)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
case MRS_EXACT:
|
||||
user_reg &= ~(0xful << shift);
|
||||
user_reg |= (uint64_t)MRS_SAFE(type) << shift;
|
||||
cur = (uint64_t)MRS_SAFE_VAL(type) << shift;
|
||||
break;
|
||||
case MRS_LOWER:
|
||||
user_reg = update_lower_register(user_reg, value, shift, width,
|
||||
sign);
|
||||
if (mrs_field_cmp(cur, new_val, shift, width, sign) < 0)
|
||||
cur = new_val;
|
||||
break;
|
||||
case MRS_HIGHER_OR_ZERO:
|
||||
if (cur == 0 || new_val == 0) {
|
||||
cur = 0;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case MRS_HIGHER:
|
||||
if (mrs_field_cmp(cur, new_val, shift, width, sign) > 0)
|
||||
cur = new_val;
|
||||
break;
|
||||
default:
|
||||
panic("Invalid field type: %d", type);
|
||||
}
|
||||
|
||||
user_reg &= ~mask;
|
||||
user_reg |= cur;
|
||||
|
||||
return (user_reg);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user