Skip to content

Commit 69b1ba8

Browse files
akky16gregkh
authored andcommitted
misc: amd-sbi: Add support for read MCA register protocol
- AMD provides custom protocol to read Machine Check Architecture(MCA) registers over sideband. The information is accessed for range of MCA registers by passing register address and thread ID to the protocol. MCA register read command using the register address to access Core::X86::Msr::MCG_CAP which determines the number of MCA banks. Access is read-only Reviewed-by: Naveen Krishna Chatradhi <[email protected]> Signed-off-by: Akshay Gupta <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent bb13a84 commit 69b1ba8

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

drivers/misc/amd-sbi/rmi-core.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,16 @@
3030
#define CPUID_WR_DATA_LEN 0x8
3131
#define CPUID_RD_REG_LEN 0xa
3232
#define CPUID_WR_REG_LEN 0x9
33+
/* MSR */
34+
#define MSR_RD_REG_LEN 0xa
35+
#define MSR_WR_REG_LEN 0x8
36+
#define MSR_RD_DATA_LEN 0x8
37+
#define MSR_WR_DATA_LEN 0x7
3338

3439
/* CPUID MSR Command Ids */
3540
#define CPUID_MCA_CMD 0x73
3641
#define RD_CPUID_CMD 0x91
42+
#define RD_MCA_CMD 0x86
3743

3844
/* CPUID MCAMSR mask & index */
3945
#define CPUID_MCA_THRD_MASK GENMASK(15, 0)
@@ -76,6 +82,16 @@ static inline void prepare_cpuid_input_message(struct cpu_msr_indata *input,
7682
input->ext = ext_func;
7783
}
7884

85+
static inline void prepare_mca_msr_input_message(struct cpu_msr_indata *input,
86+
u8 thread_id, u32 data_in)
87+
{
88+
input->rd_len = MSR_RD_DATA_LEN;
89+
input->wr_len = MSR_WR_DATA_LEN;
90+
input->proto_cmd = RD_MCA_CMD;
91+
input->thread = thread_id << 1;
92+
input->value = data_in;
93+
}
94+
7995
static int sbrmi_get_rev(struct sbrmi_data *data)
8096
{
8197
unsigned int rev;
@@ -171,6 +187,85 @@ static int rmi_cpuid_read(struct sbrmi_data *data,
171187
return ret;
172188
}
173189

190+
/* MCA MSR protocol */
191+
static int rmi_mca_msr_read(struct sbrmi_data *data,
192+
struct apml_mcamsr_msg *msg)
193+
{
194+
struct cpu_msr_outdata output = {0};
195+
struct cpu_msr_indata input = {0};
196+
int ret, val = 0;
197+
int hw_status;
198+
u16 thread;
199+
200+
mutex_lock(&data->lock);
201+
/* cache the rev value to identify if protocol is supported or not */
202+
if (!data->rev) {
203+
ret = sbrmi_get_rev(data);
204+
if (ret < 0)
205+
goto exit_unlock;
206+
}
207+
/* MCA MSR protocol for REV 0x10 is not supported*/
208+
if (data->rev == 0x10) {
209+
ret = -EOPNOTSUPP;
210+
goto exit_unlock;
211+
}
212+
213+
thread = msg->mcamsr_in_out << CPUID_MCA_THRD_INDEX & CPUID_MCA_THRD_MASK;
214+
215+
/* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */
216+
if (thread > 127) {
217+
thread -= 128;
218+
val = 1;
219+
}
220+
ret = regmap_write(data->regmap, SBRMI_THREAD128CS, val);
221+
if (ret < 0)
222+
goto exit_unlock;
223+
224+
prepare_mca_msr_input_message(&input, thread,
225+
msg->mcamsr_in_out & CPUID_MCA_FUNC_MASK);
226+
227+
ret = regmap_bulk_write(data->regmap, CPUID_MCA_CMD,
228+
&input, MSR_WR_REG_LEN);
229+
if (ret < 0)
230+
goto exit_unlock;
231+
232+
/*
233+
* For RMI Rev 0x20, new h/w status bit is introduced. which is used
234+
* by firmware to indicate completion of commands (0x71, 0x72, 0x73).
235+
* wait for the status bit to be set by the hardware before
236+
* reading the data out.
237+
*/
238+
ret = regmap_read_poll_timeout(data->regmap, SBRMI_STATUS, hw_status,
239+
hw_status & HW_ALERT_MASK, 500, 2000000);
240+
if (ret)
241+
goto exit_unlock;
242+
243+
ret = regmap_bulk_read(data->regmap, CPUID_MCA_CMD,
244+
&output, MSR_RD_REG_LEN);
245+
if (ret < 0)
246+
goto exit_unlock;
247+
248+
ret = regmap_write(data->regmap, SBRMI_STATUS,
249+
HW_ALERT_MASK);
250+
if (ret < 0)
251+
goto exit_unlock;
252+
253+
if (output.num_bytes != MSR_RD_REG_LEN - 1) {
254+
ret = -EMSGSIZE;
255+
goto exit_unlock;
256+
}
257+
if (output.status) {
258+
ret = -EPROTOTYPE;
259+
msg->fw_ret_code = output.status;
260+
goto exit_unlock;
261+
}
262+
msg->mcamsr_in_out = output.value;
263+
264+
exit_unlock:
265+
mutex_unlock(&data->lock);
266+
return ret;
267+
}
268+
174269
int rmi_mailbox_xfer(struct sbrmi_data *data,
175270
struct apml_mbox_msg *msg)
176271
{
@@ -289,6 +384,23 @@ static int apml_cpuid_xfer(struct sbrmi_data *data, struct apml_cpuid_msg __user
289384
return copy_to_user(arg, &msg, sizeof(struct apml_cpuid_msg));
290385
}
291386

387+
static int apml_mcamsr_xfer(struct sbrmi_data *data, struct apml_mcamsr_msg __user *arg)
388+
{
389+
struct apml_mcamsr_msg msg = { 0 };
390+
int ret;
391+
392+
/* Copy the structure from user */
393+
if (copy_from_user(&msg, arg, sizeof(struct apml_mcamsr_msg)))
394+
return -EFAULT;
395+
396+
/* MCAMSR Protocol */
397+
ret = rmi_mca_msr_read(data, &msg);
398+
if (ret && ret != -EPROTOTYPE)
399+
return ret;
400+
401+
return copy_to_user(arg, &msg, sizeof(struct apml_mcamsr_msg));
402+
}
403+
292404
static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
293405
{
294406
void __user *argp = (void __user *)arg;
@@ -300,6 +412,8 @@ static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
300412
return apml_mailbox_xfer(data, argp);
301413
case SBRMI_IOCTL_CPUID_CMD:
302414
return apml_cpuid_xfer(data, argp);
415+
case SBRMI_IOCTL_MCAMSR_CMD:
416+
return apml_mcamsr_xfer(data, argp);
303417
default:
304418
return -ENOTTY;
305419
}

include/uapi/misc/amd-apml.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ struct apml_cpuid_msg {
4343
__u32 pad;
4444
};
4545

46+
struct apml_mcamsr_msg {
47+
/*
48+
* MCAMSR input
49+
* [0]...[3] mca msr func,
50+
* [4][5] thread
51+
* MCAMSR output
52+
*/
53+
__u64 mcamsr_in_out;
54+
/*
55+
* Status code for MCA/MSR access
56+
*/
57+
__u32 fw_ret_code;
58+
__u32 pad;
59+
};
60+
4661
/*
4762
* AMD sideband interface base IOCTL
4863
*/
@@ -85,4 +100,22 @@ struct apml_cpuid_msg {
85100
*/
86101
#define SBRMI_IOCTL_CPUID_CMD _IOWR(SB_BASE_IOCTL_NR, 1, struct apml_cpuid_msg)
87102

103+
/**
104+
* DOC: SBRMI_IOCTL_MCAMSR_CMD
105+
*
106+
* @Parameters
107+
*
108+
* @struct apml_mcamsr_msg
109+
* Pointer to the &struct apml_mcamsr_msg that will contain the protocol
110+
* information
111+
*
112+
* @Description
113+
* IOCTL command for APML messages using generic _IOWR
114+
* The IOCTL provides userspace access to AMD sideband MCAMSR protocol
115+
* - MCAMSR protocol to get MCA bank details for Function at thread level
116+
* - returning "-EFAULT" if none of the above
117+
* "-EPROTOTYPE" error is returned to provide additional error details
118+
*/
119+
#define SBRMI_IOCTL_MCAMSR_CMD _IOWR(SB_BASE_IOCTL_NR, 2, struct apml_mcamsr_msg)
120+
88121
#endif /*_AMD_APML_H_*/

0 commit comments

Comments
 (0)