Re: [kvm-unit-tests PATCH] Enhance test of disabled APIC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/05/2018 20:05, Jim Mattson wrote:
> The test now checks to see that the memory "behind" the APIC has
> either bus error semantics (writes ignored, reads return all 1s) or
> memory semantics, and that this memory is exposed when the APIC is
> either disabled or in x2APIC mode. The test also checks to see that
> scribbling on the memory "behind" the APIC has no effect on CR8 when
> MMIO access to the APIC is disabled.
> 
> Signed-off-by: Jim Mattson <jmattson@xxxxxxxxxx>
> ---
>  lib/x86/apic.c | 12 ++++++++----
>  lib/x86/apic.h |  1 +
>  x86/apic.c     | 49 ++++++++++++++++++++++++++++++++++++++++++-------
>  3 files changed, 51 insertions(+), 11 deletions(-)
> 
> diff --git a/lib/x86/apic.c b/lib/x86/apic.c
> index a65247357371..2aeffbd99166 100644
> --- a/lib/x86/apic.c
> +++ b/lib/x86/apic.c
> @@ -151,12 +151,16 @@ int enable_x2apic(void)
>      }
>  }
>  
> -void reset_apic(void)
> +void disable_apic(void)
>  {
> -    u64 disabled = rdmsr(MSR_IA32_APICBASE) & ~(APIC_EN | APIC_EXTD);
> -    wrmsr(MSR_IA32_APICBASE, disabled);
> +    wrmsr(MSR_IA32_APICBASE, rdmsr(MSR_IA32_APICBASE) & ~(APIC_EN | APIC_EXTD));
>      apic_ops = &xapic_ops;
> -    wrmsr(MSR_IA32_APICBASE, disabled | APIC_EN);
> +}
> +
> +void reset_apic(void)
> +{
> +    disable_apic();
> +    wrmsr(MSR_IA32_APICBASE, rdmsr(MSR_IA32_APICBASE) | APIC_EN);
>  }
>  
>  u32 ioapic_read_reg(unsigned reg)
> diff --git a/lib/x86/apic.h b/lib/x86/apic.h
> index d5d4025f8f8a..be8e96ca3600 100644
> --- a/lib/x86/apic.h
> +++ b/lib/x86/apic.h
> @@ -53,6 +53,7 @@ void apic_icr_write(uint32_t val, uint32_t dest);
>  uint32_t apic_id(void);
>  
>  int enable_x2apic(void);
> +void disable_apic(void);
>  void reset_apic(void);
>  
>  #endif
> diff --git a/x86/apic.c b/x86/apic.c
> index 6cfb52d25ad5..630fe8654e5e 100644
> --- a/x86/apic.c
> +++ b/x86/apic.c
> @@ -7,6 +7,8 @@
>  #include "msr.h"
>  #include "atomic.h"
>  
> +#define MAX_TPR			0xf
> +
>  static void test_lapic_existence(void)
>  {
>      u32 lvr;
> @@ -106,25 +108,58 @@ void test_enable_x2apic(void)
>      }
>  }
>  
> +static void verify_disabled_apic_mmio(void)
> +{
> +    volatile u32 *lvr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_LVR);
> +    volatile u32 *tpr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_TASKPRI);
> +    u32 cr8 = read_cr8();
> +
> +    memset((void *)APIC_DEFAULT_PHYS_BASE, 0xff, PAGE_SIZE);
> +    report("*0xfee00030: %x", *lvr == ~0, *lvr);
> +    report("CR8: %lx", read_cr8() == cr8, read_cr8());
> +    write_cr8(cr8 ^ MAX_TPR);
> +    report("CR8: %lx", read_cr8() == (cr8 ^ MAX_TPR), read_cr8());
> +    report("*0xfee00080: %x", *tpr == ~0, *tpr);
> +    write_cr8(cr8);
> +}
> +
>  static void test_apic_disable(void)
>  {
> +    volatile u32 *lvr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_LVR);
> +    volatile u32 *tpr = (volatile u32 *)(APIC_DEFAULT_PHYS_BASE + APIC_TASKPRI);
>      u64 orig_apicbase = rdmsr(MSR_IA32_APICBASE);
> +    u32 apic_version = apic_read(APIC_LVR);
> +    u32 cr8 = read_cr8();
>  
>      report_prefix_push("apic_disable");
> +    assert_msg(orig_apicbase & APIC_EN, "APIC not enabled.");
>  
> -    report("Local apic enabled", orig_apicbase & APIC_EN);
> -    report("CPUID.1H:EDX.APIC[bit 9] is set", cpuid(1).d & (1 << 9));
> -
> -    wrmsr(MSR_IA32_APICBASE, orig_apicbase & ~(APIC_EN | APIC_EXTD));
> +    disable_apic();
>      report("Local apic disabled", !(rdmsr(MSR_IA32_APICBASE) & APIC_EN));
>      report("CPUID.1H:EDX.APIC[bit 9] is clear", !(cpuid(1).d & (1 << 9)));
> +    verify_disabled_apic_mmio();
>  
> -    wrmsr(MSR_IA32_APICBASE, orig_apicbase & ~APIC_EXTD);
> -    wrmsr(MSR_IA32_APICBASE, orig_apicbase);
> +    reset_apic();
>      apic_write(APIC_SPIV, 0x1ff);
> -    report("Local apic enabled", rdmsr(MSR_IA32_APICBASE) & APIC_EN);
> +    report("Local apic enabled in xAPIC mode",
> +	   (rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) == APIC_EN);
>      report("CPUID.1H:EDX.APIC[bit 9] is set", cpuid(1).d & (1 << 9));
> +    report("*0xfee00030: %x", *lvr == apic_version, *lvr);
> +    report("*0xfee00080: %x", *tpr == cr8, *tpr);
> +    write_cr8(cr8 ^ MAX_TPR);
> +    report("*0xfee00080: %x", *tpr == (cr8 ^ MAX_TPR) << 4, *tpr);
> +    write_cr8(cr8);
>  
> +    if (enable_x2apic()) {
> +	apic_write(APIC_SPIV, 0x1ff);
> +	report("Local apic enabled in x2APIC mode",
> +	   (rdmsr(MSR_IA32_APICBASE) & (APIC_EN | APIC_EXTD)) ==
> +	   (APIC_EN | APIC_EXTD));
> +	report("CPUID.1H:EDX.APIC[bit 9] is set", cpuid(1).d & (1 << 9));
> +	verify_disabled_apic_mmio();
> +	if (!(orig_apicbase & APIC_EXTD))
> +	    reset_apic();
> +    }
>      report_prefix_pop();
>  }
>  
> 

Applied, thanks!

Paolo



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux