static void init_intel_syscall_registers(void* dummy, int cpuNum) { x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SEG); x86_write_msr(IA32_MSR_SYSENTER_ESP, 0); x86_write_msr(IA32_MSR_SYSENTER_EIP, (addr_t)x86_sysenter); gX86SetSyscallStack = &set_intel_syscall_stack; }
/** Set up the GDT for the current CPU. * @param cpu CPU to initialize for. */ static __init_text void gdt_init(cpu_t *cpu) { gdt_tss_entry_t *desc; size_t size; ptr_t base; /* Create a copy of the statically allocated GDT. */ memcpy(cpu->arch.gdt, initial_gdt, sizeof(initial_gdt)); /* Set up the TSS descriptor. */ base = (ptr_t)&cpu->arch.tss; size = sizeof(cpu->arch.tss); desc = (gdt_tss_entry_t *)&cpu->arch.gdt[KERNEL_TSS / 0x08]; desc->base0 = base & 0xffffff; desc->base1 = ((base) >> 24) & 0xff; desc->base2 = ((base) >> 32); desc->limit0 = size & 0xffff; desc->limit1 = (size >> 16) & 0xf; desc->present = 1; desc->type = 0x9; /* Set the GDT pointer. */ x86_lgdt(cpu->arch.gdt, sizeof(cpu->arch.gdt) - 1); /* Reload the segment registers. There is a 64-bit far jump instruction * but GAS doesn't like it... use LRETQ to reload CS instead. */ __asm__ volatile( "push %0\n" "push $1f\n" "lretq\n" "1:\n" "mov %1, %%ss\n" "mov %2, %%ds\n" "mov %2, %%es\n" "mov %2, %%fs\n" "mov %2, %%gs\n" :: "i"(KERNEL_CS), "r"(KERNEL_DS), "r"(0)); /* Although once the thread system is up the GS base is pointed at the * architecture thread data, we need curr_cpu to work before that. Our * CPU data has a pointer at the start which we can use, so point the * GS base at that to begin with. */ cpu->arch.parent = cpu; x86_write_msr(X86_MSR_GS_BASE, (ptr_t)&cpu->arch); x86_write_msr(X86_MSR_KERNEL_GS_BASE, 0); }
void x86_set_tls_context(Thread* thread) { // Set FS segment base address to the TLS segment. x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage); }
static void set_intel_syscall_stack(addr_t stackTop) { x86_write_msr(IA32_MSR_SYSENTER_ESP, stackTop); }