Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <naveenkrishna.chatradhi@amd.com>
Signed-off-by: Akshay Gupta <akshay.gupta@amd.com>
Link: https://lore.kernel.org/r/20250428063034.2145566-9-akshay.gupta@amd.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Akshay Gupta and committed by
Greg Kroah-Hartman
69b1ba83 bb13a84e

+147
+114
drivers/misc/amd-sbi/rmi-core.c
··· 30 30 #define CPUID_WR_DATA_LEN 0x8 31 31 #define CPUID_RD_REG_LEN 0xa 32 32 #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 33 38 34 39 /* CPUID MSR Command Ids */ 35 40 #define CPUID_MCA_CMD 0x73 36 41 #define RD_CPUID_CMD 0x91 42 + #define RD_MCA_CMD 0x86 37 43 38 44 /* CPUID MCAMSR mask & index */ 39 45 #define CPUID_MCA_THRD_MASK GENMASK(15, 0) ··· 80 74 input->thread = thread_id << 1; 81 75 input->value = func; 82 76 input->ext = ext_func; 77 + } 78 + 79 + static inline void prepare_mca_msr_input_message(struct cpu_msr_indata *input, 80 + u8 thread_id, u32 data_in) 81 + { 82 + input->rd_len = MSR_RD_DATA_LEN; 83 + input->wr_len = MSR_WR_DATA_LEN; 84 + input->proto_cmd = RD_MCA_CMD; 85 + input->thread = thread_id << 1; 86 + input->value = data_in; 83 87 } 84 88 85 89 static int sbrmi_get_rev(struct sbrmi_data *data) ··· 183 167 exit_unlock: 184 168 if (ret < 0) 185 169 msg->cpu_in_out = 0; 170 + mutex_unlock(&data->lock); 171 + return ret; 172 + } 173 + 174 + /* MCA MSR protocol */ 175 + static int rmi_mca_msr_read(struct sbrmi_data *data, 176 + struct apml_mcamsr_msg *msg) 177 + { 178 + struct cpu_msr_outdata output = {0}; 179 + struct cpu_msr_indata input = {0}; 180 + int ret, val = 0; 181 + int hw_status; 182 + u16 thread; 183 + 184 + mutex_lock(&data->lock); 185 + /* cache the rev value to identify if protocol is supported or not */ 186 + if (!data->rev) { 187 + ret = sbrmi_get_rev(data); 188 + if (ret < 0) 189 + goto exit_unlock; 190 + } 191 + /* MCA MSR protocol for REV 0x10 is not supported*/ 192 + if (data->rev == 0x10) { 193 + ret = -EOPNOTSUPP; 194 + goto exit_unlock; 195 + } 196 + 197 + thread = msg->mcamsr_in_out << CPUID_MCA_THRD_INDEX & CPUID_MCA_THRD_MASK; 198 + 199 + /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */ 200 + if (thread > 127) { 201 + thread -= 128; 202 + val = 1; 203 + } 204 + ret = regmap_write(data->regmap, SBRMI_THREAD128CS, val); 205 + if (ret < 0) 206 + goto exit_unlock; 207 + 208 + prepare_mca_msr_input_message(&input, thread, 209 + msg->mcamsr_in_out & CPUID_MCA_FUNC_MASK); 210 + 211 + ret = regmap_bulk_write(data->regmap, CPUID_MCA_CMD, 212 + &input, MSR_WR_REG_LEN); 213 + if (ret < 0) 214 + goto exit_unlock; 215 + 216 + /* 217 + * For RMI Rev 0x20, new h/w status bit is introduced. which is used 218 + * by firmware to indicate completion of commands (0x71, 0x72, 0x73). 219 + * wait for the status bit to be set by the hardware before 220 + * reading the data out. 221 + */ 222 + ret = regmap_read_poll_timeout(data->regmap, SBRMI_STATUS, hw_status, 223 + hw_status & HW_ALERT_MASK, 500, 2000000); 224 + if (ret) 225 + goto exit_unlock; 226 + 227 + ret = regmap_bulk_read(data->regmap, CPUID_MCA_CMD, 228 + &output, MSR_RD_REG_LEN); 229 + if (ret < 0) 230 + goto exit_unlock; 231 + 232 + ret = regmap_write(data->regmap, SBRMI_STATUS, 233 + HW_ALERT_MASK); 234 + if (ret < 0) 235 + goto exit_unlock; 236 + 237 + if (output.num_bytes != MSR_RD_REG_LEN - 1) { 238 + ret = -EMSGSIZE; 239 + goto exit_unlock; 240 + } 241 + if (output.status) { 242 + ret = -EPROTOTYPE; 243 + msg->fw_ret_code = output.status; 244 + goto exit_unlock; 245 + } 246 + msg->mcamsr_in_out = output.value; 247 + 248 + exit_unlock: 186 249 mutex_unlock(&data->lock); 187 250 return ret; 188 251 } ··· 384 289 return copy_to_user(arg, &msg, sizeof(struct apml_cpuid_msg)); 385 290 } 386 291 292 + static int apml_mcamsr_xfer(struct sbrmi_data *data, struct apml_mcamsr_msg __user *arg) 293 + { 294 + struct apml_mcamsr_msg msg = { 0 }; 295 + int ret; 296 + 297 + /* Copy the structure from user */ 298 + if (copy_from_user(&msg, arg, sizeof(struct apml_mcamsr_msg))) 299 + return -EFAULT; 300 + 301 + /* MCAMSR Protocol */ 302 + ret = rmi_mca_msr_read(data, &msg); 303 + if (ret && ret != -EPROTOTYPE) 304 + return ret; 305 + 306 + return copy_to_user(arg, &msg, sizeof(struct apml_mcamsr_msg)); 307 + } 308 + 387 309 static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) 388 310 { 389 311 void __user *argp = (void __user *)arg; ··· 412 300 return apml_mailbox_xfer(data, argp); 413 301 case SBRMI_IOCTL_CPUID_CMD: 414 302 return apml_cpuid_xfer(data, argp); 303 + case SBRMI_IOCTL_MCAMSR_CMD: 304 + return apml_mcamsr_xfer(data, argp); 415 305 default: 416 306 return -ENOTTY; 417 307 }
+33
include/uapi/misc/amd-apml.h
··· 43 43 __u32 pad; 44 44 }; 45 45 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 + 46 61 /* 47 62 * AMD sideband interface base IOCTL 48 63 */ ··· 99 84 * "-EPROTOTYPE" error is returned to provide additional error details 100 85 */ 101 86 #define SBRMI_IOCTL_CPUID_CMD _IOWR(SB_BASE_IOCTL_NR, 1, struct apml_cpuid_msg) 87 + 88 + /** 89 + * DOC: SBRMI_IOCTL_MCAMSR_CMD 90 + * 91 + * @Parameters 92 + * 93 + * @struct apml_mcamsr_msg 94 + * Pointer to the &struct apml_mcamsr_msg that will contain the protocol 95 + * information 96 + * 97 + * @Description 98 + * IOCTL command for APML messages using generic _IOWR 99 + * The IOCTL provides userspace access to AMD sideband MCAMSR protocol 100 + * - MCAMSR protocol to get MCA bank details for Function at thread level 101 + * - returning "-EFAULT" if none of the above 102 + * "-EPROTOTYPE" error is returned to provide additional error details 103 + */ 104 + #define SBRMI_IOCTL_MCAMSR_CMD _IOWR(SB_BASE_IOCTL_NR, 2, struct apml_mcamsr_msg) 102 105 103 106 #endif /*_AMD_APML_H_*/