11// SPDX-License-Identifier: GPL-2.0-only
22/* Copyright(c) 2020 Intel Corporation. */
33
4+ #include <linux/io-64-nonatomic-lo-hi.h>
45#include <linux/device.h>
56#include <linux/slab.h>
67#include <linux/idr.h>
@@ -107,6 +108,88 @@ static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr,
107108}
108109static DEVICE_ATTR_RO (numa_node );
109110
111+ static ssize_t security_state_show (struct device * dev ,
112+ struct device_attribute * attr ,
113+ char * buf )
114+ {
115+ struct cxl_memdev * cxlmd = to_cxl_memdev (dev );
116+ struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
117+ unsigned long state = cxlds -> security .state ;
118+ u64 reg = readq (cxlds -> regs .mbox + CXLDEV_MBOX_BG_CMD_STATUS_OFFSET );
119+ u32 pct = FIELD_GET (CXLDEV_MBOX_BG_CMD_COMMAND_PCT_MASK , reg );
120+ u16 cmd = FIELD_GET (CXLDEV_MBOX_BG_CMD_COMMAND_OPCODE_MASK , reg );
121+
122+ if (cmd == CXL_MBOX_OP_SANITIZE && pct != 100 )
123+ return sysfs_emit (buf , "sanitize\n" );
124+
125+ if (!(state & CXL_PMEM_SEC_STATE_USER_PASS_SET ))
126+ return sysfs_emit (buf , "disabled\n" );
127+ if (state & CXL_PMEM_SEC_STATE_FROZEN ||
128+ state & CXL_PMEM_SEC_STATE_MASTER_PLIMIT ||
129+ state & CXL_PMEM_SEC_STATE_USER_PLIMIT )
130+ return sysfs_emit (buf , "frozen\n" );
131+ if (state & CXL_PMEM_SEC_STATE_LOCKED )
132+ return sysfs_emit (buf , "locked\n" );
133+ else
134+ return sysfs_emit (buf , "unlocked\n" );
135+ }
136+ static struct device_attribute dev_attr_security_state =
137+ __ATTR (state , 0444 , security_state_show , NULL );
138+
139+ static ssize_t security_sanitize_store (struct device * dev ,
140+ struct device_attribute * attr ,
141+ const char * buf , size_t len )
142+ {
143+ struct cxl_memdev * cxlmd = to_cxl_memdev (dev );
144+ struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
145+ struct cxl_port * port = dev_get_drvdata (& cxlmd -> dev );
146+ ssize_t rc ;
147+ bool sanitize ;
148+
149+ if (kstrtobool (buf , & sanitize ) || !sanitize )
150+ return - EINVAL ;
151+
152+ if (!port || !is_cxl_endpoint (port ))
153+ return - EINVAL ;
154+
155+ /* ensure no regions are mapped to this memdev */
156+ if (port -> commit_end != -1 )
157+ return - EBUSY ;
158+
159+ rc = cxl_mem_sanitize (cxlds , CXL_MBOX_OP_SANITIZE );
160+
161+ return rc ? rc : len ;
162+ }
163+ static struct device_attribute dev_attr_security_sanitize =
164+ __ATTR (sanitize , 0200 , NULL , security_sanitize_store );
165+
166+ static ssize_t security_erase_store (struct device * dev ,
167+ struct device_attribute * attr ,
168+ const char * buf , size_t len )
169+ {
170+ struct cxl_memdev * cxlmd = to_cxl_memdev (dev );
171+ struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
172+ struct cxl_port * port = dev_get_drvdata (& cxlmd -> dev );
173+ ssize_t rc ;
174+ bool erase ;
175+
176+ if (kstrtobool (buf , & erase ) || !erase )
177+ return - EINVAL ;
178+
179+ if (!port || !is_cxl_endpoint (port ))
180+ return - EINVAL ;
181+
182+ /* ensure no regions are mapped to this memdev */
183+ if (port -> commit_end != -1 )
184+ return - EBUSY ;
185+
186+ rc = cxl_mem_sanitize (cxlds , CXL_MBOX_OP_SECURE_ERASE );
187+
188+ return rc ? rc : len ;
189+ }
190+ static struct device_attribute dev_attr_security_erase =
191+ __ATTR (erase , 0200 , NULL , security_erase_store );
192+
110193static int cxl_get_poison_by_memdev (struct cxl_memdev * cxlmd )
111194{
112195 struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
@@ -352,6 +435,13 @@ static struct attribute *cxl_memdev_ram_attributes[] = {
352435 NULL ,
353436};
354437
438+ static struct attribute * cxl_memdev_security_attributes [] = {
439+ & dev_attr_security_state .attr ,
440+ & dev_attr_security_sanitize .attr ,
441+ & dev_attr_security_erase .attr ,
442+ NULL ,
443+ };
444+
355445static umode_t cxl_memdev_visible (struct kobject * kobj , struct attribute * a ,
356446 int n )
357447{
@@ -375,10 +465,16 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = {
375465 .attrs = cxl_memdev_pmem_attributes ,
376466};
377467
468+ static struct attribute_group cxl_memdev_security_attribute_group = {
469+ .name = "security" ,
470+ .attrs = cxl_memdev_security_attributes ,
471+ };
472+
378473static const struct attribute_group * cxl_memdev_attribute_groups [] = {
379474 & cxl_memdev_attribute_group ,
380475 & cxl_memdev_ram_attribute_group ,
381476 & cxl_memdev_pmem_attribute_group ,
477+ & cxl_memdev_security_attribute_group ,
382478 NULL ,
383479};
384480
@@ -427,11 +523,21 @@ void clear_exclusive_cxl_commands(struct cxl_dev_state *cxlds, unsigned long *cm
427523}
428524EXPORT_SYMBOL_NS_GPL (clear_exclusive_cxl_commands , CXL );
429525
526+ static void cxl_memdev_security_shutdown (struct device * dev )
527+ {
528+ struct cxl_memdev * cxlmd = to_cxl_memdev (dev );
529+ struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
530+
531+ if (cxlds -> security .poll )
532+ cancel_delayed_work_sync (& cxlds -> security .poll_dwork );
533+ }
534+
430535static void cxl_memdev_shutdown (struct device * dev )
431536{
432537 struct cxl_memdev * cxlmd = to_cxl_memdev (dev );
433538
434539 down_write (& cxl_memdev_rwsem );
540+ cxl_memdev_security_shutdown (dev );
435541 cxlmd -> cxlds = NULL ;
436542 up_write (& cxl_memdev_rwsem );
437543}
@@ -551,6 +657,34 @@ static const struct file_operations cxl_memdev_fops = {
551657 .llseek = noop_llseek ,
552658};
553659
660+ static void put_sanitize (void * data )
661+ {
662+ struct cxl_dev_state * cxlds = data ;
663+
664+ sysfs_put (cxlds -> security .sanitize_node );
665+ }
666+
667+ static int cxl_memdev_security_init (struct cxl_memdev * cxlmd )
668+ {
669+ struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
670+ struct device * dev = & cxlmd -> dev ;
671+ struct kernfs_node * sec ;
672+
673+ sec = sysfs_get_dirent (dev -> kobj .sd , "security" );
674+ if (!sec ) {
675+ dev_err (dev , "sysfs_get_dirent 'security' failed\n" );
676+ return - ENODEV ;
677+ }
678+ cxlds -> security .sanitize_node = sysfs_get_dirent (sec , "state" );
679+ sysfs_put (sec );
680+ if (!cxlds -> security .sanitize_node ) {
681+ dev_err (dev , "sysfs_get_dirent 'state' failed\n" );
682+ return - ENODEV ;
683+ }
684+
685+ return devm_add_action_or_reset (cxlds -> dev , put_sanitize , cxlds );
686+ }
687+
554688struct cxl_memdev * devm_cxl_add_memdev (struct cxl_dev_state * cxlds )
555689{
556690 struct cxl_memdev * cxlmd ;
@@ -579,6 +713,10 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds)
579713 if (rc )
580714 goto err ;
581715
716+ rc = cxl_memdev_security_init (cxlmd );
717+ if (rc )
718+ goto err ;
719+
582720 rc = devm_add_action_or_reset (cxlds -> dev , cxl_memdev_unregister , cxlmd );
583721 if (rc )
584722 return ERR_PTR (rc );
0 commit comments