Linux kernel IOMMU代码分析笔记(1)

Linux kernel代码版本是3.10

intel-iommu.h头文件定义了root-entry table address寄存器:

#define DMAR_RTADDR_REG 0x20    /* Root entry table */

DMAR_RTADDR_REG只在iommu_set_root_entry这个函数中使用(这个函数作用是更新root-entry table的地址):

static void iommu_set_root_entry(struct intel_iommu *iommu)
{
    void *addr;
    u32 sts;
    unsigned long flag;

    addr = iommu->root_entry;

    raw_spin_lock_irqsave(&iommu->register_lock, flag);
    dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));

    writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);

    /* Make sure hardware complete it */
    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
              readl, (sts & DMA_GSTS_RTPS), sts);

    raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
}

DMAR_RTADDR_REG存储的是root-entry table的物理地址(virt_to_phys()函数把virtual address转成physical address)。整个root-entry table4KiB大小,并且要求起始地址是“页面对齐的(page-alignedpage长度是4KiB)”,所以DMAR_RTADDR_REG12 bits0。更新DMAR_RTADDR_REG代码如下:

dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr));

更新完DMAR_RTADDR_REG寄存器,还要把global command寄存器的SRTPSet Root Table Pointer)位置1

writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);

最后读取Global Status寄存器的RTPSRoot Table Pointer Status)位,确认更新成功:

IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
                  readl, (sts & DMA_GSTS_RTPS), sts);

Lua笔记(9)——函数传参和返回值

Lua中,调用函数要加上括号(即使没有参数也不例外)。只有以下情况可以不加:函数只有一个参数,且参数是字符串或是table constructor

> print "Hello world!"
Hello world!
> print {x=10}
table: 0x1d81810

传给函数多余的实参(argument)会被丢弃,多余的形参(parameter)会赋值nil

> function f(a, b) print(a, b) end
> f(1)
1       nil
> f(1, 2)
1       2
> f(1, 2, 3)
1       2

根据实际情况,Lua会自动调整函数返回值的数量:
(1)当调用函数作为一条statement时,会丢弃所有的返回值;
(2)当调用函数作为一个表达式时,只会保留第一个返回值;
(3)只有当调用函数作为一系列表达式(a list of expressions)中的最后一个(或是唯一一个)时,才会得到所有的返回值。所谓的一系列表达式(a list of expressions)有四种情况:多重赋值(multiple assignments),函数调用传参(arguments to function calls),构建tabletable constructor)和return语句。

针对(1),(2),请看下面程序(test.lua):

function f()
        return 1, 2
end

f()

a, b = f(), 3
print(a, b)

执行结果如下:

[root@localhost ~]# ./test.lua
1       3

针对(3),请看下面程序(test.lua):

function f()
        return 1, 2
end

function g(a, b)
        print(a, b)
end

function h()
        return f()
end

a, b = f()
print(a, b)

g(f())

t = {f()}
print(t[1], t[2])

print(h())

执行结果如下:

[root@localhost ~]# ./test.lua
1       2
1       2
1       2
1       2

注意:在调用的函数外面再加上一层括号,可以强制函数只返回一个结果:

function f()
        return 1, 2
end

print(f())
print((f()))

执行结果:

[root@localhost ~]# ./test.lua
1       2
1