On Wed, Nov 09, 2011 at 03:35:01PM +0100, Walter Haidinger wrote:
> Does the patch fix the following?
>
> I've forwarding the bug report to the Linux KVM developers.
> The response:
The patch in my first email should be enough to avoid the issue, the i386
patch was fine, only the amd64 patch was incorrect.
> On 09.11.2011 14:40, Avi Kivity wrote:
> > Actually, it looks like an OpenBSD bug. According to the AMD
> > documentation:
> >> "The current P-state value can be read using the P-State Status
> >> Register. The P-State Current Limit Register and the P-State
> >> Status Register are read-only registers. Writes to these
> >> registers cause a #GP exception. Support for hardware P-state
> >> control is indicated by EDX bit 7 as returned by CPUID function
> >> 8000_0007h. Figure 18-1 shows the format of the P-State Current
> >> Limit register."
The panic you hit is for an msr read, not a write. I'm aware those registers
are read-only.
The CPUID check isn't done, it matches on all family 10 and/or higher AMD
processors.
They're pretending to be an AMD K10 processor.
On all real hardware I've tested this works fine. If you wish to be pedantic,
patches are welcome.
> >> Can you check what cpuid 80000007 returns by running 'x86info -r
> >> | grep 80000007' in a Linux guest with the same command line? if
> >> edx returns zero, then it's OpenBSD not checking cpuid
> >> correctly.
>
> EDX is zero in a Linux guest (i386 and x86_64).
The previous patch avoids touching the msr at all if ACPI indicates speed
scaling is unavailable, this should prevent your panic.
> Walter
Both i386/amd64(..fixed) patches attached below.
-Bryan.
Index: amd64/amd64/k1x-pstate.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/k1x-pstate.c,v
retrieving revision 1.2
diff -u -p -u -r1.2 k1x-pstate.c
--- amd64/amd64/k1x-pstate.c 29 May 2011 12:29:28 -0000 1.2
+++ amd64/amd64/k1x-pstate.c 8 Nov 2011 18:30:59 -0000
@@ -75,7 +75,7 @@ struct k1x_cpu_state *k1x_current_state;
void k1x_transition(struct k1x_cpu_state *, int);
#if NACPICPU > 0
-void k1x_acpi_init(struct k1x_cpu_state *, u_int64_t);
+void k1x_acpi_init(struct k1x_cpu_state *);
void k1x_acpi_states(struct k1x_cpu_state *, struct acpicpu_pss *, int,
u_int64_t);
#endif
@@ -154,14 +154,17 @@ k1x_acpi_states(struct k1x_cpu_state *cs
}
void
-k1x_acpi_init(struct k1x_cpu_state *cstate, u_int64_t msr)
+k1x_acpi_init(struct k1x_cpu_state *cstate)
{
struct acpicpu_pss *pss;
+ u_int64_t msr;
cstate->n_states = acpicpu_fetch_pss(&pss);
if (cstate->n_states == 0)
return;
+ msr = rdmsr(MSR_K1X_STATUS);
+
k1x_acpi_states(cstate, pss, cstate->n_states, msr);
return;
@@ -172,12 +175,9 @@ k1x_acpi_init(struct k1x_cpu_state *csta
void
k1x_init(struct cpu_info *ci)
{
-#if NACPICPU > 0
- u_int64_t msr;
-#endif
- u_int i;
struct k1x_cpu_state *cstate;
struct k1x_state *state;
+ u_int i;
if (setperf_prio > 1)
return;
@@ -189,8 +189,7 @@ k1x_init(struct cpu_info *ci)
cstate->n_states = 0;
#if NACPICPU > 0
- msr = rdmsr(MSR_K1X_STATUS);
- k1x_acpi_init(cstate, msr);
+ k1x_acpi_init(cstate);
#endif
if (cstate->n_states) {
printf("%s: %d MHz: speeds:",
Index: i386/i386/k1x-pstate.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/k1x-pstate.c,v
retrieving revision 1.2
diff -u -p -u -r1.2 k1x-pstate.c
--- i386/i386/k1x-pstate.c 29 May 2011 12:29:28 -0000 1.2
+++ i386/i386/k1x-pstate.c 8 Nov 2011 18:30:59 -0000
@@ -75,7 +75,7 @@ struct k1x_cpu_state *k1x_current_state;
void k1x_transition(struct k1x_cpu_state *, int);
#if NACPICPU > 0
-void k1x_acpi_init(struct k1x_cpu_state *, u_int64_t);
+void k1x_acpi_init(struct k1x_cpu_state *);
void k1x_acpi_states(struct k1x_cpu_state *, struct acpicpu_pss *, int,
u_int64_t);
#endif
@@ -154,14 +154,17 @@ k1x_acpi_states(struct k1x_cpu_state *cs
}
void
-k1x_acpi_init(struct k1x_cpu_state *cstate, u_int64_t msr)
+k1x_acpi_init(struct k1x_cpu_state *cstate)
{
struct acpicpu_pss *pss;
+ u_int64_t msr;
cstate->n_states = acpicpu_fetch_pss(&pss);
if (cstate->n_states == 0)
return;
+ msr = rdmsr(MSR_K1X_STATUS);
+
k1x_acpi_states(cstate, pss, cstate->n_states, msr);
return;
@@ -172,12 +175,9 @@ k1x_acpi_init(struct k1x_cpu_state *csta
void
k1x_init(struct cpu_info *ci)
{
-#if NACPICPU > 0
- u_int64_t msr;
-#endif
- u_int i;
struct k1x_cpu_state *cstate;
struct k1x_state *state;
+ u_int i;
if (setperf_prio > 1)
return;
@@ -189,8 +189,7 @@ k1x_init(struct cpu_info *ci)
cstate->n_states = 0;
#if NACPICPU > 0
- msr = rdmsr(MSR_K1X_STATUS);
- k1x_acpi_init(cstate, msr);
+ k1x_acpi_init(cstate);
#endif
if (cstate->n_states) {
printf("%s: %d MHz: speeds:",