Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.
RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.

Bug 1499127

Summary: Qemu and guest will become hang, when starting up network which with vhost-user and iommu backend in guest
Product: Red Hat Enterprise Linux 7 Reporter: Pei Zhang <pezhang>
Component: openvswitchAssignee: Maxime Coquelin <maxime.coquelin>
Status: CLOSED ERRATA QA Contact: Pei Zhang <pezhang>
Severity: high Docs Contact:
Priority: high    
Version: 7.5CC: ailan, atragler, chayang, fleitner, juzhang, kzhang, maxime.coquelin, michen, pvauter, tredaelli, virt-maint
Target Milestone: rc   
Target Release: ---   
Hardware: x86_64   
OS: Unspecified   
Whiteboard:
Fixed In Version: openvswitch-2.9.0-1.el7fdp Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-03-19 10:19:14 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1475436    

Description Pei Zhang 2017-10-06 07:12:09 UTC
Description of problem:
Boot guest with vhost-user and vIOMMU, when start up the network device in guest, sometimes the guest and qemu will become hang.


Version-Release number of selected component (if applicable):
3.10.0-727.el7.x86_64(both host& guest)
qemu-kvm-rhev-2.10.0-1.el7.x86_64
seabios-bin-1.10.2-4.el7.noarch


How reproducible:
2/5


Steps to Reproduce:

1.Compile dpdk from below repo and branch. These are provided by Maxime Coquelin. As dpdk with viommu is not supported yet.

repo: https://gitlab.com/mcoquelin/dpdk-next-virtio.git
branch: https://gitlab.com/mcoquelin/dpdk-next-virtio/tree/vhost_iotlb_v2

How to compile it:
https://mojo.redhat.com/docs/DOC-1093190


2. Boot testpmd, then set porlist and start
# /root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/build/app/test-pmd/testpmd \
-l 2,4,6 --socket-mem=1024,1024 -n 4 \
-d /root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/lib/librte_pmd_vhost.so \
--vdev 'net_vhost0,iface=/tmp/vhost-user1' -- \
--portmask=3 --disable-hw-vlan -i --rxq=1 --txq=1 \
--nb-cores=2 --forward-mode=io


testpmd> set portlist 0,1
testpmd> start 


3. Boot qemu
/usr/libexec/qemu-kvm -name rhel7.5 -M q35,kernel-irqchip=split \
-device intel-iommu,device-iotlb=on,intremap \
-cpu host -m 8G \
-object memory-backend-file,id=mem,size=8G,mem-path=/dev/hugepages,share=on \
-numa node,memdev=mem -mem-prealloc \
-smp 4,sockets=1,cores=4,threads=1 \
-device pcie-root-port,id=root.1,slot=1 \
-device pcie-root-port,id=root.2,slot=2 \
-chardev socket,id=char0,path=/tmp/vhost-user1 \
-device virtio-net-pci,netdev=mynet1,mac=aa:66:da:5f:dd:11,iommu_platform=on,ats=on,bus=root.1 \
-netdev type=vhost-user,id=mynet1,chardev=char0,vhostforce \
-drive file=/home/rhel7.5.qcow2,format=qcow2,if=none,id=drive-virtio-blk0,werror=stop,rerror=stop \
-device virtio-blk-pci,drive=drive-virtio-blk0,id=virtio-blk0,bus=root.2 \
-vnc :2 \
-monitor stdio \

4. After guest boot up, set network up, then guest and qemu will become hang.
# ifconfig eth0 up


Actual results:
qemu and guest will both become hang.


Expected results:
qemu and guest should work well.


Additional info:
1. Guest kernel line(iommu=pt and intel_iommu=on is not set):
# cat /proc/cmdline 
BOOT_IMAGE=/vmlinuz-3.10.0-693.5.1.el7.x86_64 root=/dev/mapper/rhel-root ro crashkernel=auto rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet LANG=en_US.UTF-8

2. In guest, stop NetworkManager before starting this test is needed.
# service NetworkManager stop
# chkconfig NetworkManager off

3. Related rhel7.4.z bug[1]
[1]Bug 1498817 - Vhost IOMMU support regression since qemu-kvm-rhev-2.9.0-16.el7_4.5

Comment 2 Maxime Coquelin 2017-10-06 07:37:19 UTC
Hi Pei,

I will try to reproduce the issue.
Does it works well when having iommu=pt and intel_iommu=on in kernel cmdline?

Thanks,
Maxime

Comment 3 Maxime Coquelin 2017-10-06 07:48:45 UTC
Other question is does the same setup works with vhost-kernel backend,
or Qemu & backend also hang?

Comment 4 Maxime Coquelin 2017-10-06 08:55:43 UTC
I reproduce an issue with user backend, but it does not hang neither the guest nor QEMU.

The problem is that QEMU sends IOTLB updates not covering the addresses passed with the IOTLB miss requests.
So the vring addresses are never translated on backend side and the rings are not started.

For example, the backend needs to translate iova 0x179d7b240, corresponding to the desc ring start address. On Qemu side, we can see:
vhost_device_iotlb_miss: miss iova 179d7b240
vhost_device_iotlb_miss: iotlb update iova 240 - len 9fdc0

Comment 6 Pei Zhang 2017-10-06 12:24:23 UTC
(In reply to Maxime Coquelin from comment #2)
> Hi Pei,
> 
> I will try to reproduce the issue.
> Does it works well when having iommu=pt and intel_iommu=on in kernel cmdline?
> 
Hi Maxime,

With iommu=pt and intel_iommu=on in kernel cmdline, still can hit hang issue.


(In reply to Maxime Coquelin from comment #3)
> Other question is does the same setup works with vhost-kernel backend,
> or Qemu & backend also hang?

1. With same steps but vhost-user network without "iommu_platform=on,ats=on"[1], everything works well, both qemu & testpmd backend works well.

[1]
-chardev socket,id=char0,path=/tmp/vhost-user1 \
-device virtio-net-pci,netdev=mynet1,mac=aa:66:da:5f:dd:11,bus=root.1 \
-netdev type=vhost-user,id=mynet1,chardev=char0,vhostforce \

Related full command:
# /usr/libexec/qemu-kvm -name rhel7.5 -M q35,kernel-irqchip=split \
-device intel-iommu,device-iotlb=on,intremap \
-cpu host -m 8G \
-object memory-backend-file,id=mem,size=8G,mem-path=/dev/hugepages,share=on \
-numa node,memdev=mem -mem-prealloc \
-smp 4,sockets=1,cores=4,threads=1 \
-device pcie-root-port,id=root.1,slot=1 \
-device pcie-root-port,id=root.2,slot=2 \
-chardev socket,id=char0,path=/tmp/vhost-user1 \
-device virtio-net-pci,netdev=mynet1,mac=aa:66:da:5f:dd:11,bus=root.1 \
-netdev type=vhost-user,id=mynet1,chardev=char0,vhostforce \
-drive file=/home/rhel7.5.qcow2,format=qcow2,if=none,id=drive-virtio-blk0,werror=stop,rerror=stop \
-device virtio-blk-pci,drive=drive-virtio-blk0,id=virtio-blk0,bus=root.2 \
-vnc :2 \
-monitor stdio \


2. Boot VM With vhost backend[2], everything works well when start up the network device in guest. Both qemu and guest work well.

[2]
-netdev tap,id=mynet1,vhost=on \
-device virtio-net-pci,netdev=mynet1,mac=aa:66:da:5f:dd:11,iommu_platform=on,ats=on,bus=root.1 \

Related full command:
/usr/libexec/qemu-kvm -name rhel7.5 -M q35,kernel-irqchip=split \
-device intel-iommu,device-iotlb=on,intremap \
-cpu host -m 8G \
-object memory-backend-file,id=mem,size=8G,mem-path=/dev/hugepages,share=on \
-numa node,memdev=mem -mem-prealloc \
-smp 4,sockets=1,cores=4,threads=1 \
-device pcie-root-port,id=root.1,slot=1 \
-device pcie-root-port,id=root.2,slot=2 \
-netdev tap,id=mynet1,vhost=on \
-device virtio-net-pci,netdev=mynet1,mac=aa:66:da:5f:dd:11,iommu_platform=on,ats=on,bus=root.1 \
-drive file=/home/rhel7.5.qcow2,format=qcow2,if=none,id=drive-virtio-blk0,werror=stop,rerror=stop \
-device virtio-blk-pci,drive=drive-virtio-blk0,id=virtio-blk0,bus=root.2 \
-vnc :2 \
-monitor stdio \

Comment 10 Maxime Coquelin 2017-10-12 16:02:44 UTC
Hi Pei,

I now understand why I didn't reproduce on my setup, and why it didn't reproduce 100% on yours.

The problem happens when QEMU is started on a different NUMA node than testpmd.
My setup has a single NUMA node, and in case of multiple node,
QEMU could be scheduled on the same node than testpmd and the problem wouldn't appear.

When it happens, virtqueue and virtio-net structures are reallocated on QEMU's NUMA node.
The problem is that it corrupts the IOTLB cache list, and as a side effect highlights a deadlock issue.

The fix is donein DPDK, I posted two patches to fix the issues:

commit 0911327e96516cf397334ed7b433b71f71514ee5
Author: Maxime Coquelin <maxime.coquelin>
Date:   Thu Oct 12 16:43:24 2017 +0200

    vhost: fix IOTLB on NUMA realloc
    
    In case of NUMA reallocation, virtqueue's iotlb list is broken,
    has its head changes but first iotlb entry in the list still points
    to the previous head pointer.
    
    Also, in case of reallocation, we want the IOTLB cache mempool to be
    on the new socket.
    
    This patch perform a full re-init of the IOTLB cache when mempool
    already exists, and calls the IOTLB cache init function in case
    the virtqueue is being reallocated on a new socket.
    
    Signed-off-by: Maxime Coquelin <maxime.coquelin>

commit f4275bf4e0406e8343f92adf8475e7b998ce147a
Author: Maxime Coquelin <maxime.coquelin>
Date:   Thu Oct 12 16:24:30 2017 +0200

    vhost: fix deadlock on IOTLB miss
    
    An optimization was done to only take the iotlb cache lock
    once per packet burst instead of once per IOVA translation.
    
    With this, IOTLB miss requests are sent to Qemu with the lock
    held, which can cause a deadlock if the socket buffer is full,
    and if Qemu is waiting for an IOTLB update to be done.
    
    Holding the lock is not necessary when sending an IOTLB miss
    request, as it is not manipulating the IOTLB cache list, which
    the lock protects. Let's just release it while sending the
    IOTLB miss.
    
    Signed-off-by: Maxime Coquelin <maxime.coquelin>


I posted the patches to my gitlab account so that you can have a try:

repo: https://gitlab.com/mcoquelin/dpdk-next-virtio.git
branch: https://gitlab.com/mcoquelin/dpdk-next-virtio/tree/vhost_iotlb_fixes-rc1

To trigger the issue systematically, you can use numactl to force QEMU to be scheduled on NUMA node 1:
numactl -i 1 sh qemu.sh

Thanks,
Maxime

Comment 11 Pei Zhang 2017-10-13 02:27:49 UTC
(In reply to Maxime Coquelin from comment #10)
> Hi Pei,
> 
> I now understand why I didn't reproduce on my setup, and why it didn't
> reproduce 100% on yours.
> 
> The problem happens when QEMU is started on a different NUMA node than
> testpmd.
> My setup has a single NUMA node, and in case of multiple node,
> QEMU could be scheduled on the same node than testpmd and the problem
> wouldn't appear.
> 
> When it happens, virtqueue and virtio-net structures are reallocated on
> QEMU's NUMA node.
> The problem is that it corrupts the IOTLB cache list, and as a side effect
> highlights a deadlock issue.
> 
> The fix is donein DPDK, I posted two patches to fix the issues:
> 
> commit 0911327e96516cf397334ed7b433b71f71514ee5
> Author: Maxime Coquelin <maxime.coquelin>
> Date:   Thu Oct 12 16:43:24 2017 +0200
> 
>     vhost: fix IOTLB on NUMA realloc
>     
>     In case of NUMA reallocation, virtqueue's iotlb list is broken,
>     has its head changes but first iotlb entry in the list still points
>     to the previous head pointer.
>     
>     Also, in case of reallocation, we want the IOTLB cache mempool to be
>     on the new socket.
>     
>     This patch perform a full re-init of the IOTLB cache when mempool
>     already exists, and calls the IOTLB cache init function in case
>     the virtqueue is being reallocated on a new socket.
>     
>     Signed-off-by: Maxime Coquelin <maxime.coquelin>
> 
> commit f4275bf4e0406e8343f92adf8475e7b998ce147a
> Author: Maxime Coquelin <maxime.coquelin>
> Date:   Thu Oct 12 16:24:30 2017 +0200
> 
>     vhost: fix deadlock on IOTLB miss
>     
>     An optimization was done to only take the iotlb cache lock
>     once per packet burst instead of once per IOVA translation.
>     
>     With this, IOTLB miss requests are sent to Qemu with the lock
>     held, which can cause a deadlock if the socket buffer is full,
>     and if Qemu is waiting for an IOTLB update to be done.
>     
>     Holding the lock is not necessary when sending an IOTLB miss
>     request, as it is not manipulating the IOTLB cache list, which
>     the lock protects. Let's just release it while sending the
>     IOTLB miss.
>     
>     Signed-off-by: Maxime Coquelin <maxime.coquelin>
> 
> 
> I posted the patches to my gitlab account so that you can have a try:
> 
> repo: https://gitlab.com/mcoquelin/dpdk-next-virtio.git
> branch:
> https://gitlab.com/mcoquelin/dpdk-next-virtio/tree/vhost_iotlb_fixes-rc1

Maxime, I was trying to verify with this repo, however I hit new issue: testpmd fail boot up with below errors:

# /root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/build/app/test-pmd/testpmd -l 2,4,6 --socket-mem=1024,1024 -n 4 -d /root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/lib/librte_pmd_vhost.so --vdev 'net_vhost0,iface=/tmp/vhost-user1' -- --portmask=3 --disable-hw-vlan -i --rxq=1 --txq=1 --nb-cores=2 --forward-mode=io
EAL: Detected 20 lcore(s)
ERROR: failed to parse device "net_vhost0"
EAL: Unable to parse device 'net_vhost0,iface=/tmp/vhost-user1'
PANIC in main():
Cannot init EAL
5: [/root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/build/app/test-pmd/testpmd() [0x420d07]]
4: [/lib64/libc.so.6(__libc_start_main+0xf5) [0x7f889551a135]]
3: [/root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/build/app/test-pmd/testpmd(main+0x972) [0x420ca2]]
2: [/root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/lib/librte_eal.so.6.1(__rte_panic+0xba) [0x7f889651315a]]
1: [/root/dpdk-next-virtio/x86_64-native-linuxapp-gcc/lib/librte_eal.so.6.1(rte_dump_stack+0x1a) [0x7f889651d75a]]
Aborted

Best Regards,
Pei

> To trigger the issue systematically, you can use numactl to force QEMU to be
> scheduled on NUMA node 1:
> numactl -i 1 sh qemu.sh
> 
> Thanks,
> Maxime

Comment 12 Maxime Coquelin 2017-10-13 06:08:23 UTC
Hi Pei,

I just reproduce your issue too.
It seems something is broken in current upstream master, on which my branch is based.

In the mean time, you can try with shared libs, or I can rebase my two patches on top of the vhost_iotlb_v2 branch you used initially.

Cheers,
Maxime

Comment 13 Maxime Coquelin 2017-10-13 07:11:56 UTC
(In reply to Maxime Coquelin from comment #12)
> In the mean time, you can try with shared libs.

Sorry, I meant without shared libs.

Maxime

Comment 14 Pei Zhang 2017-10-13 08:51:23 UTC
(In reply to Maxime Coquelin from comment #12)
> Hi Pei,
> 
> I just reproduce your issue too.
> It seems something is broken in current upstream master, on which my branch
> is based.
> 
> In the mean time, you can try with shared libs, or I can rebase my two
> patches on top of the vhost_iotlb_v2 branch you used initially.

I tried without shared libs as[1], then both qemu and VM work well, no hang any more. So the issue has gone with your fix.

[1]Keep CONFIG_RTE_BUILD_SHARED_LIB in x86_64-native-linuxapp-gcc/.config as default value n.


Thanks,
Pei

> Cheers,
> Maxime

Comment 15 Maxime Coquelin 2017-10-14 06:32:50 UTC
Fixes applied upstream, part of DPDK v17.11-rc1 tag.

Comment 16 Pei Zhang 2017-10-16 02:09:55 UTC
Since this bug is fixed in dpdk, so move component of this from qemu to dpdk.

Comment 17 Maxime Coquelin 2018-01-09 09:44:17 UTC
The fix being in DPDK's vhost-user library, moving to Openvswitch component.
The fix is released in DPDK v17.11 LTS.

Comment 20 Pei Zhang 2018-03-06 04:56:59 UTC
==Verification==
kernel-3.10.0-855.el7.x86_64
qemu-kvm-rhev-2.10.0-21.el7.x86_64
libvirt-3.9.0-13.el7.x86_64
dpdk-17.11-7.el7.x86_64
openvswitch-2.9.0-1.el7fdb.x86_64
microcode-20180108.tgz

Steps:

1. Boot OVS with vIOMMU and dpdkvhostuserclient

# ovs-vsctl show
d73b38bd-883d-471a-8bd5-5dd624885f01
    Bridge "ovsbr1"
        Port "dpdk1"
            Interface "dpdk1"
                type: dpdk
                options: {dpdk-devargs="0000:81:00.1", n_rxq="2"}
        Port "vhost-user1"
            Interface "vhost-user1"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/tmp/vhostuser1.sock"}
        Port "ovsbr1"
            Interface "ovsbr1"
                type: internal
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "dpdk0"
            Interface "dpdk0"
                type: dpdk
                options: {dpdk-devargs="0000:81:00.0", n_rxq="2"}
        Port "vhost-user0"
            Interface "vhost-user0"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/tmp/vhostuser0.sock"}


2. Boot VM with vhostuser

    <interface type='vhostuser'>
      <mac address='88:66:da:5f:dd:02'/>
      <source type='unix' path='/tmp/vhostuser0.sock' mode='server'/>
      <model type='virtio'/>
      <driver name='vhost' queues='2' rx_queue_size='1024' iommu='on' ats='on'/>
      <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
    </interface>
    <interface type='vhostuser'>
      <mac address='88:66:da:5f:dd:03'/>
      <source type='unix' path='/tmp/vhostuser1.sock' mode='server'/>
      <model type='virtio'/>
      <driver name='vhost' queues='2' rx_queue_size='1024' iommu='on' ats='on'/>
      <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
    </interface>

3. In VM, start up network

# ifconfig eth1 up
# ifconfig eth2 up

4. Reboot VM

# reboot

5. Repeat step3~4 10 times, both qemu and guest work well.  


So this bug has been fixed very well. Move status of this bug to 'VERIFIED'.

Comment 23 errata-xmlrpc 2018-03-19 10:19:14 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2018:0550