购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.3 分区中断设计

PRTOS的分区中断设计是指设计PRTOS处理和分发分区中断的方式,以确保每个分区都能够及时响应中断。PRTOS的分区中断设计包括以下4个方面。

1)中断触发:当一个虚拟机需要响应中断时,PRTOS需要将中断注入到虚拟机中。为此,PRTOS会将物理中断转换为虚拟中断,并将其投递给目标虚拟机。

2)中断分发:当多个虚拟机都需要响应中断时,PRTOS需要将中断分发给所有需要响应中断的虚拟机。PRTOS采用静态配置策略来实现中断分发。

3)中断处理程序:当虚拟机收到中断后,PRTOS需要调用相应的中断处理程序来处理中断。中断处理程序通常由分区应用程序提供,PRTOS需要将中断处理程序注入到虚拟机中,以确保虚拟机能够正确响应中断。

4)中断屏蔽:当虚拟机不希望响应中断时,PRTOS需要实现中断屏蔽功能,以防止虚拟机被不必要的中断打扰。中断屏蔽通常由虚拟机客户操作系统控制,PRTOS需要将中断屏蔽功能注入到虚拟机中。

如图4-1所示,PRTOS为分区中断管理提供了一个虚拟陷阱表,虚拟陷阱表和本地陷阱表相结合形成了一个虚拟中断模型,它虚拟化了硬件中可用的底层中断服务程序,并添加了一组与分区系统相关的新中断(虚拟分区间中断)。

4.3.1 分区中断处理流程

在分区执行的过程中,当外部中断事件因为某种条件(如硬件错误、软件异常、I/O请求等)触发时,本地CPU会停止当前执行的程序(保存当前分区的vCPU上下文),将CPU的控制权转移给PRTOS Hypervisor。PRTOS会根据外部中断向量号从本地CPU中断陷阱表中取出对应的表项,并执行本地中断处理程序。本地中断处理程序的执行逻辑如下。

第1步:检测当前中断事件是否属于某个分区。如果属于该分区,则将中断投递到该分区(即将分区中断挂起寄存器中该中断对应的位置1);如果该中断不属于任何分区,则执行PRTOS预留的默认中断处理程序。

第2步:检测当前分区的中断挂起寄存器是否有处于挂起状态的中断。如果有中断处在挂起状态,则处理该中断。

分区中断处理流程如图4-4所示。

图4-4 分区中断处理流程


提示: 如果触发的中断属于当前运行分区,则该中断会立即得到处理;如果不属于当前分区,则PRTOS会将其投递到所属目标分区(前提是已经给该中断配置了所属分区)。由于切换到pCPU内核模式后,分区vCPU的上下文保存在Hypervisor的内核栈中,并且外部硬件中断向量号和分区虚拟中断向量号不一定一致,因此当PRTOS Hypervisor将中断投递到目标分区时,仍需要构造分区环境来处理这个中断的栈帧。


4.3.2 分区陷阱表的初始化

分区陷阱表vtrap_table在分区中断虚拟化中起着非常关键的作用,分区的虚拟ISR(Interrupt Service Routines,中断服务程序)需要通过vtrap_table来派发。vtrap_table的构建过程如代码清单4-1所示。

代码清单4-1 分区陷阱表vtrap_table的构建过程

//源码路径:user/bail/x86/boot.S

01 TABLE_START vtrap_table

02 BUILD_TRAP_NOERRCODE 0x0

03 BUILD_TRAP_NOERRCODE 0x1

04 BUILD_TRAP_NOERRCODE 0x2

05 BUILD_TRAP_NOERRCODE 0x3

06 BUILD_TRAP_NOERRCODE 0x4

07 BUILD_TRAP_NOERRCODE 0x5

08 BUILD_TRAP_NOERRCODE 0x6

09 BUILD_TRAP_NOERRCODE 0x7

10 BUILD_TRAP_ERRCODE 0x8

11 BUILD_TRAP_NOERRCODE 0x9

12 BUILD_TRAP_ERRCODE 0xa

13 BUILD_TRAP_ERRCODE 0xb

14 BUILD_TRAP_ERRCODE 0xc

15 BUILD_TRAP_ERRCODE 0xd

16 BUILD_TRAP_ERRCODE 0xe

17 BUILD_TRAP_NOERRCODE 0xf

18 BUILD_TRAP_NOERRCODE 0x10

19 BUILD_TRAP_ERRCODE 0x11

20 BUILD_TRAP_NOERRCODE 0x12

21 BUILD_TRAP_NOERRCODE 0x13

22 BUILD_TRAP_ERRCODE 0x14

23 BUILD_TRAP_ERRCODE 0x15

24 BUILD_TRAP_ERRCODE 0x16

25 BUILD_TRAP_ERRCODE 0x17

26 BUILD_TRAP_ERRCODE 0x18

27 BUILD_TRAP_ERRCODE 0x19

28 BUILD_TRAP_ERRCODE 0x1a

29 BUILD_TRAP_ERRCODE 0x1b

30 BUILD_TRAP_ERRCODE 0x1c

31 BUILD_TRAP_ERRCODE 0x1d

32 BUILD_TRAP_ERRCODE 0x1e

33 BUILD_TRAP_ERRCODE 0x1f

34 BUILD_TRAP_BLOCK 0x20 NUM_OF_PART_IDT_ENTRIES

35 TABLE_END

36

37 .data

38 .word 0

39 ENTRY(part_idt_desc)

40   .word NUM_OF_PART_IDT_ENTRIES*8-1

41   .long part_idt_table

42

43 part_gdt_table:

44     .quad 0x0000000000000000

45     .quad 0x00cfba000000bfff

46     .quad 0x00cfb2000000bfff

47

48 .word 0

49 ENTRY(part_gdt_desc)

50   .word 3*8-1

51   .long part_gdt_table

52

53 debug_string:

54   .asciz "XAL Irq: Calling address 0x%08x\n"

55

56 .bss

57

58 .globl _stack

59 _stack:

60     .fill (STACK_SIZE/4)*CONFIG_MAX_NO_VCPUS,4,0

61

62 .globl part_idt_table

63 part_idt_table:

64   .zero (NUM_OF_PART_IDT_ENTRIES*8)

65

66 .previous


在上述代码中,vtrap_table的前32表项(01~31)是vCPU的预留表项,和X86处理器中前32个处理器预留表项相对应(第02~33行),其余的256表项为分区的所属外围设备中断和虚拟中断预留(第34行)。

在X86平台中,vtrap_table表项通过分区中断描述符表完成跳转,所以第62~64行定义了part_idt_table。

同时,分区应用也具有自己的代码段和数据空间,所以第43~46行为分区定义了虚拟全局描述符表part_gdt_table以及虚拟全局描述符part_gdt_desc(第49~51行)。

4.3.3 分区中断描述符表的初始化

在X86平台上,vtrap_table表项是通过分区中断描述符表完成跳转的,所以分区中断描述符表part_idt_table的初始化也非常关键,如代码清单4-2所示。

代码清单4-2 分区中断描述符表的初始化

//源码路径:user/bail/x86/arch.c

01 void init_arch(void) {

02  extern vtrap_table_t vtrap_table[];

03  long irq_nr;

04

05  hw_set_trap_gate(0, vtrap_table[0], 1);

06  hw_set_irq_gate(1, vtrap_table[1], 1);

07  hw_set_irq_gate(2, vtrap_table[2], 1);

08  hw_set_trap_gate(3, vtrap_table[3], 1);

09  hw_set_trap_gate(4, vtrap_table[4], 1);

10  hw_set_trap_gate(5, vtrap_table[5], 1);

11  hw_set_trap_gate(6, vtrap_table[6], 1);

12  hw_set_trap_gate(7, vtrap_table[7], 1);

13  hw_set_trap_gate(8, vtrap_table[8], 1);

14  hw_set_trap_gate(9, vtrap_table[9], 1);

15  hw_set_trap_gate(10, vtrap_table[10], 1);

16  hw_set_trap_gate(11, vtrap_table[11], 1);

17  hw_set_trap_gate(12, vtrap_table[12], 1);

18  hw_set_trap_gate(13, vtrap_table[13], 1);

19  hw_set_irq_gate(13, vtrap_table[13], 1);

20  hw_set_irq_gate(14, vtrap_table[14], 1);

21  hw_set_trap_gate(15, vtrap_table[15], 1);

22  hw_set_trap_gate(16, vtrap_table[16], 1);

23  hw_set_trap_gate(17, vtrap_table[17], 1);

24  hw_set_trap_gate(18, vtrap_table[18], 1);

25  hw_set_trap_gate(19, vtrap_table[19], 1);

26

27  for (irq_nr = 0x20; irq_nr < IDT_ENTRIES; irq_nr++)

28    hw_set_irq_gate(irq_nr, vtrap_table[irq_nr], 1);

29

30  prtos_x86_load_gdt(&part_gdt_desc);

31  prtos_x86_load_idtr(&part_idt_desc);

32 }


在上述代码中,第05~25行用于初始化分区中断描述符表的预留表项;第27~28行完成外围设备中断和虚拟中断预留表项。分区中断描述符表part_idt_table的大小和类型与pCPU中预留的原生中断描述符表的大小和类型(参见3.1.2小节)一致。 DmkgwWZYIE7ueHOWVihCuqV7omJTYpl0gSX7jsjrsdiXdTNH8b/gdMLNg13RkkaE

点击中间区域
呼出菜单
上一章
目录
下一章
×