在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于PCIe-Native機(jī)制的熱插拔

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

熱插拔即帶電插拔,在虛擬化場景下,熱插拔就是在虛擬機(jī)運行過程中對磁盤網(wǎng)卡等設(shè)備進(jìn)行動態(tài)調(diào)整。

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

目前,StratoVirt 標(biāo)準(zhǔn)機(jī)型中實現(xiàn)了基于 PCIe-Native 機(jī)制的熱插拔。支持熱插拔的設(shè)備包括磁盤、網(wǎng)卡、PCI 直通設(shè)備。

熱插拔的整體流程如下:

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

對于熱插主要分為兩步:

  1. 用戶通過 QMP 下發(fā) device_add 命令,StratoVirt 收到命令后會進(jìn)行設(shè)備的實例化,然后插入到對應(yīng)的 Root Port 設(shè)備上。
  2. Root Port 設(shè)備更新相關(guān)的寄存器配置,然后發(fā)送中斷通知虛擬機(jī)內(nèi)驅(qū)動處理。

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

  1. 用戶通過 QMP 下發(fā) device_del 命令,StratoVirt 收到命令后,更新 Root Port 中的寄存器,然后發(fā)送中斷通知虛擬機(jī)內(nèi)驅(qū)動處理。
  2. 虛擬機(jī)內(nèi)驅(qū)動處理后會回寫寄存器,觸發(fā) StratoVirt 側(cè)銷毀相應(yīng)設(shè)備。

具體實現(xiàn)

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

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<()>;}

熱插實現(xiàn)

StratoVirt 里通過給 RootPort 實現(xiàn)了 HotplugOps 特性,使得 PCI 設(shè)備能夠熱插到 Root Port 設(shè)備上。

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

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

這里簡單介紹下不同標(biāo)記位的含義。

符號 描述
PCI_EXP_SLTSTA Slot Status Register 表示 Slot 狀態(tài)寄存器,不同的位表示 Slot 不同的狀態(tài)
PCI_EXP_SLTSTA_PDS Presence Detect State 表示 Slot 上設(shè)備的在位狀態(tài),置 1 表示在位
PCI_EXP_HP_EV_PDC Presence Detect Changed 表示 Slot 上設(shè)備在位狀態(tài)是否發(fā)生變化
PCI_EXP_HP_EV_ABP Attention Button Pressed 表示 Attention 按鈕被按下,該按鈕用于觸發(fā)熱插拔操作
PCI_EXP_LNKSTA Link Status Register 表示 Link 狀態(tài)的寄存器
PCI_EXP_LNKSTA_DLLLA Data Link Layer Link Active 表示數(shù)據(jù)鏈路控制和管理狀態(tài),置 1 表示處于 Active 狀態(tài)
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 函數(shù)中會調(diào)用 MSIX 中斷的 notify 函數(shù)發(fā)送中斷到虛擬機(jī)內(nèi),虛擬機(jī)內(nèi) pciehp 驅(qū)動收到中斷后會處理相關(guān)的熱插請求。

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");    }}

熱拔實現(xiàn)

對于設(shè)備熱拔請求的邏輯主要在 unplug_request 函數(shù),該函數(shù)負(fù)責(zé)更新寄存器,并且通過調(diào)用 hotplug_event_notify 函數(shù)發(fā)送中斷通知虛擬機(jī)內(nèi)驅(qū)動處理設(shè)備熱拔請求。

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

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(())    }}

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

虛擬機(jī)內(nèi)驅(qū)動寫 Root Port 寄存器會調(diào)用到 write_config 函數(shù),在 write_config 函數(shù)里會調(diào)用 do_unplug 函數(shù)來處理熱拔設(shè)備相關(guān)的邏輯。

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

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

符號 描述
PCI_EXP_SLTCTL_PCC Power Controller Control 表示電源管理狀態(tài),置 1 表示上電狀態(tài)
PCI_EXP_SLTCTL_PWR_IND_OFF Power Indicator off 表示是否允許移除設(shè)備,置 1 表示設(shè)備允許被移除
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();}

在調(diào)用 remove_devices 函數(shù)移除設(shè)備之后,調(diào)用 update_register_status 函數(shù)更新寄存器的狀態(tài),主要是清理了 Link 狀態(tài)和設(shè)備在位狀態(tài),并且設(shè)置了 Presence Detect Changed(對應(yīng) PCI_EXP_HP_EV_PDC)標(biāo)記位表示設(shè)備在位狀態(tài)發(fā)生了變化。

/// 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 還會設(shè)置 Command Completed(對應(yīng) PCI_EXP_HP_EV_CCI)表示命令處理完成,最后再發(fā)送中斷通知虛擬機(jī)內(nèi)驅(qū)動。至此,整個設(shè)備熱拔流程就結(jié)束了。

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 表示命令處理完成,可以處理下一條命令

總結(jié)

PCIe Native 機(jī)制的熱插拔主要是通過 Root Port 設(shè)備上的寄存器來表示不同狀態(tài),通過中斷來通知虛擬機(jī),從而實現(xiàn)了設(shè)備的熱插拔。

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 熱插拔
    +關(guān)注

    關(guān)注

    2

    文章

    224

    瀏覽量

    37354
  • PCIe
    +關(guān)注

    關(guān)注

    15

    文章

    1239

    瀏覽量

    82658
  • 虛擬機(jī)
    +關(guān)注

    關(guān)注

    1

    文章

    917

    瀏覽量

    28202

原文標(biāo)題:StratoVirt 中的 PCI 設(shè)備熱插拔實現(xiàn)

文章出處:【微信號:openEulercommunity,微信公眾號:openEuler】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    高精度熱插拔和電源監(jiān)控

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

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

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

    即插即用和熱插拔的區(qū)別

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

    如何對BMS單元連接進(jìn)行熱插拔

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

    熱插拔PCI總線

    DN155- 熱插拔PCI總線
    發(fā)表于 05-28 12:21

    熱插拔CompactPCI總線

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

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

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

    使熱插拔與電子熔絲的優(yōu)勢

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

    熱插拔裝置軟件

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

    熱插拔

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

    PCIe總線的熱插拔機(jī)制

    當(dāng)然,熱插拔不僅僅是硬件的事,其需要軟硬件協(xié)同實現(xiàn)。要想實現(xiàn)熱插拔功能,操作系統(tǒng)、主板熱插拔驅(qū)動器、PCIe卡設(shè)備驅(qū)動以及PCIe卡硬件功能
    的頭像 發(fā)表于 09-06 09:20 ?2w次閱讀

    PCIe引腳PRSNT與熱插拔

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

    熱插拔和非熱插拔的區(qū)別

    熱插拔和非熱插拔的區(qū)別? 熱插拔和非熱插拔是指電子設(shè)備或組件在工作狀態(tài)下是否可以進(jìn)行插拔操作的一種分類。
    的頭像 發(fā)表于 12-28 10:01 ?2977次閱讀

    鍵盤熱插拔和非熱插拔的區(qū)別

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

    PCIe熱插拔機(jī)制介紹

    前言本文主要講述PCIe熱插拔機(jī)制,通過圖形方式方便讀者快速掌握。 一、概述 如果在PCIe設(shè)備不支持熱插拔的條件下,在不斷電的情況下
    的頭像 發(fā)表于 11-20 09:07 ?387次閱讀
    <b class='flag-5'>PCIe</b><b class='flag-5'>熱插拔</b><b class='flag-5'>機(jī)制</b>介紹
    主站蜘蛛池模板: 毛片福利| 国产资源网| 午夜免费啪在线观看视频网站| 一级片在线视频| 天天摸天天看| 久久精品美女久久| 午夜啪啪片| 欧美一区二区三区视频在线观看 | 亚洲一区二区三区深夜天堂| 日本视频一区二区| 亚洲成人自拍| 一级毛片不卡| 手机看片a永久免费看大片| 人人澡人| 国内一级毛片| 夜夜爱夜夜爽夜夜做夜夜欢| 欧美性受xxxx| 最好看的2019中文字幕免费高清| 网www天堂资源在线| 欧美精品video| 97干97吻| 国产区精品高清在线观看| 亚洲一区二区三区免费观看| 日韩欧美中文字幕在线视频| 国产网站免费| 免费看黄色录像| 亚洲一区二区三区高清| 欧美式free群乱| 夜夜摸夜夜爽| 欧美视频三区| 韩国r天堂| 国内自拍欧美| 天堂网在线最新版官网| 国产婷婷色| 黄色午夜网站| 天堂网中文字幕| 天天激情综合| 夜色资源站www国产在线观看| 你懂的国产| 天天草b| 性感美女逼|