⬢ DragonFlyBSD Kernel Audit
DF-4906 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/powermng/powernow/powernow.c
+++ b/sys/dev/powermng/powernow/powernow.c
@@ -81,10 +81,19 @@
 #define FID_TO_VCO_FID(fid)             \
         (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
 
+/* DF-4906: bounded wait -- a stuck change-pending bit must abort
+ * the transition instead of spinning forever in kernel context. */
+#define READ_PENDING_WAIT_MAX	1000000
 #define READ_PENDING_WAIT(status)                               \
         do {                                                    \
-                (status) = rdmsr(MSR_AMDK7_FIDVID_STATUS);      \
-        } while (PN8_STA_PENDING(status))
+                int pw_;                                        \
+                for (pw_ = 0; pw_ < READ_PENDING_WAIT_MAX; pw_++) { \
+                        (status) = rdmsr(MSR_AMDK7_FIDVID_STATUS); \
+                        if (!PN8_STA_PENDING(status))            \
+                                break;                          \
+                        DELAY(1);                               \
+                }                                               \
+        } while (0)
 #define abs(x) ( (x) < 0 ? -(x) : (x) )
 
 #define POWERNOW_MAX_STATES             16