From ff91bfb1cd33fc0e0eabcfdf53bc05baf8052fda Mon Sep 17 00:00:00 2001 From: Nugraha <richiisei@gmail.com> Date: Sun, 16 Apr 2023 03:58:57 +0700 Subject: [PATCH] feat: essential ioctl and nvme package support --- ioctl/hdr_ioctl.go | 50 +++++++++++ nvme/hdr_nvme.go | 210 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 ioctl/hdr_ioctl.go create mode 100644 nvme/hdr_nvme.go diff --git a/ioctl/hdr_ioctl.go b/ioctl/hdr_ioctl.go new file mode 100644 index 0000000..3c616da --- /dev/null +++ b/ioctl/hdr_ioctl.go @@ -0,0 +1,50 @@ +package ioctl + +// Based on `ioctl.h` + +const ( + _IOC_NRBITS = 8 + _IOC_TYPEBITS = 8 + + _IOC_SIZEBITS = 14 // OVERRIDE + _IOC_DIRBITS = 2 // OVERRIDE + + _IOC_NRMASK = (1 << _IOC_NRBITS) - 1 + _IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1 + _IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1 + _IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1 + + _IOC_NRSHIFT = 0 + _IOC_TYPESHIFT = (_IOC_NRSHIFT + _IOC_NRBITS) + _IOC_SIZESHIFT = (_IOC_TYPESHIFT + _IOC_TYPEBITS) + _IOC_DIRSHIFT = (_IOC_SIZESHIFT + _IOC_SIZEBITS) + + _IOC_NONE = 0b00 // OVERRIDE + _IOC_WRITE = 0b01 // OVERRIDE + _IOC_READ = 0b10 // OVERRIDE +) + +//go:nosplit +func IOC(dir, typ, nr, siz int) int { + return 0 | + (dir << _IOC_DIRSHIFT) | + (typ << _IOC_TYPESHIFT) | + (nr << _IOC_NRSHIFT) | + (siz << _IOC_SIZESHIFT) +} + +/* + IO ops +*/ + +//go:nosplit +func IO(typ, nr int) int { return IOC(_IOC_NONE, typ, nr, 0) } + +//go:nosplit +func IOR(typ, nr, siz int) int { return IOC(_IOC_READ, typ, nr, siz) } + +//go:nosplit +func IOW(typ, nr, siz int) int { return IOC(_IOC_WRITE, typ, nr, siz) } + +//go:nosplit +func IOWR(typ, nr, siz int) int { return IOC(_IOC_WRITE|_IOC_READ, typ, nr, siz) } diff --git a/nvme/hdr_nvme.go b/nvme/hdr_nvme.go new file mode 100644 index 0000000..482385e --- /dev/null +++ b/nvme/hdr_nvme.go @@ -0,0 +1,210 @@ +package nvme + +import ( + "unsafe" + + "github.com/ii64/gouring/ioctl" +) + +// Based on `nvme.h` w.r.t. `linux/nvme_ioctl.h` + +const ( + SizeofNvmeAdminCmd = unsafe.Sizeof(NvmeAdminCmd{}) + SizeofNvmeUserIo = unsafe.Sizeof(NvmeUserIo{}) + SizeofNvmePassthruCmd = unsafe.Sizeof(NvmePassthruCmd{}) + SizeofNvmePassthruCmd64 = unsafe.Sizeof(NvmePassthruCmd64{}) + SizeofNvmeUringCmd = unsafe.Sizeof(NvmeUringCmd{}) + SizeofNvmeIdNs = unsafe.Sizeof(NvmeIdNs{}) + SizeofNvmeLbaf = unsafe.Sizeof(NvmeLbaf{}) + + NVME_DEFAULT_IOCTL_TIMEOUT = 0 + NVME_IDENTIFY_DATA_SIZE = 0x1000 + NVME_IDENTIFY_CSI_SHIFT = 24 + NVME_IDENTIFY_CNS_NS = 0 + NVME_CSI_NVM = 0 +) + +func _SizeChecker() { + var x [1]struct{} + _ = x[SizeofNvmeAdminCmd-72] + _ = x[SizeofNvmeUserIo-48] + _ = x[SizeofNvmePassthruCmd-72] + _ = x[SizeofNvmePassthruCmd64-80] + _ = x[SizeofNvmeUringCmd-72] + _ = x[SizeofNvmeLbaf-4] + _ = x[SizeofNvmeIdNs-0x1000] +} + +// Can this NVME_URING_CMD_* folds into constant literal? + +var ( + NVME_IOCTL_ID = ioctl.IO('N', 0x40) + NVME_IOCTL_ADMIN_CMD = ioctl.IOWR('N', 0x41, int(SizeofNvmeAdminCmd)) + NVME_IOCTL_SUBMIT_IO = ioctl.IOW('N', 0x42, int(SizeofNvmeUserIo)) + NVME_IOCTL_IO_CMD = ioctl.IOR('N', 0x43, int(SizeofNvmePassthruCmd)) + NVME_IOCTL_RESET = ioctl.IO('N', 0x44) + NVME_IOCTL_SUBSYS_RESET = ioctl.IO('N', 0x45) + NVME_IOCTL_RESCAN = ioctl.IO('N', 0x46) + NVME_IOCTL_ADMIN64_CMD = ioctl.IOWR('N', 0x47, int(SizeofNvmePassthruCmd64)) + NVME_IOCTL_IO64_CMD = ioctl.IOWR('N', 0x48, int(SizeofNvmePassthruCmd64)) + NVME_IOCTL_IO64_CMD_VEC = ioctl.IOWR('N', 0x49, int(SizeofNvmePassthruCmd64)) + + NVME_URING_CMD_IO = ioctl.IOWR('N', 0x80, int(SizeofNvmeUringCmd)) + NVME_URING_CMD_IO_VEC = ioctl.IOWR('N', 0x81, int(SizeofNvmeUringCmd)) + NVME_URING_CMD_ADMIN = ioctl.IOWR('N', 0x82, int(SizeofNvmeUringCmd)) + NVME_URING_CMD_ADMIN_VEC = ioctl.IOWR('N', 0x83, int(SizeofNvmeUringCmd)) +) + +func init() { + println("dbg NVME_URING_CMD_IO", NVME_URING_CMD_IO) + println("dbg NVME_URING_CMD_IO_VEC", NVME_URING_CMD_IO_VEC) + println("dbg NVME_URING_CMD_ADMIN", NVME_URING_CMD_ADMIN) + println("dbg NVME_URING_CMD_ADMIN_VEC", NVME_URING_CMD_ADMIN_VEC) +} + +// nvme_admin_opcode +const ( + NVME_ADMIN_IDENTIFY = 0x06 +) + +// nvme_io_opcode +const ( + NVME_CMD_WRITE = 0x01 + NVME_CMD_READ = 0x02 +) + +type NvmeAdminCmd = NvmePassthruCmd + +type NvmeUserIo struct { + Opcode uint8 + Flags uint8 + Control uint16 + Nblocks uint16 + Rsvd uint16 + Metadata uint64 + Addr uint64 + Slba uint64 + Dsmgmt uint32 + Reftag uint32 + Apptag uint16 + Appmask uint16 + _pad [4]byte +} + +type NvmePassthruCmd struct { + Opcode uint8 + Flags uint8 + Rsvd1 uint16 + Nsid uint32 + Cdw2, + Cdw3 uint32 + Metadata uint64 + Addr uint64 + MetadataLen uint32 + DataLen uint32 + Cdw10, + Cdw11, + Cdw12, + Cdw13, + Cdw14, + Cdw15 uint32 + TimeoutMs uint32 + Result uint32 +} + +type NvmePassthruCmd64_Union1 uint32 + +func (u *NvmePassthruCmd64_Union1) SetDataLen(v uint32) { *u = NvmePassthruCmd64_Union1(v) } +func (u *NvmePassthruCmd64_Union1) SetVecCount(v uint32) { *u = NvmePassthruCmd64_Union1(v) } + +type NvmePassthruCmd64 struct { + Opcode uint8 + Flags uint8 + Rsvd1 uint16 + Nsid uint32 + Cdw2, + Cdw3 uint32 + Metadata uint64 + Addr uint64 + MetadataLen uint32 + // union { + // __u32 data_len; /* for non-vectored io */ + // __u32 vec_cnt; /* for vectored io */ + // }; + NvmePassthruCmd64_Union1 + Cdw10, + Cdw11, + Cdw12, + Cdw13, + Cdw14, + Cdw15 uint32 + TimeoutMs uint32 + Rsvd2 uint32 + Result uint64 +} + +type NvmeUringCmd struct { + Opcode uint8 + Flags uint8 + Rsvd1 uint16 + Nsid uint32 + Cdw2, Cdw3 uint32 + Metadata uint64 + Addr uint64 + MetadataLen uint32 + DataLen uint32 + + Cdw10, Cdw11, Cdw12, Cdw13, Cdw14, Cdw15 uint32 + + TimeoutMs uint32 + Rsvd2 uint32 +} + +type NvmeLbaf struct { + Ms uint16 // bo: Little + Ds uint8 + Rp uint8 +} + +type NvmeIdNs struct { + Nsze, + Ncap, + Nuse uint64 // bo: Little + Nsfeat, + Nlbaf, + Flbas, + Mc, + Dpc, + Dps, + Nmic, + Rescap, + Fpi, + Dlfeat uint8 + Nawun, + Nawupf, + Nacwu, + Nabsn, + Nabo, + Nabspf, + Noiob uint16 // bo: Little + Nvmcap [16]byte + Npwg, + Npwa, + Npdg, + Npda, + Nows uint16 // bo: Little + Msrl uint16 // bo: Little + Mcl uint32 // bo: Little + Msrc uint8 + Resvd81 [11]byte + Anagrpid uint32 // bo: Little + Rsvd96 [3]byte + Nsattr uint8 + Nvmsetid uint16 // bo: Little + Endgid uint16 // bo: Little + Nguid [16]byte + Eui64 [8]byte + Lbaf [16]NvmeLbaf + Rsvd192 [192]byte + Vs [3712]byte +}