Linux kernel IOMMU代码分析笔记(9)——EIM,IR和QI

支持IOMMU的硬件单元的Extended Capability Register有三个关联的位:

EIMExtended Interrupt Mode):在X86_64平台,0表示支持xAPIC1表示支持x2APICItanium平台这一位没意义。并且这一位只有在IR位设置为1才有效。

IRInterrupt Remapping support):1表示支持Interrupt remapping0表示不支持。硬件单元支持Interrupt remapping,也必须支持QI

QIQueued Invalidation support):1支持Queued Invalidation0表示不支持。

参考资料:
Intel ® Virtualization Technology for Directed I/O

Linux kernel IOMMU代码分析笔记(8)——intel_enable_irq_remapping(2)

上文

(4)

for_each_iommu(iommu, drhd) {
    /*
     * If the queued invalidation is already initialized,
     * shouldn't disable it.
     */
    if (iommu->qi)
        continue;

    /*
     * Clear previous faults.
     */
    dmar_fault(-1, iommu);

    /*
     * Disable intr remapping and queued invalidation, if already
     * enabled prior to OS handover.
     */
    iommu_disable_irq_remapping(iommu);

    dmar_disable_qi(iommu);
}

上面代码含义是如果硬件单元的queued invalidation还没有初始化,则清掉之前的fault,并且disable IRQ remappingqueued invalidation

(5)

/*
 * check for the Interrupt-remapping support
 */
for_each_iommu(iommu, drhd) {
    if (!ecap_ir_support(iommu->ecap))
        continue;

    if (eim && !ecap_eim_support(iommu->ecap)) {
        printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
               " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
        goto error;
    }
}

上述代码含义是如果硬件支持IRQ remapping并且系统支持x2APIC模式,如果硬件不支持x2APIC模式,就失败。

(6)

/*
 * Enable queued invalidation for all the DRHD's.
 */
for_each_iommu(iommu, drhd) {
    int ret = dmar_enable_qi(iommu);

    if (ret) {
        printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
               " invalidation, ecap %Lx, ret %d\n",
               drhd->reg_base_addr, iommu->ecap, ret);
        goto error;
    }
}

/*
 * Setup Interrupt-remapping for all the DRHD's now.
 */
for_each_iommu(iommu, drhd) {
    if (!ecap_ir_support(iommu->ecap))
        continue;

    if (intel_setup_irq_remapping(iommu, eim))
        goto error;

    setup = 1;
}

if (!setup)
    goto error;

上述代码分别为每个硬件单元enable queued invalidationIRQ remapping

(7)

irq_remapping_enabled = 1;

/*
 * VT-d has a different layout for IO-APIC entries when
 * interrupt remapping is enabled. So it needs a special routine
 * to print IO-APIC entries for debugging purposes too.
 */
x86_io_apic_ops.print_entries = intel_ir_io_apic_print_entries;

pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");

return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;

error:
    /*
     * handle error condition gracefully here!
     */

if (x2apic_present)
    pr_warn("Failed to enable irq remapping.  You are vulnerable to irq-injection attacks.\n");

return -1;

如果成功的话,返回IRQ_REMAP_XAPIC_MODE(0)IRQ_REMAP_X2APIC_MODE(1),否则返回-1

参考资料:
"BIOS Considerations" in *Intel ® Virtualization Technology for Directed I/O

git reset简介

git reset把当前branchHEAD恢复到之前某个snapshot。举例如下:

假设当前repository分三次添加abc文件:

[root@localhost test_git]# git log --oneline
e5b4692 Add c
be89e2d Add b
80c615e Add a

执行git reset --hard HEAD~1命令,HEAD~1表示当前HEAD之前的第一个commit

[root@localhost test_git]# git reset --hard HEAD~1
HEAD is now at be89e2d Add b
[root@localhost test_git]# git status
On branch master
nothing to commit, working directory clean
[root@localhost test_git]# git log --oneline
be89e2d Add b
80c615e Add a
[root@localhost test_git]# ls
a  b

可以看到git log中已经找不到添加c文件的log。而c文件也不存在了。

如果执行git reset --mixed HEAD~1命令,则虽然repository已经回滚到HEAD之前的第一个commit,但c文件还会存在:

[root@localhost test_git]# git reset --mixed HEAD~1
[root@localhost test_git]# git log --oneline
be89e2d Add b
80c615e Add a
[root@localhost test_git]# ls
a  b  c

恢复之前HEAD状态,可以利用git reflog找到相应的commit,然后创建一个新的branch,最后mergemaster:

[root@localhost test_git]# git reflog
be89e2d HEAD@{0}: reset: moving to HEAD~1
deb862b HEAD@{1}: commit: Add c
be89e2d HEAD@{2}: reset: moving to HEAD~1
e5b4692 HEAD@{3}: commit: Add c
be89e2d HEAD@{4}: commit: Add b
80c615e HEAD@{5}: commit (initial): Add a
[root@localhost test_git]# git checkout deb862b
Note: checking out 'deb862b'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at deb862b... Add c
[root@localhost test_git]# git log --oneline
deb862b Add c
be89e2d Add b
80c615e Add a
[root@localhost test_git]# git branch
* (HEAD detached at deb862b)
  master
[root@localhost test_git]# git checkout -b temp
Switched to a new branch 'temp'
[root@localhost test_git]# git branch
  master
* temp
[root@localhost test_git]# git checkout master
Switched to branch 'master'
[root@localhost test_git]# git merge temp
Updating be89e2d..deb862b
Fast-forward
 c | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 c
 [root@localhost test_git]# ls
a  b  c

Go语言实践技巧(4)——goroutine之间切换的时间点

以下列出了goroutine之间切换的主要的时间点:

(1)Channel发送和接收操作(如果这些操作是阻塞的);
(2)执行go语句,虽然不能保证新的goroutine马上被调度执行;
(3)阻塞的系统调用,像文件操作,网络操作等等;
(4)停下来进入垃圾回收周期以后。

换句话讲,在goroutine不能继续进行运算以后(需要更多数据,更多空间,等等),都会进行切换。

参考资料:
Performance without the event loop