Como testar Standard Hotplug Controller

1. Como testar Standard Hotplug Controller

Guilherme Giacomo Simoes
simoes_png

(usa elementary OS)

Enviado em 14/11/2024 - 15:51h

Contextualizando o problema
Eu sou um contribuidor iniciante do kernel linux.
Recentemente fiz uma alteracao nos drivers de shpc (standard hotplug controller), aonde eu substitui a funcao request_irq() pela funcao request_threaded_irq(). Isso foi uma sugestao de Lukas Wunner no commit a0d58937404f5.
Dessa forma, quando receber uma interrupcao com o numero de irq fornecido para a request_threaded_irq(), ele executa uma pequena parte no contexto de interrupcao, e a maior parte do processamento de hotplug e executado em uma thread separada. Entao e precisei criar duas funcoes, uma funcao com algumas regras basicas para lidar com a interrupcao no contexto de interrupcao, e uma outra funcao com o "resto" do codigo de hotplug para ser executada fora do contetxto de interrupcao, em uma thread.

Vou deixar aqui o diff completo da minha alteracao:

diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 012b9e3fe5b0..b82d2bc4b777 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -166,6 +166,8 @@
#define SLOT_SERR_INT_MASK 0x3

static irqreturn_t shpc_isr(int irq, void *dev_id);
+static irqreturn_t shpc_ist(int irq, void *dev_id);
+
static void start_int_poll_timer(struct controller *ctrl, int sec);

static inline u8 shpc_readb(struct controller *ctrl, int reg)
@@ -746,7 +748,7 @@ int shpchp_set_bus_speed_mode(struct slot *slot, enum pci_bus_speed value)
return retval;
}

-static irqreturn_t shpc_isr(int irq, void *dev_id)
+static irqreturn_t shpc_ist(int irq, void *dev_id)
{
struct controller *ctrl = (struct controller *)dev_id;
u32 serr_int, slot_reg, intr_loc, intr_loc2;
@@ -825,6 +827,21 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}

+static irqreturn_t shpc_isr(int irq, void *dev_id)
+{
+ pr_info("%s: isr for interrupt handler\n", __func__);
+
+ struct controller *ctrl = dev_id;
+ struct pci_dev *pdev = ctrl->pci_dev;
+
+ if (pdev->ignore_hotplug) {
+ pr_info("ignoring hotplug");
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_WAKE_THREAD;
+}
+
static int shpc_get_max_bus_speed(struct controller *ctrl)
{
int retval = 0;
@@ -1001,8 +1018,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
pci_set_master(pdev);
}

- rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
- MY_NAME, (void *)ctrl);
+ rc = request_threaded_irq(ctrl->pci_dev->irq, shpc_isr, shpc_ist,
+ IRQF_SHARED, MY_NAME, (void *)ctrl);
+
ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",
ctrl->pci_dev->irq, rc);
if (rc) {


Caso queira testar voce mesmo pode executar o
git apply <caminho-do-arquiv-com-o-diff> 
.

Bom, a minha dificuldade e de fato testar essa mudanca. Nao consigo achar uma forma de simular a conexao de um dispositivo que e compativel com shpc, e que consiga assumir o controle do hotplug de pci para entao, executar as funcoes passadas para o request_threaded_irq().

O que ja tentei
QEMU:
Estou acostumado a testar no qemu, e tambem na minha propria maquina. Estive pesquisando muito sobre dispositivos que sao compativeis com shpc no qemu, e o mais perto que cheguei de conseguir testar e com o pci-bridge passando o parametro shpc=on.
Comando completo usado para inicializar o kernel recem compilado no qemu com uma bridge shpc:
qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0 earlyprintk=serial" -drive file=ubuntu.qcow2,format=qcow2 -m 1024 -enable-kvm -net nic -net user,hostfwd=tcp::2222-:22 -nographic -d int,cpu_reset -device pci-bridge,id=pci.1,chassis_nr=1,shpc=on 


, o kernel e iniciado normalmente, e o driver do shpc e iniciado. Porem, ele e interrompido, e nao "pega" o controle do hotplug porque ele e uma root bridge. E uma coisa obvia, ela somente e uma "ponte" para outras conexoes de PCI, nao e ela que deve ser responsavel por lidar com o hotplug dos dispositivos conectados a ela. Entao, aonde tem minha alteracao relacionada a request_threaded_irq() nem chega a ser executada. Pois a bridge n assumo o controle do hotplug de PCI.

Pesquisei muito e nao consegui achar outro dispositivo no qual eu consiga conectar e acionar o driver para o shpc.

QEMU + TELNET
Tentei iniciar o qemu com o comando anterior, mas sem a bridge, passando um "monitor" como parametro:
qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0 earlyprintk=serial" -drive file=ubuntu.qcow2,format=qcow2 -m 1024 -enable-kvm -monitor telnet:127.0.0.1:5555,server,nowait -nographic 


E entao, conectei ao telnet
telnet localhost 


E tentei conectar uma bridge no telnet:
device_add pci-bridge,id=pci.1,chassis_nr=1,shpc=on 


Sem sucesso tambem, porque obviamente, ela e uma root bridge como mencionei anteriormente.

QEMU + TELNET + E1000 (e outros devices)
Tentei iniciar o qemu com a bridge e conectar via telent um device e1000:
qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0 earlyprintk=serial" -drive file=ubuntu.qcow2,format=qcow2 -m 1024 -enable-kvm -monitor telnet:127.0.0.1:5555,server,nowait -nographic -device pci-bridge,id=pci.1,chassis_nr=1,shpc=on 

device_add e1000 id=net1,bus=pci.1 


Sem sucesso pq o e1000 nao e compativel com shpc.
Tentei tambem outros devicess que nao o e1000, mas nenhum alem da bridge sao compativeis com shpc.

TENTEI CONECTAR UMA BRIDGE EM UMA BRIDGE.
qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage -append "root=/dev/sda1 console=ttyS0 earlyprintk=serial" -drive file=ubuntu.qcow2,format=qcow2 -m 1024 -enable-kvm -monitor telnet:127.0.0.1:5555,server,nowait -nographic -device pci-bridge,id=pci.1,chassis_nr=1,shpc=on 

device_add  pci-bridge,id=pci.2,bus=pci.1,shpc=on 


Sem sucesso pq a segunda bridge tambem e uma root bridge e nao pega o controle das irq's.

OUTRAS MAQUINAS VIRTUAL:
KVM + Libvirt + Virt-Manager : Resultado identico ao que tive no qemu

vmware e virtualbox: Nao tem muito suporte para simulacao de conexao pcie .

NA MINHA PROPRIA MAQUINA (Dell latitude e7450)
Nenhum PCIe era compativel com shpc


Arquivo .config
CONFIG_PCI=y
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_SHPC=y
# CONFIG_HOTPLUG_PCI_ACPI is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set







  


2. Re: Como testar Standard Hotplug Controller

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/11/2024 - 09:24h

Algum desses virtualizadores consegue simular um dispositivo NVMe? Eles se apresentam como dispositivos no barramento PCIe, não? Pra mim, seriam candidatos naturais a hot swap já que o suporte para hot swap para discos existe há anos, ainda que em outros barramentos.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


3. Re: Como testar Standard Hotplug Controller

Guilherme Giacomo Simoes
simoes_png

(usa elementary OS)

Enviado em 17/11/2024 - 11:50h


paulo1205 escreveu:

Algum desses virtualizadores consegue simular um dispositivo NVMe? Eles se apresentam como dispositivos no barramento PCIe, não? Pra mim, seriam candidatos naturais a hot swap já que o suporte para hot swap para discos existe há anos, ainda que em outros barramentos.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)

Paulo, obrigado pela reposta e pela tentiva de ajuda.
Pois entao, esses emuladores tem sim simuladores de NVMe, o problema e que esses simuldores de NVMe nao tem suporte para SHPC.

Dispositivos PCI Simuláveis no QEMU:

Placas de Rede (Network Cards)
e1000: Emula a placa Intel PRO/1000 (Gigabit Ethernet).
rtl8139: Placa Ethernet Realtek RTL8139 (100 Mbps).
virtio-net-pci: Interface de rede otimizada para virtualização
ne2k_pci: Placa Ethernet baseada no modelo Novell NE2000.
vmxnet3: Emula a NIC VMware vmxnet3.

Controladores de Armazenamento (Storage Controllers)
virtio-blk-pci: Controlador de bloco otimizado para virtualização.
virtio-scsi-pci: Controlador SCSI para discos e fitas virtuais.
lsi: Emula o controlador LSI Logic SCSI.
megasas: Emula o controlador RAID MegaRAID SAS.
ahci: Controlador SATA baseado em AHCI (Advanced Host Controller Interface).
ide: Controlador IDE genérico.

Placas Gráficas (Graphics Cards)
virtio-gpu-pci: Placa de vídeo otimizada para virtualização.
qxl: Placa de vídeo otimizada para SPICE.
vmware-svga: Emula a placa gráfica VMware SVGA II.
cirrus: Placa gráfica Cirrus Logic GD5446.
ivshmem: Dispositivo de memória compartilhada para comunicação entre máquinas virtuais.
virtio-rng-pci: Gerador de números aleatórios otimizado para virtualização.
pci-bridge: Bridge PCI genérica. (aparentemente seugndo minhas pesquisas, a unica compativel com shpc
pci-expander-bus: Extensão para criar hierarquias PCI Express.

Dispositivos Misc. (Diversos)
x3130-upstream: Emula uma bridge upstream PCI Express.
xio3130-downstream: Emula uma bridge downstream PCI Express.
vfio-pci: Usado para passthrough de dispositivos PCI reais.
intel-iommu: Simula o Intel VT-d IOMMU para virtualização.

Controlador NVMe (Non-Volatile Memory Express).
nvme: Usado para simular dispositivos de armazenamento modernos.
1b36:0011
PCI PVPanic device (-device pvpanic-pci)

1b36:0012
PCI ACPI ERST device (-device acpi-erst)

1b36:0013
PCI UFS device (-device ufs)

1b36:0014
PCI RISC-V IOMMU device

COM ABSOLUTAMENTE NENHUM DESSES CONSIGO FAZER COM QUE O SHPC TOME CONTROLE DO HOTPLUG.

O unico compativel com shpc, e o pci-bridge, porem ele nao assume o controle do hotplug por ser uma root bridge.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts