Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/nvdimm/nvdimm_spa.c
/*- | /*- | ||||
* Copyright (c) 2017, 2018 The FreeBSD Foundation | * Copyright (c) 2017, 2018 The FreeBSD Foundation | ||||
* All rights reserved. | * All rights reserved. | ||||
* Copyright (c) 2018, 2019 Intel Corporation | |||||
* | * | ||||
* This software was developed by Konstantin Belousov <kib@FreeBSD.org> | * This software was developed by Konstantin Belousov <kib@FreeBSD.org> | ||||
* under sponsorship from the FreeBSD Foundation. | * under sponsorship from the FreeBSD Foundation. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_pager.h> | #include <vm/vm_pager.h> | ||||
#include <contrib/dev/acpica/include/acpi.h> | #include <contrib/dev/acpica/include/acpi.h> | ||||
#include <contrib/dev/acpica/include/accommon.h> | #include <contrib/dev/acpica/include/accommon.h> | ||||
#include <contrib/dev/acpica/include/acuuid.h> | #include <contrib/dev/acpica/include/acuuid.h> | ||||
#include <dev/acpica/acpivar.h> | #include <dev/acpica/acpivar.h> | ||||
#include <dev/nvdimm/nvdimm_var.h> | #include <dev/nvdimm/nvdimm_var.h> | ||||
#define UUID_INITIALIZER_VOLATILE_MEMORY \ | |||||
{0x7305944f,0xfdda,0x44e3,0xb1,0x6c,{0x3f,0x22,0xd2,0x52,0xe5,0xd0}} | |||||
#define UUID_INITIALIZER_PERSISTENT_MEMORY \ | |||||
{0x66f0d379,0xb4f3,0x4074,0xac,0x43,{0x0d,0x33,0x18,0xb7,0x8c,0xdb}} | |||||
#define UUID_INITIALIZER_CONTROL_REGION \ | |||||
{0x92f701f6,0x13b4,0x405d,0x91,0x0b,{0x29,0x93,0x67,0xe8,0x23,0x4c}} | |||||
#define UUID_INITIALIZER_DATA_REGION \ | |||||
{0x91af0530,0x5d86,0x470e,0xa6,0xb0,{0x0a,0x2d,0xb9,0x40,0x82,0x49}} | |||||
#define UUID_INITIALIZER_VOLATILE_VIRTUAL_DISK \ | |||||
{0x77ab535a,0x45fc,0x624b,0x55,0x60,{0xf7,0xb2,0x81,0xd1,0xf9,0x6e}} | |||||
#define UUID_INITIALIZER_VOLATILE_VIRTUAL_CD \ | |||||
{0x3d5abd30,0x4175,0x87ce,0x6d,0x64,{0xd2,0xad,0xe5,0x23,0xc4,0xbb}} | |||||
#define UUID_INITIALIZER_PERSISTENT_VIRTUAL_DISK \ | |||||
{0x5cea02c9,0x4d07,0x69d3,0x26,0x9f,{0x44,0x96,0xfb,0xe0,0x96,0xf9}} | |||||
#define UUID_INITIALIZER_PERSISTENT_VIRTUAL_CD \ | |||||
{0x08018188,0x42cd,0xbb48,0x10,0x0f,{0x53,0x87,0xd5,0x3d,0xed,0x3d}} | |||||
struct SPA_mapping *spa_mappings; | struct SPA_mapping *spa_mappings; | ||||
int spa_mappings_cnt; | int spa_mappings_cnt; | ||||
static int | static int | ||||
nvdimm_spa_count(void *nfitsubtbl __unused, void *arg) | nvdimm_spa_count(void *nfitsubtbl __unused, void *arg) | ||||
{ | { | ||||
int *cnt; | int *cnt; | ||||
cnt = arg; | cnt = arg; | ||||
(*cnt)++; | (*cnt)++; | ||||
return (0); | return (0); | ||||
} | } | ||||
static struct nvdimm_SPA_uuid_list_elm { | static struct nvdimm_SPA_uuid_list_elm { | ||||
const char *u_name; | const char *u_name; | ||||
const char *u_id_str; | |||||
struct uuid u_id; | struct uuid u_id; | ||||
const bool u_usr_acc; | const bool u_usr_acc; | ||||
} nvdimm_SPA_uuid_list[] = { | } nvdimm_SPA_uuid_list[] = { | ||||
[SPA_TYPE_VOLATILE_MEMORY] = { | [SPA_TYPE_VOLATILE_MEMORY] = { | ||||
.u_name = "VOLA MEM ", | .u_name = "VOLA MEM ", | ||||
.u_id_str = UUID_VOLATILE_MEMORY, | .u_id = UUID_INITIALIZER_VOLATILE_MEMORY, | ||||
.u_usr_acc = true, | .u_usr_acc = true, | ||||
}, | }, | ||||
[SPA_TYPE_PERSISTENT_MEMORY] = { | [SPA_TYPE_PERSISTENT_MEMORY] = { | ||||
.u_name = "PERS MEM", | .u_name = "PERS MEM", | ||||
.u_id_str = UUID_PERSISTENT_MEMORY, | .u_id = UUID_INITIALIZER_PERSISTENT_MEMORY, | ||||
.u_usr_acc = true, | .u_usr_acc = true, | ||||
}, | }, | ||||
[SPA_TYPE_CONTROL_REGION] = { | [SPA_TYPE_CONTROL_REGION] = { | ||||
.u_name = "CTRL RG ", | .u_name = "CTRL RG ", | ||||
.u_id_str = UUID_CONTROL_REGION, | .u_id = UUID_INITIALIZER_CONTROL_REGION, | ||||
.u_usr_acc = false, | .u_usr_acc = false, | ||||
}, | }, | ||||
[SPA_TYPE_DATA_REGION] = { | [SPA_TYPE_DATA_REGION] = { | ||||
.u_name = "DATA RG ", | .u_name = "DATA RG ", | ||||
.u_id_str = UUID_DATA_REGION, | .u_id = UUID_INITIALIZER_DATA_REGION, | ||||
.u_usr_acc = true, | .u_usr_acc = true, | ||||
}, | }, | ||||
[SPA_TYPE_VOLATILE_VIRTUAL_DISK] = { | [SPA_TYPE_VOLATILE_VIRTUAL_DISK] = { | ||||
.u_name = "VIRT DSK", | .u_name = "VIRT DSK", | ||||
.u_id_str = UUID_VOLATILE_VIRTUAL_DISK, | .u_id = UUID_INITIALIZER_VOLATILE_VIRTUAL_DISK, | ||||
.u_usr_acc = true, | .u_usr_acc = true, | ||||
}, | }, | ||||
[SPA_TYPE_VOLATILE_VIRTUAL_CD] = { | [SPA_TYPE_VOLATILE_VIRTUAL_CD] = { | ||||
.u_name = "VIRT CD ", | .u_name = "VIRT CD ", | ||||
.u_id_str = UUID_VOLATILE_VIRTUAL_CD, | .u_id = UUID_INITIALIZER_VOLATILE_VIRTUAL_CD, | ||||
.u_usr_acc = true, | .u_usr_acc = true, | ||||
}, | }, | ||||
[SPA_TYPE_PERSISTENT_VIRTUAL_DISK] = { | [SPA_TYPE_PERSISTENT_VIRTUAL_DISK] = { | ||||
.u_name = "PV DSK ", | .u_name = "PV DSK ", | ||||
.u_id_str = UUID_PERSISTENT_VIRTUAL_DISK, | .u_id = UUID_INITIALIZER_PERSISTENT_VIRTUAL_DISK, | ||||
.u_usr_acc = true, | .u_usr_acc = true, | ||||
}, | }, | ||||
[SPA_TYPE_PERSISTENT_VIRTUAL_CD] = { | [SPA_TYPE_PERSISTENT_VIRTUAL_CD] = { | ||||
.u_name = "PV CD ", | .u_name = "PV CD ", | ||||
.u_id_str = UUID_PERSISTENT_VIRTUAL_CD, | .u_id = UUID_INITIALIZER_PERSISTENT_VIRTUAL_CD, | ||||
.u_usr_acc = true, | .u_usr_acc = true, | ||||
}, | }, | ||||
}; | }; | ||||
enum SPA_mapping_type | |||||
nvdimm_spa_type_from_uuid(struct uuid *uuid) | |||||
{ | |||||
int j; | |||||
for (j = 0; j < nitems(nvdimm_SPA_uuid_list); j++) { | |||||
if (uuidcmp(uuid, &nvdimm_SPA_uuid_list[j].u_id) != 0) | |||||
continue; | |||||
return (j); | |||||
} | |||||
return (SPA_TYPE_UNKNOWN); | |||||
} | |||||
static vm_memattr_t | static vm_memattr_t | ||||
nvdimm_spa_memattr(struct SPA_mapping *spa) | nvdimm_spa_memattr(struct SPA_mapping *spa) | ||||
{ | { | ||||
vm_memattr_t mode; | vm_memattr_t mode; | ||||
if ((spa->spa_efi_mem_flags & EFI_MD_ATTR_WB) != 0) | if ((spa->spa_efi_mem_flags & EFI_MD_ATTR_WB) != 0) | ||||
mode = VM_MEMATTR_WRITE_BACK; | mode = VM_MEMATTR_WRITE_BACK; | ||||
else if ((spa->spa_efi_mem_flags & EFI_MD_ATTR_WT) != 0) | else if ((spa->spa_efi_mem_flags & EFI_MD_ATTR_WT) != 0) | ||||
▲ Show 20 Lines • Show All 398 Lines • ▼ Show 20 Lines | nvdimm_spa_fini_one(struct SPA_mapping *spa) | ||||
mtx_destroy(&spa->spa_g_stat_mtx); | mtx_destroy(&spa->spa_g_stat_mtx); | ||||
} | } | ||||
static int | static int | ||||
nvdimm_spa_parse(void *nfitsubtbl, void *arg) | nvdimm_spa_parse(void *nfitsubtbl, void *arg) | ||||
{ | { | ||||
ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr; | ACPI_NFIT_SYSTEM_ADDRESS *nfitaddr; | ||||
struct SPA_mapping *spa; | struct SPA_mapping *spa; | ||||
int error, *i, j; | enum SPA_mapping_type spa_type; | ||||
int error, *i; | |||||
i = arg; | i = arg; | ||||
spa = &spa_mappings[*i]; | spa = &spa_mappings[(*i)++]; | ||||
nfitaddr = nfitsubtbl; | nfitaddr = nfitsubtbl; | ||||
spa_type = nvdimm_spa_type_from_uuid( | |||||
for (j = 0; j < nitems(nvdimm_SPA_uuid_list); j++) { | (struct uuid *)&nfitaddr->RangeGuid); | ||||
/* XXXKIB: is ACPI UUID representation compatible ? */ | if (spa_type == SPA_TYPE_UNKNOWN) { | ||||
if (uuidcmp((struct uuid *)&nfitaddr->RangeGuid, | |||||
&nvdimm_SPA_uuid_list[j].u_id) != 0) | |||||
continue; | |||||
error = nvdimm_spa_init_one(spa, nfitaddr, j); | |||||
if (error != 0) | |||||
nvdimm_spa_fini_one(spa); | |||||
break; | |||||
} | |||||
if (j == nitems(nvdimm_SPA_uuid_list) && bootverbose) { | |||||
printf("Unknown SPA UUID %d ", nfitaddr->RangeIndex); | printf("Unknown SPA UUID %d ", nfitaddr->RangeIndex); | ||||
printf_uuid((struct uuid *)&nfitaddr->RangeGuid); | printf_uuid((struct uuid *)&nfitaddr->RangeGuid); | ||||
printf("\n"); | printf("\n"); | ||||
return (0); | |||||
} | } | ||||
(*i)++; | error = nvdimm_spa_init_one(spa, nfitaddr, spa_type); | ||||
if (error != 0) | |||||
nvdimm_spa_fini_one(spa); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
nvdimm_spa_init1(ACPI_TABLE_NFIT *nfitbl) | nvdimm_spa_init1(ACPI_TABLE_NFIT *nfitbl) | ||||
{ | { | ||||
struct nvdimm_SPA_uuid_list_elm *sle; | |||||
int error, i; | int error, i; | ||||
for (i = 0; i < nitems(nvdimm_SPA_uuid_list); i++) { | |||||
sle = &nvdimm_SPA_uuid_list[i]; | |||||
error = parse_uuid(sle->u_id_str, &sle->u_id); | |||||
if (error != 0) { | |||||
if (bootverbose) | |||||
printf("nvdimm_identify: error %d parsing " | |||||
"known SPA UUID %d %s\n", error, i, | |||||
sle->u_id_str); | |||||
return (error); | |||||
} | |||||
} | |||||
error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS, | error = nvdimm_iterate_nfit(nfitbl, ACPI_NFIT_TYPE_SYSTEM_ADDRESS, | ||||
nvdimm_spa_count, &spa_mappings_cnt); | nvdimm_spa_count, &spa_mappings_cnt); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
spa_mappings = malloc(sizeof(struct SPA_mapping) * spa_mappings_cnt, | spa_mappings = malloc(sizeof(struct SPA_mapping) * spa_mappings_cnt, | ||||
M_NVDIMM, M_WAITOK | M_ZERO); | M_NVDIMM, M_WAITOK | M_ZERO); | ||||
i = 0; | i = 0; | ||||
▲ Show 20 Lines • Show All 46 Lines • Show Last 20 Lines |