mov $XEN_MINIMAL_CR4,%rcx
mov %rcx,%cr4
+ /*
+ * Possibly switch to the per-CPU idle page-tables. Note we cannot
+ * switch earlier as the per-CPU page-tables might be above 4G, and
+ * hence need to load them from 64bit code.
+ */
+ mov ap_cr3(%rip), %rax
+ test %rax, %rax
+ jz .L_skip_cr3
+ mov %rax, %cr3
+.L_skip_cr3:
+
mov stack_start(%rip),%rsp
/* Reset EFLAGS (subsumes CLI and CLD). */
int arch_vcpu_create(struct vcpu *v)
{
struct domain *d = v->domain;
+ root_pgentry_t *pgt = NULL;
int rc;
v->arch.flags = TF_kernel_mode;
else
{
/* Idle domain */
- v->arch.cr3 = __pa(idle_pg_table);
+ if ( (opt_asi_pv || opt_asi_hvm) && v->vcpu_id )
+ {
+ pgt = alloc_xenheap_page();
+
+ /*
+ * For the idle vCPU 0 (the BSP idle vCPU) use idle_pg_table
+ * directly, there's no need to create yet another copy.
+ */
+ rc = -ENOMEM;
+ if ( !pgt )
+ goto fail;
+
+ copy_page(pgt, idle_pg_table);
+ v->arch.cr3 = __pa(pgt);
+ }
+ else
+ v->arch.cr3 = __pa(idle_pg_table);
rc = 0;
v->arch.msrs = ZERO_BLOCK_PTR; /* Catch stray misuses */
}
vcpu_destroy_fpu(v);
xfree(v->arch.msrs);
v->arch.msrs = NULL;
+ free_xenheap_page(pgt);
return rc;
}
if ( (v = idle_vcpu[smp_processor_id()]) == current )
sync_local_execstate();
/* We must now be running on the idle page table. */
- ASSERT(cr3_pa(read_cr3()) == __pa(idle_pg_table));
+ ASSERT(cr3_pa(read_cr3()) == cr3_pa(v->arch.cr3));
}
return v;
extern uint64_t boot_tsc_stamp;
extern void *stack_start;
+extern unsigned long ap_cr3;
void early_cpu_init(bool verbose);
void early_time_init(void);
/* Used by the BSP/AP paths to find the higher half stack mapping to use. */
void *stack_start = cpu0_stack + STACK_SIZE - sizeof(struct cpu_info);
+/* cr3 value for the AP to load on boot. */
+unsigned long ap_cr3;
+
/* Used by the boot asm to stash the relocated multiboot info pointer. */
unsigned int asmlinkage __initdata multiboot_ptr;
stack_start = stack_base[cpu] + STACK_SIZE - sizeof(struct cpu_info);
+ /*
+ * If per-CPU idle root page table has been allocated, switch to it as
+ * part of the AP bringup trampoline.
+ */
+ ap_cr3 = idle_vcpu[cpu]->arch.cr3 != __pa(idle_pg_table) ?
+ idle_vcpu[cpu]->arch.cr3 : 0;
+
/* This grunge runs the startup process for the targeted processor. */
set_cpu_state(CPU_STATE_INIT);