Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add macOS/DriverKit through MacVFN #10

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
abab907
mmio: convert calls of 'addr + offset' to 'base-addr, offset'
Baekalfen Aug 20, 2023
1982a33
support/linux: move linux mem.c to src/support/platform/linux/
Baekalfen Sep 12, 2023
37b5cbf
support/linux: prepartory work of moving log, mem, mmio, mutex header…
Baekalfen Sep 13, 2023
3f8f21e
support/macos: add macos replacement for byteswap.h
Baekalfen Sep 13, 2023
cedbf40
support/macos: add macos replacement for errno.h
Baekalfen Sep 13, 2023
c698007
support/macos: added include/.../platform/macos/log.h
Baekalfen Sep 13, 2023
b09b63c
support/macos: added include/.../platform/macos/mem.h
Baekalfen Sep 13, 2023
0e640ea
support/macos: added include/.../platform/macos/mmio.h
Baekalfen Sep 13, 2023
6a75519
support/macos: added include/.../platform/macos/mutex.h
Baekalfen Sep 13, 2023
b7fbecc
misc/cpp: add explicit cast of void* and change string concat to acco…
Baekalfen Sep 13, 2023
d81e69f
gitignore: crc64table.h and config.h
Baekalfen Sep 13, 2023
ff1b9e6
src/iommu/context.h: Add include guard
Baekalfen Apr 11, 2024
91b3142
misc: reduce includes, add C++ ifdef
Baekalfen Apr 9, 2024
da24e66
iommu/iova: dma_map, iova_map_add, dma_unmap takes iova_mapping
Baekalfen Apr 9, 2024
45be927
skiplist: replace rand() with arc4random() as it's not present on macOS
Baekalfen Apr 10, 2024
a961d1a
skiplist: Add include guard
Baekalfen Apr 10, 2024
290dcd4
nvme_wait_rdy: timeout for macOS
Baekalfen Apr 11, 2024
3b4bae1
nvme_cq_wait_cqes: timeout for macOS and counting ticks
Baekalfen Apr 11, 2024
1c48f71
nvme/core: add serial to nvme_ctrl
Baekalfen Apr 30, 2024
87ba60d
pgmap/iommu: refactor for opaque pointers
Baekalfen May 3, 2024
3b111dd
macos: DriverKit core backend
Baekalfen Sep 13, 2023
e2144c2
misc/log: change logging on unrecoverable errors
Baekalfen May 3, 2024
934f841
ci/macos: add macOS build process
Baekalfen May 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,33 @@ jobs:
name: meson test log
path: build/meson-logs/testlog.txt

macos-build:
name: "macOS build"
needs: [sanity]
runs-on: macos-latest

steps:
- name: checkout
uses: actions/checkout@v4
with:
repository: samsungds/macvfn
ref: libvfn4 # TODO: 'master' once merged

- name: Configure PR branch as submodule
run: |
SUBMODULE_PATH="MacVFN/libvfn"
BRANCH_NAME=${GITHUB_HEAD_REF#refs/heads/}
git config -f .gitmodules submodule.$SUBMODULE_PATH.url ${GITHUB_SERVER_URL}/${{github.event.pull_request.head.repo.full_name}}
git config -f .gitmodules submodule.$SUBMODULE_PATH.branch "$BRANCH_NAME"
cat .gitmodules
git submodule update --remote --init $SUBMODULE_PATH

- name: Install dependencies
run: brew install meson

- name: Xcode build
run: make build

device-test:
name: "run emulated nvme device tests"

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
tags
crc64table.h
config.h
2 changes: 1 addition & 1 deletion docs/api/support/log.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
Logging
=======

.. kernel-doc:: include/vfn/support/log.h
.. kernel-doc:: include/vfn/support/platform/linux/log.h
2 changes: 1 addition & 1 deletion docs/api/support/mem.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
Memory Allocation Helpers
=========================

.. kernel-doc:: include/vfn/support/mem.h
.. kernel-doc:: include/vfn/support/platform/linux/mem.h
2 changes: 1 addition & 1 deletion docs/api/support/mmio.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Memory-mapped I/O
These helpers expect and return little endian types (i.e. ``leint32_t``) which
may help with locating endianness related bugs using the sparse static analyzer.

.. kernel-doc:: include/vfn/support/mmio.h
.. kernel-doc:: include/vfn/support/platform/linux/mmio.h
2 changes: 1 addition & 1 deletion docs/api/support/mutex.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
Autolockable Mutex
==================

.. kernel-doc:: include/vfn/support/mutex.h
.. kernel-doc:: include/vfn/support/platform/linux/mutex.h
10 changes: 5 additions & 5 deletions examples/cmb-p2p.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ static void *nvme_configure_cmb(struct nvme_ctrl *ctrl, uint64_t *hwaddr, uint64
struct iommu_iova_range *iova_ranges;
int num_iova_ranges;

cap = le64_to_cpu(mmio_read64(ctrl->regs + NVME_REG_CAP));
cap = le64_to_cpu(mmio_read64(ctrl->regs, NVME_REG_CAP));

if (NVME_GET(cap, CAP_CMBS))
mmio_hl_write64(ctrl->regs + NVME_REG_CMBMSC, cpu_to_le64(0x1));
mmio_hl_write64(ctrl->regs, NVME_REG_CMBMSC, cpu_to_le64(0x1));

cmbsz = le32_to_cpu(mmio_read32(ctrl->regs + NVME_REG_CMBSZ));
cmbloc = le32_to_cpu(mmio_read32(ctrl->regs + NVME_REG_CMBLOC));
cmbsz = le32_to_cpu(mmio_read32(ctrl->regs, NVME_REG_CMBSZ));
cmbloc = le32_to_cpu(mmio_read32(ctrl->regs, NVME_REG_CMBLOC));

szu = 1 << (12 + 4 * NVME_GET(cmbsz, CMBSZ_SZU));
len = szu * NVME_GET(cmbsz, CMBSZ_SZ);
Expand Down Expand Up @@ -103,7 +103,7 @@ static void *nvme_configure_cmb(struct nvme_ctrl *ctrl, uint64_t *hwaddr, uint64
printf("assigned cmb base address is 0x%lx\n", *cba);

/* set the base address and enable the memory space */
mmio_hl_write64(ctrl->regs + NVME_REG_CMBMSC, cpu_to_le64(*cba | 0x3));
mmio_hl_write64(ctrl->regs, NVME_REG_CMBMSC, cpu_to_le64(*cba | 0x3));

return cmb;
}
Expand Down
12 changes: 6 additions & 6 deletions examples/cmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,19 @@ int main(int argc, char **argv)
if (nvme_init(&ctrl, bdf, NULL))
err(1, "failed to init nvme controller");

vs = le32_to_cpu(mmio_read32(ctrl.regs + NVME_REG_VS));
vs = le32_to_cpu(mmio_read32(ctrl.regs, NVME_REG_VS));
if (vs < NVME_VERSION(1, 4, 0))
errx(1, "controller must be compliant with at least nvme v1.4.0");

cap = le64_to_cpu(mmio_read64(ctrl.regs + NVME_REG_CAP));
cap = le64_to_cpu(mmio_read64(ctrl.regs, NVME_REG_CAP));
if (!NVME_GET(cap, CAP_CMBS))
errx(1, "controller memory buffer not supported (cap 0x%lx)", cap);

/* enable the CMBSZ and CMBLOC registers */
mmio_hl_write64(ctrl.regs + NVME_REG_CMBMSC, cpu_to_le64(0x1));
mmio_hl_write64(ctrl.regs, NVME_REG_CMBMSC, cpu_to_le64(0x1));

cmbsz = le32_to_cpu(mmio_read32(ctrl.regs + NVME_REG_CMBSZ));
cmbloc = le32_to_cpu(mmio_read32(ctrl.regs + NVME_REG_CMBLOC));
cmbsz = le32_to_cpu(mmio_read32(ctrl.regs, NVME_REG_CMBSZ));
cmbloc = le32_to_cpu(mmio_read32(ctrl.regs, NVME_REG_CMBLOC));

szu = 1 << (12 + 4 * NVME_GET(cmbsz, CMBSZ_SZU));
len = szu * NVME_GET(cmbsz, CMBSZ_SZ);
Expand Down Expand Up @@ -113,7 +113,7 @@ int main(int argc, char **argv)
printf("assigned cmb base address is 0x%lx\n", cba);

/* set the base address and enable the memory space */
mmio_hl_write64(ctrl.regs + NVME_REG_CMBMSC, cpu_to_le64(cba | 0x3));
mmio_hl_write64(ctrl.regs, NVME_REG_CMBMSC, cpu_to_le64(cba | 0x3));

cmd = (union nvme_cmd) {
.opcode = nvme_admin_identify,
Expand Down
48 changes: 24 additions & 24 deletions examples/regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,30 +66,30 @@ int main(int argc, char **argv)

regs = ctrl.regs;

cap = le64_to_cpu(mmio_read64(regs + NVME_REG_CAP));
vs = le32_to_cpu(mmio_read32(regs + NVME_REG_VS));
intms = le32_to_cpu(mmio_read32(regs + NVME_REG_INTMS));
intmc = le32_to_cpu(mmio_read32(regs + NVME_REG_INTMC));
cc = le32_to_cpu(mmio_read32(regs + NVME_REG_CC));
csts = le32_to_cpu(mmio_read32(regs + NVME_REG_CSTS));
nssr = le32_to_cpu(mmio_read32(regs + NVME_REG_NSSR));
aqa = le32_to_cpu(mmio_read32(regs + NVME_REG_AQA));
asq = le64_to_cpu(mmio_read64(regs + NVME_REG_ASQ));
acq = le64_to_cpu(mmio_read64(regs + NVME_REG_ACQ));
cmbloc = le32_to_cpu(mmio_read32(regs + NVME_REG_CMBLOC));
cmbsz = le32_to_cpu(mmio_read32(regs + NVME_REG_CMBSZ));
bpinfo = le32_to_cpu(mmio_read32(regs + NVME_REG_BPINFO));
bprsel = le32_to_cpu(mmio_read32(regs + NVME_REG_BPRSEL));
bpmbl = le64_to_cpu(mmio_read64(regs + NVME_REG_BPMBL));
cmbmsc = le64_to_cpu(mmio_read64(regs + NVME_REG_CMBMSC));
cmbsts = le32_to_cpu(mmio_read32(regs + NVME_REG_CMBSTS));
pmrcap = le32_to_cpu(mmio_read32(regs + NVME_REG_PMRCAP));
pmrctl = le32_to_cpu(mmio_read32(regs + NVME_REG_PMRCTL));
pmrsts = le32_to_cpu(mmio_read32(regs + NVME_REG_PMRSTS));
pmrebs = le32_to_cpu(mmio_read32(regs + NVME_REG_PMREBS));
pmrswtp = le32_to_cpu(mmio_read32(regs + NVME_REG_PMRSWTP));
pmrmsc = le32_to_cpu(mmio_read32(regs + NVME_REG_PMRMSCL)) |
(uint64_t)le32_to_cpu(mmio_read32(regs + NVME_REG_PMRMSCU)) << 32;
cap = le64_to_cpu(mmio_read64(regs, NVME_REG_CAP));
vs = le32_to_cpu(mmio_read32(regs, NVME_REG_VS));
intms = le32_to_cpu(mmio_read32(regs, NVME_REG_INTMS));
intmc = le32_to_cpu(mmio_read32(regs, NVME_REG_INTMC));
cc = le32_to_cpu(mmio_read32(regs, NVME_REG_CC));
csts = le32_to_cpu(mmio_read32(regs, NVME_REG_CSTS));
nssr = le32_to_cpu(mmio_read32(regs, NVME_REG_NSSR));
aqa = le32_to_cpu(mmio_read32(regs, NVME_REG_AQA));
asq = le64_to_cpu(mmio_read64(regs, NVME_REG_ASQ));
acq = le64_to_cpu(mmio_read64(regs, NVME_REG_ACQ));
cmbloc = le32_to_cpu(mmio_read32(regs, NVME_REG_CMBLOC));
cmbsz = le32_to_cpu(mmio_read32(regs, NVME_REG_CMBSZ));
bpinfo = le32_to_cpu(mmio_read32(regs, NVME_REG_BPINFO));
bprsel = le32_to_cpu(mmio_read32(regs, NVME_REG_BPRSEL));
bpmbl = le64_to_cpu(mmio_read64(regs, NVME_REG_BPMBL));
cmbmsc = le64_to_cpu(mmio_read64(regs, NVME_REG_CMBMSC));
cmbsts = le32_to_cpu(mmio_read32(regs, NVME_REG_CMBSTS));
pmrcap = le32_to_cpu(mmio_read32(regs, NVME_REG_PMRCAP));
pmrctl = le32_to_cpu(mmio_read32(regs, NVME_REG_PMRCTL));
pmrsts = le32_to_cpu(mmio_read32(regs, NVME_REG_PMRSTS));
pmrebs = le32_to_cpu(mmio_read32(regs, NVME_REG_PMREBS));
pmrswtp = le32_to_cpu(mmio_read32(regs, NVME_REG_PMRSWTP));
pmrmsc = le32_to_cpu(mmio_read32(regs, NVME_REG_PMRMSCL)) |
(uint64_t)le32_to_cpu(mmio_read32(regs, NVME_REG_PMRMSCU)) << 32;

printf("%-16s %lx\n", "CAP", cap);
printf("%-16s %lx\n", "CAP.MQES", NVME_CAP_MQES(cap));
Expand Down
28 changes: 28 additions & 0 deletions include/vfn/driverkit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later or MIT */

/*
* This file is part of libvfn.
*
* Copyright (C) 2022 The libvfn Authors. All Rights Reserved.
*
* This library (libvfn) is dual licensed under the GNU Lesser General
* Public License version 2.1 or later or the MIT license. See the
* COPYING and LICENSE files for more information.
*/

#ifndef LIBVFN_VFIO_H
#define LIBVFN_VFIO_H

#ifdef __cplusplus
extern "C" {
#endif

#include <vfn/driverkit/device.h>
#include <vfn/driverkit/pci.h>
#include <vfn/iommu/dma.h>

#ifdef __cplusplus
}
#endif

#endif /* LIBVFN_VFIO_H */
37 changes: 37 additions & 0 deletions include/vfn/driverkit/device.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later or MIT */

/*
* This file is part of libvfn.
*
* Copyright (C) 2022 The libvfn Authors. All Rights Reserved.
*
* This library (libvfn) is dual licensed under the GNU Lesser General
* Public License version 2.1 or later or the MIT license. See the
* COPYING and LICENSE files for more information.
*/

#ifndef LIBVFN_DRIVERKIT_DEVICE_H
#define LIBVFN_DRIVERKIT_DEVICE_H

#include <DriverKit/OSCollection.h>
#include <PCIDriverKit/PCIDriverKit.h>
#include "iommu/context.h"

struct driverkit_bar_info {
uint8_t type;
uint8_t memory_index;
uint64_t size;
};

struct driverkit_pci_device {
IOPCIDevice *dev;
struct iommu_ctx ctx;
OSDictionary *iommu_mappings;
const char *bdf;

struct driverkit_bar_info bar_region_info[6];
};

#define __iommu_ctx(x) (&((struct driverkit_pci_device *)(x))->ctx)

#endif /* LIBVFN_DRIVERKIT_DEVICE_H */
47 changes: 47 additions & 0 deletions include/vfn/driverkit/pci.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later or MIT */

#ifndef LIBVFN_VFIO_PCI_H
#define LIBVFN_VFIO_PCI_H

#define off_t int

// NOTE: Dummy PROT to satisfy Linux code
enum {
PROT_READ = 0,
PROT_WRITE = 1,
};

// NOTE: Faux open for macOS
int vfio_pci_open(struct driverkit_pci_device *pci, const char *bdf);

/**
* vfio_pci_map_bar - faux mapping in DriverKit
* @pci: &struct driverkit_pci_device
* @idx: the vfio region index to map
* @len: number of bytes to map
* @offset: offset at which to start mapping
* @prot: what accesses to permit to the mapped area (see ``man mmap``).
*
* Used in place of VFIO map device memory region identified by @idx into virtual memory.
*
* Return: On success, returns the virtual memory address mapped. On error,
* returns ``NULL`` and sets ``errno``.
*/
void *vfio_pci_map_bar(struct driverkit_pci_device *pci, int idx, size_t len, uint64_t offset,
int prot);

/**
* vfio_pci_unmap_bar - faux unmap a region in virtual memory for DriverKit
* @pci: &struct driverkit_pci_device
* @idx: the vfio region index to unmap
* @mem: virtual memory address to unmap
* @len: number of bytes to unmap
* @offset: offset at which to start unmapping
*
* Used in place of VFIO to unmap the virtual memory address, previously mapped
* to the vfio device memory region identified by @idx.
*/
void vfio_pci_unmap_bar(struct driverkit_pci_device *pci, int idx, void *mem, size_t len,
uint64_t offset);

#endif /* LIBVFN_VFIO_PCI_H */
10 changes: 2 additions & 8 deletions include/vfn/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,15 @@
#ifndef LIBVFN_IOMMU_H
#define LIBVFN_IOMMU_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#ifndef __APPLE__
#include <linux/types.h>
#endif

#include <vfn/iommu/context.h>
#include <vfn/iommu/dma.h>

#ifdef __cplusplus
}
#endif

#endif /* LIBVFN_IOMMU_H */
8 changes: 8 additions & 0 deletions include/vfn/iommu/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ enum iommu_map_flags {
IOMMU_MAP_NOREAD = 1 << 3,
};

#ifndef __APPLE__
/**
* iommu_map_vaddr - Map a virtual memory address to an I/O virtual address
* @ctx: &struct iommu_ctx
Expand All @@ -53,6 +54,9 @@ enum iommu_map_flags {
*/
int iommu_map_vaddr(struct iommu_ctx *ctx, void *vaddr, size_t len, uint64_t *iova,
unsigned long flags);
#endif
int _iommu_map_vaddr(struct iommu_ctx *ctx, void *vaddr, size_t len, uint64_t *iova,
unsigned long flags, void *opaque);

/**
* iommu_unmap_vaddr - Unmap a virtual memory address in the IOMMU
Expand All @@ -78,12 +82,14 @@ int iommu_unmap_vaddr(struct iommu_ctx *ctx, void *vaddr, size_t *len);
*/
int iommu_unmap_all(struct iommu_ctx *ctx);

#ifndef __APPLE__
#ifndef IOMMU_IOAS_IOVA_RANGES
struct iommu_iova_range {
__aligned_u64 start;
__aligned_u64 last;
};
#endif
#endif

/**
* iommu_translate_vaddr - Translate a virtual address into an iova
Expand All @@ -98,6 +104,7 @@ struct iommu_iova_range {
*/
bool iommu_translate_vaddr(struct iommu_ctx *ctx, void *vaddr, uint64_t *iova);

#ifndef __APPLE__
/**
* iommu_get_iova_ranges - Get iova ranges
* @ctx: &struct iommu_ctx
Expand All @@ -108,5 +115,6 @@ bool iommu_translate_vaddr(struct iommu_ctx *ctx, void *vaddr, uint64_t *iova);
* Return: the number of elements in the array pointed to.
*/
int iommu_get_iova_ranges(struct iommu_ctx *ctx, struct iommu_iova_range **ranges);
#endif

#endif /* LIBVFN_IOMMU_DMA_H */
Loading