Skip to content

Commit

Permalink
macos: DriverKit core backend
Browse files Browse the repository at this point in the history
This commit introduces the bulk of macOS support to libvfn. This has to
be used together with MacVFN, which introduces a System Extension
through DriverKit.

Signed-off-by: Mads Ynddal <[email protected]>
  • Loading branch information
Baekalfen committed May 13, 2024
1 parent 379e2a1 commit 223b78a
Show file tree
Hide file tree
Showing 16 changed files with 489 additions and 5 deletions.
16 changes: 16 additions & 0 deletions include/vfn/driverkit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#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 */
2 changes: 2 additions & 0 deletions include/vfn/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
#include <stddef.h>
#include <stdint.h>

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

#include <vfn/iommu/context.h>
#include <vfn/iommu/dma.h>
Expand Down
4 changes: 4 additions & 0 deletions include/vfn/iommu/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,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 @@ -102,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 @@ -112,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 */
4 changes: 4 additions & 0 deletions include/vfn/nvme/ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ struct nvme_ctrl {
/**
* @pci: vfio pci device state
*/
#ifdef __APPLE__
struct driverkit_pci_device pci;
#else
struct vfio_pci_device pci;
#endif

/**
* @serial: Serial number from controller
Expand Down
4 changes: 2 additions & 2 deletions include/vfn/nvme/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ struct nvme_sq {
*/
static inline void nvme_sq_post(struct nvme_sq *sq, const union nvme_cmd *sqe)
{
memcpy(sq->vaddr + (sq->tail << NVME_SQES), sqe, 1 << NVME_SQES);
memcpy(((uint8_t *) sq->vaddr) + (sq->tail << NVME_SQES), sqe, 1 << NVME_SQES);

trace_guard(NVME_SQ_POST) {
trace_emit("sqid %d tail %d\n", sq->id, sq->tail);
Expand Down Expand Up @@ -177,7 +177,7 @@ static inline void nvme_sq_exec(struct nvme_sq *sq, const union nvme_cmd *sqe)
*/
static inline struct nvme_cqe *nvme_cq_head(struct nvme_cq *cq)
{
return (struct nvme_cqe *)(cq->vaddr + (cq->head << NVME_CQES));
return (struct nvme_cqe *)(((uint8_t*) cq->vaddr) + (cq->head << NVME_CQES));
}

/**
Expand Down
47 changes: 47 additions & 0 deletions src/driverkit/pci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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.
*/



#define log_fmt(fmt) "driverkit/pci: " fmt

#ifdef __cplusplus
extern "C" {
#endif

#include <vfn/support.h>

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

void *vfio_pci_map_bar(struct driverkit_pci_device *pci, int idx, size_t len, uint64_t offset, int prot)
{
struct macvfn_pci_map_bar *mapping = (struct macvfn_pci_map_bar *) zmallocn(1, sizeof(struct macvfn_pci_map_bar));
mapping->pci = pci;
mapping->idx = idx;
mapping->len = len;
mapping->offset = offset;

return mapping;
}

void vfio_pci_unmap_bar(struct driverkit_pci_device *pci, int idx, void *mem, size_t len, uint64_t offset)
{
free(mem);
}

#ifdef __cplusplus
}
#endif
10 changes: 10 additions & 0 deletions src/iommu/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,16 @@ struct iommu_ctx *iommu_get_default_context(void)

fallback:
#endif
#ifdef __APPLE__
return driverkit_get_default_iommu_context();
#else
return vfio_get_default_iommu_context();
#endif
}

struct iommu_ctx *iommu_get_context(const char *name)
{
#ifndef __APPLE__
#ifdef HAVE_VFIO_DEVICE_BIND_IOMMUFD
if (__iommufd_broken)
goto fallback;
Expand All @@ -61,8 +66,12 @@ struct iommu_ctx *iommu_get_context(const char *name)
fallback:
#endif
return vfio_get_iommu_context(name);
#else
return driverkit_get_iommu_context(name);
#endif
}

#ifndef __APPLE__
void iommu_ctx_init(struct iommu_ctx *ctx)
{
ctx->nranges = 1;
Expand All @@ -80,3 +89,4 @@ void iommu_ctx_init(struct iommu_ctx *ctx)
skiplist_init(&ctx->map.list);
pthread_mutex_init(&ctx->map.lock, NULL);
}
#endif
37 changes: 37 additions & 0 deletions src/iommu/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,27 @@
#ifndef LIBVFN_SRC_IOMMU_CONTEXT_H
#define LIBVFN_SRC_IOMMU_CONTEXT_H


#ifdef __cplusplus
extern "C" {
#endif
#include "util/skiplist.h"


struct iommu_ctx;

struct iova_mapping {
void *vaddr;
size_t len;
uint64_t iova;
void *opaque[2];

unsigned long flags;

struct skiplist_node list;
};


struct iommu_ctx_ops {
/* container/ioas ops */
int (*iova_reserve)(struct iommu_ctx *ctx, size_t len, uint64_t *iova,
Expand All @@ -31,30 +48,50 @@ struct iommu_ctx_ops {
};

struct iova_map {
#ifndef __APPLE__
pthread_mutex_t lock;
#else
IOLock* lock;
#endif
struct skiplist list;
};

struct iommu_ctx {
struct iova_map map;
struct iommu_ctx_ops ops;

#ifndef __APPLE__
pthread_mutex_t lock;
int nranges;
struct iommu_iova_range *iova_ranges;
#else
IOPCIDevice* pci;
IOLock* lock;
#endif
};

struct iommu_ctx *iommu_get_default_context(void);

#ifndef __APPLE__
struct iommu_ctx *vfio_get_default_iommu_context(void);
struct iommu_ctx *vfio_get_iommu_context(const char *name);

#ifdef HAVE_VFIO_DEVICE_BIND_IOMMUFD
struct iommu_ctx *iommufd_get_default_iommu_context(void);
struct iommu_ctx *iommufd_get_iommu_context(const char *name);
#endif
#else
struct iommu_ctx *driverkit_get_default_iommu_context(void);
struct iommu_ctx *driverkit_get_iommu_context(const char *name);
#endif

void iommu_ctx_init(struct iommu_ctx *ctx);
#ifndef __APPLE__
int iommu_iova_range_to_string(struct iommu_iova_range *range, char **str);
#endif

#ifdef __cplusplus
}
#endif

#endif /* LIBVFN_SRC_IOMMU_CONTEXT_H */
8 changes: 5 additions & 3 deletions src/iommu/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ int _iommu_map_vaddr(struct iommu_ctx *ctx, void *vaddr, size_t len, uint64_t *i
m = znew_t(struct iova_mapping, 1);
m->vaddr = vaddr;
m->len = len;
m->iova = 0;
m->opaque[0] = NULL;
m->opaque[1] = opaque;
m->iova = 0; // Physical/IOMMU address
m->opaque[0] = NULL; // IODMACommand
m->opaque[1] = opaque; // IOMemoryDescriptor
m->flags = flags;

if (ctx->ops.dma_map(ctx, m)) {
Expand Down Expand Up @@ -210,6 +210,7 @@ int iommu_unmap_all(struct iommu_ctx *ctx)
return 0;
}

#ifndef __APPLE__
int iommu_get_iova_ranges(struct iommu_ctx *ctx, struct iommu_iova_range **ranges)
{
*ranges = ctx->iova_ranges;
Expand All @@ -220,6 +221,7 @@ int iommu_iova_range_to_string(struct iommu_iova_range *r, char **str)
{
return asprintf(str, "[0x%llx; 0x%llx]", r->start, r->last);
}
#endif

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 223b78a

Please sign in to comment.