Skip to content
enlighten.c 27.4 KiB
Newer Older
Jeremy Fitzhardinge's avatar
Jeremy Fitzhardinge committed
	.set_pte_at = xen_set_pte_at,
	.set_pmd = xen_set_pmd,

	.pte_val = xen_pte_val,
	.pgd_val = xen_pgd_val,

	.make_pte = xen_make_pte,
	.make_pgd = xen_make_pgd,

#ifdef CONFIG_X86_PAE
	.set_pte_atomic = xen_set_pte_atomic,
	.set_pte_present = xen_set_pte_at,
	.set_pud = xen_set_pud,
	.pte_clear = xen_pte_clear,
	.pmd_clear = xen_pmd_clear,

	.make_pmd = xen_make_pmd,
	.pmd_val = xen_pmd_val,
#endif	/* PAE */

	.activate_mm = xen_activate_mm,
	.dup_mmap = xen_dup_mmap,
	.exit_mmap = xen_exit_mmap,

	.set_lazy_mode = xen_set_lazy_mode,
};

#ifdef CONFIG_SMP
static const struct smp_ops xen_smp_ops __initdata = {
	.smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu,
	.smp_prepare_cpus = xen_smp_prepare_cpus,
	.cpu_up = xen_cpu_up,
	.smp_cpus_done = xen_smp_cpus_done,

	.smp_send_stop = xen_smp_send_stop,
	.smp_send_reschedule = xen_smp_send_reschedule,
	.smp_call_function_mask = xen_smp_call_function_mask,
};
#endif	/* CONFIG_SMP */

static void xen_reboot(int reason)
{
#ifdef CONFIG_SMP
	smp_send_stop();
#endif

	if (HYPERVISOR_sched_op(SCHEDOP_shutdown, reason))
		BUG();
}

static void xen_restart(char *msg)
{
	xen_reboot(SHUTDOWN_reboot);
}

static void xen_emergency_restart(void)
{
	xen_reboot(SHUTDOWN_reboot);
}

static void xen_machine_halt(void)
{
	xen_reboot(SHUTDOWN_poweroff);
}

static void xen_crash_shutdown(struct pt_regs *regs)
{
	xen_reboot(SHUTDOWN_crash);
}

static const struct machine_ops __initdata xen_machine_ops = {
	.restart = xen_restart,
	.halt = xen_machine_halt,
	.power_off = xen_machine_halt,
	.shutdown = xen_machine_halt,
	.crash_shutdown = xen_crash_shutdown,
	.emergency_restart = xen_emergency_restart,
};

/* First C function to be called on Xen boot */
asmlinkage void __init xen_start_kernel(void)
{
	pgd_t *pgd;

	if (!xen_start_info)
		return;

	BUG_ON(memcmp(xen_start_info->magic, "xen-3.0", 7) != 0);

	/* Install Xen paravirt ops */
	paravirt_ops = xen_paravirt_ops;
	machine_ops = xen_machine_ops;

#ifdef CONFIG_SMP
	smp_ops = xen_smp_ops;
#endif

	xen_setup_features();

	/* Get mfn list */
	if (!xen_feature(XENFEAT_auto_translated_physmap))
		phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;

	pgd = (pgd_t *)xen_start_info->pt_base;

	init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE;

	init_mm.pgd = pgd; /* use the Xen pagetables to start */

	/* keep using Xen gdt for now; no urgent need to change it */

	x86_write_percpu(xen_cr3, __pa(pgd));

#ifdef CONFIG_SMP
	/* Don't do the full vcpu_info placement stuff until we have a
	   possible map. */
	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
#else
	/* May as well do it now, since there's no good time to call
	   it later on UP. */
	xen_setup_vcpu_info_placement();
#endif

	paravirt_ops.kernel_rpl = 1;
	if (xen_feature(XENFEAT_supervisor_mode_kernel))
		paravirt_ops.kernel_rpl = 0;

	/* set the limit of our address space */
	reserve_top_address(-HYPERVISOR_VIRT_START + 2 * PAGE_SIZE);

	/* set up basic CPUID stuff */
	cpu_detect(&new_cpu_data);
	new_cpu_data.hard_math = 1;
	new_cpu_data.x86_capability[0] = cpuid_edx(1);

	/* Poke various useful things into boot_params */
	LOADER_TYPE = (9 << 4) | 0;
	INITRD_START = xen_start_info->mod_start ? __pa(xen_start_info->mod_start) : 0;
	INITRD_SIZE = xen_start_info->mod_len;

	/* Start the world */
	start_kernel();
}