Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux vmlaunch简单崩溃ubuntu 16.04_Linux_X86 64_Virtualization - Fatal编程技术网

Linux vmlaunch简单崩溃ubuntu 16.04

Linux vmlaunch简单崩溃ubuntu 16.04,linux,x86-64,virtualization,Linux,X86 64,Virtualization,我正在将VMLaunchSimple移植到ubuntu 16.04,代码位于。并修改了vmlaunch_simple.c,使其几乎可以在ubuntu 16.04中运行。 当我加载模块(KVM和KVM_intel已卸载)时,“insmod vmlaunch_simple.ko”会挂起,其中kexec/kdump会插话,主机会重新启动。 重新启动后,崩溃日志如下所示 [ 866.579251] vmlaunch_simple: module verification failed: signatu

我正在将VMLaunchSimple移植到ubuntu 16.04,代码位于。并修改了vmlaunch_simple.c,使其几乎可以在ubuntu 16.04中运行。
当我加载模块(KVM和KVM_intel已卸载)时,“insmod vmlaunch_simple.ko”会挂起,其中kexec/kdump会插话,主机会重新启动。
重新启动后,崩溃日志如下所示

[  866.579251] vmlaunch_simple: module verification failed: signature `.....`
[  866.581183] BUG: unable to handle kernel NULL pointer dereference at 0000000000000005
[  866.584255] IP: [<0000000000000005>] 0x5
[  866.585750] PGD 0
[  866.586562] Oops: 0010 [#1] SMP
[  866.619897] task: ffff8800b99cee00 ti: ffff880234138000 task.ti: ffff880234138000
[  866.622615] RIP: 0010:[<0000000000000005>]  [<0000000000000005>] 0x5
[  866.625045] RSP: 0018:ffff88023413bc40  EFLAGS: 00010286
[  866.626989] RAX: 0000000000000000 RBX: 0000001200000018 RCX: 0000000000000006
[  866.629643] RDX: 0000000000000000 RSI: 0000000000000246 RDI: ffff88023fc8cbf0
[  866.632236] RBP: fffa322300000001 R08: 656e6f44203e313c R09: 0000000000000801
[  866.634830] R10: ffffea0008d1a600 R11: 0000000000000801 R12: ffff880035cfda40
[  866.637502] R13: 0000000000000000 R14: ffffffffc0421868 R15: ffffffffc0424bc0
[  866.640104] FS:  ffffffffe4901700(0000) GS:ffff88023fc80000(0000) knlGS:0000000000000000
[  866.643040] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  866.645162] CR2: 0000000000000005 CR3: 0000000233356000 CR4: 00000000001406e0
[  866.647807] Stack:
[  866.648576]  0000000000004402 000001e75074c4cf 000001e75076e27f 5076e27f5074c4cf
[  866.651460]  000001e7000001e7 00000000cc0ba018 ffffffff81e0f040 ffff88023413bcf8
[  866.654341]  ffffffff810003e3 ffffea0008ccd300 ffff88023413bcd0 0000000000000282
[  866.657224] Call Trace:
[  866.658152]  [<ffffffff810003e3>] ? do_one_initcall+0xb3/0x1f0
[  866.660315]  [<ffffffff811cfeb3>] ? kmem_cache_alloc_trace+0x183/0x1f0
[  866.663309]  [<ffffffff81171c37>] ? do_init_module+0x5f/0x1cf
[  866.666023]  [<ffffffff810efdba>] ? load_module+0x225a/0x28b0
[  866.668854]  [<ffffffff810ec3c0>] ? __symbol_put+0x60/0x60
[  866.671464]  [<ffffffff811f6120>] ? kernel_read+0x50/0x80
[  866.674031]  [<ffffffff810f0654>] ? SYSC_finit_module+0xb4/0xe0
[  866.676784]  [<ffffffff810f069e>] ? SyS_finit_module+0xe/0x10
[  866.679455]  [<ffffffff818046db>] ? entry_SYSCALL_64_fastpath+0x16/0x6a
[  866.682455] Code:  Bad RIP value.
[  866.684408] RIP  [<0000000000000005>] 0x5
[  866.686492]  RSP <ffff88023413bc40>
[  866.688334] CR2: 0000000000000005
[866.579251]vmlaunch\u简单:模块验证失败:签名``
[866.581183]错误:无法处理000000000000000处的内核空指针解引用5
[866.584255]IP:[]0x5
[866.585750]第0页
[866.586562]Oops:0010[#1]SMP
[866.619897]任务:ffff8800b99cee00 ti:ffff880234138000任务。ti:ffff880234138000
[866.622615]RIP:0010:[]0x5
[866.625045]RSP:0018:ffff88023413bc40 EFLAGS:00010286
[866.626989]RAX:0000000000000000 RBX:0000001200000018 RCX:000000000000000006
[866.629643]RDX:0000000000000000 RSI:0000000000000246 RDI:ffff88023fc8cbf0
[866.632236]RBP:FFFA3223000000001 R08:656e6f44203e313c R09:0000000000000 801
[866.634830]R10:FFFFEA008D1A600 R11:0000000000000 801 R12:ffff880035cfda40
[866.637502]R13:0000000000000000 R14:FFFFFF C0421868 R15:FFFFFFFF C0424BC0
[866.640104]FS:FFFFFFFFFE4901700(0000)GS:ffff88023fc80000(0000)KNLG:0000000000000000000000
[866.643040]CS:0010 DS:0000 ES:0000 CR0:00000000 80050033
[866.645162]CR2:000000000000000 5 CR3:0000000 233356000 CR4:0000000000 1406E0
[866.647807]堆栈:
[866.648576]000000000000440200001E75074C4CF 000001e75076e27f 5076e27f5074c4cf
[866.651460]000001E700001E7 00000000 CC0BA018 FFFFFFFF 81E0F040 ffff88023413bcf8
[866.654341]FFFFFF810003E3 FFFFA0008CCD300 FFFF88023413BCD00000000000000 282
[866.657224]呼叫跟踪:
[  866.658152]  [] ? do_one_initcall+0xb3/0x1f0
[  866.660315]  [] ? kmem_缓存_分配_跟踪+0x183/0x1f0
[  866.663309]  [] ? do_init_模块+0x5f/0x1cf
[  866.666023]  [] ? 加载模块+0x225a/0x28b0
[  866.668854]  [] ? __符号输入+0x60/0x60
[  866.671464]  [] ? 内核读取+0x50/0x80
[  866.674031]  [] ? SYSC_finit_模块+0xb4/0xe0
[  866.676784]  [] ? 系统限定模块+0xe/0x10
[  866.679455]  [] ? 条目\u系统调用\u 64\u快速路径+0x16/0x6a
[866.682455]代码:RIP值错误。
[866.684408]RIP[]0x5
[866.686492]RSP
[866.688334]CR2:0000000000005
源代码

#include <linux/init.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/tlbflush.h>
#include <asm/desc.h>
#include "vmxon_simple.h"

MODULE_LICENSE("Dual BSD/GPL");

#define MYPAGE_SIZE 4096
#define VMX_BASIC_MSR 0x480
#define FEATURE_CONTROL_MSR 0x3A
#define CPUID_VMX_BIT 5

bool alloc_failure = false;
int vmx_msr_addr = VMX_BASIC_MSR;
int feature_control_msr_addr = FEATURE_CONTROL_MSR;
u64    vmx_rev_id = 0;
int vmxon_success = 0;
int vmxoff_success = 0;
int vmptrld_success = 0;
int vmclear_success = 0;
int vmwrite_success = 0;
int vmread_success = 0;
int vmlaunch_success = 0;
char *vmxon_region;
char *vmcs_guest_region;
char *io_bitmap_a_region;
char *io_bitmap_b_region;
char *msr_bitmap_region;
char *virtual_apic_page;

long int vmxon_phy_region = 0;
long int vmcs_phy_region = 0;
long int io_bitmap_a_phy_region = 0;
long int io_bitmap_b_phy_region = 0;
long int msr_bitmap_phy_region = 0;
long int virtual_apic_page_phy_region = 0;

unsigned long value;
long int rflags_value = 0;
u16 tr_sel; //selector for task register

static int  do_vmclear(void);
static int  do_vmptrld(void);
static void vmxon_exit(void);
static u64  do_vmread(unsigned long field);

u16         host_gdtr[5], host_idtr[5];

#define MY_VMX_VMXON_RAX         ".byte 0xf3, 0x0f, 0xc7, 0x30"
#define MY_VMX_VMPTRLD_RAX       ".byte 0x0f, 0xc7, 0x30"
#define MY_VMX_VMCLEAR_RAX       ".byte 0x66, 0x0f, 0xc7, 0x30"
#define MY_VMX_VMLAUNCH          ".byte 0x0f, 0x01, 0xc2"
#define MY_VMX_VMRESUME          ".byte 0x0f, 0x01, 0xc3"
#define MY_VMX_VMREAD_RDX_RAX    ".byte 0x0f, 0x78, 0xd0"
#define MY_VMX_VMWRITE_RAX_RDX   ".byte 0x0f, 0x79, 0xd0"
#define MY_VMX_VMXOFF            ".byte 0x0f, 0x01, 0xc4"
#define MY_VMX_VMCALL            ".byte 0x0f, 0x01, 0xc1"
#define MY_HLT                 ".byte 0xf4"

static u64 do_vmread(unsigned long field)
{
    u64 value = 0;

    vmread_success = 1;
    asm volatile("vmread %1, %0\n"
            : "=a"(value) : "d"(field) : "cc");
    asm volatile("jbe vmread_fail\n");
    asm volatile("jmp vmread_finish\n");
    asm volatile("vmread_fail:\n");
    printk("   # vmread(0x%lX) failed\n", field);
    printk("   # RFLAGS: 0x%lX\n", rflags_value);
    vmread_success = 0;
    asm volatile("vmread_finish:\n");
    return value;
}

static int do_vmxon(void)
{
    vmxon_success = 1;
    smp_mb();
    asm volatile( "vmxon %0\n"           \
            "jbe vmxon_fail\n"     \
            "jmp vmxon_finish\n"   \
            "vmxon_fail:     \n"   \
            "   movl  $0, vmxon_success \n"\
            "vmxon_finish: \n"
            :
            : "m"(vmxon_phy_region)
            : "memory", "cc");
    if (vmxon_success == 0) {
        printk("[i] vmxon has failed! VT-X is busy by other VMM.\n");
    }

    return !(vmxon_success);
}

static int do_vmptrld(void)
{
    asm volatile("vmptrld %0\n"
            :
            : "m"(vmcs_phy_region)
            : "cc", "memory");
    asm volatile("jbe vmptrld_fail\n");
    vmptrld_success = 1;
    asm volatile("jmp vmptrld_finish\n"
            "vmptrld_fail:\n");
    vmptrld_success = 0;
    pr_err("[i] vmptrld has failed!\n");
    asm volatile("vmptrld_finish:\n");

    return !vmptrld_success;
}

static int do_vmclear(void)
{
    asm volatile ("vmclear %1 \n"
            : : "a"(&vmcs_phy_region), "m"(vmcs_phy_region)
            : "cc", "memory");
    asm volatile("jbe vmclear_fail");
    vmclear_success = 1;
    asm volatile("jmp vmclear_finish\n"
            "vmclear_fail:\n");
    vmclear_success = 0;
    pr_err("[i] vmclear has failed!\n");
    asm volatile("vmclear_finish:\n");
    printk("<1> vmclear done!\n");

    return !(vmclear_success);
}

/*do vmxoff*/
static int do_vmxoff(void)
{
    asm volatile("vmxoff\n" : : : "cc");
    asm volatile("jbe vmxoff_fail\n");
    vmxoff_success = 1;
    asm volatile("jmp vmxoff_finish\n");
    asm volatile("vmxoff_fail:\n");
    vmxoff_success = 0;
    pr_err("[i] vmxoff has failed!\n");
    asm volatile("vmxoff_finish:\n");

    printk("<1> vmxoff complete\n");
    return !(vmxoff_success);
}

static u8 do_vmwrite(u32 field, u64 val)
{
    u8 error;

    __asm __volatile ( "clc; vmwrite %%rax, %%rdx; setna %0"
            : "=q"( error ) : "a"( val), "d"( field ) : "cc");
    return error;
}

static void do_vmwrite16(unsigned long field, u16 value)
{
    do_vmwrite(field, value);
}

static void do_vmwrite32(unsigned long field, u32 value)
{
    do_vmwrite(field, value);
}

static void do_vmwrite64(unsigned long field, u64 value)
{
    do_vmwrite(field, value);
}

static void initialize_16bit_host_guest_state(void)
{
    unsigned long field,field1;
    u16         value;
    field = VMX_HOST_ES_SEL;
    field1 = VMX_GUEST_ES_SEL;
    asm ("movw %%es, %%ax\n"
            :"=a"(value)
        );
    do_vmwrite16(field,value);
    do_vmwrite16(field1,value);

    field = VMX_HOST_CS_SEL;
    field1 = VMX_GUEST_CS_SEL;
    asm ("movw %%cs, %%ax\n"
            : "=a"(value));
    do_vmwrite16(field,value);
    do_vmwrite16(field1,value);

    field = VMX_HOST_SS_SEL;
    field1 = VMX_GUEST_SS_SEL;
    asm ("movw %%ss, %%ax\n"
            : "=a"(value));
    do_vmwrite16(field,value);
    do_vmwrite16(field1,value);

    field = VMX_HOST_DS_SEL;
    field1 = VMX_GUEST_DS_SEL;
    asm ("movw %%ds, %%ax\n"
            : "=a"(value));
    do_vmwrite16(field,value);
    do_vmwrite16(field1,value);

    field = VMX_HOST_FS_SEL;
    field1 = VMX_GUEST_FS_SEL;
    asm ("movw %%fs, %%ax\n"
            : "=a"(value));
    do_vmwrite16(field,value);
    do_vmwrite16(field1,value);

    field = VMX_HOST_GS_SEL;
    field1 = VMX_GUEST_GS_SEL;
    asm ("movw %%gs, %%ax\n"
            : "=a"(value));
    do_vmwrite16(field,value);
    do_vmwrite16(field1,value);

    field = VMX_HOST_TR_SEL;
    field1 = VMX_GUEST_TR_SEL;
    asm("str %%ax\n" : "=a"(tr_sel));
    do_vmwrite16(field,tr_sel);
    do_vmwrite16(field1,tr_sel);

    field = VMX_GUEST_LDTR_SEL;
    asm("sldt %%ax\n" : "=a"(value));
    do_vmwrite16(field,value);
}

static void initialize_64bit_control(void)
{
    unsigned long field;
    u64         value;

    field = VMX_IO_BITMAP_A_FULL;
    io_bitmap_a_phy_region = __pa(io_bitmap_a_region);
    value = io_bitmap_a_phy_region;
    do_vmwrite64(field,value);

    field = VMX_IO_BITMAP_B_FULL;
    io_bitmap_b_phy_region = __pa(io_bitmap_b_region);
    value = io_bitmap_b_phy_region;
    do_vmwrite64(field,value);

    field = VMX_MSR_BITMAP_FULL;
    msr_bitmap_phy_region = __pa(msr_bitmap_region);
    value = msr_bitmap_phy_region;
    do_vmwrite64(field,value);

    field = VMX_VIRTUAL_APIC_PAGE_ADDR_FULL;
    virtual_apic_page_phy_region = __pa(virtual_apic_page);
    value = virtual_apic_page_phy_region;
    do_vmwrite64(field,value);

    field = VMX_EXECUTIVE_VMCS_PTR_FULL;
    value = 0;
    do_vmwrite64(field,value);

    field = VMX_TSC_OFFSET_FULL;
    value = 0;
    do_vmwrite64(field,value);
}

static void initialize_64bit_host_guest_state(void)
{
    unsigned long field;
    u64         value;
    field = VMX_VMS_LINK_PTR_FULL;
    value = 0xffffffffffffffffull;
    do_vmwrite64(field,value);
    field = VMX_GUEST_IA32_DEBUGCTL_FULL;
    value = 0;
    do_vmwrite64(field,value);
}

static void initialize_32bit_control(void)
{
    unsigned long field;
    u32         value;

    field = VMX_PIN_VM_EXEC_CONTROLS;
    value = 0x1e;
    do_vmwrite32(field,value);

    field = VMX_PROC_VM_EXEC_CONTROLS;
    value = 0x0401e172 ;
    do_vmwrite32(field,value);

    field = VMX_EXCEPTION_BITMAP;
    value = 0xffffffff ;
    do_vmwrite32(field,value);

    field = VMX_PF_EC_MASK;
    value = 0x0 ;
    do_vmwrite32(field,value);

    field = VMX_PF_EC_MATCH;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_CR3_TARGET_COUNT;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_EXIT_CONTROLS;
    value = 0x36fff ;
    do_vmwrite32(field,value);

    field = VMX_EXIT_MSR_STORE_COUNT;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_EXIT_MSR_LOAD_COUNT;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_ENTRY_CONTROLS;
    value = 0x13ff ;
    do_vmwrite32(field,value);

    field = VMX_ENTRY_MSR_LOAD_COUNT;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_ENTRY_INT_INFO_FIELD;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_ENTRY_EXCEPTION_EC;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_ENTRY_INSTR_LENGTH;
    value = 0 ;
    do_vmwrite32(field,value);

    field = VMX_TPR_THRESHOLD;
    value = 0 ;
    do_vmwrite32(field,value);
}

static void initialize_32bit_host_guest_state(void)
{
    unsigned long field;
    struct desc_ptr  xdesc;
    u64      value;
    s64     *host_gdt = NULL;
    s64         desc;
    s64         idtb;
    u64      gdtb;
    s64      realtrbase;
    u32      unusable_ar = 0x10000;
    u32      usable_ar;
    u16      sel_value;

    field = VMX_GUEST_ES_LIMIT;
    value = 0xffffffff ;
    do_vmwrite32(field,value);

    field = VMX_GUEST_ES_ATTR;
    value = unusable_ar;
    do_vmwrite32(field,value);

    field = VMX_GUEST_CS_LIMIT;
    value = 0xffffffff ;
    do_vmwrite32(field,value);

    asm ("movw %%cs, %%ax\n"
            : "=a"(sel_value));
    asm("lar %%eax,%%eax\n" :"=a"(usable_ar) :"a"(sel_value));
    usable_ar = usable_ar >> 8;
    usable_ar &= 0xf0ff; //clear bits 11:8

    field = VMX_GUEST_CS_ATTR;
    do_vmwrite32(field,usable_ar);
    value = do_vmread(field);

    field = VMX_GUEST_SS_LIMIT;
    value = 0xffffffff ;
    do_vmwrite32(field,value);

    asm ("movw %%ss, %%ax\n"
            : "=a"(sel_value));
    asm("lar %%eax,%%eax\n" :"=a"(usable_ar) :"a"(sel_value));
    usable_ar = usable_ar >> 8;
    usable_ar &= 0xf0ff; //clear bits 11:8

    field = VMX_GUEST_SS_ATTR;
    do_vmwrite32(field,usable_ar);

    field = VMX_GUEST_DS_LIMIT;
    value = 0xffffffff ;
    do_vmwrite32(field,value);

    field = VMX_GUEST_DS_ATTR;
    value = unusable_ar;
    do_vmwrite32(field,value);

    field = VMX_GUEST_FS_LIMIT;
    value = 0xffffffff ;
    do_vmwrite32(field,value);

    field = VMX_GUEST_FS_ATTR;
    value = unusable_ar;
    do_vmwrite32(field,value);

    field = VMX_GUEST_GS_LIMIT;
    value = 0xffffffff ;
    do_vmwrite32(field,value);

    field = VMX_GUEST_GS_ATTR;
    value = unusable_ar;
    do_vmwrite32(field,value);

    field = VMX_GUEST_LDTR_LIMIT;
    value = 0x0;
    do_vmwrite32(field,value);

    field = VMX_GUEST_LDTR_ATTR;
    value = unusable_ar;
    do_vmwrite32(field,value);

    field = VMX_GUEST_TR_LIMIT;
    asm volatile("mov %%rax, %%rax"
            :
            :"a"(tr_sel)
            );
    asm("lsl %%eax, %%eax\n" :"=a"(value));
    do_vmwrite32(field,value);

    asm("lar %%eax,%%eax\n" :"=a"(usable_ar) :"a"(tr_sel));
    usable_ar = usable_ar >> 8;

    field = VMX_GUEST_TR_ATTR;
    do_vmwrite32(field,usable_ar);

    asm(" sgdt %0 ": "=m" (xdesc));
    value = xdesc.size & 0x0ffff;
    gdtb = xdesc.address; //base

    field = VMX_GUEST_GDTR_LIMIT;
    do_vmwrite32(field,value);

    field = VMX_GUEST_GDTR_BASE;
    do_vmwrite64(field,gdtb);
    field = VMX_HOST_GDTR_BASE;
    do_vmwrite64(field,gdtb);

    host_gdt = (s64 *)gdtb;
    desc = host_gdt[ (tr_sel >> 3) + 0 ];
    realtrbase = ((desc >> 32)&0xFF000000)|((desc >> 16)&0x00FFFFFF);
    desc = host_gdt[ (tr_sel >> 3) + 1 ];
    desc <<= 48;    // maneuver to insure 'canonical' addressing
    realtrbase |= (desc >> 16)&0xFFFFFFFF00000000;
    field = VMX_HOST_TR_BASE;
    do_vmwrite64(field,realtrbase);

    field = VMX_GUEST_TR_BASE;
    do_vmwrite64(field,realtrbase);

    asm("sidt %0\n" : "=m"(xdesc));
    value = xdesc.size & 0x0ffff;
    idtb = xdesc.address; //base

    field = VMX_GUEST_IDTR_LIMIT;
    do_vmwrite32(field,value);

    field = VMX_GUEST_IDTR_BASE;
    do_vmwrite64(field,idtb);
    field = VMX_HOST_IDTR_BASE;
    do_vmwrite64(field,idtb);

    field = VMX_GUEST_INTERRUPTIBILITY_INFO;
    value = 0;
    do_vmwrite32(field,value);

    field = VMX_GUEST_ACTIVITY_STATE;
    value = 0;
    do_vmwrite32(field,value);

    field = VMX_GUEST_SMBASE;
    value = 0;
    do_vmwrite32(field,value);

    rdmsrl_safe(0x174, &value);
    field  = VMX_HOST_IA32_SYSENTER_CS;
    do_vmwrite32(field,value);
    field = VMX_GUEST_IA32_SYSENTER_CS;
    do_vmwrite32(field,value);
}

static void initialize_naturalwidth_control(void)
{
    unsigned long field;
    u64         value;

    field = VMX_CR0_MASK;
    value = 0;
    do_vmwrite64(field,value);
    field = VMX_CR4_MASK;
    value = 0;
    do_vmwrite64(field,value);

    field = VMX_CR0_READ_SHADOW;
    value = 0;
    do_vmwrite64(field,value);

    field = VMX_CR4_READ_SHADOW;
    value = 0;
    do_vmwrite64(field,value);

    field = VMX_CR3_TARGET_0;
    value = 0;
    do_vmwrite64(field,value);

    field = VMX_CR3_TARGET_1;
    value = 0;
    do_vmwrite64(field,value);

    field = VMX_CR3_TARGET_2;
    value = 0;
    do_vmwrite64(field,value);

    field = VMX_CR3_TARGET_3;
    value = 0;
    do_vmwrite64(field,value);
}

static void initialize_naturalwidth_host_guest_state(void)
{
    unsigned long field,field1;
    u64         value;
    int      fs_low;
    int      gs_low;

    field =  VMX_HOST_CR0;
    field1 = VMX_GUEST_CR0;
    asm ("movq %%cr0, %%rax\n"
            :"=a"(value)
        );
    do_vmwrite64(field,value);
    do_vmwrite64(field1,value);

    field =  VMX_HOST_CR3;
    field1 = VMX_GUEST_CR3;
    asm ("movq %%cr3, %%rax\n"
            :"=a"(value)
        );
    do_vmwrite64(field,value);
    do_vmwrite64(field1,value);

    field =  VMX_HOST_CR4;
    field1 = VMX_GUEST_CR4;
    asm ("movq %%cr4, %%rax\n"
            :"=a"(value)
        );
    do_vmwrite64(field,value);
    do_vmwrite64(field1,value);

    value=0;
    field1 = VMX_GUEST_ES_BASE;
    do_vmwrite64(field1,value);
    field1 = VMX_GUEST_CS_BASE;
    do_vmwrite64(field1,value);
    field1 = VMX_GUEST_SS_BASE;
    do_vmwrite64(field1,value);
    field1 = VMX_GUEST_DS_BASE;
    do_vmwrite64(field1,value);
    field1 = VMX_GUEST_LDTR_BASE;
    do_vmwrite64(field1,value);

    value = 0;
    field =  VMX_HOST_FS_BASE;
    field1 = VMX_GUEST_FS_BASE;

    asm volatile("mov $0xc0000100, %rcx\n");
    asm volatile("rdmsr\n" :"=a"(fs_low) : :"%rdx");
    //asm volatile ("mov %%rax, %0\n" : :"m"(fs_low) :"memory");
    asm volatile ("shl $32, %%rdx\n" :"=d"(value));
    value|=fs_low;
    do_vmwrite64(field1,value);
    do_vmwrite64(field,value);

    value = 0;
    field =  VMX_HOST_GS_BASE;
    field1 = VMX_GUEST_GS_BASE;
    asm volatile("mov $0xc0000101, %rcx\n");
    asm volatile("rdmsr\n" :"=a"(gs_low) : :"%rdx");
    //asm volatile ("mov %%rax, %0\n" : :"m"(gs_low) :"memory");
    asm volatile ("shl $32, %%rdx\n" :"=d"(value));
    value|=gs_low;
    do_vmwrite64(field1,value);
    do_vmwrite64(field,value);

    field1 = VMX_GUEST_DR7;
    value = 0x400;
    do_vmwrite64(field1,value);

    field = VMX_HOST_RSP;
    field1 = VMX_GUEST_RSP;
    asm ("movq %%rsp, %%rax\n"
            :"=a"(value)
        );
    do_vmwrite64(field1,value);
    do_vmwrite64(field,value);

    /*
       field1 = VMX_GUEST_RIP;
       value = (u64) guest_entry_code;
       do_vmwrite64(field1,value);

       field1 = VMX_HOST_RIP;
       value  = (u64) handle_vmexit;
       do_vmwrite64(field1,value); */


    field1 = VMX_GUEST_RFLAGS;
    asm volatile("pushfq\n");
    asm volatile("popq %0\n" :"=m"(value)::"memory");
    do_vmwrite64(field1,value);

    field1 = VMX_GUEST_PENDING_DEBUG_EXCEPT;
    value = 0x0;
    do_vmwrite64(field1,value);

    field1 = VMX_GUEST_IA32_SYSENTER_ESP;
    field  = VMX_HOST_IA32_SYSENTER_ESP;
    rdmsrl_safe(0x176, &value);
    do_vmwrite64(field1,value);
    do_vmwrite64(field,value);

    field1 = VMX_GUEST_IA32_SYSENTER_EIP;
    field =  VMX_HOST_IA32_SYSENTER_EIP;
    rdmsrl_safe(0x175, &value);
    do_vmwrite64(field1,value);
    do_vmwrite64(field,value);
}

static void initialize_guest_vmcs(void)
{
    initialize_16bit_host_guest_state();
    initialize_64bit_control();
    initialize_64bit_host_guest_state();
    initialize_32bit_control();
    initialize_naturalwidth_control();
    initialize_32bit_host_guest_state();
    initialize_naturalwidth_host_guest_state();
}

/* Allocate a 4K region for vmxon */
static void allocate_vmxon_region(void)
{
    vmxon_region = kmalloc(MYPAGE_SIZE,GFP_KERNEL);
}

/* Allocate a 4K vmcs region for the guest */
static void allocate_vmcs_region(void)
{
    vmcs_guest_region  =  kmalloc(MYPAGE_SIZE,GFP_KERNEL);
    io_bitmap_a_region =  kmalloc(MYPAGE_SIZE,GFP_KERNEL);
    io_bitmap_b_region =  kmalloc(MYPAGE_SIZE,GFP_KERNEL);
    msr_bitmap_region  =  kmalloc(MYPAGE_SIZE,GFP_KERNEL);
    virtual_apic_page  =  kmalloc(MYPAGE_SIZE,GFP_KERNEL);
    //Initialize data structures
    memset(vmcs_guest_region, 0, MYPAGE_SIZE);
    memset(io_bitmap_a_region, 0, MYPAGE_SIZE);
    memset(io_bitmap_b_region, 0, MYPAGE_SIZE);
    memset(msr_bitmap_region, 0, MYPAGE_SIZE);
    memset(virtual_apic_page, 0, MYPAGE_SIZE);
}

/* Dealloc vmxon region*/
static void deallocate_vmxon_region(void)
{
    if (vmxon_region) {
        printk("<1> freeing allocated vmxon region!\n");
        kfree(vmxon_region);
        vmxon_region = NULL;
    }
}

/* Dealloc vmcs guest region*/
static void deallocate_vmcs_region(void)
{
    if (vmcs_guest_region) {
        printk("<1> freeing allocated vmcs region!\n");
        kfree(vmcs_guest_region);
        vmcs_guest_region = NULL;
    }
    if (io_bitmap_a_region) {
        printk("<1> freeing allocated io bitmapA region!\n");
        kfree(io_bitmap_a_region);
        io_bitmap_a_region = NULL;
    }
    if (io_bitmap_b_region) {
        printk("<1> freeing allocated io bitmapB region!\n");
        kfree(io_bitmap_b_region);
        io_bitmap_b_region = NULL;
    }
    if (msr_bitmap_region) {
        printk("<1> freeing allocated msr bitmap region!\n");
        kfree(msr_bitmap_region);
        msr_bitmap_region = NULL;
    }
    if (virtual_apic_page) {
        printk("<1> freeing allocated virtual apic page region!\n");
        kfree(virtual_apic_page);
        virtual_apic_page = NULL;
    }
}

/*initialize revision id*/
static void vmxon_setup_revid(void)
{
    rdmsrl_safe(vmx_msr_addr, &vmx_rev_id);
}

void turn_on_vmxe( void *dummy )
{
    u64 crx[16];

    asm ( "mov %%cr4, %%rax \n"\
          "mov %%rax, %0\n" : "=m" (crx[id]) ::"ax");
    if ((crx[id] & (1 << 13)) == 0) {
        asm (   " mov  %%cr4, %%rax     \n"\
                " bts  $13, %%rax       \n"\
                " mov  %%rax, %%cr4     " ::: "ax" );

        asm (   "mov %%cr4, %%rax \n"\
                "mov %%rax, %0\n" : "=m" (crx[id]) ::"ax");
    } else {
        pr_warn("VMXE in CR4 already been set, VT-X may be used by other VMM\n");
    }
}

void turn_off_vmxe( void *dummy )
{
    u64 crx[16];

    asm ( "mov %%cr4, %%rax \n"\
          "mov %%rax, %0\n" : "=m" (crx[id]) ::"ax");
    crx[id] &= ~(1 << 13);
    asm (   " mov  %%cr4, %%rax     \n"\
            " btr  $13, %%rax       \n"\
            " mov  %%rax, %%cr4     " ::: "ax" );
}

static void vmxon_exit(void)
{
    if (vmxon_success == 1) {
        printk("<1> Machine in vmxon: Attempting vmxoff\n");
        do_vmclear();
        do_vmxoff();
        vmxon_success = 0;
    }
    turn_off_vmxe(NULL);
    deallocate_vmcs_region();
    deallocate_vmxon_region();
}

static int vmxon_init(void)
{
    unsigned long   field_1;
    u32  value_1    =0;
    int  cpuid_leaf =1;
    int  cpuid_ecx  =0;
    u64  msr3a_value = 0;
    u32     lo[2], hi[2];
    u64  start, end;

    printk("<1> In vmxon\n");

    asm volatile("cpuid\n\t"
            :"=c"(cpuid_ecx)
            :"a"(cpuid_leaf)
            :"%rbx","%rdx");

    if ((cpuid_ecx >> CPUID_VMX_BIT) & 1) {
        printk("<1> VMX supported CPU.\n");
    } else {
        printk("<1> VMX not supported by CPU. Not doing anything\n");
        goto finish_here;
    }

    rdmsrl_safe(feature_control_msr_addr, &msr3a_value);

    if (msr3a_value & 1) {
        if ((msr3a_value >> 2) & 1) {
            printk("MSR 0x3A:Lock bit is on.VMXON bit is on.OK\n");
        } else {
            printk("MSR 0x3A:Lock bit is on.VMXONbit is off.Cannot do vmxon\n");
            goto finish_here;
        }
    } else {
        printk("MSR 0x3A: Lock bit is not on. Not doing anything\n");
        goto finish_here;
    }

    allocate_vmxon_region();

    if (vmxon_region == NULL) {
        printk("<1> Error allocating vmxon region\n");
        vmxon_exit();
        vmxon_success = -ENOMEM;
        return vmxon_success;
    }

    allocate_vmcs_region();
    alloc_failure = (vmcs_guest_region == NULL)  ||
                    (io_bitmap_a_region == NULL) ||
                    (io_bitmap_b_region == NULL) ||
                    (msr_bitmap_region == NULL)  ||
                    (virtual_apic_page == NULL);

    if (alloc_failure) {
        printk("<1> Error allocating vmcs guest region\n");
        vmxon_exit();
        vmptrld_success = -ENOMEM;
        return vmptrld_success;
    }

    vmxon_setup_revid();
    vmxon_phy_region = virt_to_phys(vmxon_region);
    memset(vmxon_region, 0, MYPAGE_SIZE);
    memcpy(vmxon_region, &vmx_rev_id, 4); //copy revision id to vmxon region

    turn_on_vmxe(NULL);

    do_vmxon();

    vmcs_phy_region = virt_to_phys(vmcs_guest_region);
    memset(vmcs_guest_region, 0, MYPAGE_SIZE);
    memcpy(vmcs_guest_region, &vmx_rev_id, 4); //copy revision id to vmcs region

    do_vmclear();
    do_vmptrld();

    initialize_guest_vmcs();

    //host rip
    asm ("movq $0x6c16, %rdx");
    asm ("movq $vmexit_handler, %rax");
    asm ("vmwrite %rax, %rdx");

    //guest rip
    asm ("movq $0x681e, %rdx");
    asm ("movq $guest_entry_point, %rax");
    asm ("vmwrite %rax, %rdx");

    printk("<1> Doing vmlaunch now..\n");

    asm volatile (
            "vmlaunch                      \n"\
            "jbe vmexit_handler            \n" \
            "nop                           \n" \
            "guest_entry_point:            \n" \
            "   vmcall                     \n" \
            "   ud2                        \n" \
            "vmexit_handler: \n");

    asm volatile("sti");

    printk("<1> After vmexit\n");

    field_1 = VMX_EXIT_REASON;
    value_1 = do_vmread(field_1);
    printk("<1> Guest VMexit reason: 0x%x\n",value_1);

finish_here:
    vmxon_exit(); //do vmxoff
    printk("<1> Done\n");
    return 0;
}

static void vmxon_exit_dummy(void)
{
    printk("In Function %s\n", __func__);
}

module_init(vmxon_init);
module_exit(vmxon_exit_dummy);
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“vmxon_simple.h”
模块许可证(“双BSD/GPL”);
#定义MYPAGE_大小4096
#定义VMX_基本_MSR 0x480
#定义功能\u控制\u MSR 0x3A
#定义CPUID\U VMX\U位5
bool alloc_failure=false;
int vmx_msr_addr=vmx_BASIC_msr;
int feature\u control\u msr\u addr=feature\u control\u msr;
u64 vmx_rev_id=0;
int vmxon_success=0;
int vmxoff_success=0;
int vmptrld_success=0;
int vmclear_success=0;
int vmwrite_success=0;
int vmread_success=0;
int VMU启动成功=0;
char*vmxon_区域;
char*vmcs_客人_区域;
字符*io_位图_a_区域;
字符*io_位图_b_区域;
char*msr\u位图\u区域;
字符*虚拟apic页面;
长整数vmxon_phy_区域=0;
长整数vmcs_phy_区域=0;
长INTIO位图物理区域=0;
长int io_位图_b_物理_区域=0;
长整型msr\U位图\U物理\U区域=0;
long int virtual_apic_page_phy_region=0;
无符号长值;
长整型rflags_值=0;
u16 tr_sel//任务寄存器选择器
静态int do_vmclear(void);
静态int do_vmptrld(无效);
静态无效vmxon_出口(无效);
静态u64 do_vmread(无符号长字段);
u16主机_gdtr[5],主机_idtr[5];
#定义MY_VMX_VMXON_RAX“.字节0xf3、0x0f、0xc7、0x30”
#定义MY_VMX_VMPTRLD_RAX“。字节0x0f,0xc7,0x30”
#定义MY_VMX_VMCLEAR_RAX“.字节0x66、0x0f、0xc7、0x30”
#定义MY_VMX_VMLAUNCH“.字节0x0f,0x01,0xc2”
#定义MY_VMX_VMRESUME“.字节0x0f,0x01,0xc3”
#定义MY_VMX_VMREAD_RDX_RAX“。字节0x0f,0x78,0xd0”
#定义MY_VMX_VMWRITE_RAX_RDX“。字节0x0f,0x79,0xd0”
#定义MY_VMX_VMXOFF“.字节0x0f,0x01,0xc4”
#定义MY_VMX_VMCALL“.字节0x0f,0x01,0xc1”
#定义MY_HLT“.字节0xf4”
静态u64 do_vmread(无符号长字段)
{
u64值=0;
vmread_success=1;
asm易失性(“vmread%1,%0\n”
:“=a”(值):“d”(字段):“cc”);
asm易失性(“jbe vmread_失败\n”);
asm volatile(“jmp vmread_finish\n”);
asm易失性(“vmread_失败:\n”);
printk(#vmread(0x%lX)失败\n“,字段);
printk(“#RFLAGS:0x%lX\n”,RFLAGS_值);
vmread_success=0;
asm易失性(“vmread_finish:\n”);
返回值;
}
静态int do_vmxon(无效)
{
vmxon_成功=1;
smp_mb();
asm易失性(“vmxon%0\n”\
“jbe vmxon_失败\n”\
“jmp vmxon_完成\n”\
“vmxon_失败:\n”\
movl$0,vmxon_成功\n\
“vmxon_完成:\n”
:
:“m”(vmxon_phy_地区)
:“记忆”,“抄送”);
if(vmxon_success==0){
printk(“[i]vmxon已失败!VT-X正被其他VMM占用。\n”);
}
返回!(vmxon_成功);
}
静态int do_vmptrld(无效)
{
asm易失性(“vmptrld%0\n”
:
:“m”(vmcs_phy_地区)
:“抄送”、“记忆”);
asm易失性(“jbe vmptrld_失败\n”);
vmptrld_success=1;
asm volatile(“jmp vmptrld_完成\n”
“vmptrld_失败:\n”);
vmptrld_success=0;
pr_err(“[i]vmptrld失败!\n”);
asm挥发性(“vmptrld_完成:\n”);
return!vmptrld_成功;
}
静态int do_vmclear(void)
{
asm易失性(“vmclear%1\n”
::“a”(&vmcs\u phy\u区域),“m”(vmcs\u phy\u区域)
:“抄送”、“记忆”);
asm易失性(“jbe vmclear_fail”);
VMU成功率=1;
asm volatile(“jmp vmclear_finish\n”
“VMU清除失败:\n”);
VMU清除成功=0;
pr_err(“[i]vmclear失败!\n”);
asm挥发性(“vmclear_finish:\n”);
printk(“vmclear done!\n”);
返回!(VMU清除成功);
}
/*做vmxoff*/
静态int do_vmxo