@@ -2245,8 +2245,8 @@ void cpu_x86_fsave(CPUX86State *s, void *host, size_t len);
void cpu_x86_frstor(CPUX86State *s, void *host, size_t len);
void cpu_x86_fxsave(CPUX86State *s, void *host, size_t len);
void cpu_x86_fxrstor(CPUX86State *s, void *host, size_t len);
-void cpu_x86_xsave(CPUX86State *s, target_ulong ptr, uint64_t rbfm);
-void cpu_x86_xrstor(CPUX86State *s, target_ulong ptr, uint64_t rbfm);
+void cpu_x86_xsave(CPUX86State *s, void *host, size_t len, uint64_t rbfm);
+bool cpu_x86_xrstor(CPUX86State *s, void *host, size_t len, uint64_t rbfm);
/* cpu.c */
void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
@@ -326,7 +326,7 @@ static void xsave_sigcontext(CPUX86State *env,
/* Zero the header, XSAVE *adds* features to an existing save state. */
memset(fxstate + 1, 0, sizeof(X86XSaveHeader));
- cpu_x86_xsave(env, xstate_addr, env->xcr0);
+ cpu_x86_xsave(env, fxstate, fpend_addr - xstate_addr, env->xcr0);
__put_user(TARGET_FP_XSTATE_MAGIC1, &sw->magic1);
__put_user(extended_size, &sw->extended_size);
@@ -611,6 +611,8 @@ static bool xrstor_sigcontext(CPUX86State *env, FPStateKind fpkind,
uint32_t magic1, magic2;
uint32_t extended_size, xstate_size, min_size, max_size;
uint64_t xfeatures;
+ void *xstate;
+ bool ok;
switch (fpkind) {
case FPSTATE_XSAVE:
@@ -641,8 +643,10 @@ static bool xrstor_sigcontext(CPUX86State *env, FPStateKind fpkind,
return false;
}
- if (!access_ok(env_cpu(env), VERIFY_READ, fxstate_addr,
- xstate_size + TARGET_FP_XSTATE_MAGIC2_SIZE)) {
+ /* Re-lock the entire xstate area, with the extensions and magic. */
+ xstate = lock_user(VERIFY_READ, fxstate_addr,
+ xstate_size + TARGET_FP_XSTATE_MAGIC2_SIZE, 1);
+ if (!xstate) {
return false;
}
@@ -652,15 +656,15 @@ static bool xrstor_sigcontext(CPUX86State *env, FPStateKind fpkind,
* fpstate layout with out copying the extended state information
* in the memory layout.
*/
- if (get_user_u32(magic2, fxstate_addr + xstate_size)) {
- return false;
- }
+ magic2 = tswap32(*(uint32_t *)(xstate + xstate_size));
if (magic2 != FP_XSTATE_MAGIC2) {
+ unlock_user(xstate, fxstate_addr, 0);
break;
}
- cpu_x86_xrstor(env, fxstate_addr, xfeatures);
- return true;
+ ok = cpu_x86_xrstor(env, xstate, xstate_size, xfeatures);
+ unlock_user(xstate, fxstate_addr, 0);
+ return ok;
default:
break;
@@ -3065,42 +3065,44 @@ void cpu_x86_fxrstor(CPUX86State *env, void *host, size_t len)
do_fxrstor(&ac, 0);
}
-void cpu_x86_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
+void cpu_x86_xsave(CPUX86State *env, void *host, size_t len, uint64_t rfbm)
{
- X86Access ac;
- unsigned size;
+ X86Access ac = {
+ .haddr1 = host,
+ .env = env,
+ };
/*
* Since this is only called from user-level signal handling,
* we should have done the job correctly there.
*/
assert((rfbm & ~env->xcr0) == 0);
- size = xsave_area_size(rfbm, false);
-
- access_prepare(&ac, env, ptr, size, MMU_DATA_STORE, 0);
- do_xsave_access(&ac, ptr, rfbm, get_xinuse(env), rfbm);
+ ac.size = xsave_area_size(rfbm, false);
+ assert(ac.size <= len);
+ do_xsave_access(&ac, 0, rfbm, get_xinuse(env), rfbm);
}
-void cpu_x86_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
+bool cpu_x86_xrstor(CPUX86State *env, void *host, size_t len, uint64_t rfbm)
{
- X86Access ac;
+ X86Access ac = {
+ .haddr1 = host,
+ .env = env,
+ };
uint64_t xstate_bv;
- unsigned size;
/*
* Since this is only called from user-level signal handling,
* we should have done the job correctly there.
*/
assert((rfbm & ~env->xcr0) == 0);
- size = xsave_area_size(rfbm, false);
- access_prepare(&ac, env, ptr, size, MMU_DATA_LOAD, 0);
+ ac.size = xsave_area_size(rfbm, false);
+ assert(ac.size <= len);
- if (!valid_xrstor_header(&ac, &xstate_bv, ptr)) {
- /* TODO: Report failure to caller. */
- xstate_bv &= env->xcr0;
+ if (!valid_xrstor_header(&ac, &xstate_bv, 0)) {
+ return false;
}
-
- do_xrstor(&ac, ptr, rfbm, xstate_bv);
+ do_xrstor(&ac, 0, rfbm, xstate_bv);
+ return true;
}
#endif