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