访问硬件寄存器中的内存指针
Accessing memory pointers in hardware registers
我正在努力增强 Linux 中提供的库存 ahci 驱动程序,以便执行一些需要的任务。我正在尝试向 AHCI HBA 发出命令以供硬盘驱动器处理。但是,每当我这样做时,我的系统都会锁定并重新启动。试图解释向 AHCI 驱动器发出命令的过程对于这个问题来说远远不够。如果需要,reference this link for the full discussion(该过程相当完整地定义,因为有几个部分,但是,ch 4 具有必要的数据结构)。
本质上,将适当的结构写入由 BIOS 或 OS 定义的内存区域。我应该写入的第一个内存区域是寄存器 PxCLB 中包含的命令列表基地址(如果适用 64 位寻址,则为 PxCLBU)。我的系统是 64 位的,所以我正在尝试获取两个 32 位寄存器。我的代码基本上是这样的:
void __iomem * pbase = ahci_port_base(ap);
u32 __iomem *temp = (u32*)(pbase + PORT_LST_ADDR);
struct ahci_cmd_hdr *cmd_hdr = NULL;
cmd_hdr = (struct ahci_cmd_hdr*)(u64)
((u64)(*(temp + PORT_LST_ADDR_HI)) << 32 | *temp);
pr_info("%s:%d cmd_list is %p\n", __func__, __LINE__, cmd_hdr);
// problems with this next line, makes the system reboot
//pr_info("%s:%d cl[0]:0x%08x\n", __func__, __LINE__, cmd_hdr->opts);
函数ahci_port_base()在ahci驱动中找到(至少CentOS6.x是这样)。基本上,它 returns AHCI 内存区域中该端口的正确地址。 PORT_LST_ADDR 和 PORT_LST_ADDR_HI 都是在该驱动程序中定义的宏。我在同时获得高地址和低地址后得到的地址通常类似于 0x0000000037900000。这个内存地址在 space 中,我不能简单地取消引用它吗?
此时我的头撞到墙上了,因为this link shows以这种方式访问它基本上就是这样完成的。
The address that I get after getting both the high and low addresses
is usually something like 0x0000000037900000. Is this memory address
in a space that I cannot simply dereference it?
是的,你是对的 - 那是一个总线地址,你不能因为启用了分页就取消引用它。 (你也不应该只是取消引用 iomapped 地址——你应该为那些使用 readl()
/ writel()
,但这里的破损更微妙)。
看起来在该驱动程序中访问 ahci_cmd_hdr
的正确方法是:
struct ahci_port_priv *pp = ap->private_data;
cmd_hdr = pp->cmd_slot;
我正在努力增强 Linux 中提供的库存 ahci 驱动程序,以便执行一些需要的任务。我正在尝试向 AHCI HBA 发出命令以供硬盘驱动器处理。但是,每当我这样做时,我的系统都会锁定并重新启动。试图解释向 AHCI 驱动器发出命令的过程对于这个问题来说远远不够。如果需要,reference this link for the full discussion(该过程相当完整地定义,因为有几个部分,但是,ch 4 具有必要的数据结构)。
本质上,将适当的结构写入由 BIOS 或 OS 定义的内存区域。我应该写入的第一个内存区域是寄存器 PxCLB 中包含的命令列表基地址(如果适用 64 位寻址,则为 PxCLBU)。我的系统是 64 位的,所以我正在尝试获取两个 32 位寄存器。我的代码基本上是这样的:
void __iomem * pbase = ahci_port_base(ap);
u32 __iomem *temp = (u32*)(pbase + PORT_LST_ADDR);
struct ahci_cmd_hdr *cmd_hdr = NULL;
cmd_hdr = (struct ahci_cmd_hdr*)(u64)
((u64)(*(temp + PORT_LST_ADDR_HI)) << 32 | *temp);
pr_info("%s:%d cmd_list is %p\n", __func__, __LINE__, cmd_hdr);
// problems with this next line, makes the system reboot
//pr_info("%s:%d cl[0]:0x%08x\n", __func__, __LINE__, cmd_hdr->opts);
函数ahci_port_base()在ahci驱动中找到(至少CentOS6.x是这样)。基本上,它 returns AHCI 内存区域中该端口的正确地址。 PORT_LST_ADDR 和 PORT_LST_ADDR_HI 都是在该驱动程序中定义的宏。我在同时获得高地址和低地址后得到的地址通常类似于 0x0000000037900000。这个内存地址在 space 中,我不能简单地取消引用它吗?
此时我的头撞到墙上了,因为this link shows以这种方式访问它基本上就是这样完成的。
The address that I get after getting both the high and low addresses is usually something like 0x0000000037900000. Is this memory address in a space that I cannot simply dereference it?
是的,你是对的 - 那是一个总线地址,你不能因为启用了分页就取消引用它。 (你也不应该只是取消引用 iomapped 地址——你应该为那些使用 readl()
/ writel()
,但这里的破损更微妙)。
看起来在该驱动程序中访问 ahci_cmd_hdr
的正确方法是:
struct ahci_port_priv *pp = ap->private_data;
cmd_hdr = pp->cmd_slot;