⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.c

📁 xen 3.2.2 源码
💻 C
字号:
/* * setup.c: Setup the world for vmxassist. * * Leendert van Doorn, leendert@watson.ibm.com * Copyright (c) 2005, International Business Machines Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. */#include "vm86.h"#include "util.h"#include "machine.h"#if (VMXASSIST_BASE != TEXTADDR)#error VMXAssist base mismatch#endif#define	NR_PGD		(PGSIZE / sizeof(unsigned))#define	min(a, b)	((a) > (b) ? (b) : (a))/* Which CPU are we booting, and what is the initial CS segment? */int booting_cpu, booting_vector;unsigned long long gdt[] __attribute__ ((aligned(32))) = {	0x0000000000000000ULL,		/* 0x00: reserved */	0x0000890000000000ULL,		/* 0x08: 32-bit TSS */	0x00CF9A000000FFFFULL,		/* 0x10: CS 32-bit */	0x00CF92000000FFFFULL,		/* 0x18: DS 32-bit */};struct dtr gdtr = { sizeof(gdt)-1, (unsigned long) &gdt };struct tss tss __attribute__ ((aligned(4)));unsigned long long idt[NR_TRAPS] __attribute__ ((aligned(32)));struct dtr idtr = { sizeof(idt)-1, (unsigned long) &idt };struct vmx_assist_context oldctx;struct vmx_assist_context newctx;unsigned long memory_size;int initialize_real_mode;extern char stack_top[];extern unsigned trap_handlers[];voidbanner(void){	printf("VMXAssist (%s)\n", __DATE__);	/* Bochs its way to convey memory size */	memory_size = ((get_cmos(0x35) << 8) | get_cmos(0x34)) << 6;	if (memory_size > 0x3bc000)		memory_size = 0x3bc000;	memory_size = (memory_size << 10) + 0xF00000;	if (memory_size <= 0xF00000)		memory_size =		    (((get_cmos(0x31) << 8) | get_cmos(0x30)) + 0x400) << 10;	memory_size += 0x400 << 10; /* + 1MB */	printf("Memory size %ld MB\n", memory_size >> 20);	printf("E820 map:\n");	print_e820_map(HVM_E820, *HVM_E820_NR);	printf("\n");}voidsetup_gdt(void){	unsigned long long addr = (unsigned long long) &tss;	/* setup task state segment */	memset(&tss, 0, sizeof(tss));	tss.ss0 = DATA_SELECTOR;	tss.esp0 = (unsigned) stack_top;	tss.iomap_base = offsetof(struct tss, iomap);	tss.iomap[sizeof(tss.iomap)-1] = 0xff;	/* initialize gdt's tss selector */	gdt[TSS_SELECTOR / sizeof(gdt[0])] |=		((addr & 0xFF000000) << (56-24)) |		((addr & 0x00FF0000) << (32-16)) |		((addr & 0x0000FFFF) << (16)) |		(sizeof(tss) - 1);	/* switch to our own gdt and set current tss */	__asm__ __volatile__ ("lgdt %0" : : "m" (gdtr));	__asm__ __volatile__ ("movl %%eax,%%ds;"			      "movl %%eax,%%es;"			      "movl %%eax,%%fs;"			      "movl %%eax,%%gs;"			      "movl %%eax,%%ss" : : "a" (DATA_SELECTOR));	__asm__ __volatile__ ("ljmp %0,$1f; 1:" : : "i" (CODE_SELECTOR));	__asm__ __volatile__ ("ltr %%ax" : : "a" (TSS_SELECTOR));}voidset_intr_gate(int i, unsigned handler){	unsigned long long addr = handler;	idt[i] = ((addr & 0xFFFF0000ULL) << 32) | (0x8E00ULL << 32) |		(addr & 0xFFFFULL) | (CODE_SELECTOR << 16);}voidsetup_idt(void){	int i;	for (i = 0; i < NR_TRAPS; i++)		set_intr_gate(i, trap_handlers[i]);	__asm__ __volatile__ ("lidt %0" : : "m" (idtr));}voidsetup_pic(void){	/* mask all interrupts */	outb(PIC_MASTER + PIC_IMR, 0xFF);	outb(PIC_SLAVE + PIC_IMR, 0xFF);	/* setup master PIC */	outb(PIC_MASTER + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */	outb(PIC_MASTER + PIC_IMR, NR_EXCEPTION_HANDLER);	outb(PIC_MASTER + PIC_IMR, 1 << 2); /* slave on channel 2 */	outb(PIC_MASTER + PIC_IMR, 0x01);	/* setup slave PIC */	outb(PIC_SLAVE + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */	outb(PIC_SLAVE + PIC_IMR, NR_EXCEPTION_HANDLER + 8);	outb(PIC_SLAVE + PIC_IMR, 0x02); /* slave identity is 2 */	outb(PIC_SLAVE + PIC_IMR, 0x01);	/* enable all interrupts */	outb(PIC_MASTER + PIC_IMR, 0);	outb(PIC_SLAVE + PIC_IMR, 0);}voidsetiomap(int port){	tss.iomap[port >> 3] |= 1 << (port & 7);}voidenter_real_mode(struct regs *regs){	/* mask off TSS busy bit */	gdt[TSS_SELECTOR / sizeof(gdt[0])] &= ~0x0000020000000000ULL;	/* start 8086 emulation of BIOS */	if (initialize_real_mode) {		initialize_real_mode = 0;		regs->eflags |= EFLAGS_VM | 0x02;		regs->ves = regs->vds = regs->vfs = regs->vgs = 0xF000;		if (booting_cpu == 0) {			regs->cs = 0xF000; /* ROM BIOS POST entry point */			regs->eip = 0xFFF0;		} else {			regs->cs = booting_vector << 8; /* AP entry point */			regs->eip = 0;		}		regs->uesp = regs->uss = 0;		regs->eax = regs->ecx = regs->edx = regs->ebx = 0;		regs->esp = regs->ebp = regs->esi = regs->edi = 0;		/* intercept accesses to the PIC */		setiomap(PIC_MASTER+PIC_CMD);		setiomap(PIC_MASTER+PIC_IMR);		setiomap(PIC_SLAVE+PIC_CMD);		setiomap(PIC_SLAVE+PIC_IMR);		printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n",			regs->cs, regs->eip);		mode = VM86_REAL; /* becomes previous mode */		set_mode(regs, VM86_REAL);		/* this should get us into 16-bit mode */		return;	}	/* go from protected to real mode */	set_mode(regs, VM86_PROTECTED_TO_REAL);	emulate(regs);	if (mode != VM86_REAL)		panic("failed to emulate between clear PE and long jump.\n");}/* * Setup the environment for VMX assist. * This environment consists of flat segments (code and data), * its own gdt, idt, and tr. */voidsetup_ctx(void){	struct vmx_assist_context *c = &newctx;	memset(c, 0, sizeof(*c));	c->eip = (unsigned long) switch_to_real_mode;	c->esp = (unsigned) stack_top;	c->eflags = 0x2; /* no interrupts, please */	/*	 * Obviously, vmx assist is not running with CR0_PE disabled.	 * The reason why the vmx assist cr0 has CR0.PE disabled is	 * that a transtion to CR0.PE causes a world switch. It seems	 * more natural to enable CR0.PE to cause a world switch to	 * protected mode rather than disabling it.	 */	c->cr0 = (get_cr0() | CR0_NE) & ~CR0_PE;	c->cr3 = 0;	c->cr4 = get_cr4();	c->idtr_limit = sizeof(idt)-1;	c->idtr_base = (unsigned long) &idt;	c->gdtr_limit = sizeof(gdt)-1;	c->gdtr_base = (unsigned long) &gdt;	c->cs_sel = CODE_SELECTOR;	c->cs_limit = 0xFFFFFFFF;	c->cs_base = 0;	c->cs_arbytes.fields.seg_type = 0xb;	c->cs_arbytes.fields.s = 1;	c->cs_arbytes.fields.dpl = 0;	c->cs_arbytes.fields.p = 1;	c->cs_arbytes.fields.avl = 0;	c->cs_arbytes.fields.default_ops_size = 1;	c->cs_arbytes.fields.g = 1;	c->ds_sel = DATA_SELECTOR;	c->ds_limit = 0xFFFFFFFF;	c->ds_base = 0;	c->ds_arbytes = c->cs_arbytes;	c->ds_arbytes.fields.seg_type = 0x3;	c->es_sel = DATA_SELECTOR;	c->es_limit = 0xFFFFFFFF;	c->es_base = 0;	c->es_arbytes = c->ds_arbytes;	c->ss_sel = DATA_SELECTOR;	c->ss_limit = 0xFFFFFFFF;	c->ss_base = 0;	c->ss_arbytes = c->ds_arbytes;	c->fs_sel = DATA_SELECTOR;	c->fs_limit = 0xFFFFFFFF;	c->fs_base = 0;	c->fs_arbytes = c->ds_arbytes;	c->gs_sel = DATA_SELECTOR;	c->gs_limit = 0xFFFFFFFF;	c->gs_base = 0;	c->gs_arbytes = c->ds_arbytes;	c->tr_sel = TSS_SELECTOR;	c->tr_limit = sizeof(tss) - 1;	c->tr_base = (unsigned long) &tss;	c->tr_arbytes.fields.seg_type = 0xb; /* 0x9 | 0x2 (busy) */	c->tr_arbytes.fields.s = 0;	c->tr_arbytes.fields.dpl = 0;	c->tr_arbytes.fields.p = 1;	c->tr_arbytes.fields.avl = 0;	c->tr_arbytes.fields.default_ops_size = 0;	c->tr_arbytes.fields.g = 0;	c->ldtr_sel = 0;	c->ldtr_limit = 0;	c->ldtr_base = 0;	c->ldtr_arbytes = c->ds_arbytes;	c->ldtr_arbytes.fields.seg_type = 0x2;	c->ldtr_arbytes.fields.s = 0;	c->ldtr_arbytes.fields.dpl = 0;	c->ldtr_arbytes.fields.p = 1;	c->ldtr_arbytes.fields.avl = 0;	c->ldtr_arbytes.fields.default_ops_size = 0;	c->ldtr_arbytes.fields.g = 0;}/* * Start BIOS by causing a world switch to vmxassist, which causes * VM8086 to be enabled and control is transfered to F000:FFF0. */voidstart_bios(void){	if (booting_cpu == 0)		printf("Start BIOS ...\n");	else		printf("Start AP %d from %08x ...\n",		       booting_cpu, booting_vector << 12);	initialize_real_mode = 1;	set_cr0(get_cr0() & ~CR0_PE);	panic("vmxassist returned"); /* "cannot happen" */}intmain(void){	if (booting_cpu == 0)		banner();	setup_gdt();	setup_idt();	set_cr4(get_cr4() | CR4_VME);	setup_ctx();	if (booting_cpu == 0)		setup_pic();	start_bios();	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -