| @@ -5,6 +5,7 @@ · 4 unmodified lines |
| 5 | 5 | #include <linux/module.h> |
| 6 | 6 | #include <linux/async.h> |
| 7 | 7 | #include <linux/slab.h> |
| 8 | +#include <linux/memregion.h> |
| 8 | 9 | #include "cxlmem.h" |
| 9 | 10 | #include "cxl.h" |
| 10 | 11 | |
| @@ -96,11 +97,37 @@ static int cxl_pmem_security_freeze(struct nvdimm *nvdimm) · 85 unmodified lines |
| 96 | 97 | return cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_FREEZE_SECURITY, NULL, 0, NULL, 0); |
| 97 | 98 | } |
| 98 | 99 | |
| 100 | +static int cxl_pmem_security_unlock(struct nvdimm *nvdimm, |
| 101 | + const struct nvdimm_key_data *key_data) |
| 102 | +{ |
| 103 | + struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm); |
| 104 | + struct cxl_memdev *cxlmd = cxl_nvd->cxlmd; |
| 105 | + struct cxl_dev_state *cxlds = cxlmd->cxlds; |
| 106 | + u8 pass[NVDIMM_PASSPHRASE_LEN]; |
| 107 | + int rc; |
| 108 | + |
| 109 | + if (!cpu_cache_has_invalidate_memregion()) |
| 110 | + return -EINVAL; |
| 111 | + |
| 112 | + memcpy(pass, key_data->data, NVDIMM_PASSPHRASE_LEN); |
| 113 | + rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_UNLOCK, |
| 114 | + pass, NVDIMM_PASSPHRASE_LEN, NULL, 0); |
| 115 | + if (rc < 0) |
| 116 | + return rc; |
| 117 | + |
| 118 | + /* DIMM unlocked, invalidate all CPU caches before we read it */ |
| 119 | + cpu_cache_invalidate_memregion(IORES_DESC_PERSISTENT_MEMORY); |
| 120 | + return 0; |
| 121 | +} |
| 122 | + |
| 99 | 123 | static const struct nvdimm_security_ops __cxl_security_ops = { |
| 100 | 124 | .get_flags = cxl_pmem_get_security_flags, |
| 101 | 125 | .change_key = cxl_pmem_security_change_key, |
| 102 | 126 | .disable = cxl_pmem_security_disable, |
| 103 | 127 | .freeze = cxl_pmem_security_freeze, |
| 128 | + .unlock = cxl_pmem_security_unlock, |
| 104 | 129 | }; |
| 105 | 130 | |
| 106 | 131 | const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops; |
| 132 | + |
| 133 | +MODULE_IMPORT_NS(DEVMEM); |