12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400 |
- /*++
- Copyright (c) 2013 Minoca Corp. All Rights Reserved
- Module Name:
- archsup.S
- Abstract:
- This module implements assembly-based architecture support routines for the
- x86 platform.
- Author:
- Evan Green 7-Aug-2013
- Environment:
- Boot
- --*/
- ##
- ## ------------------------------------------------------------------- Includes
- ##
- #include <minoca/kernel/x86.inc>
- ##
- ## -------------------------------------------------------------------- Macros
- ##
- ##
- ## This macro switches the DS and ES data segments to the kernel's data
- ## segments.
- ##
- .macro LoadBootDataSegments
- movw $KERNEL_DS, %ax # Get the data segment selector,
- mov %ax, %ds # and save it into the data segments.
- mov %ax, %es #
- .endm
- ##
- ## ---------------------------------------------------------------- Definitions
- ##
- ##
- ## -------------------------------------------------------------------- Globals
- ##
- ##
- ## ----------------------------------------------------------------------- Code
- ##
- ##
- ## .text specifies that this code belongs in the executable section.
- ##
- ## .code32 specifies that this is 32-bit protected mode code.
- ##
- .text
- .code32
- ##
- ## VOID
- ## BoBreakExceptionHandlerAsm (
- ## ULONG ReturnEip,
- ## ULONG ReturnCodeSelector,
- ## ULONG ReturnEflags
- ## )
- ##
- /*++
- Routine Description:
- This routine is called directly when an debug exception occurs. It sets up
- the parameters and calls a C routine to handle the break. It then restores
- machine state to return from the exception. The arguments to this function
- are pushed by the hardware.
- Arguments:
- ReturnEip - Supplies the address after the instruction that caused the trap.
- ReturnCodeSelector - Supplies the code selector the code that trapped was
- running under.
- ReturnEflags - Supplies the EFLAGS register immediately before the trap.
- Return Value:
- None.
- --*/
- FUNCTION(BoBreakExceptionHandlerAsm)
- pushl $0 # Push a dummy error code.
- call BoGenerateTrapFrame # Create a local trap frame.
- pushl %esp # Push a pointer to it as a parameter.
- pushl $0 # Push a NULL parameter.
- pushl $EXCEPTION_BREAK # Push the break parameter.
- call KdDebugExceptionHandler # Call the main exception handler.
- addl $0xC, %esp # Pop the parameters.
- call BoRestoreTrapFrame # Restore the trap frame
- addl $4, %esp # Pop the error code.
- iret # Return from the exception.
- END_FUNCTION(BoBreakExceptionHandlerAsm)
- ##
- ## VOID
- ## BoSingleStepExceptionHandlerAsm (
- ## ULONG ReturnEip,
- ## ULONG ReturnCodeSelector,
- ## ULONG ReturnEflags
- ## )
- ##
- /*++
- Routine Description:
- This routine is called directly when an debug exception occurs. It sets up
- the parameters and calls the executive to dispatch the trap.
- Arguments:
- ReturnEip - Supplies the address after the instruction that caused the trap.
- ReturnCodeSelector - Supplies the code selector the code that trapped was
- running under.
- ReturnEflags - Supplies the EFLAGS register immediately before the trap.
- Return Value:
- None.
- --*/
- FUNCTION(BoSingleStepExceptionHandlerAsm)
- pushl $0 # Push a dummy error code.
- call BoGenerateTrapFrame # Create a local trap frame.
- pushl %esp # Push a pointer to it as a parameter.
- pushl $0 # Push a NULL parameter.
- pushl $EXCEPTION_SINGLE_STEP # Push the exception parameter.
- call KdDebugExceptionHandler # Call the main exception handler.
- addl $0xC, %esp # Pop the parameters.
- call BoRestoreTrapFrame # Restore the trap frame
- addl $4, %esp # Pop the error code.
- iret # Return from the exception.
- END_FUNCTION(BoSingleStepExceptionHandlerAsm)
- ##
- ## VOID
- ## BoDebugServiceHandlerAsm (
- ## ULONG ReturnEip,
- ## ULONG ReturnCodeSelector,
- ## ULONG ReturnEflags
- ## )
- ##
- /*++
- Routine Description:
- This routine is entered via an IDT entry to request debug service. It sets
- up the parameters and calls KdDebugExceptionHandler, and then restores
- machine state to return from the exception. The arguments to this function
- are pushed by the hardware. Upon Entry:
- eax - Supplies the debug service request.
- ecx - Supplies the parameter to the request.
- Arguments:
- ReturnEip - Supplies the address after the instruction that caused the trap.
- ReturnCodeSelector - Supplies the code selector the code that trapped was
- running under.
- ReturnEflags - Supplies the EFLAGS register immediately before the trap.
- Return Value:
- None.
- --*/
- FUNCTION(BoDebugServiceHandlerAsm)
- pushl $0 # Push a dummy error code.
- call BoGenerateTrapFrame # Create a local trap frame.
- mov TRAP_EAX(%esp), %eax # Get eax, containing the service request.
- mov TRAP_ECX(%esp), %ecx # Get ecx, containing the parameter.
- pushl %esp # Push a pointer to the trap frame.
- pushl %ecx # Push exception parameter.
- pushl %eax # Push exception type.
- call KdDebugExceptionHandler # Call the main exception handler.
- addl $0xc, %esp # Pop the parameters.
- call BoRestoreTrapFrame # Restore the trap frame
- addl $4, %esp # Pop the error code.
- iret # Return from the exception.
- END_FUNCTION(BoDebugServiceHandlerAsm)
- ##
- ## VOID
- ## BoDivideByZeroExceptionHandlerAsm (
- ## ULONG ReturnEip,
- ## ULONG ReturnCodeSelector,
- ## ULONG ReturnEflags
- ## )
- ##
- /*++
- Routine Description:
- This routine is called directly when a divide by zero exception occurs.
- Arguments:
- ReturnEip - Supplies the address after the instruction that caused the trap.
- ReturnCodeSelector - Supplies the code selector the code that trapped was
- running under.
- ReturnEflags - Supplies the EFLAGS register immediately before the trap.
- Return Value:
- None.
- --*/
- FUNCTION(BoDivideByZeroExceptionHandlerAsm)
- pushl $0 # Push a dummy error code.
- call BoGenerateTrapFrame # Create a local trap frame.
- pushl %esp # Push a pointer to it as a parameter.
- call BoDivideByZeroHandler # Call the main exception handler.
- addl $0x4, %esp # Pop the parameters.
- call BoRestoreTrapFrame # Restore the trap frame
- addl $4, %esp # Pop the error code.
- iret # Return from the exception.
- END_FUNCTION(BoDivideByZeroExceptionHandlerAsm)
- ##
- ## VOID
- ## BoProtectionFaultHandlerAsm (
- ## ULONG ReturnEip,
- ## ULONG ReturnCodeSelector,
- ## ULONG ReturnEflags
- ## )
- ##
- /*++
- Routine Description:
- This routine is called directly when a general protection fault occurs.
- It's job is to prepare the trap frame, call the appropriate handler, and
- then restore the trap frame.
- Arguments:
- ReturnEip - Supplies the address after the instruction that caused the trap.
- ReturnCodeSelector - Supplies the code selector the code that trapped was
- running under.
- ReturnEflags - Supplies the EFLAGS register immediately before the trap.
- Return Value:
- None.
- --*/
- FUNCTION(BoProtectionFaultHandlerAsm)
- call BoGenerateTrapFrame # Create a local trap frame.
- pushl %esp # Push a pointer to it as a parameter.
- pushl $0 # Push dummy parameter.
- pushl $EXCEPTION_ACCESS_VIOLATION # Push exception type parameter.
- call KdDebugExceptionHandler # Let the debugger handle this.
- addl $0xC, %esp # Pop the parameter.
- call BoRestoreTrapFrame # Restore the trap frame
- addl $4, %esp
- iret # Return from the exception.
- END_FUNCTION(BoProtectionFaultHandlerAsm)
- ##
- ## VOID
- ## BoPageFaultHandlerAsm (
- ## ULONG ReturnEip,
- ## ULONG ReturnCodeSelector,
- ## ULONG ReturnEflags
- ## )
- ##
- /*++
- Routine Description:
- This routine is called directly when a page fault occurs.
- Arguments:
- ReturnEip - Supplies the address after the instruction that caused the
- fault.
- ReturnCodeSelector - Supplies the code selector the code that faulted was
- running under.
- ReturnEflags - Supplies the EFLAGS register immediately before the fault.
- Return Value:
- None.
- --*/
- FUNCTION(BoPageFaultHandlerAsm)
- call BoGenerateTrapFrame # Create a local trap frame.
- movl %cr2, %eax # Get the faulting address.
- xor %edx, %edx # Zero edx.
- movl %edx, %cr2 # Clear CR2.
- sti # Re-enable interrupts.
- pushl %esp # Push a pointer to it as a parameter.
- pushl %eax #
- call BoPageFaultHandler # Call the main exception handler.
- addl $8, %esp # Pop the parameters.
- call BoRestoreTrapFrame # Restore the trap frame
- addl $4, %esp # Pop the error code.
- iret # Return from the exception.
- END_FUNCTION(BoPageFaultHandlerAsm)
- ##
- ## VOID
- ## BoLoadBootDataSegments (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine switches the data segments DS and ES to the boot data
- segment selectors.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- FUNCTION(BoLoadBootDataSegments)
- LoadBootDataSegments # Load the boot data segments.
- movw $KERNEL_DS, %ax # Get the data segment selector,
- mov %ax, %ss # and save it into the stack register.
- mov %ax, %fs # Load it.
- mov %ax, %gs # Load it in GS as well.
- ret #
- END_FUNCTION(BoLoadBootDataSegments)
- ##
- ## VOID
- ## ArLoadTr (
- ## USHORT TssSegment
- ## )
- ##
- /*++
- Routine Description:
- This routine loads a TSS (Task Selector State).
- Arguments:
- TssSegment - Supplies the segment selector in the GDT that describes the
- TSS.
- Return Value:
- None.
- --*/
- FUNCTION(ArLoadTr)
- ltr 4(%esp) # Load the Task Register.
- ret # That's it!
- END_FUNCTION(ArLoadTr)
- ##
- ## VOID
- ## ArStoreTr (
- ## PULONG TssSegment
- ## )
- ##
- /*++
- Routine Description:
- This routine retrieves the current TSS (Task Selector State) register.
- Arguments:
- TssSegment - Supplies a pointer where the current TSS segment register will
- be returned.
- Return Value:
- None.
- --*/
- FUNCTION(ArStoreTr)
- movl 4(%esp), %eax # Get the address parameter.
- str (%eax) # Store the TR register into it.
- ret # Return
- END_FUNCTION(ArStoreTr)
- ##
- ## VOID
- ## ArLoadIdtr (
- ## PVOID IdtBase
- ## )
- ##
- /*++
- Routine Description:
- This routine loads the given Interrupt Descriptor Table.
- Arguments:
- IdtBase - Supplies a pointer to the base of the IDT.
- Return Value:
- None.
- --*/
- FUNCTION(ArLoadIdtr)
- movl 4(%esp), %eax # Get the base parameter.
- lidt (%eax) # Load the IDT register.
- ret # That's it!
- END_FUNCTION(ArLoadIdtr)
- ##
- ## VOID
- ## ArStoreIdtr (
- ## PTABLE_REGISTER IdtRegister
- ## )
- ##
- /*++
- Routine Description:
- This routine stores the interrupt descriptor table register into the given
- value.
- Arguments:
- IdtRegister - Supplies a pointer that will receive the value.
- Return Value:
- None.
- --*/
- FUNCTION(ArStoreIdtr)
- movl 4(%esp), %eax # Get the address parameter.
- sidt (%eax) # Store the IDT register into it.
- ret # Return politely.
- END_FUNCTION(ArStoreIdtr)
- ##
- ## VOID
- ## ArLoadGdtr (
- ## TABLE_REGISTER Gdt
- ## )
- ##
- /*++
- Routine Description:
- This routine loads a global descriptor table.
- Arguments:
- Gdt - Supplies a pointer to the Gdt pointer, which contains the base and
- limit for the GDT.
- Return Value:
- None.
- --*/
- FUNCTION(ArLoadGdtr)
- ##
- ## Load the GDT and then perform a long jump. The long jump is required for
- ## the new GDT to actually be loaded.
- ##
- lgdt 4(%esp) # Load the GDT.
- ljmp $KERNEL_CS, $LoadGdtJump # Long jump.
- LoadGdtJump:
- ret # Simply return.
- END_FUNCTION(ArLoadGdtr)
- ##
- ## VOID
- ## ArStoreGdtr (
- ## PTABLE_REGISTER GdtRegister
- ## )
- ##
- /*++
- Routine Description:
- This routine stores the GDT register into the given value.
- Arguments:
- GdtRegister - Supplies a pointer that will receive the value.
- Return Value:
- None.
- --*/
- FUNCTION(ArStoreGdtr)
- movl 4(%esp), %eax # Get the address parameter.
- sgdt (%eax) # Store the GDT register into it.
- ret # Return politely.
- END_FUNCTION(ArStoreGdtr)
- ##
- ## PVOID
- ## ArGetFaultingAddress (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine determines which address caused a page fault.
- Arguments:
- None.
- Return Value:
- Returns the faulting address.
- --*/
- FUNCTION(ArGetFaultingAddress)
- movl %cr2, %eax # Return CR2.
- ret #
- END_FUNCTION(ArGetFaultingAddress)
- ##
- ## VOID
- ## ArSetFaultingAddress (
- ## PVOID Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the CR2 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetFaultingAddress)
- movl 4(%esp), %eax
- movl %eax, %cr2
- ret
- END_FUNCTION(ArSetFaultingAddress)
- ##
- ## ULONG
- ## ArGetCurrentPageDirectory (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the active page directory.
- Arguments:
- None.
- Return Value:
- Returns the page directory currently in use by the system.
- --*/
- FUNCTION(ArGetCurrentPageDirectory)
- movl %cr3, %eax # Return CR3.
- ret #
- END_FUNCTION(ArGetCurrentPageDirectory)
- ##
- ## VOID
- ## ArSetCurrentPageDirectory (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the CR3 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetCurrentPageDirectory)
- movl 4(%esp), %eax
- movl %eax, %cr3
- ret
- END_FUNCTION(ArSetCurrentPageDirectory)
- ##
- ## ULONG
- ## ArGetControlRegister0 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of CR0.
- Arguments:
- None.
- Return Value:
- Returns CR0.
- --*/
- FUNCTION(ArGetControlRegister0)
- movl %cr0, %eax
- ret
- END_FUNCTION(ArGetControlRegister0)
- ##
- ## VOID
- ## ArSetControlRegister0 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the CR0 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetControlRegister0)
- movl 4(%esp), %eax
- movl %eax, %cr0
- ret
- END_FUNCTION(ArSetControlRegister0)
- ##
- ## ULONG
- ## ArGetControlRegister4 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of CR4.
- Arguments:
- None.
- Return Value:
- Returns CR4.
- --*/
- FUNCTION(ArGetControlRegister4)
- movl %cr4, %eax
- ret
- END_FUNCTION(ArGetControlRegister4)
- ##
- ## VOID
- ## ArSetControlRegister4 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the CR4 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetControlRegister4)
- movl 4(%esp), %eax
- movl %eax, %cr4
- ret
- END_FUNCTION(ArSetControlRegister4)
- ##
- ## ULONG
- ## ArGetDebugRegister0 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of DR0.
- Arguments:
- None.
- Return Value:
- Returns DR0.
- --*/
- FUNCTION(ArGetDebugRegister0)
- movl %dr0, %eax
- ret
- END_FUNCTION(ArGetDebugRegister0)
- ##
- ## VOID
- ## ArSetDebugRegister0 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the DR0 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetDebugRegister0)
- movl 4(%esp), %eax
- movl %eax, %dr0
- ret
- END_FUNCTION(ArSetDebugRegister0)
- ##
- ## ULONG
- ## ArGetDebugRegister1 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of DR1.
- Arguments:
- None.
- Return Value:
- Returns DR1.
- --*/
- FUNCTION(ArGetDebugRegister1)
- movl %dr1, %eax
- ret
- END_FUNCTION(ArGetDebugRegister1)
- ##
- ## VOID
- ## ArSetDebugRegister1 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the DR1 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetDebugRegister1)
- movl 4(%esp), %eax
- movl %eax, %dr1
- ret
- END_FUNCTION(ArSetDebugRegister1)
- ##
- ## ULONG
- ## ArGetDebugRegister2 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of DR2.
- Arguments:
- None.
- Return Value:
- Returns DR2.
- --*/
- FUNCTION(ArGetDebugRegister2)
- movl %dr2, %eax
- ret
- END_FUNCTION(ArGetDebugRegister2)
- ##
- ## VOID
- ## ArSetDebugRegister2 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the DR2 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetDebugRegister2)
- movl 4(%esp), %eax
- movl %eax, %dr2
- ret
- END_FUNCTION(ArSetDebugRegister2)
- ##
- ## ULONG
- ## ArGetDebugRegister3 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of DR3.
- Arguments:
- None.
- Return Value:
- Returns DR3.
- --*/
- FUNCTION(ArGetDebugRegister3)
- movl %dr3, %eax
- ret
- END_FUNCTION(ArGetDebugRegister3)
- ##
- ## VOID
- ## ArSetDebugRegister3 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the DR3 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetDebugRegister3)
- movl 4(%esp), %eax
- movl %eax, %dr3
- ret
- END_FUNCTION(ArSetDebugRegister3)
- ##
- ## ULONG
- ## ArGetDebugRegister6 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of DR6.
- Arguments:
- None.
- Return Value:
- Returns DR6.
- --*/
- FUNCTION(ArGetDebugRegister6)
- movl %dr6, %eax
- ret
- END_FUNCTION(ArGetDebugRegister6)
- ##
- ## VOID
- ## ArSetDebugRegister6 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the DR6 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetDebugRegister6)
- movl 4(%esp), %eax
- movl %eax, %dr6
- ret
- END_FUNCTION(ArSetDebugRegister6)
- ##
- ## ULONG
- ## ArGetDebugRegister7 (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine returns the current value of DR7.
- Arguments:
- None.
- Return Value:
- Returns DR7.
- --*/
- FUNCTION(ArGetDebugRegister7)
- movl %dr7, %eax
- ret
- END_FUNCTION(ArGetDebugRegister7)
- ##
- ## VOID
- ## ArSetDebugRegister7 (
- ## ULONG Value
- ## )
- ##
- /*++
- Routine Description:
- This routine sets the DR7 register.
- Arguments:
- Value - Supplies the value to set.
- Return Value:
- None.
- --*/
- FUNCTION(ArSetDebugRegister7)
- movl 4(%esp), %eax
- movl %eax, %dr7
- ret
- END_FUNCTION(ArSetDebugRegister7)
- ##
- ## ULONGLONG
- ## ArReadTimeStampCounter (
- ## VOID
- ## )
- ##
- /*++
- Routine Description:
- This routine reads the time stamp counter from the current processor. It
- is essential that callers of this function understand that this returns
- instruction cycles, which does not always translate directly into units
- of time. For example, some processors halt the timestamp counter during
- performance and CPU idle state transitions. In other cases, the timestamp
- counters of all processors are not in sync, so as execution of a thread
- bounces unpredictably from one core to another, different timelines may be
- observed. Additionally, one must understand that this intrinsic is not a
- serializing instruction to the hardware, so the processor may decide to
- execute any number of instructions after this one before actually snapping
- the timestamp counter. To all those who choose to continue to use this
- primitive to measure time, you have been warned.
- Arguments:
- None.
- Return Value:
- Returns the current instruction cycle count since the processor was started.
- --*/
- FUNCTION(ArReadTimeStampCounter)
- rdtsc # Store the timestamp counter in EDX:EAX.
- ret # And return!
- END_FUNCTION(ArReadTimeStampCounter)
- ##
- ## --------------------------------------------------------- Internal Functions
- ##
- ##
- ## VOID
- ## BoRestoreTrapFrame (
- ## TRAP_FRAME TrapFrame
- ## )
- ##
- /*++
- Routine Description:
- This routine restores information contained in a trap frame to the
- processor and prepares the machine for an iret back to the code that
- generated this trap frame. It's not really a function because it assumes
- a specific stack layout and modifies data that technically belongs to the
- caller. It should only be called immediately before returning from an
- exception or interrupt.
- Arguments:
- TrapFrame - Supplies the trap frame to restore. It is assumed that the
- IOPL and VM fields of the Eflags register have remained unchanged from
- when the exception was generated.
- Return Value:
- Upon return, the trap frame will have been popped off the stack, and the
- machine will be in the same state as right after the exception happened.
- --*/
- BoRestoreTrapFrame:
- ##
- ## Restore the common data segment registers. Hold off on DS, as this routine
- ## will make a couple more DS: accesses. Save it in ESI.
- ##
- movl TRAP_DS+4(%esp), %esi # Save DS into ESI for now.
- movl TRAP_ES+4(%esp), %eax # Restore ES.
- movw %ax, %es #
- movl TRAP_FS+4(%esp), %eax # Restore FS.
- movw %ax, %fs #
- movl TRAP_GS+4(%esp), %eax # Restore GS.
- movw %ax, %gs #
- RestoreTrapFrameToKernelMode:
- ##
- ## The exception came from kernel mode, so restore the stack segment register.
- ##
- movl TRAP_SS+4(%esp), %eax # Restore SS. If this doesn't allow access
- movw %ax, %ss # to the current stack, this will be bad.
- ##
- ## Build the iret return on the value The parameters going on the new stack are
- ## Ebx, Return Address, Error Code, Eip, CS, and Eflags.
- ##
- ## Note that if the stack pointer doesn't change, the Ebx and Return address
- ## values destroy data that was on the stack there (immediately after the
- ## Eflags, CS, Eip). This happens to be the last two values in the trap frame
- ## structure. Luckily those members are Esp and Eflags, which are restored
- ## immediately before their values are destroyed.
- ##
- movl TRAP_ESP+4(%esp), %ebx # Get the kernel Esp.
- RestoreTrapFrameGeneralRegisters:
- subl $24, %ebx # Make room for the new parameters.
- movl TRAP_EIP+4(%esp), %ecx # Restore Eip.
- movl %ecx, 12(%ebx) #
- movl TRAP_CS+4(%esp), %ecx # Restore CS.
- movl %ecx, 16(%ebx) #
- movl TRAP_EFLAGS+4(%esp), %ecx # Restore Eflags.
- movl %ecx, 20(%ebx) #
- movl TRAP_EBX+4(%esp), %ecx # Save Ebx.
- movl %ecx, (%ebx) #
- movl (%esp), %ecx # Save this function's return address.
- movl %ecx, 4(%ebx) #
- ##
- ## Now that all DS: accesses are finished, restore DS.
- ##
- movw %si, %ds
- ##
- ## Restore the general registers.
- ##
- movl TRAP_EAX+4(%esp), %eax #
- movl TRAP_ECX+4(%esp), %ecx #
- movl TRAP_EDX+4(%esp), %edx #
- movl TRAP_ESI+4(%esp), %esi #
- movl TRAP_EDI+4(%esp), %edi #
- movl TRAP_EBP+4(%esp), %ebp #
- ##
- ## Transition to the new kernel mode stack pointer, pop Ebx, and return.
- ##
- movl %ebx, %esp # Move stacks!
- popl %ebx # Restore Ebx.
- ret
- ##
- ## TRAP_FRAME
- ## BoGenerateTrapFrame (
- ## ULONG ReturnEip,
- ## ULONG ReturnCs,
- ## ULONG ReturnEflags,
- ## ...
- ## )
- ##
- /*++
- Routine Description:
- This routine generates a trap frame based on the data pushed onto the
- stack by the processor after an exception. It is not really a function
- in that it assumes a certain stack layout and will modify data that
- belongs to the caller. This function should only be called immediately
- after an interrupt/exception.
- Arguments:
- ReturnEip - Supplies the instruction that generated the exception.
- ReturnCs - Supplies the code selector of the code that generated the
- exception.
- ReturnEflags - Supplies the flags of the code that generated the
- exception.
- Return Value:
- Upon return, a TRAP_FRAME will be on the top of the stack.
- --*/
- BoGenerateTrapFrame:
- ##
- ## Allocate room on the stack for the trap frame plus the return address,
- ## minus the original return address.
- ##
- subl $TRAP_FRAME_SIZE, %esp #
- pushl %eax # Save eax for a moment while the return
- movl TRAP_FRAME_SIZE+4(%esp), %eax # address is moved.
- movl %eax, 4(%esp) #
- popl %eax # Restore eax
- movl %eax, TRAP_EAX+4(%esp) # Save the general registers.
- movl %ebx, TRAP_EBX+4(%esp) #
- movl %ecx, TRAP_ECX+4(%esp) #
- movl %edx, TRAP_EDX+4(%esp) #
- movl %esi, TRAP_ESI+4(%esp) #
- movl %edi, TRAP_EDI+4(%esp) #
- movl %ebp, TRAP_EBP+4(%esp) #
- movl TRAP_RET_ERRORCODE+4(%esp), %eax # Save the error code.
- movl %eax, TRAP_ERRORCODE+4(%esp) #
- movl TRAP_RET_EIP+4(%esp), %eax # Save the return address.
- movl %eax, TRAP_EIP+4(%esp) #
- movl TRAP_RET_CS+4(%esp), %eax # Save the return CS.
- movl %eax, TRAP_CS+4(%esp) #
- movl TRAP_RET_EFLAGS+4(%esp), %eax # Save eflags.
- movl %eax, TRAP_EFLAGS+4(%esp)
- ##
- ## The exception came from ring 0, so the only things pushed on the stack
- ## by the processor are Eip, CS, and Eflags. The data segments also don't need
- ## to be saved. Get the data segments from their current values. Since there
- ## was no stack change, the Esp is simply this current one except all the
- ## stuff pushed by the exception, plus the error code.
- ##
- movl %esp, %eax # Save Esp.
- addl $TRAP_FRAME_SIZE+20, %eax # Remove exception stack items.
- movl %eax, TRAP_ESP+4(%esp) #
- xorl %eax, %eax # Zero out eax.
- movw %ds, %ax # Save DS.
- movl %eax, TRAP_DS+4(%esp) #
- movw %es, %ax # Save ES.
- movl %eax, TRAP_ES+4(%esp) #
- movw %fs, %ax # Save FS.
- movl %eax, TRAP_FS+4(%esp) #
- movw %gs, %ax # Save GS.
- movl %eax, TRAP_GS+4(%esp) #
- movw %ss, %ax # Save SS.
- movl %eax, TRAP_SS+4(%esp) #
- GenerateTrapFrameEnd:
- LoadBootDataSegments # Load valid data segments.
- ret #
|