diff options
author | ionescu007 <aionescu+git@gmail.com> | 2016-09-03 19:12:39 +0300 |
---|---|---|
committer | ionescu007 <aionescu+git@gmail.com> | 2016-09-03 19:12:39 +0300 |
commit | 98af3a870a27d66e820379056ea09153ef823332 (patch) | |
tree | 8cf0d7897585cbc257bf265907bb80852e4c4be3 | |
parent | f5dd1af02f22e2caf564dea4705bce2d42167061 (diff) |
Officially add support for UEFI: Uefisor!
Documentation to follow.
-rw-r--r-- | nt/shvos.c (renamed from shvos.c) | 0 | ||||
-rw-r--r-- | nt/shvosx64.asm (renamed from shvosx64.asm) | 0 | ||||
-rw-r--r-- | shv.vcxproj | 10 | ||||
-rw-r--r-- | shv.vcxproj.filters | 38 | ||||
-rw-r--r-- | uefi/shvos.c | 391 | ||||
-rw-r--r-- | uefi/shvosx64.asm | 99 |
6 files changed, 536 insertions, 2 deletions
diff --git a/shvosx64.asm b/nt/shvosx64.asm index 1e75175..1e75175 100644 --- a/shvosx64.asm +++ b/nt/shvosx64.asm diff --git a/shv.vcxproj b/shv.vcxproj index fd0e09c..83c4c65 100644 --- a/shv.vcxproj +++ b/shv.vcxproj @@ -55,12 +55,15 @@ </Link> </ItemDefinitionGroup> <ItemGroup> - <ClCompile Include="shvos.c" /> <ClCompile Include="shv.c" /> <ClCompile Include="shvutil.c" /> <ClCompile Include="shvvmx.c" /> <ClCompile Include="shvvmxhv.c" /> <ClCompile Include="shvvp.c" /> + <ClCompile Include="nt\shvos.c" /> + <ClCompile Include="uefi\shvos.c"> + <ExcludedFromBuild>true</ExcludedFromBuild> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="shv.h" /> @@ -70,7 +73,10 @@ </ItemGroup> <ItemGroup> <MASM Include="shvvmxhvx64.asm" /> - <MASM Include="shvosx64.asm" /> + <MASM Include="nt\shvosx64.asm" /> + <MASM Include="uefi\shvosx64.asm"> + <ExcludedFromBuild>true</ExcludedFromBuild> + </MASM> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> diff --git a/shv.vcxproj.filters b/shv.vcxproj.filters new file mode 100644 index 0000000..6e2914c --- /dev/null +++ b/shv.vcxproj.filters @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="shv.c" /> + <ClCompile Include="shvutil.c" /> + <ClCompile Include="shvvmx.c" /> + <ClCompile Include="shvvmxhv.c" /> + <ClCompile Include="shvvp.c" /> + <ClCompile Include="nt\shvos.c"> + <Filter>NT</Filter> + </ClCompile> + <ClCompile Include="uefi\shvos.c"> + <Filter>UEFI</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="shv.h" /> + <ClInclude Include="ntint.h" /> + <ClInclude Include="shv_x.h" /> + <ClInclude Include="vmx.h" /> + </ItemGroup> + <ItemGroup> + <Filter Include="NT"> + <UniqueIdentifier>{dbe9fd1c-cc57-4f03-a093-03b3312ec3ac}</UniqueIdentifier> + </Filter> + <Filter Include="UEFI"> + <UniqueIdentifier>{1bdf620e-c034-447a-bf4f-c9e7004a2328}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <MASM Include="nt\shvosx64.asm"> + <Filter>NT</Filter> + </MASM> + <MASM Include="uefi\shvosx64.asm"> + <Filter>UEFI</Filter> + </MASM> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/uefi/shvos.c b/uefi/shvos.c new file mode 100644 index 0000000..db19f21 --- /dev/null +++ b/uefi/shvos.c @@ -0,0 +1,391 @@ +/*++ + +Copyright (c) Alex Ionescu. All rights reserved. + +Module Name: + + shvos.c + +Abstract: + + This module implements the OS-facing UEFI stubs for SimpleVisor. + +Author: + + Alex Ionescu (@aionescu) 29-Aug-2016 - Initial version + +Environment: + + Kernel mode only. + +--*/ + +// +// Basic UEFI Libraries +// +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseMemoryLib.h> + +// +// Boot and Runtime Services +// +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> + +// +// Multi-Processor Service +// +#include <Pi/PiDxeCis.h> +#include <Protocol/MpService.h> + +// +// Variable Arguments (CRT) +// +#include <varargs.h> + +// +// External SimpleVisor Headers +// +#include "ntint.h" +#include "shv_x.h" + +// +// We run on any UEFI Specification +// +extern CONST UINT32 _gUefiDriverRevision = 0; + +// +// Our name +// +CHAR8 *gEfiCallerBaseName = "SimpleVisor"; + +// +// PI Multi Processor Services Protocol +// +EFI_MP_SERVICES_PROTOCOL* _gPiMpService; + +// +// TSS Segment we will use +// +#define KGDT64_SYS_TSS 0x60 + +EFI_STATUS +__forceinline +ShvOsErrorToError ( + INT32 Error + ) +{ + // + // Convert the possible SimpleVisor errors into NT Hyper-V Errors + // + if (Error == SHV_STATUS_NOT_AVAILABLE) + { + return EFI_NOT_AVAILABLE_YET; + } + if (Error == SHV_STATUS_NO_RESOURCES) + { + return EFI_OUT_OF_RESOURCES; + } + if (Error == SHV_STATUS_NOT_PRESENT) + { + return EFI_NOT_FOUND; + } + if (Error == SHV_STATUS_SUCCESS) + { + return EFI_SUCCESS; + } + + // + // Unknown/unexpected error + // + return EFI_LOAD_ERROR; +} + +VOID +_str ( + _In_ UINT16* Tr + ) +{ + // + // Use the UEFI framework function + // + *Tr = AsmReadTr(); +} + +VOID +_sldt ( + _In_ UINT16* Ldtr + ) +{ + // + // Use the UEFI framework function + // + *Ldtr = AsmReadLdtr(); +} + +VOID +__lgdt ( + _In_ IA32_DESCRIPTOR* Gdtr + ) +{ + // + // Use the UEFI framework function + // + AsmWriteGdtr(Gdtr); +} + +VOID +ShvOsUnprepareProcessor ( + _In_ PSHV_VP_DATA VpData + ) +{ + UNREFERENCED_PARAMETER(VpData); + + // + // Nothing to do + // +} + +INT32 +ShvOsPrepareProcessor ( + _In_ PSHV_VP_DATA VpData + ) +{ + PKGDTENTRY64 TssEntry, NewGdt; + PKTSS64 Tss; + KDESCRIPTOR Gdtr; + + // + // Clear AC in case it's not been reset yet + // + __writeeflags(__readeflags() & ~EFLAGS_ALIGN_CHECK); + + // + // Capture the current GDT + // + _sgdt(&Gdtr.Limit); + + // + // Allocate a new GDT as big as the old one, or to cover selector 0x60 + // + NewGdt = AllocateRuntimeZeroPool(MAX(Gdtr.Limit + 1, + KGDT64_SYS_TSS + sizeof(*TssEntry))); + if (NewGdt == NULL) + { + return SHV_STATUS_NO_RESOURCES; + } + + // + // Copy the old GDT + // + CopyMem(NewGdt, Gdtr.Base, Gdtr.Limit + 1); + + // + // Allocate a TSS + // + Tss = AllocateRuntimeZeroPool(sizeof(*Tss)); + if (Tss == NULL) + { + FreePool(NewGdt); + return SHV_STATUS_NO_RESOURCES; + } + + // + // Fill out the TSS Entry + // + TssEntry = (PKGDTENTRY64)((uintptr_t)NewGdt + KGDT64_SYS_TSS); + TssEntry->BaseLow = (uintptr_t)Tss & 0xffff; + TssEntry->Bits.BaseMiddle = ((uintptr_t)Tss >> 16) & 0xff; + TssEntry->Bits.BaseHigh = ((uintptr_t)Tss >> 24) & 0xff; + TssEntry->BaseUpper = (uintptr_t)Tss >> 32; + TssEntry->LimitLow = sizeof(KTSS64) - 1; + TssEntry->Bits.Type = AMD64_TSS; + TssEntry->Bits.Dpl = 0; + TssEntry->Bits.Present = 1; + TssEntry->Bits.System = 0; + TssEntry->Bits.LongMode = 0; + TssEntry->Bits.DefaultBig = 0; + TssEntry->Bits.Granularity = 0; + TssEntry->MustBeZero = 0; + + // + // Load the new GDT + // + Gdtr.Base = NewGdt; + Gdtr.Limit = KGDT64_SYS_TSS + sizeof(*TssEntry) - 1; + _lgdt(&Gdtr.Limit); + + // + // Load the task register + // + _ltr(KGDT64_SYS_TSS); + return SHV_STATUS_SUCCESS; +} + +VOID +ShvOsRunCallbackOnProcessors ( + _In_ PSHV_CPU_CALLBACK Routine, + _In_ VOID* Context + ) +{ + // + // Call the routine on the current CPU + // + Routine(Context); + + // + // And then on all other processors + // + _gPiMpService->StartupAllAPs(_gPiMpService, + Routine, + TRUE, + NULL, + 0, + Context, + NULL); +} + +VOID +ShvOsFreeContiguousAlignedMemory ( + _In_ VOID* BaseAddress, + _In_ size_t Size + ) +{ + // + // Free the memory + // + FreeAlignedPages(BaseAddress, Size); +} + +VOID* +ShvOsAllocateContigousAlignedMemory ( + _In_ size_t Size + ) +{ + // + // Allocate a contiguous chunk of RAM to back this allocation. + // + return AllocateAlignedRuntimePages(Size, EFI_PAGE_SIZE); +} + +UINT64 +ShvOsGetPhysicalAddress ( + _In_ VOID* BaseAddress + ) +{ + // + // UEFI runs with paging disabled + // + return (UINT64)BaseAddress; +} + +INT32 +ShvOsGetCurrentProcessorNumber ( + VOID + ) +{ + EFI_STATUS efiStatus; + UINTN cpuIndex; + + // + // Ask PI MP Services for the CPU index + // + efiStatus = _gPiMpService->WhoAmI(_gPiMpService, &cpuIndex); + if (efiStatus != EFI_SUCCESS) + { + cpuIndex = ~0ULL; + } + + // + // Return the index + // + return (INT32)cpuIndex; +} + +INT32 +ShvOsGetActiveProcessorCount ( + VOID + ) +{ + EFI_STATUS efiStatus; + UINTN cpuCount, enabledCpuCount; + + // + // Ask PI MP Services for how many CPUs there are + // + efiStatus = _gPiMpService->GetNumberOfProcessors(_gPiMpService, + &cpuCount, + &enabledCpuCount); + if (efiStatus != EFI_SUCCESS) + { + enabledCpuCount = 0; + } + + // + // Return the count + // + return (INT32)enabledCpuCount; +} + +VOID +ShvOsDebugPrintWide ( + _In_ CHAR16* Format, + ... + ) +{ + VA_LIST arglist; + CHAR16* debugString; + + // + // Call the debugger API + // + VA_START(arglist, Format); + debugString = CatVSPrint(NULL, Format, arglist); + Print(debugString); + FreePool(debugString); + VA_END(arglist); +} + +EFI_STATUS +EFIAPI +UefiUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + // + // Call the hypervisor unloadpoint + // + ShvUnload(); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ) +{ + EFI_STATUS efiStatus; + + // + // Find the PI MpService protocol used for multi-processor startup + // + efiStatus = gBS->LocateProtocol(&gEfiMpServiceProtocolGuid, + NULL, + &_gPiMpService); + if (EFI_ERROR(efiStatus)) + { + Print(L"Unable to locate the MpServices procotol: %r\n", efiStatus); + return efiStatus; + } + + // + // Call the hypervisor entrypoint + // + return ShvOsErrorToError(ShvLoad()); +} + diff --git a/uefi/shvosx64.asm b/uefi/shvosx64.asm new file mode 100644 index 0000000..c1bdf84 --- /dev/null +++ b/uefi/shvosx64.asm @@ -0,0 +1,99 @@ +;++ +; +; Copyright (c) Alex Ionescu. All rights reserved. +; +; Module: +; +; shvx64.asm +; +; Abstract: +; +; This module implements AMD64-specific routines for the Simple Hyper Visor. +; +; Author: +; +; Alex Ionescu (@aionescu) 16-Mar-2016 - Initial version +; +; Environment: +; +; Kernel mode only. +; +;-- + + .code + + _ltr PROC + ltr cx + _ltr ENDP + + ShvOsCaptureContext PROC + pushfq + mov [rcx+78h], rax + mov [rcx+80h], rcx + mov [rcx+88h], rdx + mov [rcx+0B8h], r8 + mov [rcx+0C0h], r9 + mov [rcx+0C8h], r10 + mov [rcx+0D0h], r11 + + mov word ptr [rcx+38h], cs + mov word ptr [rcx+3Ah], ds + mov word ptr [rcx+3Ch], es + mov word ptr [rcx+42h], ss + mov word ptr [rcx+3Eh], fs + mov word ptr [rcx+40h], gs + + mov [rcx+90h], rbx + mov [rcx+0A0h], rbp + mov [rcx+0A8h], rsi + mov [rcx+0B0h], rdi + mov [rcx+0D8h], r12 + mov [rcx+0E0h], r13 + mov [rcx+0E8h], r14 + mov [rcx+0F0h], r15 + + lea rax, [rsp+10h] + mov [rcx+98h], rax + mov rax, [rsp+8] + mov [rcx+0F8h], rax + mov eax, [rsp] + mov [rcx+44h], eax + + add rsp, 8 + ret + ShvOsCaptureContext ENDP + + ShvOsRestoreContext PROC + mov ax, [rcx+42h] + mov [rsp+20h], ax + mov rax, [rcx+98h] + mov [rsp+18h], rax + mov eax, [rcx+44h] + mov [rsp+10h], eax + mov ax, [rcx+38h] + mov [rsp+8], ax + mov rax, [rcx+0F8h] + mov [rsp], rax + + mov rax, [rcx+78h] + mov rdx, [rcx+88h] + mov r8, [rcx+0B8h] + mov r9, [rcx+0C0h] + mov r10, [rcx+0C8h] + mov r11, [rcx+0D0h] + cli + + mov rbx, [rcx+90h] + mov rsi, [rcx+0A8h] + mov rdi, [rcx+0B0h] + mov rbp, [rcx+0A0h] + mov r12, [rcx+0D8h] + mov r13, [rcx+0E0h] + mov r14, [rcx+0E8h] + mov r15, [rcx+0F0h] + mov rcx, [rcx+80h] + + iretq + ShvOsRestoreContext ENDP + + end |