[PATCH 0/3] acpi, nfit: Add dirty shutdown count to sysfs
by Dan Williams
The Intel NVDIMM command specification publishes a dirty-shutdown-count
in addition to the dirty-shutdown / flush-failed indication that comes
from the ACPI NFIT. This is expected to be a common property of NVDIMMs
and is a static hardware health detail to be cached / exported via
sysfs.
Add plumbing for retrieving this data at driver load time, publish the
count, and use the dynamically retrieved dirty-shutdown indicator to
augment the existing 'flush_failed' flag.
---
Dan Williams (3):
acpi, nfit: Introduce nfit_mem flags
acpi, nfit: Collect shutdown status
tools/testing/nvdimm: Populate dirty shutdown data
drivers/acpi/nfit/core.c | 115 ++++++++++++++++++++++++++++-----
drivers/acpi/nfit/intel.h | 34 ++++++++++
drivers/acpi/nfit/nfit.h | 11 +++
tools/testing/nvdimm/Kbuild | 1
tools/testing/nvdimm/acpi_nfit_test.c | 8 ++
tools/testing/nvdimm/test/nfit.c | 3 +
tools/testing/nvdimm/test/nfit_test.h | 24 -------
7 files changed, 152 insertions(+), 44 deletions(-)
2 years, 3 months
[PATCH 0/3] kvm "fake DAX" device
by Pankaj Gupta
This patch series has implementation for "fake DAX".
"fake DAX" is fake persistent memory(nvdimm) in guest
which allows to bypass the guest page cache. This also
implements a VIRTIO based asynchronous flush mechanism.
Sharing guest driver and qemu device changes in separate
patch sets for easy review and it has been tested together.
Details of project idea for 'fake DAX' flushing interface
is shared [2] & [3].
Implementation is divided into two parts:
New virtio pmem guest driver and qemu code changes for new
virtio pmem paravirtualized device.
1. Guest virtio-pmem kernel driver
---------------------------------
- Reads persistent memory range from paravirt device and
registers with 'nvdimm_bus'.
- 'nvdimm/pmem' driver uses this information to allocate
persistent memory region and setup filesystem operations
to the allocated memory.
- virtio pmem driver implements asynchronous flushing
interface to flush from guest to host.
2. Qemu virtio-pmem device
---------------------------------
- Creates virtio pmem device and exposes a memory range to
KVM guest.
- At host side this is file backed memory which acts as
persistent memory.
- Qemu side flush uses aio thread pool API's and virtio
for asynchronous guest multi request handling.
David Hildenbrand CCed also posted a modified version[4] of
qemu virtio-pmem code based on updated Qemu memory device API.
Virtio-pmem errors handling:
----------------------------------------
Checked behaviour of virtio-pmem for below types of errors
Need suggestions on expected behaviour for handling these errors?
- Hardware Errors: Uncorrectable recoverable Errors:
a] virtio-pmem:
- As per current logic if error page belongs to Qemu process,
host MCE handler isolates(hwpoison) that page and send SIGBUS.
Qemu SIGBUS handler injects exception to KVM guest.
- KVM guest then isolates the page and send SIGBUS to guest
userspace process which has mapped the page.
b] Existing implementation for ACPI pmem driver:
- Handles such errors with MCE notifier and creates a list
of bad blocks. Read/direct access DAX operation return EIO
if accessed memory page fall in bad block list.
- It also starts backgound scrubbing.
- Similar functionality can be reused in virtio-pmem with MCE
notifier but without scrubbing(no ACPI/ARS)? Need inputs to
confirm if this behaviour is ok or needs any change?
Changes from RFC v3: [1]
- Rebase to latest upstream - Luiz
- Call ndregion->flush in place of nvdimm_flush- Luiz
- kmalloc return check - Luiz
- virtqueue full handling - Stefan
- Don't map entire virtio_pmem_req to device - Stefan
- request leak,correct sizeof req- Stefan
- Move declaration to virtio_pmem.c
Changes from RFC v2:
- Add flush function in the nd_region in place of switching
on a flag - Dan & Stefan
- Add flush completion function with proper locking and wait
for host side flush completion - Stefan & Dan
- Keep userspace API in uapi header file - Stefan, MST
- Use LE fields & New device id - MST
- Indentation & spacing suggestions - MST & Eric
- Remove extra header files & add licensing - Stefan
Changes from RFC v1:
- Reuse existing 'pmem' code for registering persistent
memory and other operations instead of creating an entirely
new block driver.
- Use VIRTIO driver to register memory information with
nvdimm_bus and create region_type accordingly.
- Call VIRTIO flush from existing pmem driver.
Pankaj Gupta (3):
nd: move nd_region to common header
libnvdimm: nd_region flush callback support
virtio-pmem: Add virtio-pmem guest driver
[1] https://lkml.org/lkml/2018/7/13/102
[2] https://www.spinics.net/lists/kvm/msg149761.html
[3] https://www.spinics.net/lists/kvm/msg153095.html
[4] https://marc.info/?l=qemu-devel&m=153555721901824&w=2
drivers/acpi/nfit/core.c | 7 -
drivers/nvdimm/claim.c | 3
drivers/nvdimm/nd.h | 39 -----
drivers/nvdimm/pmem.c | 12 +
drivers/nvdimm/region_devs.c | 12 +
drivers/virtio/Kconfig | 9 +
drivers/virtio/Makefile | 1
drivers/virtio/virtio_pmem.c | 255 +++++++++++++++++++++++++++++++++++++++
include/linux/libnvdimm.h | 4
include/linux/nd.h | 40 ++++++
include/uapi/linux/virtio_ids.h | 1
include/uapi/linux/virtio_pmem.h | 40 ++++++
12 files changed, 374 insertions(+), 49 deletions(-)
2 years, 3 months
[PATCH] acpi, nfit: Move acpi_nfit_get_security_ops() to generic location
by Dan Williams
In anticipation of other DIMMs adding security operations support, don't
require them to edit intel.h. Instead have intel.h optionally arrange
for intel_security_ops to be NULL or not based on build parameters.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/acpi/nfit/core.c | 10 ++++++++++
drivers/acpi/nfit/intel.c | 3 ++-
drivers/acpi/nfit/intel.h | 18 +++---------------
3 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index e5f7c664a7c8..b7773c70ee81 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1835,6 +1835,16 @@ static void shutdown_dimm_notify(void *data)
mutex_unlock(&acpi_desc->init_mutex);
}
+static const struct nvdimm_security_ops *acpi_nfit_get_security_ops(int family)
+{
+ switch (family) {
+ case NVDIMM_FAMILY_INTEL:
+ return intel_security_ops;
+ default:
+ return NULL;
+ }
+}
+
static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
{
struct nfit_mem *nfit_mem;
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c
index 70bccb0c57e2..8d2413810a5f 100644
--- a/drivers/acpi/nfit/intel.c
+++ b/drivers/acpi/nfit/intel.c
@@ -358,7 +358,7 @@ static int intel_dimm_security_state(struct nvdimm *nvdimm,
return rc;
}
-const struct nvdimm_security_ops intel_security_ops = {
+static const struct nvdimm_security_ops __intel_security_ops = {
.state = intel_dimm_security_state,
.unlock = intel_dimm_security_unlock,
.change_key = intel_dimm_security_update_passphrase,
@@ -366,3 +366,4 @@ const struct nvdimm_security_ops intel_security_ops = {
.freeze_lock = intel_dimm_security_freeze_lock,
.erase = intel_dimm_security_erase,
};
+const struct nvdimm_security_ops *intel_security_ops = &__intel_security_ops;
diff --git a/drivers/acpi/nfit/intel.h b/drivers/acpi/nfit/intel.h
index f9ac718776ca..f831084f95fa 100644
--- a/drivers/acpi/nfit/intel.h
+++ b/drivers/acpi/nfit/intel.h
@@ -8,7 +8,7 @@
#ifdef CONFIG_X86
-extern const struct nvdimm_security_ops intel_security_ops;
+extern const struct nvdimm_security_ops *intel_security_ops;
#define ND_INTEL_STATUS_SIZE 4
#define ND_INTEL_PASSPHRASE_SIZE 32
@@ -64,19 +64,7 @@ struct nd_intel_overwrite {
struct nd_intel_query_overwrite {
u32 status;
} __packed;
+#else /* CONFIG_X86 */
+#define intel_security_ops (NULL)
#endif /* CONFIG_X86 */
-
-static inline const struct nvdimm_security_ops *
-acpi_nfit_get_security_ops(int family)
-{
- switch (family) {
-#ifdef CONFIG_X86
- case NVDIMM_FAMILY_INTEL:
- return &intel_security_ops;
-#endif
- default:
- return NULL;
- }
-}
-
#endif
2 years, 3 months
[PATCH] libnvdimm, security: Comment fixes
by Dan Williams
Correct some spelling and stray comments.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/dimm_devs.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 06d0395c1f43..8740c6c61912 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -237,8 +237,8 @@ static int nvdimm_security_erase(struct device *dev, unsigned int keyid)
rc = nvdimm->security_ops->erase(nvdimm,
(struct nvdimm_key_data *) payload->data);
up_read(&key->sem);
- /* remove key since secure erase kills the passphrase */
+ /* remove key since secure erase kills the passphrase */
if (!is_userkey) {
key_unlink(nvdimm_keyring, key);
key_invalidate(key);
@@ -423,14 +423,12 @@ static int nvdimm_security_change_key(struct device *dev,
goto out;
}
- /* we need to check description as well */
-
if (!update)
key = nvdimm_replace_key(key);
/*
- * We don't need to release key->sem here because nvdimm_repalce_key
- * will.
+ * We don't need to release key->sem here because
+ * nvdimm_replace_key will.
*/
if (!key)
goto out;
2 years, 3 months
[PATCH] libnvdimm: Drop nvdimm_bus from security_ops interface
by Dan Williams
All that is missing is a helper to go from an nvdimm to its bus. With
the new nvdimm_to_bus() and nvdimm_ctl() helpers some boilerplate can be
consolidated.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/acpi/nfit/intel.c | 46 +++++++++++++++-----------------------------
drivers/nvdimm/bus.c | 6 ++++++
drivers/nvdimm/dimm_devs.c | 25 +++++++++---------------
include/linux/libnvdimm.h | 28 +++++++++++++++------------
4 files changed, 47 insertions(+), 58 deletions(-)
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c
index 419a7d54d4e8..70bccb0c57e2 100644
--- a/drivers/acpi/nfit/intel.c
+++ b/drivers/acpi/nfit/intel.c
@@ -18,10 +18,9 @@
#include "intel.h"
#include "nfit.h"
-static int intel_dimm_security_erase(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm, const struct nvdimm_key_data *nkey)
+static int intel_dimm_security_erase(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *nkey)
{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
int cmd_rc, rc = 0;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
struct {
@@ -47,8 +46,7 @@ static int intel_dimm_security_erase(struct nvdimm_bus *nvdimm_bus,
wbinvd_on_all_cpus();
memcpy(nd_cmd.cmd.passphrase, nkey->data,
sizeof(nd_cmd.cmd.passphrase));
- rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_CALL, &nd_cmd,
- sizeof(nd_cmd), &cmd_rc);
+ rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), &cmd_rc);
if (rc < 0)
goto out;
if (cmd_rc < 0) {
@@ -75,10 +73,8 @@ static int intel_dimm_security_erase(struct nvdimm_bus *nvdimm_bus,
return rc;
}
-static int intel_dimm_security_freeze_lock(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm)
+static int intel_dimm_security_freeze_lock(struct nvdimm *nvdimm)
{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
int cmd_rc, rc = 0;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
struct {
@@ -100,8 +96,7 @@ static int intel_dimm_security_freeze_lock(struct nvdimm_bus *nvdimm_bus,
if (!test_bit(NVDIMM_INTEL_FREEZE_LOCK, &nfit_mem->dsm_mask))
return -ENOTTY;
- rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_CALL, &nd_cmd,
- sizeof(nd_cmd), &cmd_rc);
+ rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), &cmd_rc);
if (rc < 0)
goto out;
if (cmd_rc < 0) {
@@ -122,10 +117,9 @@ static int intel_dimm_security_freeze_lock(struct nvdimm_bus *nvdimm_bus,
return rc;
}
-static int intel_dimm_security_disable(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm, const struct nvdimm_key_data *nkey)
+static int intel_dimm_security_disable(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *nkey)
{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
int cmd_rc, rc = 0;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
struct {
@@ -149,8 +143,7 @@ static int intel_dimm_security_disable(struct nvdimm_bus *nvdimm_bus,
memcpy(nd_cmd.cmd.passphrase, nkey->data,
sizeof(nd_cmd.cmd.passphrase));
- rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_CALL, &nd_cmd,
- sizeof(nd_cmd), &cmd_rc);
+ rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), &cmd_rc);
if (rc < 0)
goto out;
if (cmd_rc < 0) {
@@ -182,12 +175,10 @@ static int intel_dimm_security_disable(struct nvdimm_bus *nvdimm_bus,
* if the old passphrase is NULL. This typically happens when we are
* enabling security from the disabled state.
*/
-static int intel_dimm_security_update_passphrase(
- struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
+static int intel_dimm_security_update_passphrase(struct nvdimm *nvdimm,
const struct nvdimm_key_data *old_data,
const struct nvdimm_key_data *new_data)
{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
int cmd_rc, rc = 0;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
struct {
@@ -216,8 +207,7 @@ static int intel_dimm_security_update_passphrase(
memset(nd_cmd.cmd.old_pass, 0, sizeof(nd_cmd.cmd.old_pass));
memcpy(nd_cmd.cmd.new_pass, new_data->data,
sizeof(nd_cmd.cmd.new_pass));
- rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_CALL, &nd_cmd,
- sizeof(nd_cmd), &cmd_rc);
+ rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), &cmd_rc);
if (rc < 0)
goto out;
if (cmd_rc < 0) {
@@ -241,10 +231,9 @@ static int intel_dimm_security_update_passphrase(
return rc;
}
-static int intel_dimm_security_unlock(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm, const struct nvdimm_key_data *nkey)
+static int intel_dimm_security_unlock(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *nkey)
{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
int cmd_rc, rc = 0;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
struct {
@@ -268,8 +257,7 @@ static int intel_dimm_security_unlock(struct nvdimm_bus *nvdimm_bus,
memcpy(nd_cmd.cmd.passphrase, nkey->data,
sizeof(nd_cmd.cmd.passphrase));
- rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_CALL, &nd_cmd,
- sizeof(nd_cmd), &cmd_rc);
+ rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), &cmd_rc);
if (rc < 0)
goto out;
if (cmd_rc < 0) {
@@ -300,10 +288,9 @@ static int intel_dimm_security_unlock(struct nvdimm_bus *nvdimm_bus,
return rc;
}
-static int intel_dimm_security_state(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm, enum nvdimm_security_state *state)
+static int intel_dimm_security_state(struct nvdimm *nvdimm,
+ enum nvdimm_security_state *state)
{
- struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
int cmd_rc, rc = 0;
struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
struct {
@@ -331,8 +318,7 @@ static int intel_dimm_security_state(struct nvdimm_bus *nvdimm_bus,
}
*state = NVDIMM_SECURITY_DISABLED;
- rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_CALL, &nd_cmd,
- sizeof(nd_cmd), &cmd_rc);
+ rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), &cmd_rc);
if (rc < 0)
goto out;
if (cmd_rc < 0) {
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 9743d8083538..eae17d8ee539 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -331,6 +331,12 @@ struct nvdimm_bus *to_nvdimm_bus(struct device *dev)
}
EXPORT_SYMBOL_GPL(to_nvdimm_bus);
+struct nvdimm_bus *nvdimm_to_bus(struct nvdimm *nvdimm)
+{
+ return to_nvdimm_bus(nvdimm->dev.parent);
+}
+EXPORT_SYMBOL_GPL(nvdimm_to_bus);
+
struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
struct nvdimm_bus_descriptor *nd_desc)
{
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 752149c9450c..06d0395c1f43 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -174,13 +174,11 @@ static int nvdimm_check_key_len(unsigned short len)
int nvdimm_security_get_state(struct device *dev)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
if (!nvdimm->security_ops)
return 0;
- return nvdimm->security_ops->state(nvdimm_bus, nvdimm,
- &nvdimm->state);
+ return nvdimm->security_ops->state(nvdimm, &nvdimm->state);
}
static int nvdimm_security_erase(struct device *dev, unsigned int keyid)
@@ -236,8 +234,8 @@ static int nvdimm_security_erase(struct device *dev, unsigned int keyid)
down_read(&key->sem);
payload = key->payload.data[0];
- rc = nvdimm->security_ops->erase(nvdimm_bus, nvdimm,
- (void *)payload->data);
+ rc = nvdimm->security_ops->erase(nvdimm,
+ (struct nvdimm_key_data *) payload->data);
up_read(&key->sem);
/* remove key since secure erase kills the passphrase */
@@ -257,7 +255,6 @@ static int nvdimm_security_erase(struct device *dev, unsigned int keyid)
static int nvdimm_security_freeze_lock(struct device *dev)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
int rc;
if (!nvdimm->security_ops)
@@ -266,7 +263,7 @@ static int nvdimm_security_freeze_lock(struct device *dev)
if (nvdimm->state == NVDIMM_SECURITY_UNSUPPORTED)
return -EOPNOTSUPP;
- rc = nvdimm->security_ops->freeze_lock(nvdimm_bus, nvdimm);
+ rc = nvdimm->security_ops->freeze_lock(nvdimm);
if (rc < 0)
return rc;
@@ -277,7 +274,6 @@ static int nvdimm_security_freeze_lock(struct device *dev)
static int nvdimm_security_disable(struct device *dev, unsigned int keyid)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
struct key *key;
int rc;
struct user_key_payload *payload;
@@ -304,8 +300,8 @@ static int nvdimm_security_disable(struct device *dev, unsigned int keyid)
down_read(&key->sem);
payload = key->payload.data[0];
- rc = nvdimm->security_ops->disable(nvdimm_bus, nvdimm,
- (void *)payload->data);
+ rc = nvdimm->security_ops->disable(nvdimm,
+ (struct nvdimm_key_data *) payload->data);
up_read(&key->sem);
if (rc < 0) {
dev_warn(dev, "unlock failed\n");
@@ -328,7 +324,6 @@ static int nvdimm_security_disable(struct device *dev, unsigned int keyid)
int nvdimm_security_unlock_dimm(struct device *dev)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
struct key *key;
struct user_key_payload *payload;
int rc;
@@ -361,8 +356,8 @@ int nvdimm_security_unlock_dimm(struct device *dev)
dev_dbg(dev, "%s: key: %#x\n", __func__, key_serial(key));
down_read(&key->sem);
payload = key->payload.data[0];
- rc = nvdimm->security_ops->unlock(nvdimm_bus, nvdimm,
- (const void *)payload->data);
+ rc = nvdimm->security_ops->unlock(nvdimm,
+ (struct nvdimm_key_data *) payload->data);
up_read(&key->sem);
if (rc == 0) {
@@ -388,7 +383,6 @@ static int nvdimm_security_change_key(struct device *dev,
unsigned int old_keyid, unsigned int new_keyid)
{
struct nvdimm *nvdimm = to_nvdimm(dev);
- struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
struct key *key, *old_key;
int rc;
void *old_data = NULL, *new_data;
@@ -451,8 +445,7 @@ static int nvdimm_security_change_key(struct device *dev,
new_data = payload->data;
- rc = nvdimm->security_ops->change_key(nvdimm_bus, nvdimm, old_data,
- new_data);
+ rc = nvdimm->security_ops->change_key(nvdimm, old_data, new_data);
/* copy new payload to old payload */
if (rc == 0) {
if (update)
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 0d85e092a6dd..c352b8195675 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -172,23 +172,17 @@ struct nvdimm_key_data {
};
struct nvdimm_security_ops {
- int (*state)(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm,
+ int (*state)(struct nvdimm *nvdimm,
enum nvdimm_security_state *state);
- int (*unlock)(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm,
+ int (*unlock)(struct nvdimm *nvdimm,
const struct nvdimm_key_data *nkey);
- int (*change_key)(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm,
+ int (*change_key)(struct nvdimm *nvdimm,
const struct nvdimm_key_data *old_data,
const struct nvdimm_key_data *new_data);
- int (*disable)(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm,
+ int (*disable)(struct nvdimm *nvdimm,
const struct nvdimm_key_data *nkey);
- int (*freeze_lock)(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm);
- int (*erase)(struct nvdimm_bus *nvdimm_bus,
- struct nvdimm *nvdimm,
+ int (*freeze_lock)(struct nvdimm *nvdimm);
+ int (*erase)(struct nvdimm *nvdimm,
const struct nvdimm_key_data *nkey);
};
@@ -202,6 +196,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
struct nvdimm_bus_descriptor *nfit_desc);
void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus);
struct nvdimm_bus *to_nvdimm_bus(struct device *dev);
+struct nvdimm_bus *nvdimm_to_bus(struct nvdimm *nvdimm);
struct nvdimm *to_nvdimm(struct device *dev);
struct nd_region *to_nd_region(struct device *dev);
struct device *nd_region_dev(struct nd_region *nd_region);
@@ -243,6 +238,15 @@ void nvdimm_flush(struct nd_region *nd_region);
int nvdimm_has_flush(struct nd_region *nd_region);
int nvdimm_has_cache(struct nd_region *nd_region);
+static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
+ unsigned int buf_len, int *cmd_rc)
+{
+ struct nvdimm_bus *nvdimm_bus = nvdimm_to_bus(nvdimm);
+ struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
+
+ return nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, cmd_rc);
+}
+
#ifdef CONFIG_ARCH_HAS_PMEM_API
#define ARCH_MEMREMAP_PMEM MEMREMAP_WB
void arch_wb_cache_pmem(void *addr, size_t size);
2 years, 3 months
[PATCH v5 00/11] mm: Teach memory_failure() about ZONE_DEVICE pages
by Dan Williams
Changes since v4 [1]:
* Rework dax_lock_page() to reuse get_unlocked_mapping_entry() (Jan)
* Change the calling convention to take a 'struct page *' and return
success / failure instead of performing the pfn_to_page() internal to
the api (Jan, Ross).
* Rename dax_lock_page() to dax_lock_mapping_entry() (Jan)
* Account for the case that a given pfn can be fsdax mapped with
different sizes in different vmas (Jan)
* Update collect_procs() to determine the mapping size of the pfn for
each page given it can be variable in the dax case.
[1]: https://lists.01.org/pipermail/linux-nvdimm/2018-June/016279.html
---
As it stands, memory_failure() gets thoroughly confused by dev_pagemap
backed mappings. The recovery code has specific enabling for several
possible page states and needs new enabling to handle poison in dax
mappings.
In order to support reliable reverse mapping of user space addresses:
1/ Add new locking in the memory_failure() rmap path to prevent races
that would typically be handled by the page lock.
2/ Since dev_pagemap pages are hidden from the page allocator and the
"compound page" accounting machinery, add a mechanism to determine the
size of the mapping that encompasses a given poisoned pfn.
3/ Given pmem errors can be repaired, change the speculatively accessed
poison protection, mce_unmap_kpfn(), to be reversible and otherwise
allow ongoing access from the kernel.
A side effect of this enabling is that MADV_HWPOISON becomes usable for
dax mappings, however the primary motivation is to allow the system to
survive userspace consumption of hardware-poison via dax. Specifically
the current behavior is:
mce: Uncorrected hardware memory error in user-access at af34214200
{1}[Hardware Error]: It has been corrected by h/w and requires no further action
mce: [Hardware Error]: Machine check events logged
{1}[Hardware Error]: event severity: corrected
Memory failure: 0xaf34214: reserved kernel page still referenced by 1 users
[..]
Memory failure: 0xaf34214: recovery action for reserved kernel page: Failed
mce: Memory error not recovered
<reboot>
...and with these changes:
Injecting memory failure for pfn 0x20cb00 at process virtual address 0x7f763dd00000
Memory failure: 0x20cb00: Killing dax-pmd:5421 due to hardware memory corruption
Memory failure: 0x20cb00: recovery action for dax page: Recovered
Given all the cross dependencies I propose taking this through
nvdimm.git with acks from Naoya, x86/core, x86/RAS, and of course dax
folks.
---
Dan Williams (11):
device-dax: Convert to vmf_insert_mixed and vm_fault_t
device-dax: Enable page_mapping()
device-dax: Set page->index
filesystem-dax: Set page->index
mm, madvise_inject_error: Let memory_failure() optionally take a page reference
mm, memory_failure: Collect mapping size in collect_procs()
filesystem-dax: Introduce dax_lock_mapping_entry()
mm, memory_failure: Teach memory_failure() about dev_pagemap pages
x86/mm/pat: Prepare {reserve,free}_memtype() for "decoy" addresses
x86/memory_failure: Introduce {set,clear}_mce_nospec()
libnvdimm, pmem: Restore page attributes when clearing errors
arch/x86/include/asm/set_memory.h | 42 ++++++
arch/x86/kernel/cpu/mcheck/mce-internal.h | 15 --
arch/x86/kernel/cpu/mcheck/mce.c | 38 -----
arch/x86/mm/pat.c | 16 ++
drivers/dax/device.c | 75 +++++++----
drivers/nvdimm/pmem.c | 26 ++++
drivers/nvdimm/pmem.h | 13 ++
fs/dax.c | 125 +++++++++++++++++-
include/linux/dax.h | 24 +++
include/linux/huge_mm.h | 5 -
include/linux/mm.h | 1
include/linux/set_memory.h | 14 ++
mm/huge_memory.c | 4 -
mm/madvise.c | 18 ++-
mm/memory-failure.c | 201 +++++++++++++++++++++++------
15 files changed, 483 insertions(+), 134 deletions(-)
2 years, 3 months
[PATCH 0/5] Adding nvdimm overwrite support
by Dave Jiang
The following series implements the overwrite support for Intel nvdimm.
Overwrite DSM commands are part of Intel DSM v1.7 spec. It allows the
nvdimm to wipe all the information on the target nvdimm (including the
label area). The operation can take tens of mintues or more depending
on the size of the nvdimm.
---
Dave Jiang (5):
libnvdimm: introduce NDD_SECURITY_BUSY flag
libnvdimm: Add security DSM overwrite support
nfit_test: Add overwrite support for nfit_test
libnvdimm: add overwrite status notification
libnvdimm: add documentation for ovewrite
Documentation/nvdimm/security.txt | 11 ++
drivers/acpi/nfit/core.c | 5 +
drivers/acpi/nfit/intel.c | 118 +++++++++++++++++++++
drivers/acpi/nfit/intel.h | 4 +
drivers/acpi/nfit/nfit.h | 1
drivers/nvdimm/dimm.c | 4 +
drivers/nvdimm/dimm_devs.c | 207 +++++++++++++++++++++++++++++++++++++
drivers/nvdimm/nd-core.h | 3 +
drivers/nvdimm/nd.h | 3 +
drivers/nvdimm/region_devs.c | 7 +
include/linux/libnvdimm.h | 9 ++
tools/testing/nvdimm/test/nfit.c | 55 ++++++++++
12 files changed, 425 insertions(+), 2 deletions(-)
--
2 years, 3 months
[PATCH v9 00/12] Adding security support for nvdimm
by Dave Jiang
The following series implements security support for nvdimm. Mostly adding
new security DSM support from the Intel NVDIMM DSM spec v1.7, but also
adding generic support libnvdimm for other vendors. The most important
security features are unlocking locked nvdimms, and updating/setting security
passphrase to nvdimms.
v9:
- Addressed various misc comments. (David, Dan)
- Removed init_cred and replaced with current_cred(). (David)
- Changed NVDIMM_PREFIX to char[] constant (David)
- Moved NVDIMM_PREFIX to include/uapi/linux/ndctl.h (Dan)
- Reworked security_update to use old user key to verify against kernel
key and then update with new user key. (David)
- Added requirement of disable and erase to require old user key for
verify. (Dan)
- Updated documentation. (Dave)
v8:
- Make the keys retained by the kernel user searchable in order to find the
key that needs to be updated for key update.
v7:
- Add CONFIG_KEYS depenency for libnvdimm. (Alison)
- Export lookup_user_key(). (David)
- Modified "update" to take two key ids and and use lookup_user_key() in
order to improve security. (David)
- Use key ptrs and key_validate() for cached keys. (David)
v6:
- Fix intel DSM data structures to use defined size for passphrase (Robert)
- Fix memcpy size to use sizeof data structure member (Robert)
- Fix defined dimm id length (Robert)
- Making intel_security_ops const (Eric)
- Remove unused var in nvdimm_key_search() (Eric)
- Added wbinvd before secure erase is issued (Robert)
- Removed key_put_sync() usage (David)
- Use init_cred instead of creating own cred (David)
- Exported init_cred symbol
- Move keyring to dedicated (David)
- Use logon_key_type and friends instead of creating custom (David)
- Use key_lookup() with stored key serial (David)
- Exported key_lookup() symbol
- Mark passed in key data as const (David)
- Added comment for change_pass_phrase to explain how it works (David)
- Unlink key when it's being removed from keyring. (David)
- Removed request_key() from all security ops except update and unlock.
- Update will now update the existing key's payload with the new key's
retrieved from userspace when the new payload is accepted by nvdimm.
v5:
- Moved dimm_id initialization (Dan)
- Added a key_put_sync() in order to run key_gc_work and cleanup old key. (Dan)
- Added check to block security state changes while DIMM is active. (Dan)
v4:
- flip payload layout for update passphrase to make it easier on userland.
v3:
- Set x86 wrappers for x86 only bits. (Dan)
- Fixed up some verbiage in commit headers.
- Put in usage of sysfs_streq() for sysfs inputs.
- 0-day build fixes for non-x86 archs.
v2:
- Move inclusion of intel.h to relevant source files and not in nfit.h. (Dan)
- Moved security ring relevant code to dimm_devs.c. (Dan)
- Added dimm_id to nfit_mem to avoid recreate per sysfs show call. (Dan)
- Added routine to return security_ops based on family supplied. (Dan)
- Added nvdimm_key_data struct to wrap raw passphrase string. (Dan)
- Allocate firmware package on stack. (Dan)
- Added missing frozen state detection when retrieving security state.
---
Dave Jiang (12):
nfit: add support for Intel DSM 1.7 commands
libnvdimm: create keyring to store security keys
nfit/libnvdimm: store dimm id as a member to struct nvdimm
keys: export lookup_user_key to external users
nfit/libnvdimm: add unlock of nvdimm support for Intel DIMMs
nfit/libnvdimm: add set passphrase support for Intel nvdimms
nfit/libnvdimm: add disable passphrase support to Intel nvdimm.
nfit/libnvdimm: add freeze security support to Intel nvdimm
nfit/libnvdimm: add support for issue secure erase DSM to Intel nvdimm
nfit_test: add context to dimm_dev for nfit_test
nfit_test: add test support for Intel nvdimm security DSMs
libnvdimm: add documentation for nvdimm security support
Documentation/nvdimm/security.txt | 99 +++++++
drivers/acpi/nfit/Makefile | 1
drivers/acpi/nfit/core.c | 58 +++-
drivers/acpi/nfit/intel.c | 382 ++++++++++++++++++++++++++
drivers/acpi/nfit/intel.h | 82 ++++++
drivers/acpi/nfit/nfit.h | 20 +
drivers/nvdimm/Kconfig | 1
drivers/nvdimm/bus.c | 2
drivers/nvdimm/core.c | 7
drivers/nvdimm/dimm.c | 7
drivers/nvdimm/dimm_devs.c | 549 +++++++++++++++++++++++++++++++++++++
drivers/nvdimm/nd-core.h | 6
drivers/nvdimm/nd.h | 2
include/linux/key.h | 3
include/linux/libnvdimm.h | 42 +++
include/uapi/linux/ndctl.h | 6
security/keys/internal.h | 2
security/keys/process_keys.c | 1
tools/testing/nvdimm/Kbuild | 1
tools/testing/nvdimm/test/nfit.c | 227 ++++++++++++++-
20 files changed, 1462 insertions(+), 36 deletions(-)
create mode 100644 Documentation/nvdimm/security.txt
create mode 100644 drivers/acpi/nfit/intel.c
create mode 100644 drivers/acpi/nfit/intel.h
--
2 years, 3 months
[PATCH 0/2] Minor fixups for nd_device_register
by Alexander Duyck
This patch series addresses a couple minor issues in nd_device_register.
The first patch resolves an issue in which we weren't holding the parent
lock so it is possible the parent could have been released prior to us
taking care of initializing the device via the asynchronous init.
The second patch moves the initialization of the device node to the
earliest point where we can do it. By doing this we can avoid repeatedly
updating the node on each uevent.
---
Alexander Duyck (2):
nvdimm: Hold reference on parent while scheduling async init
nvdimm: Set device node in nd_device_register
drivers/nvdimm/bus.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
--
2 years, 3 months
[GIT PULL v2] libnvdimm/dax fixes for 4.19-rc6
by Williams, Dan J
Hi Greg, please pull from...
git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm tags/libnvdimm-fixes-4.19-rc6
...to receive a regression fix and 2 other fixes. Details are in the
tag message. Arguably only the 'address_space_operations' fix is urgent
for -rc6, the others can reasonably wait, but I see no reason to hold
them back. This has all appeared in -next with no reported issues.
---
The following changes since commit 11da3a7f84f19c26da6f86af878298694ede0804:
Linux 4.19-rc3 (2018-09-09 17:26:43 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm tags/libnvdimm-fixes-4.19-rc6
for you to fetch changes up to 41c9b1be335b5afc3b5fb71c5d16f9d5939cd13f:
device-dax: Add missing address_space_operations (2018-09-22 09:07:33 -0700)
----------------------------------------------------------------
libnvdimm/dax for 4.19-rc6
* (2) fixes for the dax error handling updates that were merged for
v4.19-rc1. My mails to Al have been bouncing recently, so I do not have
his ack but the uaccess change is of the trivial / obviously correct
variety. The address_space_operations fixes a regression.
* A filesystem-dax fix to correct the zero page lookup to be compatible
with non-x86 (mips and s390) architectures.
----------------------------------------------------------------
Dave Jiang (2):
uaccess: Fix is_source param for check_copy_size() in copy_to_iter_mcsafe()
device-dax: Add missing address_space_operations
Matthew Wilcox (1):
filesystem-dax: Fix use of zero page
drivers/dax/device.c | 6 ++++++
fs/dax.c | 13 ++-----------
include/linux/uio.h | 2 +-
3 files changed, 9 insertions(+), 12 deletions(-)
2 years, 3 months