1/* 2 * Copyright (c) 2018, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <stdio.h> 12#include <string.h> 13#include <assert.h> 14 15#include <barrelfish/barrelfish.h> 16#include <driverkit/driverkit.h> 17#include <skb/skb.h> 18 19#include "intel_vtd.h" 20 21#define DRIVER_DEBUG(x...) debug_printf("[iommu] " x) 22 23 24vregion_flags_t vtd_table_map_attrs = VREGION_FLAGS_READ_WRITE; 25 26 27/** 28 * Driver initialization function. This function is called by the driver domain 29 * (see also 'create_handler' in ddomain_service.c). 30 * Typically through a request from the device manager. 31 * 32 * The init function is supposed to set `dev` to the exported service iref. 33 * The init function may use `bfi->dstate` to store additional state about the device. 34 * 35 * \param[in] bfi The instance of this driver. 36 * \param[in] name The name of this driver instance. 37 * \param[in] flags Additional flags (The exact flags supported is device/driver specific). 38 * \param[in] c Capabilities (for registers etc.) as provided by the device manager. 39 * The exact layout of the `c` is device specific. 40 * \param[out] dev The service iref over which the device can be contacted. 41 * 42 * \retval SYS_ERR_OK Device initialized successfully. 43 * \retval LIB_ERR_MALLOC_FAIL Unable to allocate memory for the driver. 44 */ 45static errval_t init(struct bfdriver_instance *bfi, uint64_t flags, iref_t *dev) { 46 errval_t err; 47 48 DRIVER_DEBUG("Initialize: %s\n", bfi->name); 49 50 debug_printf("Initializing Intel VT-d driver module...\n"); 51 52 if (capref_is_null(bfi->caps[0])) { 53 return DRIVERKIT_ERR_NO_CAP_FOUND; 54 } 55 56 struct frame_identity id; 57 err = frame_identify(bfi->caps[0], &id); 58 if (err_is_fail(err)) { 59 return err; 60 } 61 62 struct vtd *vtd = calloc(sizeof(*vtd), 1); 63 if (vtd == NULL) { 64 return LIB_ERR_MALLOC_FAIL; 65 } 66 67 err = vtd_create(vtd, bfi->caps[0]); 68 if (err_is_fail(err)) { 69 goto err_out; 70 } 71 72 bfi->dstate = vtd; 73 74 // 3. Set iref of your exported service (this is reported back to Kaluga) 75 *dev = 0x00; 76 77 return SYS_ERR_OK; 78 79err_out: 80 free(vtd); 81 return err; 82} 83 84/** 85 * Instructs driver to attach to the device. 86 * This function is only called if the driver has previously detached 87 * from the device (see also detach). 88 * 89 * \note After detachment the driver can not assume anything about the 90 * configuration of the device. 91 * 92 * \param[in] bfi The instance of this driver. 93 * \retval SYS_ERR_OK Device initialized successfully. 94 */ 95static errval_t attach(struct bfdriver_instance* bfi) { 96 DRIVER_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 97 98 return SYS_ERR_OK; 99} 100 101/** 102 * Instructs driver to detach from the device. 103 * The driver must yield any control over to the device after this function returns. 104 * The device may be left in any state. 105 * 106 * \param[in] bfi The instance of this driver. 107 * \retval SYS_ERR_OK Device initialized successfully. 108 */ 109static errval_t detach(struct bfdriver_instance* bfi) { 110 DRIVER_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 111 112 return SYS_ERR_OK; 113} 114 115/** 116 * Instructs the driver to go in a particular sleep state. 117 * Supported states are platform/device specific. 118 * 119 * \param[in] bfi The instance of this driver. 120 * \retval SYS_ERR_OK Device initialized successfully. 121 */ 122static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) { 123 DRIVER_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 124 125 return SYS_ERR_OK; 126} 127 128/** 129 * Destroys this driver instance. The driver will yield any 130 * control over the device and free any state allocated. 131 * 132 * \param[in] bfi The instance of this driver. 133 * \retval SYS_ERR_OK Device initialized successfully. 134 */ 135static errval_t destroy(struct bfdriver_instance* bfi) { 136 DRIVER_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 137 138 139 return SYS_ERR_OK; 140} 141 142static errval_t get_ep(struct bfdriver_instance* bfi, bool lmp, struct capref* ret_cap) 143{ 144 struct vtd *vtd = (struct vtd*) bfi->dstate; 145 return iommu_request_endpoint(lmp? IDC_ENDPOINT_LMP: IDC_ENDPOINT_UMP, ret_cap, (struct iommu*) vtd); 146} 147/** 148 * Registers the driver module with the system. 149 * 150 * To link this particular module in your driver domain, 151 * add it to the addModules list in the Hakefile. 152 */ 153DEFINE_MODULE(iommu_intel_module, init, attach, detach, set_sleep_level, destroy, get_ep); 154