/* fpu_image includes 512 bytes of image itself and
* additional 15 bytes required for manual 16-byte alignment. */
char fpu_image[527];
+ u32_t checksum;
};
#define INMEMORY(p) (!p->p_seg.p_cr3 || get_cpulocal_var(ptproc) == p)
.endif
DPADD+= ${LIBTIMERS} ${LIBSYS} ${LIBEXEC}
-LDADD+= -ltimers -lsys -lexec
+LDADD+= -ltimers -lsys -lexec -lz
CFLAGS += -D__kernel__
FORWARD _PROTOTYPE( void ser_init, (void));
#endif
+PRIVATE u32_t fpusum(struct proc *p)
+{
+ void *save_area = p->p_fpu_state.fpu_save_area_p;
+ return crc32(0, save_area, FPU_XFP_SIZE);
+}
+
+PUBLIC void fpu_makechecksum(struct proc *p)
+{
+ p->p_fpu_state.checksum = fpusum(p);
+}
+
+PUBLIC void fpu_verifychecksum(struct proc *p)
+{
+ static int n;
+ n++;
+ if(p->p_fpu_state.checksum != fpusum(p)) {
+ printf("%d / %s fpu state broken!", p->p_endpoint, p->p_name);
+ util_stacktrace();
+ }
+}
+
PUBLIC __dead void arch_monitor(void)
{
monitor();
PUBLIC void save_local_fpu(struct proc *pr)
{
+ static int n;
+ phys_bytes save_area = (phys_bytes) pr->p_fpu_state.fpu_save_area_p;
if(!is_fpu())
return;
+ /* save area must be 16-byte aligned */
+ assert(!(save_area % FPUALIGN));
+
/* Save changed FPU context. */
if(osfxsr_feature) {
- fxsave(pr->p_fpu_state.fpu_save_area_p);
+ fxsave(save_area);
fninit();
} else {
- fnsave(pr->p_fpu_state.fpu_save_area_p);
+ fnsave(save_area);
}
+
+ fpu_makechecksum(pr);
}
PUBLIC void save_fpu(struct proc *pr)
fninit();
pr->p_misc_flags |= MF_FPU_INITIALIZED;
} else {
+ phys_bytes save_area = (phys_bytes) pr->p_fpu_state.fpu_save_area_p;
+ /* save area must be 16-byte aligned */
+ assert(!(save_area % FPUALIGN));
+ fpu_verifychecksum(pr);
if(osfxsr_feature) {
- fxrstor(pr->p_fpu_state.fpu_save_area_p);
+ fxrstor(save_area);
} else {
- frstor(pr->p_fpu_state.fpu_save_area_p);
+ frstor(save_area);
}
}
}
_PROTOTYPE( void ia32_msr_write, (u32_t reg, u32_t hi, u32_t lo) );
_PROTOTYPE( void fninit, (void));
_PROTOTYPE( void clts, (void));
-_PROTOTYPE( void fxsave, (void *));
-_PROTOTYPE( void fnsave, (void *));
-_PROTOTYPE( void fxrstor, (void *));
-_PROTOTYPE( void frstor, (void *));
+_PROTOTYPE( void fxsave, (vir_bytes));
+_PROTOTYPE( void fnsave, (vir_bytes));
+_PROTOTYPE( void fxrstor, (vir_bytes));
+_PROTOTYPE( void frstor, (vir_bytes));
_PROTOTYPE( unsigned short fnstsw, (void));
_PROTOTYPE( void fnstcw, (unsigned short* cw));
SSREG = SPREG+W
P_STACKTOP = SSREG+W
FP_SAVE_AREA_P = P_STACKTOP
- P_LDT_SEL = FP_SAVE_AREA_P + 532
+ P_LDT_SEL = FP_SAVE_AREA_P + 536
P_CR3 = P_LDT_SEL+W
P_CR3_V = P_CR3+4
P_LDT = P_CR3_V+W
*/
#define DEBUG_RACE 0
+#define DEBUG_FPUCHECK 1
+
/* DEBUG_DUMPIPC dumps all IPC to serial; due to the amount of logging it is
* strongly recommended to set "ctty 0" in the boot monitor and run inside a
* virtual machine if you enable this; on the hardware it would take forever
int tlb_must_refresh = 0;
#endif
+ char buf[100];
+ u32_t c;
+ c = crc32(0, buf, 100);
+
p = get_cpulocal_var(proc_ptr);
/*
* if the current process is still runnable check the misc flags and let
_PROTOTYPE(void switch_address_space, (struct proc * p));
_PROTOTYPE(void release_address_space, (struct proc *pr));
+_PROTOTYPE(void fpu_makechecksum, (struct proc *p));
+_PROTOTYPE(void fpu_verifychecksum, (struct proc *p));
+
_PROTOTYPE(void enable_fpu_exception, (void));
_PROTOTYPE(void disable_fpu_exception, (void));
_PROTOTYPE(void release_fpu, (struct proc * p));
#if (_MINIX_CHIP == _CHIP_INTEL)
rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */
rpc->p_fpu_state.fpu_save_area_p = old_fpu_save_area_p;
- if(proc_used_fpu(rpp))
+ if(proc_used_fpu(rpp)) {
+ fpu_verifychecksum(rpp);
memcpy(rpc->p_fpu_state.fpu_save_area_p,
rpp->p_fpu_state.fpu_save_area_p,
FPU_XFP_SIZE);
+ fpu_verifychecksum(rpc);
+ }
#endif
if(++gen >= _ENDPOINT_MAX_GENERATION) /* increase generation */
gen = 1; /* generation number wraparound */
rp->p_misc_flags |= MF_FPU_INITIALIZED;
memcpy(rp->p_fpu_state.fpu_save_area_p, &(mc.mc_fpu_state),
FPU_XFP_SIZE);
+ fpu_makechecksum(rp);
} else
rp->p_misc_flags &= ~MF_FPU_INITIALIZED;
/* force reloading FPU in either case */
#if (_MINIX_CHIP == _CHIP_INTEL)
if(sc.sc_flags & MF_FPU_INITIALIZED)
{
+ fpu_verifychecksum(rp);
memcpy(rp->p_fpu_state.fpu_save_area_p, &sc.sc_fpu_state,
FPU_XFP_SIZE);
+ fpu_makechecksum(rp);
rp->p_misc_flags |= MF_FPU_INITIALIZED; /* Restore math usage flag. */
/* force reloading FPU */
release_fpu(rp);