From 0735ac1f2551d9f9d356126aaf3b1110150918e6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 7 Jan 2011 14:48:57 +1100 Subject: hwrng: via_rng - Fix asm constraints The inline asm to invoke xstore did not specify the constraints correctly. In particular, dx/di should have been marked as output registers as well as input as they're modified by xstore. Thanks to Mario Holbe for creating this patch and testing it. Tested-by: Mario 'BitKoenig' Holbe Signed-off-by: Herbert Xu --- drivers/char/hw_random/via-rng.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 794aacb715c1..7f86666bb393 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c @@ -81,8 +81,7 @@ static inline u32 xstore(u32 *addr, u32 edx_in) ts_state = irq_ts_save(); asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" - :"=m"(*addr), "=a"(eax_out) - :"D"(addr), "d"(edx_in)); + : "=m" (*addr), "=a" (eax_out), "+d" (edx_in), "+D" (addr)); irq_ts_restore(ts_state); return eax_out; -- cgit v1.2.3 From 55db8387a5e8d07407f0b7c6b2526417a2bc6243 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 7 Jan 2011 14:55:06 +1100 Subject: hwrng: via_rng - Fix memory scribbling on some CPUs It has been reported that on at least one Nano CPU the xstore instruction will write as many as 16 bytes of data to the output buffer. This causes memory corruption as we use rng->priv which is only 4-8 bytes long. This patch fixes this by using an intermediate buffer on the stack with at least 16 bytes and aligned to a 16-byte boundary. The problem was observed on the following processor: processor : 0 vendor_id : CentaurHauls cpu family : 6 model : 15 model name : VIA Nano processor U2250 (1.6GHz Capable) stepping : 3 cpu MHz : 1600.000 cache size : 1024 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush acpi mmx fxsr sse sse2 ss tm syscall nx lm constant_tsc up rep_good pni monitor vmx est tm2 ssse3 cx16 xtpr rng rng_en ace ace_en ace2 phe phe_en lahf_lm bogomips : 3192.08 clflush size : 64 cache_alignment : 128 address sizes : 36 bits physical, 48 bits virtual power management: Tested-by: Mario 'BitKoenig' Holbe Signed-off-by: Herbert Xu --- drivers/char/hw_random/via-rng.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/char') diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 7f86666bb393..d0387a84eec1 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c @@ -24,6 +24,7 @@ * warranty of any kind, whether express or implied. */ +#include #include #include #include @@ -34,7 +35,6 @@ #include -#define PFX KBUILD_MODNAME ": " enum { @@ -89,8 +89,10 @@ static inline u32 xstore(u32 *addr, u32 edx_in) static int via_rng_data_present(struct hwrng *rng, int wait) { + char buf[16 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ + ((aligned(STACK_ALIGN))); + u32 *via_rng_datum = (u32 *)PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); u32 bytes_out; - u32 *via_rng_datum = (u32 *)(&rng->priv); int i; /* We choose the recommended 1-byte-per-instruction RNG rate, @@ -114,6 +116,7 @@ static int via_rng_data_present(struct hwrng *rng, int wait) break; udelay(10); } + rng->priv = *via_rng_datum; return bytes_out ? 1 : 0; } -- cgit v1.2.3