On 13/06/2011 18:02, "Andrew Cooper" <andrew.cooper3@xxxxxxxxxx> wrote:
> Introduce the boolean variable 'kexecing' which indicates to functions
> whether we are on the kexec path or not. This is used by
> disable_local_APIC() to try and revert the APIC mode back to how it
> was found on boot.
Does this need to be done only on the kexec path, rather than
unconditionally in disable_local_APIC()?
-- Keir
> We also need some fudging of the x2apic_enabled variable. It is used
> in multiple places over the codebase to mean multiple things,
> including:
> What did the user specifify on the command line?
> Did the BIOS boot me in x2apic mode?
> Is the BSP Local APIC in x2apic mode?
> What mode is my Local APIC in?
>
> Therefore, set it up to prevent a protection fault when disabling the
> IOAPICs. (In this case, it is used in the "What mode is my Local APIC
> in?" case, so the processor doesnt suffer a protection fault because
> of trying to use x2apic MSRs when it should be using xapic MMIO)
>
> Finally, make sure that interrupts are disabled when jumping into the
> purgatory code. It would be bad to service interrupts in the Xen
> context when the next kernel is booting.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
>
> diff -r 3ad737eb0a8d -r b6666fbafe33 xen/arch/x86/apic.c
> --- a/xen/arch/x86/apic.c Mon Jun 13 17:45:43 2011 +0100
> +++ b/xen/arch/x86/apic.c Mon Jun 13 17:45:43 2011 +0100
> @@ -37,6 +37,7 @@
> #include <asm/asm_defns.h> /* for BUILD_SMP_INTERRUPT */
> #include <mach_apic.h>
> #include <io_ports.h>
> +#include <xen/kexec.h>
>
> static bool_t tdt_enabled __read_mostly;
> static bool_t tdt_enable __initdata = 1;
> @@ -345,6 +346,33 @@ void disable_local_APIC(void)
> wrmsrl(MSR_IA32_APICBASE, msr_content &
> ~(MSR_IA32_APICBASE_ENABLE|MSR_IA32_APICBASE_EXTD));
> }
> +
> + if ( kexecing )
> + {
> + uint64_t msr_content;
> + rdmsrl(MSR_IA32_APICBASE, msr_content);
> + msr_content &= ~(MSR_IA32_APICBASE_ENABLE|MSR_IA32_APICBASE_EXTD);
> + wrmsrl(MSR_IA32_APICBASE, msr_content);
> +
> + switch ( apic_boot_mode )
> + {
> + case APIC_MODE_DISABLED:
> + break; /* Nothing to do - we did this above */
> + case APIC_MODE_XAPIC:
> + msr_content |= MSR_IA32_APICBASE_ENABLE;
> + wrmsrl(MSR_IA32_APICBASE, msr_content);
> + break;
> + case APIC_MODE_X2APIC:
> + msr_content |= (MSR_IA32_APICBASE_ENABLE|MSR_IA32_APICBASE_EXTD);
> + wrmsrl(MSR_IA32_APICBASE, msr_content);
> + break;
> + default:
> + printk("Default case when reverting #%d lapic to boot state\n",
> + smp_processor_id());
> + break;
> + }
> + }
> +
> }
>
> /*
> diff -r 3ad737eb0a8d -r b6666fbafe33 xen/arch/x86/crash.c
> --- a/xen/arch/x86/crash.c Mon Jun 13 17:45:43 2011 +0100
> +++ b/xen/arch/x86/crash.c Mon Jun 13 17:45:43 2011 +0100
> @@ -27,6 +27,7 @@
> #include <asm/hvm/support.h>
> #include <asm/apic.h>
> #include <asm/io_apic.h>
> +#include <xen/iommu.h>
>
> static atomic_t waiting_for_crash_ipi;
> static unsigned int crashing_cpu;
> @@ -82,6 +83,15 @@ static void nmi_shootdown_cpus(void)
> iommu_crash_shutdown();
>
> __stop_this_cpu();
> +
> + /* This is a bit of a hack due to the problems with the x2apic_enabled
> + * variable, but we can't do any better without a significant refactoring
> + * of the APIC code */
> + if ( current_local_apic_mode() == APIC_MODE_X2APIC )
> + x2apic_enabled = 1;
> + else
> + x2apic_enabled = 0;
> +
> disable_IO_APIC();
>
> local_irq_restore(flags);
> diff -r 3ad737eb0a8d -r b6666fbafe33 xen/arch/x86/machine_kexec.c
> --- a/xen/arch/x86/machine_kexec.c Mon Jun 13 17:45:43 2011 +0100
> +++ b/xen/arch/x86/machine_kexec.c Mon Jun 13 17:45:43 2011 +0100
> @@ -91,6 +91,11 @@ void machine_kexec(xen_kexec_image_t *im
> if ( hpet_broadcast_is_available() )
> hpet_disable_legacy_broadcast();
>
> + /* We are about to permenantly jump out of the Xen context into the kexec
> + * purgatory code. We really dont want to be still servicing interupts.
> + */
> + local_irq_disable();
> +
> /*
> * compat_machine_kexec() returns to idle pagetables, which requires us
> * to be running on a static GDT mapping (idle pagetables have no GDT
> diff -r 3ad737eb0a8d -r b6666fbafe33 xen/common/kexec.c
> --- a/xen/common/kexec.c Mon Jun 13 17:45:43 2011 +0100
> +++ b/xen/common/kexec.c Mon Jun 13 17:45:43 2011 +0100
> @@ -29,6 +29,8 @@
> #include <compat/kexec.h>
> #endif
>
> +bool_t kexecing = FALSE;
> +
> static DEFINE_PER_CPU_READ_MOSTLY(void *, crash_notes);
>
> static Elf_Note *xen_crash_note;
> @@ -220,6 +222,8 @@ void kexec_crash(void)
> if ( !test_bit(KEXEC_IMAGE_CRASH_BASE + pos, &kexec_flags) )
> return;
>
> + kexecing = TRUE;
> +
> kexec_common_shutdown();
> kexec_crash_save_cpu();
> machine_crash_shutdown();
> @@ -232,6 +236,8 @@ static long kexec_reboot(void *_image)
> {
> xen_kexec_image_t *image = _image;
>
> + kexecing = TRUE;
> +
> kexec_common_shutdown();
> machine_reboot_kexec(image);
>
> diff -r 3ad737eb0a8d -r b6666fbafe33 xen/include/xen/kexec.h
> --- a/xen/include/xen/kexec.h Mon Jun 13 17:45:43 2011 +0100
> +++ b/xen/include/xen/kexec.h Mon Jun 13 17:45:43 2011 +0100
> @@ -12,6 +12,8 @@ typedef struct xen_kexec_reserve {
>
> extern xen_kexec_reserve_t kexec_crash_area;
>
> +extern bool_t kexecing;
> +
> void set_kexec_crash_area_size(u64 system_ram);
>
> /* We have space for 4 images to support atomic update
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|