1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AMD HSMP Platform Driver 4 * Copyright (c) 2024, AMD. 5 * All Rights Reserved. 6 * 7 * This file provides an ACPI based driver implementation for HSMP interface. 8 */ 9 10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12 #include <asm/amd_hsmp.h> 13 14 #include <linux/acpi.h> 15 #include <linux/device.h> 16 #include <linux/dev_printk.h> 17 #include <linux/ioport.h> 18 #include <linux/kstrtox.h> 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <linux/sysfs.h> 22 #include <linux/uuid.h> 23 24 #include <uapi/asm-generic/errno-base.h> 25 26 #include <asm/amd_node.h> 27 28 #include "hsmp.h" 29 30 #define DRIVER_NAME "amd_hsmp" 31 #define DRIVER_VERSION "2.3" 32 #define ACPI_HSMP_DEVICE_HID "AMDI0097" 33 34 /* These are the strings specified in ACPI table */ 35 #define MSG_IDOFF_STR "MsgIdOffset" 36 #define MSG_ARGOFF_STR "MsgArgOffset" 37 #define MSG_RESPOFF_STR "MsgRspOffset" 38 39 static struct hsmp_plat_device *hsmp_pdev; 40 41 static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset, 42 u32 *value, bool write) 43 { 44 if (write) 45 iowrite32(*value, sock->virt_base_addr + offset); 46 else 47 *value = ioread32(sock->virt_base_addr + offset); 48 49 return 0; 50 } 51 52 /* This is the UUID used for HSMP */ 53 static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd, 54 0xa6, 0x9f, 0x4e, 0xa2, 55 0x87, 0x1f, 0xc2, 0xf6); 56 57 static inline bool is_acpi_hsmp_uuid(union acpi_object *obj) 58 { 59 if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE) 60 return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid); 61 62 return false; 63 } 64 65 static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind) 66 { 67 char *uid; 68 69 /* 70 * UID (ID00, ID01..IDXX) is used for differentiating sockets, 71 * read it and strip the "ID" part of it and convert the remaining 72 * bytes to integer. 73 */ 74 uid = acpi_device_uid(ACPI_COMPANION(dev)); 75 76 return kstrtou16(uid + 2, 10, sock_ind); 77 } 78 79 static acpi_status hsmp_resource(struct acpi_resource *res, void *data) 80 { 81 struct hsmp_socket *sock = data; 82 struct resource r; 83 84 switch (res->type) { 85 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 86 if (!acpi_dev_resource_memory(res, &r)) 87 return AE_ERROR; 88 if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE)) 89 return AE_ERROR; 90 sock->mbinfo.base_addr = r.start; 91 sock->mbinfo.size = resource_size(&r); 92 break; 93 case ACPI_RESOURCE_TYPE_END_TAG: 94 break; 95 default: 96 return AE_ERROR; 97 } 98 99 return AE_OK; 100 } 101 102 static int hsmp_read_acpi_dsd(struct hsmp_socket *sock) 103 { 104 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 105 union acpi_object *guid, *mailbox_package; 106 union acpi_object *dsd; 107 acpi_status status; 108 int ret = 0; 109 int j; 110 111 status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL, 112 &buf, ACPI_TYPE_PACKAGE); 113 if (ACPI_FAILURE(status)) { 114 dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n", 115 acpi_format_exception(status)); 116 return -ENODEV; 117 } 118 119 dsd = buf.pointer; 120 121 /* HSMP _DSD property should contain 2 objects. 122 * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER 123 * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE 124 * This mailbox object contains 3 more acpi objects of type 125 * ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets 126 * these packages inturn contain 2 acpi objects of type 127 * ACPI_TYPE_STRING and ACPI_TYPE_INTEGER 128 */ 129 if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) { 130 ret = -EINVAL; 131 goto free_buf; 132 } 133 134 guid = &dsd->package.elements[0]; 135 mailbox_package = &dsd->package.elements[1]; 136 if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) { 137 dev_err(sock->dev, "Invalid hsmp _DSD table data\n"); 138 ret = -EINVAL; 139 goto free_buf; 140 } 141 142 for (j = 0; j < mailbox_package->package.count; j++) { 143 union acpi_object *msgobj, *msgstr, *msgint; 144 145 msgobj = &mailbox_package->package.elements[j]; 146 msgstr = &msgobj->package.elements[0]; 147 msgint = &msgobj->package.elements[1]; 148 149 /* package should have 1 string and 1 integer object */ 150 if (msgobj->type != ACPI_TYPE_PACKAGE || 151 msgstr->type != ACPI_TYPE_STRING || 152 msgint->type != ACPI_TYPE_INTEGER) { 153 ret = -EINVAL; 154 goto free_buf; 155 } 156 157 if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR, 158 msgstr->string.length)) { 159 sock->mbinfo.msg_id_off = msgint->integer.value; 160 } else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR, 161 msgstr->string.length)) { 162 sock->mbinfo.msg_resp_off = msgint->integer.value; 163 } else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR, 164 msgstr->string.length)) { 165 sock->mbinfo.msg_arg_off = msgint->integer.value; 166 } else { 167 ret = -ENOENT; 168 goto free_buf; 169 } 170 } 171 172 if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off || 173 !sock->mbinfo.msg_arg_off) 174 ret = -EINVAL; 175 176 free_buf: 177 ACPI_FREE(buf.pointer); 178 return ret; 179 } 180 181 static int hsmp_read_acpi_crs(struct hsmp_socket *sock) 182 { 183 acpi_status status; 184 185 status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS, 186 hsmp_resource, sock); 187 if (ACPI_FAILURE(status)) { 188 dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n", 189 acpi_format_exception(status)); 190 return -EINVAL; 191 } 192 if (!sock->mbinfo.base_addr || !sock->mbinfo.size) 193 return -EINVAL; 194 195 /* The mapped region should be un-cached */ 196 sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr, 197 sock->mbinfo.size); 198 if (!sock->virt_base_addr) { 199 dev_err(sock->dev, "Failed to ioremap MP1 base address\n"); 200 return -ENOMEM; 201 } 202 203 return 0; 204 } 205 206 /* Parse the ACPI table to read the data */ 207 static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind) 208 { 209 struct hsmp_socket *sock = &hsmp_pdev->sock[sock_ind]; 210 int ret; 211 212 sock->sock_ind = sock_ind; 213 sock->dev = dev; 214 sock->amd_hsmp_rdwr = amd_hsmp_acpi_rdwr; 215 216 sema_init(&sock->hsmp_sem, 1); 217 218 dev_set_drvdata(dev, sock); 219 220 /* Read MP1 base address from CRS method */ 221 ret = hsmp_read_acpi_crs(sock); 222 if (ret) 223 return ret; 224 225 /* Read mailbox offsets from DSD table */ 226 return hsmp_read_acpi_dsd(sock); 227 } 228 229 static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj, 230 const struct bin_attribute *bin_attr, char *buf, 231 loff_t off, size_t count) 232 { 233 struct device *dev = container_of(kobj, struct device, kobj); 234 struct hsmp_socket *sock = dev_get_drvdata(dev); 235 236 return hsmp_metric_tbl_read(sock, buf, count); 237 } 238 239 static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, 240 const struct bin_attribute *battr, int id) 241 { 242 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) 243 return battr->attr.mode; 244 245 return 0; 246 } 247 248 static int init_acpi(struct device *dev) 249 { 250 u16 sock_ind; 251 int ret; 252 253 ret = hsmp_get_uid(dev, &sock_ind); 254 if (ret) 255 return ret; 256 if (sock_ind >= hsmp_pdev->num_sockets) 257 return -EINVAL; 258 259 ret = hsmp_parse_acpi_table(dev, sock_ind); 260 if (ret) { 261 dev_err(dev, "Failed to parse ACPI table\n"); 262 return ret; 263 } 264 265 /* Test the hsmp interface */ 266 ret = hsmp_test(sock_ind, 0xDEADBEEF); 267 if (ret) { 268 dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n", 269 boot_cpu_data.x86, boot_cpu_data.x86_model); 270 dev_err(dev, "Is HSMP disabled in BIOS ?\n"); 271 return ret; 272 } 273 274 ret = hsmp_cache_proto_ver(sock_ind); 275 if (ret) { 276 dev_err(dev, "Failed to read HSMP protocol version\n"); 277 return ret; 278 } 279 280 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { 281 ret = hsmp_get_tbl_dram_base(sock_ind); 282 if (ret) 283 dev_err(dev, "Failed to init metric table\n"); 284 } 285 286 return ret; 287 } 288 289 static const struct bin_attribute hsmp_metric_tbl_attr = { 290 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, 291 .read_new = hsmp_metric_tbl_acpi_read, 292 .size = sizeof(struct hsmp_metric_table), 293 }; 294 295 static const struct bin_attribute *hsmp_attr_list[] = { 296 &hsmp_metric_tbl_attr, 297 NULL 298 }; 299 300 static const struct attribute_group hsmp_attr_grp = { 301 .bin_attrs_new = hsmp_attr_list, 302 .is_bin_visible = hsmp_is_sock_attr_visible, 303 }; 304 305 static const struct attribute_group *hsmp_groups[] = { 306 &hsmp_attr_grp, 307 NULL 308 }; 309 310 static const struct acpi_device_id amd_hsmp_acpi_ids[] = { 311 {ACPI_HSMP_DEVICE_HID, 0}, 312 {} 313 }; 314 MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids); 315 316 static int hsmp_acpi_probe(struct platform_device *pdev) 317 { 318 int ret; 319 320 hsmp_pdev = get_hsmp_pdev(); 321 if (!hsmp_pdev) 322 return -ENOMEM; 323 324 if (!hsmp_pdev->is_probed) { 325 hsmp_pdev->num_sockets = amd_num_nodes(); 326 if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) 327 return -ENODEV; 328 329 hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, 330 sizeof(*hsmp_pdev->sock), 331 GFP_KERNEL); 332 if (!hsmp_pdev->sock) 333 return -ENOMEM; 334 } 335 336 ret = init_acpi(&pdev->dev); 337 if (ret) { 338 dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n"); 339 return ret; 340 } 341 342 if (!hsmp_pdev->is_probed) { 343 ret = hsmp_misc_register(&pdev->dev); 344 if (ret) 345 return ret; 346 hsmp_pdev->is_probed = true; 347 } 348 349 return 0; 350 } 351 352 static void hsmp_acpi_remove(struct platform_device *pdev) 353 { 354 /* 355 * We register only one misc_device even on multi-socket system. 356 * So, deregister should happen only once. 357 */ 358 if (hsmp_pdev->is_probed) { 359 hsmp_misc_deregister(); 360 hsmp_pdev->is_probed = false; 361 } 362 } 363 364 static struct platform_driver amd_hsmp_driver = { 365 .probe = hsmp_acpi_probe, 366 .remove = hsmp_acpi_remove, 367 .driver = { 368 .name = DRIVER_NAME, 369 .acpi_match_table = amd_hsmp_acpi_ids, 370 .dev_groups = hsmp_groups, 371 }, 372 }; 373 374 module_platform_driver(amd_hsmp_driver); 375 376 MODULE_IMPORT_NS("AMD_HSMP"); 377 MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver"); 378 MODULE_VERSION(DRIVER_VERSION); 379 MODULE_LICENSE("GPL"); 380