【问题标题】:Write to port 0cf8h fails with segfault写入端口 0cf8h 失败并出现段错误
【发布时间】:2013-11-30 22:35:06
【问题描述】:

我有一个 e2-2000 型号的 AMD 处理器。这是家庭 0fh。 根据family 0fh BKDG,我有这个代码来读取设备和供应商ID:

ReadPCIConfiguration:
movq    $0x80000100, %rax
movq    $0x0cf8, %rdx
outl    %eax, %dx          # sigsegv caught here
movq    $0x0cfc, %rdx
inl     %dx, %eax
ret

据我所知,读/写 PCI 配置的算法如下:

  • 将目标总线号、设备号功能号和偏移量或寄存器号写入配置地址端口
  • 对配置数据端口执行 1、2 或 4 字节读/写操作

Ports 0xcf8..0xcfb - 配置地址端口(双字)

位的意思:

  • 31 - EnReg - 启用事务 (R/W)
  • 24..31 - 保留 (R/O)
  • 16..23 - BusNum (R/W)
  • 11..15 - DevNum (R/W)
  • 8..10 - FuncNum (R/W)
  • 2..7 - RegNum (R/W)
  • 0..1 - 保留 (R/O)

所以,我写到 bus - 0, dev - 0, func - 1, reg - 00

我做错了吗?

(我从用户空间运行编译和链接的应用程序,GNU/Debian "Wheezy" Linux 3.11.6)

【问题讨论】:

  • 我不是硬件专家,但操作系统可能不允许您直接写入端口?绝对有一个系统调用,以确保只有具有正确权限的进程才能这样做。
  • 也许你是对的。但问题是,将来代码应该在操作系统启动时运行(以重新配置系统内存映射),我想至少测试代码的读取访问权限和读取正确性。
  • 虚拟化它?在 virtualbox 内的操作系统之前运行它。由于没有操作系统,那肯定不会出现段错误,但我不知道你的代码是做什么的!
  • 我明白了。我发现一个解决方案是一个名为iopermiopl 的电话。也许我应该删除这个问题?

标签: linux assembly x86-64 pci


【解决方案1】:

默认情况下,Linux 不允许用户态代码写入 I/O 端口。 (从安全角度来看,这样做可能非常危险。)如果您希望 Linux 允许您的进程访问 I/O 端口,您有两种选择:

  1. 您可以使用ioperm 系统调用。但是,ioperm 已被弃用一段时间,而 Josh Triplett 最近的pushed a patch 允许用户将其从内核中删除。如果您希望您的代码在可预见的未来继续工作,请避免使用ioperm

  2. 您可以读取和写入 /dev/port。见mem(4)。显然,您的进程需要 /dev/mem 的读写权限;在 Wheezy 上,这意味着它需要以 root 身份运行,除非您更改设备上的权限。

【讨论】:

  • 所以,您说ioperm 现在已弃用。 iopl 系统调用呢?
  • 查看 Josh Triplett 的电子邮件。他推送的补丁允许用户编译出ioplioperm
  • 嗯嗯。看起来,我将在我自己的测试中使用iopl,并在将来使用/dev/port。但他们为什么要禁用iopermiopl?也许那是出于某些安全原因?无论如何,感谢您的快速回答。
猜你喜欢
  • 1970-01-01
  • 2016-07-28
  • 2021-12-22
  • 2018-02-24
  • 2012-09-24
  • 2016-03-12
  • 1970-01-01
  • 2022-06-12
  • 2011-03-26
相关资源
最近更新 更多