From 03d71535eca82570372650678eb91e447eacfb86 Mon Sep 17 00:00:00 2001 From: aiju Date: Tue, 19 Jul 2011 15:42:00 +0200 Subject: [PATCH] reading from/writing to non-existant MSRs via /dev/msr no longer crashes the system --- sys/src/9/pc/devarch.c | 6 ++++-- sys/src/9/pc/fns.h | 4 ++++ sys/src/9/pc/l.s | 21 +++++++++++++++++++++ sys/src/9/pc/trap.c | 8 +++++++- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index 3228736ee..46c98b19c 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -397,7 +397,8 @@ archread(Chan *c, void *a, long n, vlong offset) error(Ebadarg); vp = a; for(port = offset; port < offset+n; port += 8) - rdmsr(port, vp++); + if(tryrdmsr(port, vp++) < 0) + error(Ebadarg); return n; case Qioalloc: @@ -475,7 +476,8 @@ archwrite(Chan *c, void *a, long n, vlong offset) error(Ebadarg); vp = a; for(port = offset; port < offset+n; port += 8) - wrmsr(port, *vp++); + if(trywrmsr(port, *vp++) < 0) + error(Ebadarg); return n; default: diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index c612a2c59..123abca5c 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -167,6 +167,10 @@ void trapenable(int, void (*)(Ureg*, void*), void*, char*); void trapinit(void); void trapinit0(void); int tas(void*); +int tryrdmsr(int, vlong*); +void tryrdmsrbody(void); +int trywrmsr(int, vlong); +void trywrmsrbody(void); uvlong tscticks(uvlong*); ulong umbmalloc(ulong, int, int); void umbfree(ulong, int); diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 3cc9170dc..6618421a2 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -691,6 +691,17 @@ TEXT rdmsr(SB), $0 /* model-specific register */ MOVL AX, 0(CX) /* lo */ MOVL DX, 4(CX) /* hi */ RET + +TEXT tryrdmsr(SB), $0 /* model-specific register */ + MOVL $0, BP + MOVL index+0(FP), CX +TEXT tryrdmsrbody(SB), $0 + RDMSR + MOVL vlong+4(FP), CX /* &vlong */ + MOVL AX, 0(CX) /* lo */ + MOVL DX, 4(CX) /* hi */ + MOVL BP, AX + RET TEXT wrmsr(SB), $0 MOVL index+0(FP), CX @@ -699,6 +710,16 @@ TEXT wrmsr(SB), $0 WRMSR RET +TEXT trywrmsr(SB), $0 + MOVL $0, BP + MOVL index+0(FP), CX + MOVL lo+4(FP), AX + MOVL hi+8(FP), DX +TEXT trywrmsrbody(SB), $0 + WRMSR + MOVL BP, AX + RET + /* * Try to determine the CPU type which requires fiddling with EFLAGS. * If the Id bit can be toggled then the CPUID instruction can be used diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index 661aa06e8..ba52895ea 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -463,7 +463,13 @@ trap(Ureg* ureg) return; } } - + if(vno == VectorGPF && !user && + (ureg->pc == (ulong)(void*)tryrdmsrbody || + ureg->pc == (ulong)(void*)trywrmsrbody)){ + ureg->bp = -1; + ureg->pc += 2; + return; + } dumpregs(ureg); if(!user){ ureg->sp = (ulong)&ureg->sp;