blob: e56ed115e334253d13f0bc7c138453401b7affbe [file] [log] [blame]
/* 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 */