关闭

UEFI抢占机制

标签: UEFI
296人阅读 评论(0) 收藏 举报
分类:

本文件纯属个人理解,如有错误,欢迎指出


1. Task Priority Level, 任务优先级

任务优先级数值越大,优先级越高。优先级高于当前任务优先级的任务可能抢占当前中断当前任务的执行。在UEFI标准中,只有4个优先级

 

表格 1 任务优先级

Task Priority Level

Value

中断

使用经典场景

TPL_APPLICATION

4

启用

.efi文件运行时的默认优先级;调用WaitForEvent时必须处于TPL_APPLICATION优先级

TPL_CALLBACK

8

启用

中间优先级

TPL_NOTIFY

16

启用

中间优先级

TPL_HIGH_LEVEL

31

禁用

最高优先级,处于此优先级时

 

可调用BootServiceRiseTPL/RestoreTPL提升或降低任务优先级。在RestoreTPL时,会调用处于等调用事件处理函数队列中高于当前任务优先级的事件处理函数。

2. Event, 事件

用于同步事件,如,定时器到达指定点后,定时器中断程序会通过调用事件中指定的回调函数及参数完成指定定时任务。

事件共有如下几种类型

 

表格 2 Event类型

Type

功能

EVT_TIMER

0x80000000

定时器

EVT_RUNTIME

0x40000000

运行时事件

EVT_NOTIFY_WAIT

0x00000100

等待事件,checkEvent时会被移入Notify_Callback待调用队列,在RestoreTPL时调用notify_callback函数

EVT_NOTIFY_SIGNAL

0x00000200

通知事件,创建时增加进signal队列,如果

EVT_SIGNAL_EXITBOOT_SERVICES

0x00000201

退出BOOT_SERVICES时通知事件,只在进OS才发生

EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE

0x60000202

UNKOWN

 

 

表格 3 有效Event类型组合

Type组合

有效TPL

Notify Function

Notify Context

略注

EVT_TIMER | EVT_NOTIFY_SIGNAL

TPL_CALLBACK

TPL_NOTIFY

必须有

 

Timer到达后,会将此Event移入signaled事件队列,在RestoreTPL时如果当前TPLCreateEvent时指定的TPL则调用通知函数

EVT_TIMER

Ignore

Ignore

Ignore

 

EVT_NOTIFY_WAIT

TPL_CALLBACK

TPL_NOTIFY

必须有

 

CheckEvent会通过RestoreTPL调用notify_callback

EVT_NOTIFY_SIGNAL

TPL_CALLBACK

TPL_NOTIFY

必须有

 

当有程序调用SignalEvent时,Event会被移入signaled事件队列RestoreTPL时如果当前TPLCreateEvent时指定的TPL则调用通知函数

EVT_SIGNAL_EXIT_BOOT_SERVICES

TPL_CALLBACK

TPL_NOTIFY

必须有

 

退出BOOT_SERVICES时通知事件,只在进OS才发生

EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE

TPL_CALLBACK

TPL_NOTIFY

必须有

 

 

0x00000000

Ignore

Ignore

Ignore

 

EVT_TIMER | EVT_NOTIFY_WAIT

TPL_CALLBACK

TPL_NOTIFY

必须有

 

到时间自动转成Signaled状态,CoreSignalEvent ,但checkevent不会调用通知函数

3. Timer, 定时器

定时器在UEFI中有着关重要的地位:1. 任务时间片切换, 2.定时功能

UEFI通常来讲只会启用BSP一个CPU内核;UEFI不但没有实现多任务机制,中断也除了定时器外全部禁用(SMI在这不涉及,不多提)。当进入时间中断处理函数时,会将TPL提升至TPL_HIGH_LEVEL,此时中断被关闭,然后将定时器事件队列中的已经抵达时间点的事件状态转为signaled。然后调用RestoreTPL函数逐级调用所有已被signaled的事件处理函数;中断在处理TPL_HIGH_LEVEL之下的事件时被打开。如果有低等级事件耗时过长,时间中断有可能再次进入。

 

4. 情景分析

 

① DXE驱动程序启动,后台Timer1已超时,事件1,事件2已经转成signaled状态

② 定时器中断触发,驱动程序强行被暂停,中断程序将任务优先级直接提到TPL_HIGH_LEVEL,中断被关闭,然后检查定时器队列中所有Timer Event是否超时,如有超时,移到signaled事件队列,在本情景中,Timer1 Event被移到signaled队列

③ 定时器队列检查程序完成,RestoreTPLTPL_APPLICATION:降至TPL_NOTIFY,然后开启中断;接着查看此任务优先级signaled队列,发现Timer1需要处理,将Timer1 Eventsignaled队列断开,调用Timer1处理程序

④ 继续降至TPL_CALLBACK, 发现事件1需要处理,将事件1 Eventsignaled队列断开调用其处理程序

⑤ 事件1处理完成后,发现事件2需要处理,将事件2 Eventsignaled队列断开调用事件2处理程序

⑥ 事件2处理程序还未完成,但时间中断再次降临,事件2处理程序被中断,任务优先级再次被提到TPL_HIGH_LEVEL,中断关闭执行定时器队列检查程序,发现Timer2已经超时,将其移到signaled队列

⑦ 定时器队列检查完成,Restore TPLTPL_CALLBACK(在跳回TPL_NOTIFY时开启中断)TPL_HIGH_LEVELTPL_NOTIFY上没有signaled状态的事件。中断返回,继续执行事件2处理程序

⑧ 执行完事件2处理程序后,发现Timer2Event处于signaled状态,帮执行Timer2的处理程序

事件2处理程序完成。Restore TPLsignaled队列中未找到其它节点,返回,第一次中断返回,继续DXE驱动执行


5.SpinLock机制

SpinLock的数据结构体是EFI_LOCK,内含三个变量

  • Tpl 锁的TPL等级;上锁时TPL被提升至此等级,释放时还原TPL等级
  • OwnerTpl 记录上锁之前程序的等级
  • EFI_LOCK_STATE 锁的状态 共三种状态(uninitialized, Released, Acquired)

SpinLock相关函数有三个

  • EfiAcquireLock 先将当前任务优先级提升到Tpl,然后状态转换成Acquired
  • EfiAcquireLockOrFail 先检查锁的状态,如果为Acquired,则返回Fail, 然后执行EfiAcquireLock逻辑
  • EfiReleaseLock 先将状态转换成Released,然后将当前任务优先级还原

其实函数EfiAcquireLockOrFail的作用只是防止高优先级的任务异步获取低等级的锁。

SpinLock工作的基础是只有高于当前优先级的任务才能抢占当前的任务


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:27926次
    • 积分:515
    • 等级:
    • 排名:千里之外
    • 原创:22篇
    • 转载:24篇
    • 译文:0篇
    • 评论:2条
    最新评论