diff --git a/minix/kernel/arch/i386/arch_smp.c b/minix/kernel/arch/i386/arch_smp.c index 8998b8904..7a7458160 100644 --- a/minix/kernel/arch/i386/arch_smp.c +++ b/minix/kernel/arch/i386/arch_smp.c @@ -218,6 +218,9 @@ static void ap_finish_booting(void) /* inform the world of our presence. */ ap_cpu_ready = cpu; + /* Set up sysenter/syscall. */ + setup_sysenter_syscall(); + /* * Finish processor initialisation. CPUs must be excluded from running. * lapic timer calibration locks and unlocks the BKL because of the @@ -298,6 +301,7 @@ void smp_init (void) ioapic_enabled = 0; tss_init_all(); + setup_sysenter_syscall(); /* * we still run on the boot stack and we cannot use cpuid as its value diff --git a/minix/kernel/arch/i386/include/arch_proto.h b/minix/kernel/arch/i386/include/arch_proto.h index 3aa879096..6679cb5a5 100644 --- a/minix/kernel/arch/i386/include/arch_proto.h +++ b/minix/kernel/arch/i386/include/arch_proto.h @@ -249,6 +249,11 @@ reg_t read_ebp(void); */ int tss_init(unsigned cpu, void * kernel_stack); +/* + * Set up MSRs for sysenter or syscall for the current cpu. + * Assumes that tss_init has been called before for that cpu ! */ +void setup_sysenter_syscall(void); + void int_gate_idt(unsigned vec_nr, vir_bytes offset, unsigned dpl_type); void __copy_msg_from_user_end(void); diff --git a/minix/kernel/arch/i386/include/arch_smp.h b/minix/kernel/arch/i386/include/arch_smp.h index 3a013a982..6b79bdd5d 100644 --- a/minix/kernel/arch/i386/include/arch_smp.h +++ b/minix/kernel/arch/i386/include/arch_smp.h @@ -16,6 +16,7 @@ */ #define smp_single_cpu_fallback() do { \ tss_init(0, get_k_stack_top(0)); \ + setup_sysenter_syscall(); \ bsp_cpu_id = 0; \ ncpus = 1; \ bsp_finish_booting(); \ diff --git a/minix/kernel/arch/i386/mpx.S b/minix/kernel/arch/i386/mpx.S index fa38697e5..6fbb72855 100644 --- a/minix/kernel/arch/i386/mpx.S +++ b/minix/kernel/arch/i386/mpx.S @@ -405,6 +405,7 @@ ENTRY(restore_user_context_sysenter) /* restore PSW */ movl PSWREG(%ebp), %edi /* load desired PSW to EDI */ + andl $0xfffffdff, %edi /* Clear IF to avoid receiving int. */ push %edi popf @@ -421,6 +422,7 @@ ENTRY(restore_user_context_syscall) /* restore PSW (before we switch to user stack!) */ movl PSWREG(%ebp), %edi /* load desired PSW to EDI */ + andl $0xfffffdff, %edi /* Clear IF to avoid receiving int. */ push %edi popf @@ -429,6 +431,7 @@ ENTRY(restore_user_context_syscall) mov AXREG(%ebp), %eax /* trap return value */ mov BXREG(%ebp), %ebx /* secondary return value */ + sti sysret /* jump to EIP in user */ ENTRY(restore_user_context_int) diff --git a/minix/kernel/arch/i386/protect.c b/minix/kernel/arch/i386/protect.c index ca9a9fd98..0307915db 100644 --- a/minix/kernel/arch/i386/protect.c +++ b/minix/kernel/arch/i386/protect.c @@ -151,35 +151,10 @@ static struct gate_table_s gate_table_exceptions[] = { { NULL, 0, 0} }; -int tss_init(unsigned cpu, void * kernel_stack) +void setup_sysenter_syscall(void) { - struct tss_s * t = &tss[cpu]; - int index = TSS_INDEX(cpu); - struct segdesc_s *tssgdt; - - tssgdt = &gdt[index]; - - init_param_dataseg(tssgdt, (phys_bytes) t, - sizeof(struct tss_s), INTR_PRIVILEGE); - tssgdt->access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; - - /* Build TSS. */ - memset(t, 0, sizeof(*t)); - t->ds = t->es = t->fs = t->gs = t->ss0 = KERN_DS_SELECTOR; - t->cs = KERN_CS_SELECTOR; - t->iobase = sizeof(struct tss_s); /* empty i/o permissions map */ - - /* - * make space for process pointer and cpu id and point to the first - * usable word - */ - k_percpu_stacks[cpu] = t->sp0 = ((unsigned) kernel_stack) - X86_STACK_TOP_RESERVED; - /* - * set the cpu id at the top of the stack so we know on which cpu is - * this stack in use when we trap to kernel - */ - *((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu; - + const int cpu = cpuid; + struct tss_s const *const t = &tss[cpu]; /* Set up Intel SYSENTER support if available. */ if(minix_feature_flags & MKF_I386_INTEL_SYSENTER) { ia32_msr_write(INTEL_MSR_SYSENTER_CS, 0, KERN_CS_SELECTOR); @@ -211,7 +186,36 @@ int tss_init(unsigned cpu, void * kernel_stack) set_star_cpu(7); assert(CONFIG_MAX_CPUS <= 8); } +} +int tss_init(unsigned cpu, void * kernel_stack) +{ + struct tss_s * t = &tss[cpu]; + int index = TSS_INDEX(cpu); + struct segdesc_s *tssgdt; + + tssgdt = &gdt[index]; + + init_param_dataseg(tssgdt, (phys_bytes) t, + sizeof(struct tss_s), INTR_PRIVILEGE); + tssgdt->access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; + + /* Build TSS. */ + memset(t, 0, sizeof(*t)); + t->ds = t->es = t->fs = t->gs = t->ss0 = KERN_DS_SELECTOR; + t->cs = KERN_CS_SELECTOR; + t->iobase = sizeof(struct tss_s); /* empty i/o permissions map */ + + /* + * make space for process pointer and cpu id and point to the first + * usable word + */ + k_percpu_stacks[cpu] = t->sp0 = ((unsigned) kernel_stack) - X86_STACK_TOP_RESERVED; + /* + * set the cpu id at the top of the stack so we know on which cpu is + * this stack in use when we trap to kernel + */ + *((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu; return SEG_SELECTOR(index); } diff --git a/minix/kernel/main.c b/minix/kernel/main.c index 3198aba73..1f5f3e51f 100644 --- a/minix/kernel/main.c +++ b/minix/kernel/main.c @@ -42,6 +42,7 @@ void bsp_finish_booting(void) sprofiling = 0; /* we're not profiling until instructed to */ #endif /* SPROFILE */ + setup_sysenter_syscall(); cpu_identify(); vm_running = 0;