| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- // SPDX-License-Identifier: GPL-2.0-only
- /* Copyright(c) 2022 Intel Corporation. All rights reserved. */
- #include <linux/libnvdimm.h>
- #include <linux/unaligned.h>
- #include <linux/module.h>
- #include <linux/async.h>
- #include <linux/slab.h>
- #include <linux/memregion.h>
- #include "cxlmem.h"
- #include "cxl.h"
- static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
- enum nvdimm_passphrase_type ptype)
- {
- struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
- struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
- unsigned long security_flags = 0;
- struct cxl_get_security_output {
- __le32 flags;
- } out;
- struct cxl_mbox_cmd mbox_cmd;
- u32 sec_out;
- int rc;
- mbox_cmd = (struct cxl_mbox_cmd) {
- .opcode = CXL_MBOX_OP_GET_SECURITY_STATE,
- .size_out = sizeof(out),
- .payload_out = &out,
- };
- rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
- if (rc < 0)
- return 0;
- sec_out = le32_to_cpu(out.flags);
- /* cache security state */
- mds->security.state = sec_out;
- if (ptype == NVDIMM_MASTER) {
- if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)
- set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
- else
- set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
- if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PLIMIT)
- set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
- return security_flags;
- }
- if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) {
- if (sec_out & CXL_PMEM_SEC_STATE_FROZEN ||
- sec_out & CXL_PMEM_SEC_STATE_USER_PLIMIT)
- set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
- if (sec_out & CXL_PMEM_SEC_STATE_LOCKED)
- set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
- else
- set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
- } else {
- set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
- }
- return security_flags;
- }
- static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
- const struct nvdimm_key_data *old_data,
- const struct nvdimm_key_data *new_data,
- enum nvdimm_passphrase_type ptype)
- {
- struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
- struct cxl_mbox_cmd mbox_cmd;
- struct cxl_set_pass set_pass;
- set_pass = (struct cxl_set_pass) {
- .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
- CXL_PMEM_SEC_PASS_USER,
- };
- memcpy(set_pass.old_pass, old_data->data, NVDIMM_PASSPHRASE_LEN);
- memcpy(set_pass.new_pass, new_data->data, NVDIMM_PASSPHRASE_LEN);
- mbox_cmd = (struct cxl_mbox_cmd) {
- .opcode = CXL_MBOX_OP_SET_PASSPHRASE,
- .size_in = sizeof(set_pass),
- .payload_in = &set_pass,
- };
- return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
- }
- static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
- const struct nvdimm_key_data *key_data,
- enum nvdimm_passphrase_type ptype)
- {
- struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
- struct cxl_disable_pass dis_pass;
- struct cxl_mbox_cmd mbox_cmd;
- dis_pass = (struct cxl_disable_pass) {
- .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
- CXL_PMEM_SEC_PASS_USER,
- };
- memcpy(dis_pass.pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
- mbox_cmd = (struct cxl_mbox_cmd) {
- .opcode = CXL_MBOX_OP_DISABLE_PASSPHRASE,
- .size_in = sizeof(dis_pass),
- .payload_in = &dis_pass,
- };
- return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
- }
- static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
- const struct nvdimm_key_data *key_data)
- {
- return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_USER);
- }
- static int cxl_pmem_security_disable_master(struct nvdimm *nvdimm,
- const struct nvdimm_key_data *key_data)
- {
- return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_MASTER);
- }
- static int cxl_pmem_security_freeze(struct nvdimm *nvdimm)
- {
- struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
- struct cxl_mbox_cmd mbox_cmd = {
- .opcode = CXL_MBOX_OP_FREEZE_SECURITY,
- };
- return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
- }
- static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
- const struct nvdimm_key_data *key_data)
- {
- struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
- u8 pass[NVDIMM_PASSPHRASE_LEN];
- struct cxl_mbox_cmd mbox_cmd;
- int rc;
- memcpy(pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
- mbox_cmd = (struct cxl_mbox_cmd) {
- .opcode = CXL_MBOX_OP_UNLOCK,
- .size_in = NVDIMM_PASSPHRASE_LEN,
- .payload_in = pass,
- };
- rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
- if (rc < 0)
- return rc;
- return 0;
- }
- static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
- const struct nvdimm_key_data *key,
- enum nvdimm_passphrase_type ptype)
- {
- struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
- struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
- struct cxl_mbox_cmd mbox_cmd;
- struct cxl_pass_erase erase;
- int rc;
- erase = (struct cxl_pass_erase) {
- .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
- CXL_PMEM_SEC_PASS_USER,
- };
- memcpy(erase.pass, key->data, NVDIMM_PASSPHRASE_LEN);
- mbox_cmd = (struct cxl_mbox_cmd) {
- .opcode = CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE,
- .size_in = sizeof(erase),
- .payload_in = &erase,
- };
- rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
- if (rc < 0)
- return rc;
- return 0;
- }
- static const struct nvdimm_security_ops __cxl_security_ops = {
- .get_flags = cxl_pmem_get_security_flags,
- .change_key = cxl_pmem_security_change_key,
- .disable = cxl_pmem_security_disable,
- .freeze = cxl_pmem_security_freeze,
- .unlock = cxl_pmem_security_unlock,
- .erase = cxl_pmem_security_passphrase_erase,
- .disable_master = cxl_pmem_security_disable_master,
- };
- const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops;
|