1/** 2 * \file 3 * \brief Module to set the System Memory Page Tables of the Xeon Phi 4 */ 5 6/* 7 * Copyright (c) 2014 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <string.h> 17#include <barrelfish/barrelfish.h> 18 19#include <dev/xeon_phi/xeon_phi_smpt_dev.h> 20 21#include "xeon_phi_internal.h" 22#include "smpt.h" 23 24/* 25 * XXX: Setting a system memory pagetable entry basically enables the coprocessor 26 * to access host memory directly. This is an open issue and should be 27 * restricted by capabilities somehow. 28 * 29 * Anyhow, since the access to this memory range is controlled as normal 30 * memory, we can trust the kernels on the card not to introduce potential 31 * vulnerabilities... 32 * 33 * Note: the system memory pagetables are rather coarse grained (16GB) 34 */ 35 36/** 37 * \brief calculates the base address offset of the Xeon Phi GDDR 38 * 39 * This function will return 0 if the ID is the local card. 40 * 41 * \param phi the local xeon phi 42 * \param id the xeon phi id of the other card 43 * 44 * \returns offset base address of GDDR (0 if local) i 45 */ 46lpaddr_t smpt_get_coprocessor_address(struct xeon_phi *phi, 47 uint8_t id) 48{ 49 if (id == phi->id) { 50 return 0; 51 } 52 53 uint8_t slot = xeon_phi_smpt_system_page_num - 1; 54 if (id < phi->id) { 55 slot = slot - id; 56 } else { 57 slot = slot - id + 1; 58 } 59 60 assert(slot < xeon_phi_smpt_system_page_num); 61 62 XSMPT_DEBUG("Calculating slot for id %u: slot=%u, offset=%016lx\n", id, slot, 63 phi->smpt->offsets[slot]); 64 65 return ((lpaddr_t) slot * XEON_PHI_SYSMEM_PAGE_SIZE) + phi->smpt->offsets[slot]; 66} 67 68/** 69 * \brief sets the offset into the system memory page where the card is mapped 70 * 71 * \param phi the local xeon phi 72 * \param id ID of the card 73 * \param offset the offest into the page 74 */ 75void smpt_set_coprocessor_offset(struct xeon_phi *phi, 76 uint8_t id, 77 lpaddr_t offset) 78{ 79 80 uint8_t slot = xeon_phi_smpt_system_page_num - 1; 81 if (id < phi->id) { 82 slot = slot - id; 83 } else { 84 slot = slot - id + 1; 85 } 86 87 XSMPT_DEBUG("Offset for slot %u: offset=%016lx\n", slot, 88 phi->smpt->offsets[slot]); 89 90 phi->smpt->offsets[slot] = offset; 91} 92 93/** 94 * \brief calculates the ID of the Xeon Phi based on the physical address 95 * 96 * \param phi the local Xeon Phi 97 * \param addr physical address to lookup 98 * 99 * \returns the ID of the Xeon Phi this memory address belogngs to 100 */ 101uint8_t smtp_get_xeon_phi_id_from_addr(struct xeon_phi *phi, 102 lpaddr_t addr) 103{ 104 /* align the address first */ 105 if (addr >= XEON_PHI_SYSMEM_KNC_BASE) { 106 addr -= XEON_PHI_SYSMEM_BASE; 107 uint64_t slot = (addr / XEON_PHI_SYSMEM_PAGE_SIZE); 108 assert(slot < 32); 109 slot = xeon_phi_smpt_system_page_num - slot; 110 uint8_t id = xeon_phi_smpt_system_page_num - slot; 111 if (id > phi->id) { 112 id = id - 1; 113 } 114 return id; 115 } 116 return phi->id; 117} 118 119/** 120 * \brief sets the entry of the SMPT for the Xeon Phi with given id 121 * 122 * \param phi the local Xeon Phi 123 * \param id ID of the other Xeon Phi 124 * \param addr the physical (host)address 125 * 126 * \returns 1 on SUCCESS 127 * 0 on attempt to set the own SMPT entry 128 */ 129uint8_t smpt_set_coprocessor_address(struct xeon_phi *phi, 130 uint8_t id, 131 lpaddr_t addr) 132{ 133 if (id == phi->id) { 134 return 0; 135 } 136 137 uint8_t slot = xeon_phi_smpt_system_page_num - 1; 138 if (id < phi->id) { 139 slot = slot - id; 140 } else { 141 slot = slot - id + 1; 142 } 143 144 XSMPT_DEBUG("Setting Co-processor slot %u to address 0x%016lx\n", slot, addr); 145 146 smpt_set_address(phi, slot, addr, 1); 147 148 return 1; 149} 150 151/** 152 * \brief Sets an entry in the system memory pagetable to a give address 153 * 154 * \param phi reference to the card structure 155 * \param slot pagetable entry to set 156 * \param address host address to set 157 * \param snooping enable snooping = 1, disable snooping = 0 158 * 159 * \return SYS_ERR_OK on success 160 */ 161void smpt_set_address(struct xeon_phi *phi, 162 uint8_t slot, 163 lpaddr_t address, 164 uint8_t snooping) 165{ 166 lpaddr_t e_address = (address >> xeon_phi_smpt_system_page_shift); 167 xeon_phi_smpt_entry_t e = xeon_phi_smpt_entry_default; 168 e = xeon_phi_smpt_entry_host_address_insert(e, (uint32_t) e_address); 169 170 if ((address >> 32) != e) { 171 assert(address > e); 172 phi->smpt->offsets[slot] = ((address >> 32) - e) << 32; 173 XSMPT_DEBUG("Slot[%u] = 0x%08x + 0x%08lx\n", slot, e, ((address >> 32) - e)); 174 } 175 176 if (snooping) { 177 snooping = xeon_phi_smpt_snooping_enabled; 178 } else { 179 snooping = xeon_phi_smpt_snooping_disabled; 180 } 181 e = xeon_phi_smpt_entry_snoop_disabled_insert(e, snooping); 182 183 smpt_set_entry(phi, slot, e); 184} 185 186/** 187 * \brief Resets the system memory page tables 188 */ 189void smpt_reset(struct xeon_phi *phi) 190{ 191 for (uint32_t i = 0; i < xeon_phi_smpt_system_page_num; ++i) { 192 smpt_clear_entry(phi, i); 193 } 194} 195 196#ifdef __k1om__ 197/** 198 * \brief initializes the SMPT for the Xeon Phi Card 199 * 200 * \return SYS_ERR_OK on success 201 */ 202errval_t smpt_init(struct xeon_phi *phi) 203{ 204 if (phi->smpt) { 205 if (phi->smpt->smpt_enabled) { 206 debug_printf("WARNING: SMPT already setup"); 207 return SYS_ERR_OK; 208 } 209 } 210 phi->smpt = calloc(1, sizeof(struct smpt_info)); 211 if (!phi->smpt) { 212 return LIB_ERR_MALLOC_FAIL; 213 } 214 return SYS_ERR_OK; 215} 216#else 217/** 218 * \brief initializes the system memory page tables with a 219 * 1:1 mapping 220 * 221 * \return SYS_ERR_OK on success 222 */ 223errval_t smpt_init(struct xeon_phi *phi) 224{ 225 if (phi->smpt) { 226 if (phi->smpt->smpt_enabled) { 227 debug_printf("WARNING: SMPT already setup"); 228 return SYS_ERR_OK; 229 } 230 } 231 phi->smpt = calloc(1, sizeof(struct smpt_info)); 232 if (!phi->smpt) { 233 return LIB_ERR_MALLOC_FAIL; 234 } 235 236 xeon_phi_smpt_initialize(&phi->smpt->smpt_register, XEON_PHI_MMIO_TO_SBOX(phi)); 237 238 lpaddr_t host_address = 0; 239 240 uint32_t netries = xeon_phi_smpt_system_page_num - XEON_PHI_NUM_MAX; 241 242 for (uint32_t i = 0; i < netries; ++i) { 243 smpt_set_address(phi, i, host_address, 1); 244 host_address += xeon_phi_smpt_system_page_size; 245 } 246 247 phi->smpt->smpt_enabled = 1; 248 249 return SYS_ERR_OK; 250} 251#endif 252