schedule(): use XSAVE/XRSTOR and swap floating point registers in context switch

This commit is contained in:
Balazs Gerofi
2015-08-07 08:41:00 +09:00
parent d5c243571f
commit aa191b87d3
3 changed files with 61 additions and 14 deletions

View File

@@ -143,6 +143,8 @@ static void init_idt(void)
reload_idt();
}
static int xsave_available = 0;
void init_fpu(void)
{
unsigned long reg;
@@ -170,20 +172,24 @@ void init_fpu(void)
reg |= ((1 << 9) | (1 << 10));
if(cpuid01_ecx & (1 << 26)) {
/* XSAVE set, enable access to xcr0 */
dkprintf("init_fpu(): XSAVE available\n");
xsave_available = 1;
reg |= (1 << 18);
}
asm volatile("movq %0, %%cr4" : : "r"(reg));
kprintf("init_fpu(): SSE init: CR4 = 0x%016lX; ", reg);
dkprintf("init_fpu(): SSE init: CR4 = 0x%016lX\n", reg);
/* Set xcr0[2:1] to enable avx ops */
if(cpuid01_ecx & (1 << 28)) {
reg = xgetbv(0);
reg |= 0x6;
xsetbv(0, reg);
dkprintf("init_fpu(): AVX init: XCR0 = 0x%016lX\n", reg);
}
kprintf("XCR0 = 0x%016lX\n", reg);
/* TODO: set MSR_IA32_XSS to enable xsaves/xrstors */
#else
kprintf("init_fpu(): SSE not enabled\n");
#endif
@@ -1186,10 +1192,11 @@ release_fp_regs(struct process *proc)
{
int pages;
if (!proc->fp_regs)
if (proc && !proc->fp_regs)
return;
pages = (sizeof(fp_regs_struct) + 4095) >> 12;
ihk_mc_free_pages(proc->fp_regs, 1);
ihk_mc_free_pages(proc->fp_regs, pages);
proc->fp_regs = NULL;
}
@@ -1198,14 +1205,30 @@ save_fp_regs(struct process *proc)
{
int pages;
if (proc->fp_regs)
return;
pages = (sizeof(fp_regs_struct) + 4095) >> 12;
proc->fp_regs = ihk_mc_alloc_pages(pages, IHK_MC_AP_NOWAIT);
if(!proc->fp_regs)
return;
memset(proc->fp_regs, 0, sizeof(fp_regs_struct));
// TODO: do xsave
if (!proc->fp_regs) {
pages = (sizeof(fp_regs_struct) + 4095) >> 12;
proc->fp_regs = ihk_mc_alloc_pages(pages, IHK_MC_AP_NOWAIT);
if (!proc->fp_regs) {
kprintf("error: allocating fp_regs pages\n");
return;
}
memset(proc->fp_regs, 0, sizeof(fp_regs_struct));
}
if (xsave_available) {
unsigned int low, high;
/* Request full save of x87, SSE and AVX states */
low = 0x7;
high = 0;
asm volatile("xsave %0" : : "m" (*proc->fp_regs), "a" (low), "d" (high)
: "memory");
dkprintf("fp_regs for TID %d saved\n", proc->ftn->tid);
}
}
void
@@ -1213,8 +1236,22 @@ restore_fp_regs(struct process *proc)
{
if (!proc->fp_regs)
return;
// TODO: do xrstor
release_fp_regs(proc);
if (xsave_available) {
unsigned int low, high;
/* Request full restore of x87, SSE and AVX states */
low = 0x7;
high = 0;
asm volatile("xrstor %0" : : "m" (*proc->fp_regs),
"a" (low), "d" (high));
dkprintf("fp_regs for TID %d restored\n", proc->ftn->tid);
}
// XXX: why release??
//release_fp_regs(proc);
}
ihk_mc_user_context_t *lookup_user_context(struct process *proc)

View File

@@ -58,6 +58,7 @@
#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
#define MSR_NHM_TURBO_RATIO_LIMIT 0x000001ad
#define MSR_IA32_CR_PAT 0x00000277
#define MSR_IA32_XSS 0xda0
#define CVAL(event, mask) \

View File

@@ -2304,6 +2304,15 @@ redo:
restore_debugreg(next->ptrace_debugreg);
}
/* Take care of floating point registers except for idle process */
if (prev && prev != &cpu_local_var(idle)) {
save_fp_regs(prev);
}
if (next != &cpu_local_var(idle)) {
restore_fp_regs(next);
}
ihk_mc_load_page_table(next->vm->page_table);
dkprintf("[%d] schedule: tlsblock_base: 0x%lX\n",