bhyve: refactor NVMe PRP memcpy
Add a "copy direction" parameter to nvme_prp_memcpy such that data can be copied to the memory specified by the PRP entries (current behavior) or copied from the PRP entries (new behavior). The upcoming deallocate functionality will use the copy from capability. Reviewed by: jhb, araujo Approved by: jhb (maintainer) MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D21837
This commit is contained in:
parent
239e5865df
commit
da8de3e9a8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=359362
@ -140,6 +140,11 @@ enum nvme_cmd_cdw11 {
|
|||||||
NVME_CMD_CDW11_IV = 0xFFFF0000,
|
NVME_CMD_CDW11_IV = 0xFFFF0000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum nvme_copy_dir {
|
||||||
|
NVME_COPY_TO_PRP,
|
||||||
|
NVME_COPY_FROM_PRP,
|
||||||
|
};
|
||||||
|
|
||||||
#define NVME_CQ_INTEN 0x01
|
#define NVME_CQ_INTEN 0x01
|
||||||
#define NVME_CQ_INTCOAL 0x02
|
#define NVME_CQ_INTCOAL 0x02
|
||||||
|
|
||||||
@ -545,10 +550,10 @@ pci_nvme_init_controller(struct vmctx *ctx, struct pci_nvme_softc *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nvme_prp_memcpy(struct vmctx *ctx, uint64_t prp1, uint64_t prp2, uint8_t *src,
|
nvme_prp_memcpy(struct vmctx *ctx, uint64_t prp1, uint64_t prp2, uint8_t *b,
|
||||||
size_t len)
|
size_t len, enum nvme_copy_dir dir)
|
||||||
{
|
{
|
||||||
uint8_t *dst;
|
uint8_t *p;
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
|
|
||||||
if (len > (8 * 1024)) {
|
if (len > (8 * 1024)) {
|
||||||
@ -559,14 +564,17 @@ nvme_prp_memcpy(struct vmctx *ctx, uint64_t prp1, uint64_t prp2, uint8_t *src,
|
|||||||
bytes = PAGE_SIZE - (prp1 & PAGE_MASK);
|
bytes = PAGE_SIZE - (prp1 & PAGE_MASK);
|
||||||
bytes = MIN(bytes, len);
|
bytes = MIN(bytes, len);
|
||||||
|
|
||||||
dst = vm_map_gpa(ctx, prp1, bytes);
|
p = vm_map_gpa(ctx, prp1, bytes);
|
||||||
if (dst == NULL) {
|
if (p == NULL) {
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dst, src, bytes);
|
if (dir == NVME_COPY_TO_PRP)
|
||||||
|
memcpy(p, b, bytes);
|
||||||
|
else
|
||||||
|
memcpy(b, p, bytes);
|
||||||
|
|
||||||
src += bytes;
|
b += bytes;
|
||||||
|
|
||||||
len -= bytes;
|
len -= bytes;
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
@ -575,12 +583,15 @@ nvme_prp_memcpy(struct vmctx *ctx, uint64_t prp1, uint64_t prp2, uint8_t *src,
|
|||||||
|
|
||||||
len = MIN(len, PAGE_SIZE);
|
len = MIN(len, PAGE_SIZE);
|
||||||
|
|
||||||
dst = vm_map_gpa(ctx, prp2, len);
|
p = vm_map_gpa(ctx, prp2, len);
|
||||||
if (dst == NULL) {
|
if (p == NULL) {
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dst, src, len);
|
if (dir == NVME_COPY_TO_PRP)
|
||||||
|
memcpy(p, b, len);
|
||||||
|
else
|
||||||
|
memcpy(b, p, len);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -726,16 +737,19 @@ nvme_opc_get_log_page(struct pci_nvme_softc* sc, struct nvme_command* command,
|
|||||||
switch (logpage) {
|
switch (logpage) {
|
||||||
case NVME_LOG_ERROR:
|
case NVME_LOG_ERROR:
|
||||||
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
||||||
command->prp2, (uint8_t *)&sc->err_log, logsize);
|
command->prp2, (uint8_t *)&sc->err_log, logsize,
|
||||||
|
NVME_COPY_TO_PRP);
|
||||||
break;
|
break;
|
||||||
case NVME_LOG_HEALTH_INFORMATION:
|
case NVME_LOG_HEALTH_INFORMATION:
|
||||||
/* TODO: present some smart info */
|
/* TODO: present some smart info */
|
||||||
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
||||||
command->prp2, (uint8_t *)&sc->health_log, logsize);
|
command->prp2, (uint8_t *)&sc->health_log, logsize,
|
||||||
|
NVME_COPY_TO_PRP);
|
||||||
break;
|
break;
|
||||||
case NVME_LOG_FIRMWARE_SLOT:
|
case NVME_LOG_FIRMWARE_SLOT:
|
||||||
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
||||||
command->prp2, (uint8_t *)&sc->fw_log, logsize);
|
command->prp2, (uint8_t *)&sc->fw_log, logsize,
|
||||||
|
NVME_COPY_TO_PRP);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WPRINTF(("%s get log page %x command not supported",
|
WPRINTF(("%s get log page %x command not supported",
|
||||||
@ -760,12 +774,14 @@ nvme_opc_identify(struct pci_nvme_softc* sc, struct nvme_command* command,
|
|||||||
switch (command->cdw10 & 0xFF) {
|
switch (command->cdw10 & 0xFF) {
|
||||||
case 0x00: /* return Identify Namespace data structure */
|
case 0x00: /* return Identify Namespace data structure */
|
||||||
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
||||||
command->prp2, (uint8_t *)&sc->nsdata, sizeof(sc->nsdata));
|
command->prp2, (uint8_t *)&sc->nsdata, sizeof(sc->nsdata),
|
||||||
|
NVME_COPY_TO_PRP);
|
||||||
break;
|
break;
|
||||||
case 0x01: /* return Identify Controller data structure */
|
case 0x01: /* return Identify Controller data structure */
|
||||||
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1,
|
||||||
command->prp2, (uint8_t *)&sc->ctrldata,
|
command->prp2, (uint8_t *)&sc->ctrldata,
|
||||||
sizeof(sc->ctrldata));
|
sizeof(sc->ctrldata),
|
||||||
|
NVME_COPY_TO_PRP);
|
||||||
break;
|
break;
|
||||||
case 0x02: /* list of 1024 active NSIDs > CDW1.NSID */
|
case 0x02: /* list of 1024 active NSIDs > CDW1.NSID */
|
||||||
dest = vm_map_gpa(sc->nsc_pi->pi_vmctx, command->prp1,
|
dest = vm_map_gpa(sc->nsc_pi->pi_vmctx, command->prp1,
|
||||||
|
Loading…
Reference in New Issue
Block a user