|  | /* Copyright (c) 2009-13 The Regents of the University of California | 
|  | * Barret Rhoden <brho@cs.berkeley.edu> | 
|  | * See LICENSE for details. | 
|  | * | 
|  | * x86 trap.h bit-specific functions.  This is included by trap.h, do not | 
|  | * include it directly.  Any function beginning with x86_ is internal to x86, | 
|  | * and not to be called by the main kernel.  Other functions are part of the | 
|  | * kernel-arch interface. */ | 
|  |  | 
|  | #ifndef ROS_KERN_ARCH_TRAP32_H | 
|  | #define ROS_KERN_ARCH_TRAP32_H | 
|  |  | 
|  | #ifndef ROS_KERN_ARCH_TRAP_H | 
|  | #error "Do not include arch/trap32.h directly." | 
|  | #endif | 
|  |  | 
|  | /* For kernel contexts, when we save/restore/move them around. */ | 
|  | struct kernel_ctx { | 
|  | struct hw_trapframe 		hw_tf; | 
|  | }; | 
|  |  | 
|  | static inline bool in_kernel(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return (hw_tf->tf_cs & ~3) == GD_KT; | 
|  | } | 
|  |  | 
|  | static inline void save_kernel_ctx(struct kernel_ctx *ctx) | 
|  | { | 
|  | /* Save the regs and the future esp. */ | 
|  | /* Careful when updating; %0, %1, and %2 are not listed as clobbers */ | 
|  | asm volatile("movl %%esp,(%0);       " /* save esp in it's slot*/ | 
|  | "pushl %%eax;           " /* temp save eax */ | 
|  | "leal 1f,%%eax;         " /* get future eip */ | 
|  | "movl %%eax,(%1);       " /* store future eip */ | 
|  | "popl %%eax;            " /* restore eax */ | 
|  | "movl %2,%%esp;         " /* move to the beginning of the tf */ | 
|  | "addl $0x20,%%esp;      " /* move to after the push_regs */ | 
|  | "pushal;                " /* save regs */ | 
|  | "addl $0x44,%%esp;      " /* move to esp slot */ | 
|  | "popl %%esp;            " /* restore esp */ | 
|  | "1:                     " /* where this tf will restart */ | 
|  | : | 
|  | : "r"(&ctx->hw_tf.tf_esp), "r"(&ctx->hw_tf.tf_eip), | 
|  | "g"(&ctx->hw_tf) | 
|  | : "eax", "memory", "cc"); | 
|  | } | 
|  |  | 
|  | static inline uintptr_t x86_get_ip_hw(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return hw_tf->tf_eip; | 
|  | } | 
|  |  | 
|  | static inline void x86_advance_ip(struct hw_trapframe *hw_tf, size_t bytes) | 
|  | { | 
|  | hw_tf->tf_eip += bytes; | 
|  | } | 
|  |  | 
|  | static inline void x86_fake_rdtscp(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | uint64_t tsc_time = read_tsc(); | 
|  | hw_tf->tf_eip += 3; | 
|  | hw_tf->tf_regs.reg_eax = tsc_time & 0xffffffff; | 
|  | hw_tf->tf_regs.reg_edx = tsc_time >> 32; | 
|  | hw_tf->tf_regs.reg_ecx = core_id(); | 
|  | } | 
|  |  | 
|  | static inline void x86_sysenter_init(uintptr_t stacktop) | 
|  | { | 
|  | write_msr(MSR_IA32_SYSENTER_CS, GD_KT); | 
|  | write_msr(MSR_IA32_SYSENTER_ESP, stacktop); | 
|  | write_msr(MSR_IA32_SYSENTER_EIP, (uintptr_t) &sysenter_handler); | 
|  | } | 
|  |  | 
|  | static inline void x86_set_sysenter_stacktop(uintptr_t stacktop) | 
|  | { | 
|  | write_msr(MSR_IA32_SYSENTER_ESP, stacktop); | 
|  | } | 
|  |  | 
|  | static inline long x86_get_sysenter_arg0(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return hw_tf->tf_regs.reg_eax; | 
|  | } | 
|  |  | 
|  | static inline long x86_get_sysenter_arg1(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return hw_tf->tf_regs.reg_esi; | 
|  | } | 
|  |  | 
|  | static inline long x86_get_systrap_arg0(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return hw_tf->tf_regs.reg_eax; | 
|  | } | 
|  |  | 
|  | static inline long x86_get_systrap_arg1(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return hw_tf->tf_regs.reg_edx; | 
|  | } | 
|  |  | 
|  | static inline uintptr_t x86_get_stacktop_tss(struct taskstate *tss) | 
|  | { | 
|  | return tss->ts_esp0; | 
|  | } | 
|  |  | 
|  | static inline void x86_set_stacktop_tss(struct taskstate *tss, uintptr_t top) | 
|  | { | 
|  | tss->ts_esp0 = top; | 
|  | tss->ts_ss0 = GD_KD; | 
|  | } | 
|  |  | 
|  | static inline uintptr_t x86_get_hwtf_pc(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return hw_tf->tf_eip; | 
|  | } | 
|  |  | 
|  | static inline uintptr_t x86_get_hwtf_fp(struct hw_trapframe *hw_tf) | 
|  | { | 
|  | return hw_tf->tf_regs.reg_ebp; | 
|  | } | 
|  |  | 
|  | #endif /* ROS_KERN_ARCH_TRAP32_H */ |