色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于PCIe-Native機制的熱插拔

openEuler ? 來源:openEuler ? 作者:openEuler ? 2022-09-06 10:32 ? 次閱讀

熱插拔即帶電插拔,在虛擬化場景下,熱插拔就是在虛擬機運行過程中對磁盤網卡等設備進行動態調整。

常見的熱插拔機制有 ACPI 機制的熱插拔,PCIe-Native 機制的熱插拔。ACPI 機制的熱插拔依賴 ACPI 表,在 ACPI 表中會存放設備熱插拔相關的信息。PCIe-Native 機制的熱插拔是 PCI 規范中定義的,設備一般是熱插到 Root Port 設備上,Root Port 設備可以認為是一個虛擬的橋設備,對應一個插槽。Root Port 設備本身不支持熱插拔,因此需要在啟動虛擬機前提前配置。

目前,StratoVirt 標準機型中實現了基于 PCIe-Native 機制的熱插拔。支持熱插拔的設備包括磁盤、網卡、PCI 直通設備。

熱插拔的整體流程如下:

3699a45a-2d1a-11ed-ba43-dac502259ad0.png

對于熱插主要分為兩步:

  1. 用戶通過 QMP 下發 device_add 命令,StratoVirt 收到命令后會進行設備的實例化,然后插入到對應的 Root Port 設備上。
  2. Root Port 設備更新相關的寄存器配置,然后發送中斷通知虛擬機內驅動處理。

對于熱拔也可以分為兩步:

  1. 用戶通過 QMP 下發 device_del 命令,StratoVirt 收到命令后,更新 Root Port 中的寄存器,然后發送中斷通知虛擬機內驅動處理。
  2. 虛擬機內驅動處理后會回寫寄存器,觸發 StratoVirt 側銷毀相應設備。

具體實現

在 StratoVirt 的 pci/src/hotplug.rs 文件中定義了熱插拔特性,其中 plug 函數對應熱插操作,用于熱插設備。unplug_request 函數對應熱拔操作,用于發起熱拔設備請求,這里只是通知虛擬機內驅動去處理熱拔請求,還未移除設備,可以理解為是一個異步請求。當虛擬機內驅動處理完成后,寫寄存器觸發設備下線后,會回調 unplug 函數用于銷毀設備。

pub trait HotplugOps: Send {    /// Plug device, usually called when hot plug device in device_add.    fn plug(&mut self, dev: &Arc>) -> Result<()>;
    /// Unplug device request, usually called when hot unplug device in device_del.    /// Only send unplug request to the guest OS, without actually removing the device.    fn unplug_request(&mut self, dev: &Arc>) -> Result<()>;
    /// Remove the device.    fn unplug(&mut self, dev: &Arc>) -> Result<()>;}

熱插實現

StratoVirt 里通過給 RootPort 實現了 HotplugOps 特性,使得 PCI 設備能夠熱插到 Root Port 設備上。

設備熱插的主要實現邏輯在 plug 函數里。首先獲取了設備的 devfn 號,也就是 Device 號和 Function 號,目前熱插只支持 Device 號和 Function 號都為 0 的設備。因此這里做了判斷。

然后會在 RootPort 設備的 PCI 配置空間中的 PCI Express Capability(PCI 配置空間和 PCI Express Capability 寄存器定義可以參考 PCI 規范)中設置 Slot 狀態寄存器和 Link 狀態寄存器,然后通過 hotplug_event_notify 函數發送中斷通知虛擬機。這里熱插設備主要是通過 Attention Button Pressed(對應 PCI_EXP_HP_EV_ABP)事件觸發的。

這里簡單介紹下不同標記位的含義。

符號 描述
PCI_EXP_SLTSTA Slot Status Register 表示 Slot 狀態寄存器,不同的位表示 Slot 不同的狀態
PCI_EXP_SLTSTA_PDS Presence Detect State 表示 Slot 上設備的在位狀態,置 1 表示在位
PCI_EXP_HP_EV_PDC Presence Detect Changed 表示 Slot 上設備在位狀態是否發生變化
PCI_EXP_HP_EV_ABP Attention Button Pressed 表示 Attention 按鈕被按下,該按鈕用于觸發熱插拔操作
PCI_EXP_LNKSTA Link Status Register 表示 Link 狀態的寄存器
PCI_EXP_LNKSTA_DLLLA Data Link Layer Link Active 表示數據鏈路控制和管理狀態,置 1 表示處于 Active 狀態
impl HotplugOps for RootPort {    fn plug(&mut self, dev: &Arc>) -> Result<()> {        let devfn = dev            .lock()            .unwrap()            .devfn()            .chain_err(|| "Failed to get devfn")?;        // Only if devfn is equal to 0, hot plugging is supported.        if devfn == 0 {            let offset = self.config.ext_cap_offset;            le_write_set_value_u16(                &mut self.config.config,                (offset + PCI_EXP_SLTSTA) as usize,                PCI_EXP_SLTSTA_PDS | PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP,            )?;            le_write_set_value_u16(                &mut self.config.config,                (offset + PCI_EXP_LNKSTA) as usize,                PCI_EXP_LNKSTA_NLW | PCI_EXP_LNKSTA_DLLLA,            )?;            self.hotplug_event_notify();        }        Ok(())    }}

在 hotplug_event_notify 函數中會調用 MSIX 中斷的 notify 函數發送中斷到虛擬機內,虛擬機內 pciehp 驅動收到中斷后會處理相關的熱插請求。

fn hotplug_event_notify(&mut self) {    if let Some(msix) = self.config.msix.as_mut() {        msix.lock()            .unwrap()            .notify(0, self.dev_id.load(Ordering::Acquire));    } else {        error!("Failed to send interrupt: msix does not exist");    }}

熱拔實現

對于設備熱拔請求的邏輯主要在 unplug_request 函數,該函數負責更新寄存器,并且通過調用 hotplug_event_notify 函數發送中斷通知虛擬機內驅動處理設備熱拔請求。

unplug_request 函數里主要是清零了 Link 狀態寄存器中的 PCI_EXP_LNKSTA_DLLLA 標記位,并且在 Slot 狀態寄存器中的設置了 PCI_EXP_HP_EV_ABP 標記位。從這里也可以發現,其實無論是熱插請求還是熱拔請求,都是通過 Attention Button Pressed(對應 PCI_EXP_HP_EV_ABP)事件觸發的,虛擬機內驅動會根據設備的在位狀態來判斷是熱插請求還是熱拔請求。

impl HotplugOps for RootPort {    fn unplug_request(&mut self, dev: &Arc>) -> Result<()> {        let devfn = dev            .lock()            .unwrap()            .devfn()            .chain_err(|| "Failed to get devfn")?;        if devfn != 0 {            return self.unplug(dev);        }
        let offset = self.config.ext_cap_offset;        le_write_clear_value_u16(            &mut self.config.config,            (offset + PCI_EXP_LNKSTA) as usize,            PCI_EXP_LNKSTA_DLLLA,        )?;
        let mut slot_status = PCI_EXP_HP_EV_ABP;        if let Some(&true) = FAST_UNPLUG_FEATURE.get() {            slot_status |= PCI_EXP_HP_EV_PDC;        }        le_write_set_value_u16(            &mut self.config.config,            (offset + PCI_EXP_SLTSTA) as usize,            slot_status,        )?;        self.hotplug_event_notify();        Ok(())    }}

對于熱拔設備,StratoVirt 側在更新寄存器發送中斷通知虛擬機內驅動后,實際上還沒有真正的移除設備,而是等到虛擬機內驅動處理后回寫寄存器通知 StratoVirt 側下線設備后,才會真正銷毀設備。

虛擬機內驅動寫 Root Port 寄存器會調用到 write_config 函數,在 write_config 函數里會調用 do_unplug 函數來處理熱拔設備相關的邏輯。

    fn write_config(&mut self, offset: usize, data: &[u8]) {        ...
        self.do_unplug(offset, end, old_ctl);    }

do_unplug 函數里首先保證了寫入的寄存器是 Slot Control 寄存器,否則直接返回,不做處理。然后判斷在設備當前在位的情況下,寫入的寄存器標記位為 PCI_EXP_SLTCTL_PWR_IND_OFF 和 PCI_EXP_SLTCTL_PCC 時,并且這兩個標記位發生了變化,也就是寫入之前的沒有這兩個標記位,上述條件都滿足時,會調用 remove_devices 函數開始真正銷毀設備。

符號 描述
PCI_EXP_SLTCTL_PCC Power Controller Control 表示電源管理狀態,置 1 表示上電狀態
PCI_EXP_SLTCTL_PWR_IND_OFF Power Indicator off 表示是否允許移除設備,置 1 表示設備允許被移除
fn do_unplug(&mut self, offset: usize, end: usize, old_ctl: u16) {    let cap_offset = self.config.ext_cap_offset;    // Only care the write config about slot control    if !ranges_overlap(        offset,        end,        (cap_offset + PCI_EXP_SLTCTL) as usize,        (cap_offset + PCI_EXP_SLTCTL + 2) as usize,    ) {        return;    }
    let status =        le_read_u16(&self.config.config, (cap_offset + PCI_EXP_SLTSTA) as usize).unwrap();    let val = le_read_u16(&self.config.config, offset).unwrap();    // Only unplug device when the slot is on    // Don't unplug when slot is off for guest OS overwrite the off status before slot on.    if (status & PCI_EXP_SLTSTA_PDS != 0)        && (val as u16 & PCI_EXP_SLTCTL_PCC == PCI_EXP_SLTCTL_PCC)        && (val as u16 & PCI_EXP_SLTCTL_PWR_IND_OFF == PCI_EXP_SLTCTL_PWR_IND_OFF)        && (old_ctl & PCI_EXP_SLTCTL_PCC != PCI_EXP_SLTCTL_PCC            || old_ctl & PCI_EXP_SLTCTL_PWR_IND_OFF != PCI_EXP_SLTCTL_PWR_IND_OFF)    {        self.remove_devices();
        if let Err(e) = self.update_register_status() {            error!("{}", e.display_chain());            error!("Failed to update register status");        }    }
    self.hotplug_command_completed();    self.hotplug_event_notify();}

在調用 remove_devices 函數移除設備之后,調用 update_register_status 函數更新寄存器的狀態,主要是清理了 Link 狀態和設備在位狀態,并且設置了 Presence Detect Changed(對應 PCI_EXP_HP_EV_PDC)標記位表示設備在位狀態發生了變化。

/// Update register when the guest OS trigger the removal of the device.fn update_register_status(&mut self) -> Result<()> {    let cap_offset = self.config.ext_cap_offset;    le_write_clear_value_u16(        &mut self.config.config,        (cap_offset + PCI_EXP_SLTSTA) as usize,        PCI_EXP_SLTSTA_PDS,    )?;    le_write_clear_value_u16(        &mut self.config.config,        (cap_offset + PCI_EXP_LNKSTA) as usize,        PCI_EXP_LNKSTA_DLLLA,    )?;    le_write_set_value_u16(        &mut self.config.config,        (cap_offset + PCI_EXP_SLTSTA) as usize,        PCI_EXP_SLTSTA_PDC,    )?;    Ok(())}

在更新完寄存器后,在 hotplug_command_completed 還會設置 Command Completed(對應 PCI_EXP_HP_EV_CCI)表示命令處理完成,最后再發送中斷通知虛擬機內驅動。至此,整個設備熱拔流程就結束了。

fn hotplug_command_completed(&mut self) {    if let Err(e) = le_write_set_value_u16(        &mut self.config.config,        (self.config.ext_cap_offset + PCI_EXP_SLTSTA) as usize,        PCI_EXP_HP_EV_CCI,    ) {        error!("{}", e.display_chain());        error!("Failed to write command completed");    }}
符號 描述
PCI_EXP_HP_EV_CCI Command Completed 表示命令處理完成,可以處理下一條命令

總結

PCIe Native 機制的熱插拔主要是通過 Root Port 設備上的寄存器來表示不同狀態,通過中斷來通知虛擬機,從而實現了設備的熱插拔。

審核編輯:湯梓紅


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 熱插拔
    +關注

    關注

    2

    文章

    226

    瀏覽量

    37826
  • PCIe
    +關注

    關注

    15

    文章

    1283

    瀏覽量

    83686
  • 虛擬機
    +關注

    關注

    1

    文章

    954

    瀏覽量

    28632

原文標題:StratoVirt 中的 PCI 設備熱插拔實現

文章出處:【微信號:openEulercommunity,微信公眾號:openEuler】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    高精度熱插拔和電源監控

    本內容提供了高精度熱插拔和電源監控,介紹什么是熱插拔和利用熱插拔進行的設計方案及電源監控知識。
    發表于 11-04 10:00 ?1727次閱讀
    高精度<b class='flag-5'>熱插拔</b>和電源監控

    熱插拔是什么?熱插拔有哪些特點?

    什么是熱插拔熱插拔(hot-plugging或Hot Swap)即帶電插拔熱插拔功能就是允許用戶在不關閉系統,不切斷電源的情況下取出和更換損壞的硬盤、電源或板卡等部件,從而提高了系
    發表于 12-13 10:53

    即插即用和熱插拔的區別

    本帖最后由 eehome 于 2013-1-5 10:01 編輯 “即插即用”是指安裝了設備之后系統可以自動配置和管理設備,不需要人工處理即可使用。“熱插拔”是指可以在開機狀態下將設備與主機
    發表于 10-23 10:26

    如何對BMS單元連接進行熱插拔

    過渡到熱插拔測試,一些故障實際上是針對熱插拔失效機制的。觀察表明,2、3、4故障與熱插拔故障檢測有關。當然,由于不同的熱插拔連接模式的出現,
    發表于 09-07 18:20

    熱插拔CompactPCI總線

    DN200- 熱插拔CompactPCI總線
    發表于 07-17 06:32

    熱插拔的基本原理是什么?熱插拔有哪些功能?

    熱插拔的基本原理是什么?熱插拔有哪些功能?
    發表于 05-24 06:01

    使熱插拔與電子熔絲的優勢

    使用熱插拔控制器的優勢電子熔絲與熱插拔控制器之間的主要區別是熱插拔是一種能夠驅動外部FET的控制器(如圖1所示)。FET通過熱插拔控制器中的控制邏輯進行開啟和關閉,以調節負載處的電源供
    發表于 11-17 07:12

    熱插拔裝置軟件

    熱插拔裝置軟件USB Safely Remove是一款支持熱插拔裝置和迅速切斷一個公用的熱插拔裝置的軟件。
    發表于 04-23 09:32 ?151次下載

    熱插拔

    熱插拔              熱插拔(hot-plugging或Hot Swap)功能就是允許用戶在不關閉系統,不切斷電源的情況下取出和更換
    發表于 12-17 11:41 ?653次閱讀

    PCIe總線的熱插拔機制

    當然,熱插拔不僅僅是硬件的事,其需要軟硬件協同實現。要想實現熱插拔功能,操作系統、主板熱插拔驅動器、PCIe卡設備驅動以及PCIe卡硬件功能
    的頭像 發表于 09-06 09:20 ?2w次閱讀

    PCIe引腳PRSNT與熱插拔

    熱插拔的基本目的是要讓PCIe設備按照規定的順序、原則,從系統中移除或插入到系統中來,并能正常的工作,且不影響系統的正常運行。事實上,PCIe熱插拔”的關鍵目的就是為前面面所提到的系
    的頭像 發表于 12-14 10:59 ?5210次閱讀

    熱插拔和非熱插拔的區別

    熱插拔和非熱插拔的區別? 熱插拔和非熱插拔是指電子設備或組件在工作狀態下是否可以進行插拔操作的一種分類。
    的頭像 發表于 12-28 10:01 ?3302次閱讀

    熱插拔是什么原理

    熱插拔(Hot Swap)是一種允許在系統運行過程中,動態地插入或移除硬件設備的技術。這種技術在計算機硬件、通信設備和存儲設備等領域得到了廣泛應用。熱插拔技術的目的是為了提高系統的可擴展性、可靠性
    的頭像 發表于 01-16 11:03 ?4745次閱讀
    <b class='flag-5'>熱插拔</b>是什么原理

    鍵盤熱插拔和非熱插拔的區別

    鍵盤熱插拔和非熱插拔的區別 鍵盤是計算機外設設備之一,熱插拔是指在計算機運行中插入或拔出設備而無需重啟計算機,非熱插拔則需要重啟計算機才能生效。鍵盤
    的頭像 發表于 02-02 17:34 ?1.1w次閱讀

    PCIe熱插拔機制介紹

    前言本文主要講述PCIe熱插拔機制,通過圖形方式方便讀者快速掌握。 一、概述 如果在PCIe設備不支持熱插拔的條件下,在不斷電的情況下
    的頭像 發表于 11-20 09:07 ?1255次閱讀
    <b class='flag-5'>PCIe</b><b class='flag-5'>熱插拔</b><b class='flag-5'>機制</b>介紹
    主站蜘蛛池模板: 国产一区私人高清影院 | 视频一区精品自拍亚洲 | 国产 精品 亚洲 欧美 高清 | 出差无套内射小秘书 | 亚洲AV久久无码精品热九九 | 久久有码中文字幕 | 亚州综合网| 《乳色吐息》无删减版在线观看 | 国产精品久免费的黄网站 | 伊人狠狠丁香婷婷综合尤物 | 手机在线观看毛片 | 久久AAAA片一区二区 | 草民电影网午夜伦理电影网 | 文中字幕一区二区三区视频播放 | 亚洲VA欧美VA天堂V国产综合 | 超碰97人人做人人爱网站 | 男插女高潮一区二区 | 免费视频网站嗯啊轻点 | 俄罗斯女人与马Z00Z视频 | 久久视频这有精品63在线国产 | 暖暖 免费 高清 日本在线 | 精品无码乱码AV | 北条麻妃久久99精品 | 欧美一区二区三区久久综 | 老司机福利视频一区在线播放 | 和老外3p爽粗大免费视频 | 亚洲精品久久久久中文字幕二区 | 久久精品观看 | 99久久热视频只有精品 | 欧美日本韩国一二区视频 | 99热久久这里只有精品视频 | 美女xx00| 亚在线观看免费视频入口 | 亚欧免费观看在线观看更新 | 黄色三级网站在线观看 | 久久久久99精品成人片三人毛片 | 色偷偷超碰97人人澡人人 | 青青草原在线新免费 | 久久视热频这里只精品 | 欧美精品一区二区三区四区 | 国产免费人成在线视频视频 |