设为首页 收藏本站
查看: 2779|回复: 0

[经验分享] Xen源代码分析(一)——head.s

[复制链接]

尚未签到

发表于 2015-4-13 11:05:26 | 显示全部楼层 |阅读模式
      启动汇编部分代码是xen 的引导启动程序,位于./xen/arch/x86/boot目录下。代码描述了从xen加载到调用第一个C函数“__start_xen”之间的初始化系统环境过程。主要涉及的文件流程为head.S->trampoline.S->x86_32.s,其中head.s为冲GRUB进入XEN的入口文件,首先看看head.s部分都做了什么(只看32位体系)。




/* 只能由 grub 来引导,head.S 是从GRUB进入XEN 的入口文件;
开始执行的第一个汇编文件,包括初始化页表,解析早期命令行参数等工作
*/
#include
#include
#include
#include
#include
#include
#include
.text
.code32
/*当xen运行时,cpu已经处于保护模式了,和LINUX内核的处理方式一致,虚拟地址等于物理地址加上固定值*/
/*在xen\include\asm-x86\x86_32\page.h中有__XEN_VIRT_START的定义*/
#define sym_phys(sym)     ((sym) - __XEN_VIRT_START)
/**
*xen 编译时的映像布局由xen\arch\x86\xen.lds.S 控制:
...
#ifdef __x86_64__
#define FORMAT "elf64-x86-64"
#else
#define FORMAT "elf32-i386"
#endif
ENTRY(start)
#endif
OUTPUT_FORMAT(FORMAT, FORMAT, FORMAT)
#ifdef __x86_64__
OUTPUT_ARCH(i386:x86-64)
#else
OUTPUT_ARCH(i386)
#endif
PHDRS
{
text PT_LOAD ;
}
SECTIONS
{
. = __XEN_VIRT_START + 0x100000;
_start = .;
.text : {
_stext = .;            //Text and read-only data
*(.text)
*(.text.cold)
*(.text.unlikely)
*(.fixup)
*(.gnu.warning)
_etext = .;             //End of text section
} :text = 0x9090
...
**/
/*根据INTEL手册GDT第一项无用,故而从0x08开始*/
/*ring0,code,32-bit mode*/
#define BOOT_CS32        0x0008
/*ring0,code,64-bit mode*/
#define BOOT_CS64        0x0010
/*ring0,data*/
#define BOOT_DS          0x0018
/*real-mode code*/
#define BOOT_PSEUDORM_CS 0x0020
/*5 real-mode data*/
#define BOOT_PSEUDORM_DS 0x0028
ENTRY(start)
jmp     __start
.align 4
/*** MULTIBOOT HEADER ****/
#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_MODS_ALIGNED | \
MULTIBOOT_HEADER_WANT_MEMORY)
/* Magic number indicating a Multiboot header. */
.long   MULTIBOOT_HEADER_MAGIC
/* Flags to bootloader (see Multiboot spec). */
.long   MULTIBOOT_HEADER_FLAGS
/* Checksum: must be the negated sum of the first two fields. */
.long   -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
/**
* 上面的定义是给grub看的,表明支持multiboot, 详细内容见multiboot协议
**/
.section .init.text, "ax"
/*.asciz is just like .ascii, but each string is followed by a zero
byte.*/
.Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!"
.Lbad_ldr_msg: .asciz "ERR: Not a Multiboot bootloader!"
bad_cpu:/*打印bad cpu错误*/
mov     $(sym_phys(.Lbad_cpu_msg)),%esi # Error message
jmp     print_err
not_multiboot:/*打印非多启动错误*/
mov     $(sym_phys(.Lbad_ldr_msg)),%esi # Error message
print_err:/*这里的打印用的是最基本的往显卡缓存写入数据的方式*/
mov     $0xB8000,%edi  # VGA framebuffer
1:      mov     (%esi),%bl
test    %bl,%bl        # Terminate on '\0' sentinel
2:      je      2b
mov     $0x3f8+5,%dx   # UART Line Status Register
3:      in      %dx,%al
test    $0x20,%al      # Test THR Empty flag
je      3b
mov     $0x3f8+0,%dx   # UART Transmit Holding Register
mov     %bl,%al
out     %al,%dx        # Send a character over the serial line
movsb                  # Write a character to the VGA framebuffer
mov     $7,%al
stosb                  # Write an attribute to the VGA framebuffer
jmp     1b
gdt_boot_descr:/*GDT定义,传统模式下的全局描述符表寄存器(GDTR)长48位,由16位的界限和32位的基地址构成。由于段描述符总是8字节长,故界限的值应为8N-1。
Trampoline_gdt共定义了6个描述符项,界限是6*8-1。*/
.word   6*8-1
.long   sym_phys(trampoline_gdt)
__start:
cld
cli
/* Initialise GDT and basic data segments. */
lgdt    %cs:sym_phys(gdt_boot_descr)
mov     $BOOT_DS,%ecx
mov     %ecx,%ds
mov     %ecx,%es
mov     %ecx,%ss
/*
验证并存储多重启动信息,详见“多重启动规范”。
当boot loader引导32位操作系统的时候,机器必须有如下的状态:
EAX:
必须包含魔数0X2BADB002,这个值告诉操作系统目前它是由兼容的Multiboot 的boot loader引导的。
EBX:
必须包含boot loader提供的多重引导信息结构的32位物理地址。
CS:
必须是32位的读/执行的代码段,偏移是0以及界限是 0XFFFFFFFF。具体值没有定义。
SS:
必须是32位的读/执行数据段,偏移是0以及界限是 0XFFFFFFFF。具体值没有定义。
A20 GATE :
必须enable。
CR0:
31位(PG)必须清除,第0位(PE)必须设置。其他位没有定义。
EFLAGS:
第17(VM)位必须清除,第9位(IF)必须清除,其他位没有定义。
*/
/* Check for Multiboot bootloader */
cmp     $0x2BADB002,%eax
jne     not_multiboot
/* Set up trampoline segment 64k below EBDA */
movzwl  0x40e,%eax          /* EBDA segment */
cmp     $0xa000,%eax        /* sanity check (high) */
jae     0f
cmp     $0x4000,%eax        /* sanity check (low) */
jae     1f
0:
movzwl  0x413,%eax          /* use base memory size on failure */
shl     $10-4,%eax
1:
sub     $0x1000,%eax
/* From arch/x86/smpboot.c: start_eip had better be page-aligned! */
xor     %al, %al
shl     $4, %eax
mov     %eax,sym_phys(trampoline_phys)
/* Save the Multiboot info struct (after relocation) for later use. */
mov     $sym_phys(cpu0_stack)+1024,%esp
push    %ebx
call    reloc
mov     %eax,sym_phys(multiboot_ptr)
/* Initialize BSS (no nasty surprises!) */
/*初始化BSS段,存放程序中未初始化的全局变量。
BSS段在xen\arch\x86\x86_32\xen.lds.S中定义*/
mov     $sym_phys(__bss_start),%edi
mov     $sym_phys(_end),%ecx
sub     %edi,%ecx
xor     %eax,%eax
rep     stosb
/*
查询并保存CPU拓展信息。
CPUID指令可提供关于处理器的实现及其能力的完整信息,任意特权级的软件都可以使用它。
EAX寄存器用于决定CPUID生成什么信息
EAX = 0x80000000,返回信息:
EAX: Maximum Input Value for Extended Function CPUID Information. PIV之后的CPU,均大于0x80000000
EBX: Reserved
ECX: Reserved
EDX: Reserved
EAX = 0x80000001,返回信息:
EAX:     Extended Processor Signature and Feature Bits.
EBX:       Reserved
ECX:       Bit 0: LAHF/SAHF available in 64-bit mode
Bits 31-1 Reserved
EDX:      Bits 10-0: Reserved
Bit 11: SYSCALL/SYSRET available (when in 64-bit mode)
Bits 19-12: Reserved = 0
Bit 20: Execute Disable Bit available
Bits 28-21: Reserved = 0
Bit 29: Intel? 64 Architecture available if 1
Bits 31-30: Reserved = 0
cpuid_ext_features在xen\arch\x86\boot\trampoline.S中定义。boot_cpu_data在\xen\include\asm-x86 \ processor.h中定义,是cpuinfo_x86的实例。
CPUINFO86_ext_features 在xen\arch\x86\x86_32 \ asm-offsets.c中定义:OFFSET(CPUINFO86_ext_features, struct cpuinfo_x86, x86_capability[1]);
OFFSET解释如下:
#define offsetof (s, m) (size_t)&(((s*)0)->m)
m为结构体s中的一项,返回m距结构体起始地址的偏移量。ANSI C中常数0允许转换成任何类型的指针,但转换后指针为NULL。例中&(((s*)0)->m)这一步,并不访问m元素,只是获取m的地址,编译时不生成访问m的代码。
#define DEFINE(_sym,_val)  __asm__  __volatile__  (“\n->” #_sym “%0” #_val:: “i”(_val))
#是注释符号;%0是占位符,这里指代“i”(_val)。
#define OFFSET(_sym, _str, _mem)  DEFINE(_sym, offsetof(_str, _mem))
这条宏是将_str结构体的_mem项的偏移量赋值给_sym。
*/
/* Interrogate CPU extended features via CPUID. */
mov     $0x80000000,%eax
cpuid
xor     %edx,%edx
cmp     $0x80000000,%eax    # any function > 0x80000000?
jbe     1f
mov     $0x80000001,%eax
cpuid
1:      mov     %edx,sym_phys(cpuid_ext_features)
mov     %edx,sym_phys(boot_cpu_data)+CPUINFO86_ext_features
#if defined(__x86_64__)
/* Check for availability of long mode. */
bt      $29,%edx
jnc     bad_cpu
/* Initialise L2 identity-map and xen page table entries (16MB). */
mov     $sym_phys(l2_identmap),%edi
mov     $sym_phys(l2_xenmap),%esi
mov     $sym_phys(l2_bootmap),%edx
mov     $0x1e3,%eax                  /* PRESENT+RW+A+D+2MB+GLOBAL */
mov     $8,%ecx
1:      mov     %eax,(%edi)
add     $8,%edi
mov     %eax,(%esi)
add     $8,%esi
mov     %eax,(%edx)
add     $8,%edx
add     $(118(%edi) /* high mapping */
stosl                                /* low mapping */
add     $4,%edi
add     $(1

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-56609-1-1.html 上篇帖子: 使用virt-install 创建Xen虚拟机 下篇帖子: 运行编译的xen tools时,遇到错误ImportError: No module named xen.xm
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表