summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMukesh Rathor <mukesh.rathor@oracle.com>2013-12-13 19:03:37 +0100
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2014-01-06 16:44:10 +0100
commit8d656bbe43aee6d1be6b49fcf8acbc04588472bc (patch)
treefd4e39fe2758a0c6b9542c84152c3041bed1df0e /arch
parentxen/pvh: Setup up shared_info. (diff)
downloadlinux-8d656bbe43aee6d1be6b49fcf8acbc04588472bc.tar.xz
linux-8d656bbe43aee6d1be6b49fcf8acbc04588472bc.zip
xen/pvh: Load GDT/GS in early PV bootup code for BSP.
During early bootup we start life using the Xen provided GDT, which means that we are running with %cs segment set to FLAT_KERNEL_CS (FLAT_RING3_CS64 0xe033, GDT index 261). But for PVH we want to be use HVM type mechanism for segment operations. As such we need to switch to the HVM one and also reload ourselves with the __KERNEL_CS:eip to run in the proper GDT and segment. For HVM this is usually done in 'secondary_startup_64' in (head_64.S) but since we are not taking that bootup path (we start in PV - xen_start_kernel) we need to do that in the early PV bootup paths. For good measure we also zero out the %fs, %ds, and %es (not strictly needed as Xen has already cleared them for us). The %gs is loaded by 'switch_to_new_gdt'. Signed-off-by: Mukesh Rathor <mukesh.rathor@oracle.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Reviewed-by: David Vrabel <david.vrabel@citrix.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/xen/enlighten.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 23ead298edbd..1170d00879d5 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1410,8 +1410,43 @@ static void __init xen_boot_params_init_edd(void)
* we do this, we have to be careful not to call any stack-protected
* function, which is most of the kernel.
*/
-static void __init xen_setup_stackprotector(void)
+static void __init xen_setup_gdt(void)
{
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+#ifdef CONFIG_X86_64
+ unsigned long dummy;
+
+ switch_to_new_gdt(0); /* GDT and GS set */
+
+ /* We are switching of the Xen provided GDT to our HVM mode
+ * GDT. The new GDT has __KERNEL_CS with CS.L = 1
+ * and we are jumping to reload it.
+ */
+ asm volatile ("pushq %0\n"
+ "leaq 1f(%%rip),%0\n"
+ "pushq %0\n"
+ "lretq\n"
+ "1:\n"
+ : "=&r" (dummy) : "0" (__KERNEL_CS));
+
+ /*
+ * While not needed, we also set the %es, %ds, and %fs
+ * to zero. We don't care about %ss as it is NULL.
+ * Strictly speaking this is not needed as Xen zeros those
+ * out (and also MSR_FS_BASE, MSR_GS_BASE, MSR_KERNEL_GS_BASE)
+ *
+ * Linux zeros them in cpu_init() and in secondary_startup_64
+ * (for BSP).
+ */
+ loadsegment(es, 0);
+ loadsegment(ds, 0);
+ loadsegment(fs, 0);
+#else
+ /* PVH: TODO Implement. */
+ BUG();
+#endif
+ return; /* PVH does not need any PV GDT ops. */
+ }
pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot;
pv_cpu_ops.load_gdt = xen_load_gdt_boot;
@@ -1494,7 +1529,7 @@ asmlinkage void __init xen_start_kernel(void)
* Set up kernel GDT and segment registers, mainly so that
* -fstack-protector code can be executed.
*/
- xen_setup_stackprotector();
+ xen_setup_gdt();
xen_init_irq_ops();
xen_init_cpuid_mask();