github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/kvm_amd64.S (about)

     1  // Copyright 2017 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  // kvm_gen.cc generates machine code from this file and saves it into kvm_amd64.S.h.
     5  
     6  // +build
     7  
     8  #include "kvm.h"
     9  
    10  .global kvm_asm64_enable_long, kvm_asm64_enable_long_end
    11  kvm_asm64_enable_long:
    12  .code32
    13  	mov %cr0, %eax
    14  	or $0x80000000, %eax
    15  	mov %eax, %cr0
    16  	ljmp $SEL_CS64, NEXT_INSN
    17  .code64
    18  	mov $SEL_TSS64, %rax
    19  	ltr %ax
    20  kvm_asm64_enable_long_end:
    21  	nop
    22  
    23  .global kvm_asm32_paged, kvm_asm32_paged_end
    24  kvm_asm32_paged:
    25  .code32
    26  	mov %cr0, %eax
    27  	or $0x80000000, %eax
    28  	mov %eax, %cr0
    29  kvm_asm32_paged_end:
    30  	nop
    31  
    32  .global kvm_asm32_vm86, kvm_asm32_vm86_end
    33  kvm_asm32_vm86:
    34  .code32
    35  	mov $SEL_TSS32, %ax
    36  	ltr %ax
    37  	ljmp $SEL_TSS32_VM86, $0
    38  kvm_asm32_vm86_end:
    39  	nop
    40  
    41  .global kvm_asm32_paged_vm86, kvm_asm32_paged_vm86_end
    42  kvm_asm32_paged_vm86:
    43  .code32
    44  	mov %cr0, %eax
    45  	or $0x80000000, %eax
    46  	mov %eax, %cr0
    47  	mov $SEL_TSS32, %ax
    48  	ltr %ax
    49  	ljmp $SEL_TSS32_VM86, $0
    50  kvm_asm32_paged_vm86_end:
    51  	nop
    52  
    53  .global kvm_asm16_cpl3, kvm_asm16_cpl3_end
    54  kvm_asm16_cpl3:
    55  .code16
    56  	mov %cr0, %eax
    57  	or $1, %eax
    58  	mov %eax, %cr0
    59  	mov $SEL_TSS16, %ax
    60  	ltr %ax
    61  	mov $SEL_DS16_CPL3, %ax
    62  	mov %ax, %ds
    63  	mov %ax, %es
    64  	mov %ax, %fs
    65  	mov %ax, %gs
    66  	mov $0x100, %sp
    67  	movw $PREFIX_SIZE, 0x100
    68  	movw $SEL_CS16_CPL3, 0x102
    69  	movw $0x100, 0x104
    70  	movw $SEL_DS16_CPL3, 0x106
    71  	lret
    72  kvm_asm16_cpl3_end:
    73  	nop
    74  
    75  .global kvm_asm64_cpl3, kvm_asm64_cpl3_end
    76  kvm_asm64_cpl3:
    77  .code32
    78  	mov %cr0, %eax
    79  	or $0x80000000, %eax
    80  	mov %eax, %cr0
    81  	ljmp $SEL_CS64, NEXT_INSN
    82  .code64
    83  	mov $SEL_TSS64, %rax
    84  	ltr %ax
    85  	mov $SEL_DS64_CPL3, %rax
    86  	mov %ax, %ds
    87  	mov %ax, %es
    88  	mov %ax, %fs
    89  	mov %ax, %gs
    90  	mov $ADDR_STACK0, %rsp
    91  	movq $PREFIX_SIZE, 0(%rsp)
    92  	movq $SEL_CS64_CPL3, 4(%rsp)
    93  	movq $ADDR_STACK0, 8(%rsp)
    94  	movq $SEL_DS64_CPL3, 12(%rsp)
    95  	lretl
    96  kvm_asm64_cpl3_end:
    97  	nop
    98  
    99  .global kvm_asm64_init_vm, kvm_asm64_init_vm_end
   100  kvm_asm64_init_vm:
   101  .code32
   102  	// CR0.PG = 1
   103  	mov %cr0, %eax
   104  	or $0x80000000, %eax
   105  	mov %eax, %cr0
   106  	ljmp $SEL_CS64, NEXT_INSN
   107  .code64
   108  	mov $SEL_TSS64, %rax
   109  	ltr %ax
   110  
   111  	// Enable and lock non-SMM VM
   112  	mov $MSR_IA32_FEATURE_CONTROL, %rcx
   113  	rdmsr
   114  	or $0x5, %rax
   115  	wrmsr
   116  
   117  	// CR4.VMXE = 1
   118  	mov %cr4, %rax
   119  	or $0x2000, %rax
   120  	mov %rax, %cr4
   121  
   122  	// Write VMCS revision into VMXON and VMCS regions
   123  	mov $MSR_IA32_VMX_BASIC, %rcx
   124  	rdmsr
   125  	mov $ADDR_VAR_VMXON, %rdx
   126  	mov %eax, (%rdx)
   127  	mov $ADDR_VAR_VMCS, %rdx
   128  	mov %eax, (%rdx)
   129  
   130  	mov $ADDR_VAR_VMXON_PTR, %rax
   131  	vmxon (%rax)
   132  	mov $ADDR_VAR_VMCS_PTR, %rax
   133  	vmclear (%rax)
   134  	vmptrld (%rax)
   135  
   136  #define VMSET(FIELD, VAL)	\
   137  	mov $FIELD, %rdx;	\
   138  	mov VAL, %rax;		\
   139  	vmwrite %rax, %rdx;	\
   140  	/**/
   141  
   142  #define VMSET_LIMITED(FIELD, VAL, MSR)	\
   143  	mov $MSR, %rcx;		\
   144  	rdmsr;			\
   145  	or VAL, %rax;		\
   146  	and %rdx, %rax;		\
   147  	mov $FIELD, %rdx;	\
   148  	vmwrite %rax, %rdx;	\
   149  	/**/
   150  
   151  	VMSET_LIMITED(0x00004000, $0, 0x481) // Pin-based VM-execution controls
   152  	VMSET_LIMITED(0x00004002, $0, 0x482) // Primary processor-based VM-execution controls
   153  
   154  	VMSET(0x0000401E, $((1<<0) | (1<<7))) // Secondary processor-based VM-execution controls
   155  	VMSET_LIMITED(0x0000400C, $0x36fff, 0x483) // VM-exit controls (F6FFF)
   156  	VMSET_LIMITED(0x00004012, $0x17ff, 0x484) // VM-entry controls (51FF)
   157  
   158  	VMSET(0x00002C04, $0) // Host IA32_PERF_GLOBAL_CTR
   159  	VMSET(0x00002800, $0xffffffffffffffff) // VMCS link pointer
   160  
   161  	VMSET(0x00000C02, $SEL_CS64) // host CS
   162  
   163  	mov $SEL_DS64, %rax
   164  	mov $0x00000C00, %rdx // host ES
   165  	vmwrite %rax, %rdx
   166  	mov $0x00000C04, %rdx // host SS
   167  	vmwrite %rax, %rdx
   168  	mov $0x00000C06, %rdx // host DS
   169  	vmwrite %rax, %rdx
   170  	mov $0x00000C08, %rdx // host FS
   171  	vmwrite %rax, %rdx
   172  	mov $0x00000C0A, %rdx // host GS
   173  	vmwrite %rax, %rdx
   174  	mov $SEL_TSS64, %rax
   175  	mov $0x00000C0C, %rdx // host TR
   176  	vmwrite %rax, %rdx
   177  
   178  	VMSET(0x00002C02, $0x500) // host EFER
   179  
   180  	VMSET(0x00004C00, $SEL_CS64) // Host IA32_SYSENTER_CS
   181  	VMSET(0x00006C10, $0) // Host IA32_SYSENTER_ESP
   182  	VMSET(0x00006C12, $0) // Host IA32_SYSENTER_EIP
   183  
   184  	mov %cr0, %rax
   185  	VMSET(0x00006C00, %rax) // host CR0
   186  	mov %cr3, %rax
   187  	VMSET(0x00006C02, %rax) // host CR3
   188  	mov %cr4, %rax
   189  	VMSET(0x00006C04, %rax) // host CR4
   190  
   191  	VMSET(0x00006C06, $0) // host FS base
   192  	VMSET(0x00006C08, $0) // host GS base
   193  	VMSET(0x00006C0A, $ADDR_VAR_TSS64) // host TR base
   194  
   195  	VMSET(0x00006C0C, $ADDR_GDT) // host GDTR base
   196  	VMSET(0x00006C0E, $ADDR_VAR_IDT) // host IDTR base
   197  
   198  	VMSET(0x00006C14, $0) // host RSP
   199  	VMSET(0x00006C16, ADDR_VAR_VMEXIT_PTR) // host RIP
   200  
   201  	VMSET(0x00000000, $1) // VPID
   202  	VMSET(0x00000002, $0) // Posted-interrupt notification vector
   203  	//VMSET(0x00000004, $0) // EPTP index
   204  
   205  	VMSET(0x00002000, $0) // Address of I/O bitmap A
   206  	VMSET(0x00002002, $0) // Address of I/O bitmap B
   207  	VMSET(0x00002004, $0) // Address of MSR bitmaps
   208  	VMSET(0x00002006, $0) // VM-exit MSR-store address
   209  
   210  	mov $0x277, %rcx
   211  	rdmsr
   212  	shl $32, %rdx
   213  	or %rdx, %rax
   214  	VMSET(0x00002C00, %rax) // Host IA32_PAT
   215  
   216  	VMSET(0x00004004, $0) // Exception bitmap
   217  	VMSET(0x0000400A, $0) // CR3-target count
   218  	VMSET(0x0000400E, $0) // VM-exit MSR-store count
   219  	VMSET(0x00004010, $0) // VM-exit MSR-load count
   220  	VMSET(0x00004016, $0) // VM-entry interruption-information field
   221  	VMSET(0x00004014, $0) // VM-entry MSR-load count
   222  
   223  	VMSET(0x00006000, $0xffffffffffffffff) // CR0 guest/host mask
   224  	VMSET(0x00006002, $0xffffffffffffffff) // CR4 guest/host mask
   225  
   226  	VMSET(0x0000201C, $0) // EOI-exit bitmap 0
   227  	VMSET(0x0000201E, $0) // EOI-exit bitmap 1
   228  	VMSET(0x00002020, $0) // EOI-exit bitmap 2
   229  	VMSET(0x00002022, $0) // EOI-exit bitmap 3
   230  
   231  	VMSET(0x00000800, $SEL_DS64) // Guest ES selector
   232  	VMSET(0x00000802, $SEL_CS64) // Guest CS selector
   233  	VMSET(0x00000804, $SEL_DS64) // Guest SS selector
   234  	VMSET(0x00000806, $SEL_DS64) // Guest DS selector
   235  	VMSET(0x00000808, $SEL_DS64) // Guest FS selector
   236  	VMSET(0x0000080A, $SEL_DS64) // Guest GS selector
   237  	VMSET(0x0000080C, $0) // Guest LDTR selector
   238  	VMSET(0x0000080E, $SEL_TSS64) // Guest TR selector
   239  
   240  	VMSET(0x00006812, $0) // Guest LDTR base
   241  	VMSET(0x00006814, $ADDR_VAR_TSS64) // Guest TR base
   242  	VMSET(0x00006816, $ADDR_GDT) // Guest GDTR base
   243  	VMSET(0x00006818, $ADDR_VAR_IDT) // Guest IDTR base
   244  
   245  	VMSET(0x00004800, $0xfffff) // Guest ES limit
   246  	VMSET(0x00004802, $0xfffff) // Guest CS limit
   247  	VMSET(0x00004804, $0xfffff) // Guest SS limit
   248  	VMSET(0x00004806, $0xfffff) // Guest DS limit
   249  	VMSET(0x00004808, $0xfffff) // Guest FS limit
   250  	VMSET(0x0000480A, $0xfffff) // Guest GS limit
   251  	VMSET(0x0000480C, $0) // Guest LDTR limit
   252  	VMSET(0x0000480E, $0x1fff) // Guest TR limit
   253  	VMSET(0x00004810, $0x1fff) // Guest GDTR limit
   254  	VMSET(0x00004812, $0x1fff) // Guest IDTR limit
   255  
   256  	VMSET(0x00004814, $0x4093) // Guest ES access rights
   257  	VMSET(0x00004816, $0x209b) // Guest CS access rights
   258  	VMSET(0x00004818, $0x4093) // Guest SS access rights
   259  	VMSET(0x0000481A, $0x4093) // Guest DS access rights
   260  	VMSET(0x0000481C, $0x4093) // Guest FS access rights
   261  	VMSET(0x0000481E, $0x4093) // Guest GS access rights
   262  	VMSET(0x00004820, $0x82) // Guest LDTR access rights
   263  	VMSET(0x00004822, $0x8b) // Guest TR access rights
   264  
   265  	VMSET(0x0000681C, $0) // Guest RSP
   266  	VMSET(0x0000681E, $ADDR_VAR_USER_CODE) // Guest RIP
   267  	VMSET(0x00006820, $((1<<1))) // Guest RFLAGS
   268  	VMSET(0x00002806, $0x500) // Guest IA32_EFER
   269  	VMSET(0x0000280A, $0) // Guest PDPTE0
   270  	VMSET(0x0000280C, $0) // Guest PDPTE1
   271  	VMSET(0x0000280E, $0) // Guest PDPTE2
   272  	VMSET(0x00002810, $0) // Guest PDPTE3
   273  
   274  	mov %cr0, %rax
   275  	VMSET(0x00006800, %rax) // Guest CR0
   276  	mov %cr3, %rax
   277  	VMSET(0x00006802, %rax) // Guest CR3
   278  	mov %cr4, %rax
   279  	VMSET(0x00006804, %rax) // Guest CR4
   280  
   281  	// Write 1 additional random field.
   282  	mov $ADDR_VAR_VMWRITE_FLD, %rax
   283  	mov (%rax), %rdx
   284  	mov $ADDR_VAR_VMWRITE_VAL, %rax
   285  	mov (%rax), %rcx
   286  	xor %rax, %rax
   287  	vmread %rdx, %rax
   288  	xor %rcx, %rax
   289  	vmwrite %rax, %rdx
   290  
   291  	vmlaunch
   292  
   293  	mov $0x00004400, %rdx
   294  	vmread %rdx, %rax
   295  	hlt
   296  kvm_asm64_init_vm_end:
   297  	nop
   298  
   299  .global kvm_asm64_vm_exit, kvm_asm64_vm_exit_end
   300  kvm_asm64_vm_exit:
   301  .code64
   302  	//vmresume
   303  	mov $0x00004400, %rbx // VM-instruction error
   304  	vmread %rbx, %rdx
   305  	mov $0x00004402, %rbx // Exit reason
   306  	vmread %rbx, %rcx
   307  	mov $0x00006400, %rax // Exit qualification
   308  	vmread %rax, %rax
   309  	mov $0x0000681E, %rbx // Guest RIP
   310  	vmread %rbx, %rbx
   311  	hlt
   312  kvm_asm64_vm_exit_end:
   313  	nop