romutil.py revision 5852
11156SN/A# Copyright (c) 2008 The Regents of The University of Michigan 21762SN/A# All rights reserved. 31156SN/A# 41156SN/A# Redistribution and use in source and binary forms, with or without 51156SN/A# modification, are permitted provided that the following conditions are 61156SN/A# met: redistributions of source code must retain the above copyright 71156SN/A# notice, this list of conditions and the following disclaimer; 81156SN/A# redistributions in binary form must reproduce the above copyright 91156SN/A# notice, this list of conditions and the following disclaimer in the 101156SN/A# documentation and/or other materials provided with the distribution; 111156SN/A# neither the name of the copyright holders nor the names of its 121156SN/A# contributors may be used to endorse or promote products derived from 131156SN/A# this software without specific prior written permission. 141156SN/A# 151156SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161156SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171156SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 181156SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 191156SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 201156SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 211156SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 221156SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 231156SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 241156SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 251156SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 261156SN/A# 272665SN/A# Authors: Gabe Black 282665SN/A 291156SN/Amicrocode = ''' 301156SN/Adef rom 3111263Sandreas.sandberg@arm.com{ 3211263Sandreas.sandberg@arm.com # This vectors the CPU into an interrupt handler in long mode. 331156SN/A # On entry, t1 is set to the vector of the interrupt and t7 is the current 342566SN/A # ip. We need that because rdip returns the next ip. 351156SN/A extern longModeInterrupt: 361156SN/A 379850SN/A # 384762SN/A # Get the 64 bit interrupt or trap gate descriptor from the IDT 3911263Sandreas.sandberg@arm.com # 409850SN/A 418641SN/A # Load the gate descriptor from the IDT 425882SN/A slli t4, t1, 4, dataSize=8 431156SN/A ld t2, idtr, [1, t0, t4], 8, dataSize=8, addressSize=8 446216SN/A ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8 456658SN/A 468232SN/A # Check permissions 4711263Sandreas.sandberg@arm.com chks t1, t4, IntGateCheck 482566SN/A 493348SN/A mov t1, t1, t4, dataSize=8 501156SN/A 511157SN/A # Check that it's the right type 521156SN/A srli t4, t1, 40, dataSize=8 535603SN/A andi t4, t4, 0xe, dataSize=8 541156SN/A xori t4, t4, 0xe, flags=(EZF,), dataSize=8 552107SN/A fault "new GeneralProtection(0)", flags=(nCEZF,) 561156SN/A 571156SN/A 581156SN/A # 591156SN/A # Get the target CS descriptor using the selector in the gate 601156SN/A # descriptor. 611156SN/A # 621156SN/A srli t10, t4, 16, dataSize=8 631156SN/A andi t5, t10, 0xF8, dataSize=8 641156SN/A andi t0, t10, 0x4, flags=(EZF,), dataSize=2 651156SN/A br rom_local_label("globalDescriptor"), flags=(CEZF,) 661156SN/A ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8 671156SN/A br rom_local_label("processDescriptor") 681156SN/AglobalDescriptor: 691156SN/A ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8 701156SN/AprocessDescriptor: 711156SN/A chks t10, t3, IntCSCheck, dataSize=8 721156SN/A wrdl hs, t3, t10, dataSize=8 731156SN/A 741156SN/A # Stick the target offset in t9. 751156SN/A wrdh t9, t4, t2, dataSize=8 761156SN/A 771156SN/A 781156SN/A # 791156SN/A # Figure out where the stack should be 801156SN/A # 811156SN/A 824981SN/A # Record what we might set the stack selector to. 839339SN/A rdsel t11, ss 841634SN/A 851634SN/A # Check if we're changing privelege level. At this point we can assume 861156SN/A # we're going to a DPL that's less than or equal to the CPL. 871156SN/A rdattr t10, hs, dataSize=8 881156SN/A srli t10, t10, 3, dataSize=8 894981SN/A andi t10, t10, 3, dataSize=8 902627SN/A rdattr t5, cs, dataSize=8 912282SN/A srli t5, t5, 3, dataSize=8 922627SN/A sub t5, t5, t10, dataSize=8 931156SN/A andi t0, t5, 0x3, flags=(EZF,), dataSize=8 941156SN/A # We're going to change priviledge, so zero out the stack selector. We 951156SN/A # need to let the IST have priority so we don't branch yet. 961156SN/A wrsel t11, t0, flags=(nCEZF,) 971156SN/A 984981SN/A # Check the IST field of the gate descriptor 991156SN/A srli t10, t4, 32, dataSize=8 1001156SN/A andi t10, t10, 0x7, dataSize=8 1011156SN/A subi t0, t10, 1, flags=(ECF,), dataSize=8 1021156SN/A br rom_local_label("istStackSwitch"), flags=(nCECF,) 1031156SN/A br rom_local_label("cplStackSwitch"), flags=(nCEZF,) 1041156SN/A 1051156SN/A # If we're here, it's because the stack isn't being switched. 1061156SN/A # Set t6 to the new rsp. 1071156SN/A subi t6, rsp, 40, dataSize=8 1081156SN/A 1099339SN/A # Align the stack 1105603SN/A andi t6, t6, 0xF0, dataSize=1 1115603SN/A 1125603SN/A # Check that we can access everything we need to on the stack 1135603SN/A ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8 1145603SN/A ldst t0, hs, [1, t0, t6], 32, dataSize=8, addressSize=8 1155603SN/A br rom_local_label("stackSwitched") 1165603SN/A 1175603SN/AistStackSwitch: 1185603SN/A panic "IST based stack switching isn't implemented" 1195603SN/A br rom_local_label("stackSwitched") 1205603SN/A 1215603SN/AcplStackSwitch: 1225603SN/A panic "CPL change initiated stack switching isn't implemented" 1235603SN/A 1245603SN/AstackSwitched: 1255603SN/A 1265603SN/A 1275603SN/A ## 1285603SN/A ## Point of no return. 1295603SN/A ## We're now going to irrevocably modify visible state. 1305603SN/A ## Anything bad that's going to happen should have happened by now or will 1315603SN/A ## happen right now. 1325603SN/A ## 1335603SN/A wrip t0, t9, dataSize=8 1345603SN/A 1355603SN/A 1365603SN/A # 1375603SN/A # Build up the interrupt stack frame 1389339SN/A # 1399339SN/A 1405603SN/A 1411156SN/A # Write out the contents of memory 1421156SN/A st t7, hs, [1, t0, t6], dataSize=8 1434981SN/A limm t5, 0, dataSize=8 1444981SN/A rdsel t5, cs, dataSize=2 1454981SN/A st t5, hs, [1, t0, t6], 8, dataSize=8 1464981SN/A rflags t10, dataSize=8 1474981SN/A st t10, hs, [1, t0, t6], 16, dataSize=8 1484981SN/A st rsp, hs, [1, t0, t6], 24, dataSize=8 1494981SN/A rdsel t5, ss, dataSize=2 1504981SN/A st t5, hs, [1, t0, t6], 32, dataSize=8 1514981SN/A 1524981SN/A # Set the stack segment 1534981SN/A mov rsp, rsp, t6, dataSize=8 1544981SN/A wrsel ss, t11, dataSize=2 1554981SN/A 1561939SN/A # 15711005SN/A # Set up the target code segment 1582008SN/A # 1592008SN/A srli t5, t4, 16, dataSize=8 1602282SN/A andi t5, t5, 0xFF, dataSize=8 1612282SN/A wrdl cs, t3, t5, dataSize=8 1622282SN/A wrsel cs, t5, dataSize=2 1632008SN/A 1642008SN/A # 1655603SN/A # Adjust rflags which is still in t10 from above 1665603SN/A # 1675603SN/A 1685603SN/A # Set IF to the lowest bit of the original gate type. 1692008SN/A # The type field of the original gate starts at bit 40. 17011005SN/A 1712008SN/A # Set the TF, NT, and RF bits. We'll flip them at the end. 1722008SN/A limm t6, (1 << 8) | (1 << 14) | (1 << 16) 1732008SN/A or t10, t10, t6 1742008SN/A srli t5, t4, 40, dataSize=8 1752008SN/A srli t7, t10, 9, dataSize=8 1762008SN/A xor t5, t7, t5, dataSize=8 1772008SN/A andi t5, t5, 1, dataSize=8 1782008SN/A slli t5, t5, 9, dataSize=8 1792282SN/A or t6, t5, t6, dataSize=8 1802282SN/A 1815603SN/A # Put the results into rflags 1822282SN/A wrflags t6, t10 1832008SN/A 1842008SN/A eret 1852008SN/A}; 1862008SN/A 1872008SN/Adef rom 1882008SN/A{ 1892008SN/A # This vectors the CPU into an interrupt handler in legacy mode. 1902008SN/A extern legacyModeInterrupt: 1915603SN/A panic "Legacy mode interrupts not implemented (in microcode)" 1922008SN/A eret 1932008SN/A}; 1942008SN/A''' 1955603SN/A