Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1297463
  • 博文数量: 196
  • 博客积分: 4141
  • 博客等级: 中将
  • 技术积分: 2253
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-21 20:04
文章存档

2019年(31)

2016年(1)

2014年(16)

2011年(8)

2010年(25)

2009年(115)

分类: 虚拟化

2009-03-22 15:03:12

/* This code sits at 0xFFC00000 to do the low-level guest<->host switch.

2

3 There is are two pages above us for this CPU (struct lguest_pages).

4 The second page (struct lguest_ro_state) becomes read-only after the

5 context switch. The first page (the stack for traps) remains writable,

6 but while we're in here, the guest cannot be running.

7 */

8 #include

9 #include

10 #include "lg.h"

11

/* 在include/linux/linkage.h

 * #ifndef ENTRY

 * #define ENTRY(name) \

 * .globl name; \

 * ALIGN; \

 * name:

 * #endif

 */

/* 通过切换gdt, idt, tr,来实现从host 到guest 的转换*/

12 .text

13 ENTRY(start_switcher_text)

14

15 /* %eax points to lguest pages for this CPU. %ebx contains cr3 value.

16 All normal registers can be clobbered! */

17 ENTRY(switch_to_guest)

18 /* Save host segments on host stack. */

19 pushl %es

20 pushl %ds

21 pushl %gs

22 pushl %fs

23 /* With CONFIG_FRAME_POINTER, gcc doesn'
t let us clobber */

24 pushl %ebp

25 /* Save host stack. */

// eax存放的是lguest_pages 的地址LGUEST_PAGES_host_sp 则是esp 在lguest_pages 中的偏移位置

26 movl %esp, LGUEST_PAGES_host_sp(%eax)

27 /* Switch to guest stack: if we get NMI we expect to be there. */

28 movl %eax, %edx

29 addl $LGUEST_PAGES_regs, %edx

30 movl %edx, %esp

31 /* Switch to guest's GDT, IDT. */

32 lgdt LGUEST_PAGES_guest_gdt_desc(%eax)

33 lidt LGUEST_PAGES_guest_idt_desc(%eax)

34 /* Switch to guest'
s TSS while GDT still writable. */

35 movl $(GDT_ENTRY_TSS*8), %edx

36 ltr %dx

37 /* Set host's TSS GDT entry to available (clear byte 5 bit 2). */

38 movl (LGUEST_PAGES_host_gdt_desc+2)(%eax), %edx

39 andb $0xFD, (GDT_ENTRY_TSS*8 + 5)(%edx)

40 /* Switch to guest page tables: lguest_pages->state now read-only. */

41 movl %ebx, %cr3

42 /* Restore guest regs */

43 popl %ebx

44 popl %ecx

45 popl %edx

46 popl %esi

47 popl %edi

48 popl %ebp

49 popl %gs

50 popl %eax

51 popl %fs

52 popl %ds

53 popl %es

54 /* Skip error code and trap number */

55 addl $8, %esp

56 iret

57

58 #define SWITCH_TO_HOST \

59 /* Save guest state */ \

60 pushl %es; \

61 pushl %ds; \

62 pushl %fs; \

63 pushl %eax; \

64 pushl %gs; \

65 pushl %ebp; \

66 pushl %edi; \

67 pushl %esi; \

68 pushl %edx; \

69 pushl %ecx; \

70 pushl %ebx; \

71 /* Load lguest ds segment for convenience. */ \

72 movl $(LGUEST_DS), %eax; \

73 movl %eax, %ds; \

74 /* Figure out where we are, based on stack (at top of regs). */ \

75 movl %esp, %eax; \

76 subl $LGUEST_PAGES_regs, %eax; \

77 /* Put trap number in %ebx before we switch cr3 and lose it. */ \

78 movl LGUEST_PAGES_regs_trapnum(%eax), %ebx; \

79 /* Switch to host page tables (host GDT, IDT and stack are in host \

80 mem, so need this first) */ \

81 movl LGUEST_PAGES_host_cr3(%eax), %edx; \

82 movl %edx, %cr3; \

83 /* Set guest'
s TSS to available (clear byte 5 bit 2). */ \

84 andb $0xFD, (LGUEST_PAGES_guest_gdt+GDT_ENTRY_TSS*8+5)(%eax); \

85 /* Switch to host's GDT & IDT. */ \

86 lgdt LGUEST_PAGES_host_gdt_desc(%eax); \

87 lidt LGUEST_PAGES_host_idt_desc(%eax); \

88 /* Switch to host'
s stack. */ \

89 movl LGUEST_PAGES_host_sp(%eax), %esp; \

90 /* Switch to host's TSS */ \

91 movl $(GDT_ENTRY_TSS*8), %edx; \

92 ltr %dx; \

93 popl %ebp; \

94 popl %fs; \

95 popl %gs; \

96 popl %ds; \

97 popl %es

98

99 /* Return to run_guest_once. */

100 return_to_host:

101 SWITCH_TO_HOST

102 iret

103

104 deliver_to_host:

105 SWITCH_TO_HOST

106 /* Decode IDT and jump to hosts'
irq handler. When that does iret, it

107 * will return to run_guest_once. This is a feature. */

108 movl (LGUEST_PAGES_host_idt_desc+2)(%eax), %edx

109 leal (%edx,%ebx,8), %eax

110 movzwl (%eax),%edx

111 movl 4(%eax), %eax

112 xorw %ax, %ax

113 orl %eax, %edx

114 jmp *%edx

115

116 /* Real hardware interrupts are delivered straight to the host. Others

117 cause us to return to run_guest_once so it can decide what to do. Note

118 that some of these are overridden by the guest to deliver directly, and

119 never enter here (see load_guest_idt_entry). */

120 .macro IRQ_STUB N TARGET

121 .data; .long 1f; .text; 1:

122 /* Make an error number for most traps, which don't have one. */

/* .if语句处理错误码 */

123 .if (\N <> 8) && (\N < 10 || \N > 14) && (\N <> 17)

124 pushl $0

125 .endif

126 pushl $\N

127 jmp \TARGET

128 ALIGN

129 .endm

130

131 .macro IRQ_STUBS FIRST LAST TARGET

132 irq=\FIRST

133 .rept \LAST-\FIRST+1

134 IRQ_STUB irq \TARGET

135 irq=irq+1

136 .endr

137 .endm

138

139 /* We intercept every interrupt, because we may need to switch back to

140 * host. Unfortunately we can'
t tell them apart except by entry

141 * point, so we need 256 entry points.

142 */

143 .data

144 .global default_idt_entries

145 default_idt_entries:

146 .text

147 IRQ_STUBS 0 1 return_to_host /* First two traps */

148 IRQ_STUB 2 handle_nmi /* NMI */

149 IRQ_STUBS 3 31 return_to_host /* Rest of traps */

150 IRQ_STUBS 32 127 deliver_to_host /* Real interrupts */

151 IRQ_STUB 128 return_to_host /* System call (overridden) */

152 IRQ_STUBS 129 255 deliver_to_host /* Other real interrupts */

153

154 /* We ignore NMI and return. */

155 handle_nmi:

156 addl $8, %esp

157 iret

158

159 ENTRY(end_switcher_text)

 

阅读(1828) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~