1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * This software may be distributed and modified according to the terms of 5 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 6 * See "LICENSE_GPLv2.txt" for details. 7 * 8 * @TAG(GD_GPL) 9 */ 10 11#include <config.h> 12#include <types.h> 13#include <api/failures.h> 14#include <kernel/vspace.h> 15#include <object/structures.h> 16#include <arch/machine.h> 17#include <arch/model/statedata.h> 18#include <arch/machine/fpu.h> 19#include <arch/object/objecttype.h> 20#include <arch/object/ioport.h> 21#include <arch/kernel/ept.h> 22 23#include <arch/object/iospace.h> 24#include <plat/machine/intel-vtd.h> 25 26 27bool_t 28Arch_isFrameType(word_t type) 29{ 30 switch (type) { 31 case seL4_X86_4K: 32 return true; 33 case seL4_X86_LargePageObject: 34 return true; 35 default: 36 return false; 37 } 38} 39 40deriveCap_ret_t 41Mode_deriveCap(cte_t* slot, cap_t cap) 42{ 43 deriveCap_ret_t ret; 44 45 switch (cap_get_capType(cap)) { 46 case cap_frame_cap: 47 cap = cap_frame_cap_set_capFMapType(cap, X86_MappingNone); 48 ret.cap = cap_frame_cap_set_capFMappedASID(cap, asidInvalid); 49 ret.status = EXCEPTION_NONE; 50 return ret; 51 52 default: 53 /* This assert has no equivalent in haskell, 54 * as the options are restricted by type */ 55 fail("Invalid arch cap type"); 56 } 57} 58 59finaliseCap_ret_t Mode_finaliseCap(cap_t cap, bool_t final) 60{ 61 finaliseCap_ret_t fc_ret; 62 63 switch (cap_get_capType(cap)) { 64 65 case cap_frame_cap: 66 if (cap_frame_cap_get_capFMappedASID(cap)) { 67 switch (cap_frame_cap_get_capFMapType(cap)) { 68#ifdef CONFIG_VTX 69 case X86_MappingEPT: 70 unmapEPTPage( 71 cap_frame_cap_get_capFSize(cap), 72 cap_frame_cap_get_capFMappedASID(cap), 73 cap_frame_cap_get_capFMappedAddress(cap), 74 (void *)cap_frame_cap_get_capFBasePtr(cap) 75 ); 76 break; 77#endif 78 case X86_MappingVSpace: 79 80#ifdef CONFIG_BENCHMARK_USE_KERNEL_LOG_BUFFER 81 /* If the last cap to the user-level log buffer frame is being revoked, 82 * reset the ksLog so that the kernel doesn't log anymore 83 */ 84 if (unlikely(cap_frame_cap_get_capFSize(cap) == X86_LargePage)) { 85 if (pptr_to_paddr((void *)cap_frame_cap_get_capFBasePtr(cap)) == ksUserLogBuffer) { 86 ksUserLogBuffer = 0; 87 88 /* Invalidate log page table entries */ 89 clearMemory(ia32KSGlobalLogPT, BIT(seL4_PageTableBits)); 90 91 for (int idx = 0; idx < BIT(PT_INDEX_BITS); idx++) { 92 invalidateTLBEntry(KS_LOG_PPTR + (idx << seL4_PageBits), MASK(ksNumCPUs)); 93 } 94 95 userError("Log buffer frame is invalidated, kernel can't benchmark anymore\n"); 96 } 97 } 98#endif /* CONFIG_BENCHMARK_USE_KERNEL_LOG_BUFFER */ 99 100 unmapPage( 101 cap_frame_cap_get_capFSize(cap), 102 cap_frame_cap_get_capFMappedASID(cap), 103 cap_frame_cap_get_capFMappedAddress(cap), 104 (void *)cap_frame_cap_get_capFBasePtr(cap) 105 ); 106 break; 107#ifdef CONFIG_IOMMU 108 case X86_MappingIOSpace: 109 unmapIOPage(cap); 110 break; 111#endif 112 default: 113 fail("No mapping type for mapped cap"); 114 break; 115 } 116 } 117 break; 118 119 default: 120 fail("Invalid arch cap type"); 121 } 122 123 fc_ret.remainder = cap_null_cap_new(); 124 fc_ret.cleanupInfo = cap_null_cap_new(); 125 return fc_ret; 126} 127 128bool_t CONST Mode_sameRegionAs(cap_t cap_a, cap_t cap_b) 129{ 130 return false; 131} 132 133word_t 134Mode_getObjectSize(word_t t) 135{ 136 fail("Invalid object type"); 137 return 0; 138} 139 140cap_t 141Mode_createObject(object_t t, void *regionBase, word_t userSize, bool_t deviceMemory) 142{ 143 switch (t) { 144 case seL4_X86_4K: 145 return cap_frame_cap_new( 146 X86_SmallPage, /* capFSize */ 147 ASID_LOW(asidInvalid), /* capFMappedASIDLow */ 148 false, /* capFMappedAddress */ 149 X86_MappingNone, /* capFMapType */ 150 deviceMemory, /* capFIsDevice */ 151 ASID_HIGH(asidInvalid), /* capFMappedASIDHigh */ 152 VMReadWrite, /* capFVMRights */ 153 (word_t)regionBase /* capFBasePtr */ 154 ); 155 156 case seL4_X86_LargePageObject: 157 return cap_frame_cap_new( 158 X86_LargePage, /* capFSize */ 159 ASID_LOW(asidInvalid), /* capFMappedASIDLow */ 160 false, /* capFMappedAddress */ 161 X86_MappingNone, /* capFMapType */ 162 deviceMemory, /* capFIsDevice */ 163 ASID_HIGH(asidInvalid), /* capFMappedASIDHigh */ 164 VMReadWrite, /* capFVMRights */ 165 (word_t)regionBase /* capFBasePtr */ 166 ); 167 168 case seL4_X86_PageTableObject: 169 return cap_page_table_cap_new( 170 0, /* capPTIsMapped */ 171 asidInvalid, /* capPTMappedASID */ 172 0, /* capPTMappedAddress */ 173 (word_t)regionBase /* capPTBasePtr */ 174 ); 175 176 case seL4_X86_PageDirectoryObject: 177 copyGlobalMappings(regionBase); 178 return cap_page_directory_cap_new( 179 0, /* capPDIsMapped */ 180 asidInvalid, /* capPDMappedASID */ 181 0, /* capPDMappedAddress */ 182 (word_t)regionBase /* capPDBasePtr */ 183 ); 184 185#ifdef CONFIG_IOMMU 186 case seL4_X86_IOPageTableObject: 187 return cap_io_page_table_cap_new( 188 0, /* capIOPTIsMapped */ 189 0, /* capIOPTLevel */ 190 0, /* capIOPTMappedAddress */ 191 0, /* capIOPTIOASID */ 192 (word_t)regionBase /* capIOPTBasePtr */ 193 ); 194#endif 195 196 default: 197 fail("Mode_createObject got an API type or invalid object type"); 198 } 199} 200 201exception_t 202Mode_decodeInvocation( 203 word_t invLabel, 204 word_t length, 205 cptr_t cptr, 206 cte_t* slot, 207 cap_t cap, 208 extra_caps_t excaps, 209 word_t* buffer 210) 211{ 212 switch (cap_get_capType(cap)) { 213 case cap_page_directory_cap: 214 case cap_page_table_cap: 215 case cap_frame_cap: 216 return decodeX86MMUInvocation(invLabel, length, cptr, slot, cap, excaps, buffer); 217 default: 218 current_syscall_error.type = seL4_InvalidCapability; 219 current_syscall_error.invalidCapNumber = 0; 220 return EXCEPTION_SYSCALL_ERROR; 221 } 222} 223