.intel_syntax noprefix .global outsw .global outb .global outw .global outl .global inb .global inw .global inl .global rep_outsw .global rep_insw .global flush_tss .global load_idtr # ebx, esi, edi, ebp, and esp; outsw: push ebp mov ebp, esp push esi mov dx, [ebp + 4+4] mov esi, [ebp + 8+4] outsw pop esi mov esp, ebp pop ebp ret outl: mov eax, [esp + 8] mov dx, [esp + 4] out dx, eax ret outb: mov al, [esp + 8] mov dx, [esp + 4] out dx, al ret outw: mov ax, [esp + 8] mov dx, [esp + 4] out dx, ax ret inl: mov dx, [esp + 4] in eax, dx ret inw: mov dx, [esp + 4] in ax, dx ret inb: mov dx, [esp + 4] in al, dx ret rep_outsw: push ebp mov ebp, esp push edi mov ecx, [ebp + 4+4] #ECX is counter for OUTSW mov edx, [ebp + 8+4] #Data port, in and out mov edi, [ebp + 12+4] #Memory area rep outsw #in to [RDI] pop edi mov esp, ebp pop ebp ret rep_insw: push ebp mov ebp, esp push edi mov ecx, [ebp + 4+4] #ECX is counter for INSW mov edx, [ebp + 8+4] #Data port, in and out mov edi, [ebp + 12+4] #Memory area rep insw #in to [RDI] pop edi mov esp, ebp pop ebp ret flush_tss: mov ax, 40 ltr ax ret load_idtr: mov edx, [esp + 4] lidt [edx] ret test_user_function: mov eax, 0x00 int 0x80 mov ecx, 0x03 mov ebx, 0x04 mov eax, 0x02 int 0x80 mov ebx, eax mov eax, 0x01 int 0x80 loop: jmp loop ret .global spin_lock .global spin_unlock .extern locked spin_lock: mov eax, 1 xchg eax, ebx test eax, eax jnz spin_lock ret spin_unlock: xor eax, eax xchg eax, ebx ret .global jump_usermode jump_usermode: mov ax, (4 * 8) | 3 # user data segment with RPL 3 mov ds, ax mov es, ax mov fs, ax mov gs, ax # sysexit sets SS # setup wrmsr inputs xor edx, edx # not necessary; set to 0 mov eax, 0x100008 # SS=0x10+0x10=0x20, CS=0x8+0x10=0x18 mov ecx, 0x174 # MSR specifier: IA32_SYSENTER_CS wrmsr # set sysexit segments # setup sysexit inputs mov edx, [esp + 4] # to be loaded into EIP mov ecx, [esp + 8] # to be loaded into ESP mov esp, ecx mov ebp, ecx sti sysexit