Skip to content

Commit c126e37

Browse files
author
Keith Busch
authored
Merge pull request #549 from RevanthRajashekar/master
nvme: add Persistent Memory Region (PMR) registers
2 parents 1235e53 + e68f3f8 commit c126e37

5 files changed

Lines changed: 83 additions & 16 deletions

File tree

Documentation/nvme-sanitize-log.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ T{
9090
0x0100
9191
T}:T{
9292
.sp
93-
Global Data Erased bit If set to 1 then non\-volatile storage in the NVM subsystem has not been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation\&. If cleared to 0, then non\-volatile storage in the NVM subsystem has been written to: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation of the NVM subsystem\&.
93+
Global Data Erased bit If set to 1 then no namespace logical block in the NVM subsystem has been written to and no Persistent Memory Region in the NVM subsystem has been enabled: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation\&. If cleared to 0, then a namespace logical block in the NVM subsystem has been written to or a Persistent Memory Region in the NVM subsystem has been enabled: a) since being manufactured and the NVM subsystem has never been sanitized; or b) since the most recent successful sanitize operation of the NVM subsystem\&.
9494
T}
9595
.TE
9696
.sp 1

linux/nvme.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ enum {
124124
NVME_REG_BPINFO = 0x0040, /* Boot Partition Information */
125125
NVME_REG_BPRSEL = 0x0044, /* Boot Partition Read Select */
126126
NVME_REG_BPMBL = 0x0048, /* Boot Partition Memory Buffer Location */
127+
NVME_REG_PMRCAP = 0x0e00, /* Persistent Memory Capabilities */
128+
NVME_REG_PMRCTL = 0x0e04, /* Persistent Memory Region Control */
129+
NVME_REG_PMRSTS = 0x0e08, /* Persistent Memory Region Status */
127130
NVME_REG_DBS = 0x1000, /* SQ 0 Tail Doorbell */
128131
};
129132

@@ -1441,6 +1444,7 @@ enum {
14411444
NVME_SC_THIN_PROV_NOT_SUPP = 0x11b,
14421445
NVME_SC_CTRL_LIST_INVALID = 0x11c,
14431446
NVME_SC_BP_WRITE_PROHIBITED = 0x11e,
1447+
NVME_SC_PMR_SAN_PROHIBITED = 0x123,
14441448

14451449
/*
14461450
* I/O Command Set Specific - NVM commands:

nvme-print.c

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,9 +1769,11 @@ static void show_sanitize_log_sstat(__u16 status)
17691769

17701770
printf("\t [8]\t");
17711771
if (status & NVME_SANITIZE_LOG_GLOBAL_DATA_ERASED)
1772-
str = "Global Data Erased set: NVM storage has not been written";
1772+
str = "Global Data Erased set: no NS LB in the NVM subsystem has been written to "\
1773+
"and no PMR in the NVM subsystem has been enabled";
17731774
else
1774-
str = "Global Data Erased cleared: NVM storage has been written";
1775+
str = "Global Data Erased cleared: a NS LB in the NVM subsystem has been written to "\
1776+
"or a PMR in the NVM subsystem has been enabled";
17751777
printf("%s\n", str);
17761778
}
17771779

@@ -1947,6 +1949,7 @@ const char *nvme_status_to_string(__u32 status)
19471949
case NVME_SC_ANA_INACCESSIBLE: return "ASYMMETRIC_NAMESPACE_ACCESS_INACCESSIBLE: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace being in the ANA Inaccessible state";
19481950
case NVME_SC_ANA_TRANSITION: return "ASYMMETRIC_NAMESPACE_ACCESS_TRANSITION: The requested function (e.g., command) is not able to be performed as a result of the relationship between the controller and the namespace transitioning between Asymmetric Namespace Access states";
19491951
case NVME_SC_CMD_INTERRUPTED: return "CMD_INTERRUPTED: Command processing was interrupted and the controller is unable to successfully complete the command. The host should retry the command.";
1952+
case NVME_SC_PMR_SAN_PROHIBITED: return "Sanitize Prohibited While Persistent Memory Region is Enabled: A sanitize operation is prohibited while the Persistent Memory Region is enabled.";
19501953
default: return "Unknown";
19511954
}
19521955
}
@@ -3105,18 +3108,20 @@ void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n)
31053108

31063109
static void show_registers_cap(struct nvme_bar_cap *cap)
31073110
{
3108-
printf("\tMemory Page Size Maximum (MPSMAX): %u bytes\n", 1 << (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4)));
3109-
printf("\tMemory Page Size Minimum (MPSMIN): %u bytes\n", 1 << (12 + (cap->mpsmax_mpsmin & 0x0f)));
3110-
printf("\tBoot Partition Support (BPS): %s\n", (cap->bps_css_nssrs_dstrd & 0x2000) ? "Yes":"No");
3111-
printf("\tCommand Sets Supported (CSS): NVM command set is %s\n",
3111+
printf("\tPersistent Memory Region Supported (PMRS): The Persistent Memory Region is %s\n",
3112+
(cap->rsvd_pmrs & 0x01) ? "supported":"not supported");
3113+
printf("\tMemory Page Size Maximum (MPSMAX): %u bytes\n", 1 << (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4)));
3114+
printf("\tMemory Page Size Minimum (MPSMIN): %u bytes\n", 1 << (12 + (cap->mpsmax_mpsmin & 0x0f)));
3115+
printf("\tBoot Partition Support (BPS): %s\n", (cap->bps_css_nssrs_dstrd & 0x2000) ? "Yes":"No");
3116+
printf("\tCommand Sets Supported (CSS): NVM command set is %s\n",
31123117
(cap->bps_css_nssrs_dstrd & 0x0020) ? "supported":"not supported");
3113-
printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n", (cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No");
3114-
printf("\tDoorbell Stride (DSTRD): %u bytes\n", 1 << (2 + (cap->bps_css_nssrs_dstrd & 0x000f)));
3115-
printf("\tTimeout (TO): %u ms\n", cap->to * 500);
3116-
printf("\tArbitration Mechanism Supported (AMS): Weighted Round Robin with Urgent Priority Class is %s\n",
3118+
printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n", (cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No");
3119+
printf("\tDoorbell Stride (DSTRD): %u bytes\n", 1 << (2 + (cap->bps_css_nssrs_dstrd & 0x000f)));
3120+
printf("\tTimeout (TO): %u ms\n", cap->to * 500);
3121+
printf("\tArbitration Mechanism Supported (AMS): Weighted Round Robin with Urgent Priority Class is %s\n",
31173122
(cap->ams_cqr & 0x02) ? "supported":"not supported");
3118-
printf("\tContiguous Queues Required (CQR): %s\n", (cap->ams_cqr & 0x01) ? "Yes":"No");
3119-
printf("\tMaximum Queue Entries Supported (MQES): %u\n\n", cap->mqes + 1);
3123+
printf("\tContiguous Queues Required (CQR): %s\n", (cap->ams_cqr & 0x01) ? "Yes":"No");
3124+
printf("\tMaximum Queue Entries Supported (MQES): %u\n\n", cap->mqes + 1);
31203125
}
31213126

31223127
static void show_registers_version(__u32 vs)
@@ -3329,6 +3334,44 @@ static void show_registers_bpmbl(uint64_t bpmbl)
33293334
printf("\tBoot Partition Memory Buffer Base Address (BMBBA): %"PRIx64"\n", bpmbl);
33303335
}
33313336

3337+
static void show_registers_pmrcap(__u32 pmrcap)
3338+
{
3339+
printf("\tPersistent Memory Region Timeout (PMRTO): %x\n", (pmrcap & 0x00ff0000) >> 16);
3340+
printf("\tPersistent Memory Region Write Barrier Mechanisms(PMRWBM): %x\n", (pmrcap & 0x00003c00) >> 10);
3341+
printf("\tPersistent Memory Region Time Units (PMRTU): PMR time unit is %s\n",
3342+
(pmrcap & 0x00000300) >> 8 ? "minutes":"500 milliseconds");
3343+
printf("\tBase Indicator Register (BIR): %x\n", (pmrcap & 0x000000e0) >> 5);
3344+
printf("\tWrite Data Support (WDS): Write data to the PMR is %s\n",
3345+
(pmrcap & 0x00000010) ? "supported":"not supported");
3346+
printf("\tRead Data Support (RDS): Read data from the PMR is %s\n",
3347+
(pmrcap & 0x00000008) ? "supported":"not supported");
3348+
}
3349+
3350+
static void show_registers_pmrctl(__u32 pmrctl)
3351+
{
3352+
printf("\tEnable (EN): PMR is %s\n", (pmrctl & 0x00000001) ? "READY":"Disabled");
3353+
}
3354+
3355+
static const char *nvme_register_pmr_hsts_to_string(__u8 hsts)
3356+
{
3357+
switch (hsts) {
3358+
case 0: return "Normal Operation";
3359+
case 1: return "Restore Error";
3360+
case 2: return "Read Only";
3361+
case 3: return "Unreliable";
3362+
default: return "Reserved";
3363+
}
3364+
}
3365+
3366+
static void show_registers_pmrsts(__u32 pmrsts, __u32 pmrctl)
3367+
{
3368+
printf("\tHealth Status (HSTS): %s\n", nvme_register_pmr_hsts_to_string((pmrsts & 0x00000e00) >> 9));
3369+
printf("\tNot Ready (NRDY): The Persistent Memory Region is %s to process "\
3370+
"PCI Express memory read and write requests\n",
3371+
(pmrsts & 0x00000100) == 0 && (pmrctl & 0x00000001) ? "READY":"Not Ready");
3372+
printf("\tError (ERR): %x\n", (pmrsts & 0x000000ff));
3373+
}
3374+
33323375
static inline uint32_t mmio_read32(void *addr)
33333376
{
33343377
__le32 *p = addr;
@@ -3348,7 +3391,7 @@ void json_ctrl_registers(void *bar)
33483391
{
33493392
uint64_t cap, asq, acq, bpmbl;
33503393
uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc,
3351-
bpinfo, bprsel;
3394+
bpinfo, bprsel, pmrcap, pmrctl, pmrsts;
33523395
struct json_object *root;
33533396

33543397
cap = mmio_read64(bar + NVME_REG_CAP);
@@ -3366,6 +3409,9 @@ void json_ctrl_registers(void *bar)
33663409
bpinfo = mmio_read32(bar + NVME_REG_BPINFO);
33673410
bprsel = mmio_read32(bar + NVME_REG_BPRSEL);
33683411
bpmbl = mmio_read64(bar + NVME_REG_BPMBL);
3412+
pmrcap = mmio_read32(bar + NVME_REG_PMRCAP);
3413+
pmrctl = mmio_read32(bar + NVME_REG_PMRCTL);
3414+
pmrsts = mmio_read32(bar + NVME_REG_PMRSTS);
33693415

33703416
root = json_create_object();
33713417
json_object_add_value_uint(root, "cap", cap);
@@ -3383,6 +3429,9 @@ void json_ctrl_registers(void *bar)
33833429
json_object_add_value_int(root, "bpinfo", bpinfo);
33843430
json_object_add_value_int(root, "bprsel", bprsel);
33853431
json_object_add_value_uint(root, "bpmbl", bpmbl);
3432+
json_object_add_value_int(root, "pmrcap", pmrcap);
3433+
json_object_add_value_int(root, "pmrctl", pmrctl);
3434+
json_object_add_value_int(root, "pmrsts", pmrsts);
33863435
json_print_object(root, NULL);
33873436
printf("\n");
33883437
json_free_object(root);
@@ -3391,7 +3440,8 @@ void json_ctrl_registers(void *bar)
33913440
void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics)
33923441
{
33933442
uint64_t cap, asq, acq, bpmbl;
3394-
uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc, bpinfo, bprsel;
3443+
uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc, bpinfo,
3444+
bprsel, pmrcap, pmrctl, pmrsts;
33953445

33963446
int human = mode & HUMAN;
33973447

@@ -3410,6 +3460,9 @@ void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics)
34103460
bpinfo = mmio_read32(bar + NVME_REG_BPINFO);
34113461
bprsel = mmio_read32(bar + NVME_REG_BPRSEL);
34123462
bpmbl = mmio_read64(bar + NVME_REG_BPMBL);
3463+
pmrcap = mmio_read32(bar + NVME_REG_PMRCAP);
3464+
pmrctl = mmio_read32(bar + NVME_REG_PMRCTL);
3465+
pmrsts = mmio_read32(bar + NVME_REG_PMRSTS);
34133466

34143467
if (human) {
34153468
if (cap != 0xffffffff) {
@@ -3465,6 +3518,15 @@ void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics)
34653518

34663519
printf("bpmbl : %"PRIx64"\n", bpmbl);
34673520
show_registers_bpmbl(bpmbl);
3521+
3522+
printf("pmrcap : %x\n", pmrcap);
3523+
show_registers_pmrcap(pmrcap);
3524+
3525+
printf("pmrctl : %x\n", pmrctl);
3526+
show_registers_pmrctl(pmrctl);
3527+
3528+
printf("pmrsts : %x\n", pmrsts);
3529+
show_registers_pmrsts(pmrsts, pmrctl);
34683530
}
34693531
} else {
34703532
if (cap != 0xffffffff)

nvme-status.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static inline __u8 nvme_cmd_specific_status_to_errno(__u16 status)
8080
case NVME_SC_NS_IS_PRIVATE:
8181
case NVME_SC_BP_WRITE_PROHIBITED:
8282
case NVME_SC_READ_ONLY:
83+
case NVME_SC_PMR_SAN_PROHIBITED:
8384
return EPERM;
8485
case NVME_SC_OVERLAPPING_RANGE:
8586
case NVME_SC_NS_NOT_ATTACHED:

nvme.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ struct nvme_bar_cap {
110110
__u8 to;
111111
__u16 bps_css_nssrs_dstrd;
112112
__u8 mpsmax_mpsmin;
113-
__u8 reserved;
113+
__u8 rsvd_pmrs;
114114
};
115115

116116
#ifdef __CHECKER__

0 commit comments

Comments
 (0)