日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

optee中添加一个中断以及底层代码的相关解读

發布時間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 optee中添加一个中断以及底层代码的相关解读 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

optee、中斷、gic、gicv3、itr_add、安全中斷、tee、trustzone、ATF

★★★ 個人博客導讀首頁—點擊此處 ★★★
.
說明:
在默認情況下,本文講述的都是ARMV8-aarch64架構,optee3.14版本

思考:
如何將一個中斷配置成安全中斷?
如何打開或關閉某一個中斷?
中斷來了之后,能否指定routing到哪個Core?
optee中如何注冊一個中斷?
能否指定一個中斷為FIQ或IRQ?

1、optee中注冊一個中斷

其實呢,我們在代碼全局搜索itr_add是能搜索到好多示例的

我們以optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c代碼為例,進行一個講解:

(1)、定義一個struct itr_handler結構體,.it為硬件中斷號,.handler執行中斷處理函數

(optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c)static enum itr_return tzc_it_handler(struct itr_handler *handler __unused){EMSG("TZC permission failure");tzc_fail_dump();if (IS_ENABLED(CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION))panic();elsetzc_int_clear();return ITRR_HANDLED;}static struct itr_handler tzc_itr_handler = {.it = STM32MP1_IRQ_TZC,.handler = tzc_it_handler,};DECLARE_KEEP_PAGER(tzc_itr_handler);

(2)、在初始化的代碼中,注冊該中斷和enable該中斷

itr_add(&tzc_itr_handler); itr_enable(tzc_itr_handler.it);

至此一個中斷示例講完了,就是這么簡單。

2、optee中斷的處理流程


(1)、有關itr_core_handler

在中間層實現了一個名叫itr_core_handler虛函數,如果平臺未實現該函數,則發生中斷時會調用此處函數。此處邏輯就是panic()

(optee_os/core/kernel/interrupt.c)134 /* This function is supposed to be overridden in platform specific code */ 135 void __weak __noreturn itr_core_handler(void) 136 { 137 panic("Secure interrupt handler not defined"); 138 }

(2)、gic層的處理

  • 讀gicd寄存器,讀取中斷號
  • 進行中斷處理
  • 寫EOIR(End of Interrupt Registers),將該中斷號的中斷置為inactive
(optee_os/core/drivers/gic.c)void gic_it_handle(struct gic_data *gd){uint32_t iar;uint32_t id;iar = gic_read_iar(gd);id = iar & GICC_IAR_IT_ID_MASK;if (id <= gd->max_it)itr_handle(id);elseDMSG("ignoring interrupt %" PRIu32, id);gic_write_eoir(gd, iar);}

有關EOIR寄存器的介紹,可參見gic文檔

小小小總結一下: optee os中的中斷管理,不算復雜, 只有一個硬件中斷號,也不需要給中斷號做map。不像Linux抽象出來irq domain、中斷級聯、硬件中斷號和軟件中斷號需要進行map

3、optee中斷的API介紹(或叫中間層)

  • itr_handle : 回調driver中注冊的handler函數。itr_handle維護者一個LIST,將中斷號和driver中的handler結構體綁定
  • itr_add : 注冊一個中斷
  • itr_enable : enable一個中斷,其實就是修改gicd寄存器, 注:這是Linux Kernel沒有的API吧,optee勝一局
  • itr_disable :disable一個中斷,其實就是修改gicd寄存器, 注:這是Linux Kernel沒有的API吧,optee勝一局
  • itr_raise_sgi : 產生一個SGI中斷
  • itr_set_affinity :設置中斷affinity,也就是指定一個中斷,發生中斷時routing到哪顆Core上。 注:這是Linux Kernel沒有的API吧,optee勝一局
(optee_os/core/kernel/interrupt.c)void itr_init(struct itr_chip *chip){itr_chip = chip;}#ifdef CFG_DTint dt_get_irq(const void *fdt, int node){const uint32_t *prop = NULL;int len = 0;int it_num = DT_INFO_INVALID_INTERRUPT;if (!itr_chip || !itr_chip->dt_get_irq)return it_num;prop = fdt_getprop(fdt, node, "interrupts", &len);if (!prop)return it_num;return itr_chip->dt_get_irq(prop, len);}#endifvoid itr_handle(size_t it){struct itr_handler *h = NULL;bool was_handled = false;SLIST_FOREACH(h, &handlers, link) {if (h->it == it) {if (h->handler(h) == ITRR_HANDLED)was_handled = true;else if (!(h->flags & ITRF_SHARED))break;}}if (!was_handled) {EMSG("Disabling unhandled interrupt %zu", it);itr_chip->ops->disable(itr_chip, it);}}struct itr_handler *itr_alloc_add(size_t it, itr_handler_t handler,uint32_t flags, void *data){struct itr_handler *hdl = calloc(1, sizeof(*hdl));if (hdl) {hdl->it = it;hdl->handler = handler;hdl->flags = flags;hdl->data = data;itr_add(hdl);}return hdl;}void itr_free(struct itr_handler *hdl){if (!hdl)return;itr_chip->ops->disable(itr_chip, hdl->it);SLIST_REMOVE(&handlers, hdl, itr_handler, link);free(hdl);}void itr_add(struct itr_handler *h){struct itr_handler __maybe_unused *hdl = NULL;SLIST_FOREACH(hdl, &handlers, link)if (hdl->it == h->it)assert((hdl->flags & ITRF_SHARED) &&(h->flags & ITRF_SHARED));itr_chip->ops->add(itr_chip, h->it, h->flags);SLIST_INSERT_HEAD(&handlers, h, link);}void itr_enable(size_t it){itr_chip->ops->enable(itr_chip, it);}void itr_disable(size_t it){itr_chip->ops->disable(itr_chip, it);}void itr_raise_pi(size_t it){itr_chip->ops->raise_pi(itr_chip, it);}void itr_raise_sgi(size_t it, uint8_t cpu_mask){itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask);}void itr_set_affinity(size_t it, uint8_t cpu_mask){itr_chip->ops->set_affinity(itr_chip, it, cpu_mask);}/* This function is supposed to be overridden in platform specific code */void __weak __noreturn itr_core_handler(void){panic("Secure interrupt handler not defined");}

4、注冊要給中斷時底層都做了什么(itr_add做了什么?)

我們知道itr_add()調用了gic_op_add()函數,那么我們就從gic_op_add()看起

(1)、gic_op_add做了哪些事情呢?

  • gic_it_add:向gic中注冊中斷
  • gic_it_set_cpu_mask:設置該中斷的cpu mask,其實就是設置哪些cpu可以接受該中斷,這里設置的是any online core
  • gic_it_set_prio : 設置中斷優先級,中斷優先級是0x00-0xFF,數字越小優先級越高,這里設置的是0X01
(optee_os/core/drivers/gic.c)static void gic_op_add(struct itr_chip *chip, size_t it,uint32_t flags __unused){struct gic_data *gd = container_of(chip, struct gic_data, chip);if (it > gd->max_it)panic();gic_it_add(gd, it);/* Set the CPU mask to deliver interrupts to any online core */gic_it_set_cpu_mask(gd, it, 0xff);gic_it_set_prio(gd, it, 0x1);}

(2)、gic_it_add向gic中注冊中斷都干了什么事情呢

  • Disable the interrupt
  • Make it non-pending
  • Assign it to group0
  • Assign it to group1S
(optee_os/core/drivers/gic.c)static void gic_it_add(struct gic_data *gd, size_t it){size_t idx = it / NUM_INTS_PER_REG;uint32_t mask = 1 << (it % NUM_INTS_PER_REG);/* Disable the interrupt */io_write32(gd->gicd_base + GICD_ICENABLER(idx), mask);/* Make it non-pending */io_write32(gd->gicd_base + GICD_ICPENDR(idx), mask);/* Assign it to group0 */io_clrbits32(gd->gicd_base + GICD_IGROUPR(idx), mask);#if defined(CFG_ARM_GICV3)/* Assign it to group1S */io_setbits32(gd->gicd_base + GICD_IGROUPMODR(idx), mask);#endif}

我們以gicv3為例,這里也許你就有疑問了,為啥要Assign it to group0呢? 其實不要看這里的注釋,需要在gicv3/gicv3的文檔中可以找到答案:

  • 如果是gicv2,那么操作GICD_IGROUPR寄存器,給相關bit清0,就是將該中斷配置成group0,gicv2中group0是安全中斷,這符合我們的要求。
  • 如果是gicv3,那么先操作GICD_IGROUPR寄存器,給相關bit清0,清零該bit后對應了兩種結果:
    將該中斷置成了group0或group1s. 那么到底是用哪種結果呢? 那時gic硬件在處理該中斷時,還會再看GICD_IGROUPMODR寄存器,如果對應的bit為1, 那么該中斷就是group1s,否則是group0。
    所以呢,如果是gicv3,這里結合GICD_IGROUPR和GICD_IGROUPMODR就能將該中斷號配置成group1s

GICD_IGROUPMODR對應表格中的Group modifier bit
GICD_IGROUPR對應表格中的Group state bit

總結

以上是生活随笔為你收集整理的optee中添加一个中断以及底层代码的相关解读的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。