mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
x86: mtrr: Add support for writing to MTRRs on any CPU
To enable support for the 'mtrr' command, add a way to perform MTRR operations on selected CPUs. This works by setting up a little 'operation' structure and sending it around the CPUs for action. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Wolfgang Wallner <wolfgang.wallner@br-automation.com>
This commit is contained in:
parent
aa3a4d870e
commit
8dda2baa97
3 changed files with 105 additions and 3 deletions
|
@ -221,3 +221,84 @@ int mtrr_set_next_var(uint type, uint64_t start, uint64_t size)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** enum mtrr_opcode - supported operations for mtrr_do_oper() */
|
||||||
|
enum mtrr_opcode {
|
||||||
|
MTRR_OP_SET,
|
||||||
|
MTRR_OP_SET_VALID,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct mtrr_oper - An MTRR operation to perform on a CPU
|
||||||
|
*
|
||||||
|
* @opcode: Indicates operation to perform
|
||||||
|
* @reg: MTRR reg number to select (0-7, -1 = all)
|
||||||
|
* @valid: Valid value to write for MTRR_OP_SET_VALID
|
||||||
|
* @base: Base value to write for MTRR_OP_SET
|
||||||
|
* @mask: Mask value to write for MTRR_OP_SET
|
||||||
|
*/
|
||||||
|
struct mtrr_oper {
|
||||||
|
enum mtrr_opcode opcode;
|
||||||
|
int reg;
|
||||||
|
bool valid;
|
||||||
|
u64 base;
|
||||||
|
u64 mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mtrr_do_oper(void *arg)
|
||||||
|
{
|
||||||
|
struct mtrr_oper *oper = arg;
|
||||||
|
u64 mask;
|
||||||
|
|
||||||
|
switch (oper->opcode) {
|
||||||
|
case MTRR_OP_SET_VALID:
|
||||||
|
mask = native_read_msr(MTRR_PHYS_MASK_MSR(oper->reg));
|
||||||
|
if (oper->valid)
|
||||||
|
mask |= MTRR_PHYS_MASK_VALID;
|
||||||
|
else
|
||||||
|
mask &= ~MTRR_PHYS_MASK_VALID;
|
||||||
|
wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), mask);
|
||||||
|
break;
|
||||||
|
case MTRR_OP_SET:
|
||||||
|
wrmsrl(MTRR_PHYS_BASE_MSR(oper->reg), oper->base);
|
||||||
|
wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), oper->mask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtrr_start_op(int cpu_select, struct mtrr_oper *oper)
|
||||||
|
{
|
||||||
|
struct mtrr_state state;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mtrr_open(&state, true);
|
||||||
|
ret = mp_run_on_cpus(cpu_select, mtrr_do_oper, oper);
|
||||||
|
mtrr_close(&state, true);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("run", ret);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mtrr_set_valid(int cpu_select, int reg, bool valid)
|
||||||
|
{
|
||||||
|
struct mtrr_oper oper;
|
||||||
|
|
||||||
|
oper.opcode = MTRR_OP_SET_VALID;
|
||||||
|
oper.reg = reg;
|
||||||
|
oper.valid = valid;
|
||||||
|
|
||||||
|
return mtrr_start_op(cpu_select, &oper);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mtrr_set(int cpu_select, int reg, u64 base, u64 mask)
|
||||||
|
{
|
||||||
|
struct mtrr_oper oper;
|
||||||
|
|
||||||
|
oper.opcode = MTRR_OP_SET;
|
||||||
|
oper.reg = reg;
|
||||||
|
oper.base = base;
|
||||||
|
oper.mask = mask;
|
||||||
|
|
||||||
|
return mtrr_start_op(cpu_select, &oper);
|
||||||
|
}
|
||||||
|
|
|
@ -159,6 +159,27 @@ int mtrr_set_next_var(uint type, uint64_t base, uint64_t size);
|
||||||
*/
|
*/
|
||||||
void mtrr_read_all(struct mtrr_info *info);
|
void mtrr_read_all(struct mtrr_info *info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtrr_set_valid() - Set the valid flag for a selected MTRR and CPU(s)
|
||||||
|
*
|
||||||
|
* @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...)
|
||||||
|
* @reg: MTRR register to write (0-7)
|
||||||
|
* @valid: Valid flag to write
|
||||||
|
* @return 0 on success, -ve on error
|
||||||
|
*/
|
||||||
|
int mtrr_set_valid(int cpu_select, int reg, bool valid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mtrr_set() - Set the valid flag for a selected MTRR and CPU(s)
|
||||||
|
*
|
||||||
|
* @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...)
|
||||||
|
* @reg: MTRR register to write (0-7)
|
||||||
|
* @base: Base address and MTRR_BASE_TYPE_MASK
|
||||||
|
* @mask: Mask and MTRR_PHYS_MASK_VALID
|
||||||
|
* @return 0 on success, -ve on error
|
||||||
|
*/
|
||||||
|
int mtrr_set(int cpu_select, int reg, u64 base, u64 mask);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)
|
#if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0)
|
||||||
|
|
|
@ -96,7 +96,7 @@ static int do_mtrr_set(uint reg, int argc, char *const argv[])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mtrr_set_valid(int reg, bool valid)
|
static int mtrr_set_valid_(int reg, bool valid)
|
||||||
{
|
{
|
||||||
struct mtrr_state state;
|
struct mtrr_state state;
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
|
@ -134,9 +134,9 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
return CMD_RET_USAGE;
|
return CMD_RET_USAGE;
|
||||||
}
|
}
|
||||||
if (*cmd == 'e')
|
if (*cmd == 'e')
|
||||||
return mtrr_set_valid(reg, true);
|
return mtrr_set_valid_(reg, true);
|
||||||
else if (*cmd == 'd')
|
else if (*cmd == 'd')
|
||||||
return mtrr_set_valid(reg, false);
|
return mtrr_set_valid_(reg, false);
|
||||||
else if (*cmd == 's')
|
else if (*cmd == 's')
|
||||||
return do_mtrr_set(reg, argc - 1, argv + 1);
|
return do_mtrr_set(reg, argc - 1, argv + 1);
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue