interrupts_and_exceptions.py revision 7087:fb8d5786ff30
1# Copyright (c) 2007-2008 The Hewlett-Packard Development Company 2# All rights reserved. 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Redistribution and use in source and binary forms, with or without 14# modification, are permitted provided that the following conditions are 15# met: redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer; 17# redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution; 20# neither the name of the copyright holders nor the names of its 21# contributors may be used to endorse or promote products derived from 22# this software without specific prior written permission. 23# 24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35# 36# Authors: Gabe Black 37 38microcode = ''' 39def macroop IRET_REAL { 40 panic "Real mode iret isn't implemented!" 41}; 42 43def macroop IRET_PROT { 44 .adjust_env oszIn64Override 45 46 # Check for a nested task. This isn't supported at the moment. 47 rflag t1, 14; #NT bit 48 panic "Task switching with iret is unimplemented!", flags=(nCEZF,) 49 50 #t1 = temp_RIP 51 #t2 = temp_CS 52 #t3 = temp_RFLAGS 53 #t4 = handy m5 register 54 55 # Pop temp_RIP, temp_CS, and temp_RFLAGS 56 ld t1, ss, [1, t0, rsp], "0 * env.stackSize", dataSize=ssz 57 ld t2, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz 58 ld t3, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz 59 60 # Read the handy m5 register for use later 61 rdm5reg t4 62 63 64### 65### Handle if we're returning to virtual 8086 mode. 66### 67 68 #IF ((temp_RFLAGS.VM=1) && (CPL=0) && (LEGACY_MODE)) 69 # IRET_FROM_PROTECTED_TO_VIRTUAL 70 71 #temp_RFLAGS.VM != 1 72 rcri t0, t3, 18, flags=(ECF,) 73 br label("protToVirtFallThrough"), flags=(nCECF,) 74 75 #CPL=0 76 andi t0, t4, 0x30, flags=(EZF,) 77 br label("protToVirtFallThrough"), flags=(nCEZF,) 78 79 #(LEGACY_MODE) 80 rcri t0, t4, 1, flags=(ECF,) 81 br label("protToVirtFallThrough"), flags=(nCECF,) 82 83 panic "iret to virtual mode not supported" 84 85protToVirtFallThrough: 86 87 88 89 #temp_CPL = temp_CS.rpl 90 andi t5, t2, 0x3 91 92 93### 94### Read in the info for the new CS segment. 95### 96 97 #CS = READ_DESCRIPTOR (temp_CS, iret_chk) 98 andi t0, t2, 0xFC, flags=(EZF,), dataSize=2 99 br label("processCSDescriptor"), flags=(CEZF,) 100 andi t6, t2, 0xF8, dataSize=8 101 andi t0, t2, 0x4, flags=(EZF,), dataSize=2 102 br label("globalCSDescriptor"), flags=(CEZF,) 103 ld t8, tsl, [1, t0, t6], dataSize=8 104 br label("processCSDescriptor") 105globalCSDescriptor: 106 ld t8, tsg, [1, t0, t6], dataSize=8 107processCSDescriptor: 108 chks t2, t6, dataSize=8 109 110 111### 112### Get the new stack pointer and stack segment off the old stack if necessary, 113### and piggyback on the logic to check the new RIP value. 114### 115 #IF ((64BIT_MODE) || (temp_CPL!=CPL)) 116 #{ 117 118 #(64BIT_MODE) 119 andi t0, t4, 0xE, flags=(EZF,) 120 # Since we just found out we're in 64 bit mode, take advantage and 121 # do the appropriate RIP checks. 122 br label("doPopStackStuffAndCheckRIP"), flags=(CEZF,) 123 124 # Here, we know we're -not- in 64 bit mode, so we should do the 125 # appropriate/other RIP checks. 126 # if temp_RIP > CS.limit throw #GP(0) 127 rdlimit t6, cs, dataSize=8 128 sub t0, t1, t6, flags=(ECF,) 129 fault "new GeneralProtection(0)", flags=(CECF,) 130 131 #(temp_CPL!=CPL) 132 srli t7, t4, 4 133 xor t7, t7, t5 134 andi t0, t7, 0x3, flags=(EZF,) 135 br label("doPopStackStuff"), flags=(nCEZF,) 136 # We can modify user visible state here because we're know 137 # we're done with things that can fault. 138 addi rsp, rsp, "3 * env.stackSize" 139 br label("fallThroughPopStackStuff") 140 141doPopStackStuffAndCheckRIP: 142 # Check if the RIP is canonical. 143 srai t7, t1, 47, flags=(EZF,), dataSize=ssz 144 # if t7 isn't 0 or -1, it wasn't canonical. 145 br label("doPopStackStuff"), flags=(CEZF,) 146 addi t0, t7, 1, flags=(EZF,), dataSize=ssz 147 fault "new GeneralProtection(0)", flags=(nCEZF,) 148 149doPopStackStuff: 150 # POP.v temp_RSP 151 ld t6, ss, [1, t0, rsp], "3 * env.dataSize", dataSize=ssz 152 # POP.v temp_SS 153 ld t9, ss, [1, t0, rsp], "4 * env.dataSize", dataSize=ssz 154 # SS = READ_DESCRIPTOR (temp_SS, ss_chk) 155 andi t0, t9, 0xFC, flags=(EZF,), dataSize=2 156 br label("processSSDescriptor"), flags=(CEZF,) 157 andi t7, t9, 0xF8, dataSize=8 158 andi t0, t9, 0x4, flags=(EZF,), dataSize=2 159 br label("globalSSDescriptor"), flags=(CEZF,) 160 ld t7, tsl, [1, t0, t7], dataSize=8 161 br label("processSSDescriptor") 162globalSSDescriptor: 163 ld t7, tsg, [1, t0, t7], dataSize=8 164processSSDescriptor: 165 chks t9, t7, dataSize=8 166 167 # This actually updates state which is wrong. It should wait until we know 168 # we're not going to fault. Unfortunately, that's hard to do. 169 wrdl ss, t7, t9 170 wrsel ss, t9 171 172### 173### From this point downwards, we can't fault. We can update user visible state. 174### 175 # RSP.s = temp_RSP 176 mov rsp, rsp, t6, dataSize=ssz 177 178 #} 179 180fallThroughPopStackStuff: 181 182 # Update CS 183 wrdl cs, t8, t2 184 wrsel cs, t2 185 186 #CPL = temp_CPL 187 188 #IF (changing CPL) 189 #{ 190 srli t7, t4, 4 191 xor t7, t7, t5 192 andi t0, t7, 0x3, flags=(EZF,) 193 br label("skipSegmentSquashing"), flags=(CEZF,) 194 195 # The attribute register needs to keep track of more info before this will 196 # work the way it needs to. 197 # FOR (seg = ES, DS, FS, GS) 198 # IF ((seg.attr.dpl < cpl && ((seg.attr.type = 'data') 199 # || (seg.attr.type = 'non-conforming-code'))) 200 # { 201 # seg = NULL 202 # } 203 #} 204 205skipSegmentSquashing: 206 207 # Ignore this for now. 208 #RFLAGS.v = temp_RFLAGS 209 wrflags t0, t3 210 # VIF,VIP,IOPL only changed if (old_CPL = 0) 211 # IF only changed if (old_CPL <= old_RFLAGS.IOPL) 212 # VM unchanged 213 # RF cleared 214 215 #RIP = temp_RIP 216 wrip t0, t1, dataSize=ssz 217}; 218 219def macroop IRET_VIRT { 220 panic "Virtual mode iret isn't implemented!" 221}; 222''' 223#let {{ 224# class INT(Inst): 225# "GenFault ${new UnimpInstFault}" 226# class INTO(Inst): 227# "GenFault ${new UnimpInstFault}" 228#}}; 229