Linux kernel 在qemu系统mips中访问0xCxxxxxxx来宾内核指针
在我基于QEMU的项目(系统仿真)中,我分析了来宾Linux的各种内核结构。要读取来宾虚拟内存,我使用Linux kernel 在qemu系统mips中访问0xCxxxxxxx来宾内核指针,linux-kernel,mips,qemu,Linux Kernel,Mips,Qemu,在我基于QEMU的项目(系统仿真)中,我分析了来宾Linux的各种内核结构。要读取来宾虚拟内存,我使用cpu\u memory\u rw\u debug()函数 特别是,我使用某种启发式方法在内核内存中搜索struct module链表。 假设此列表中元素的相关部分如下所示: --------------------- --------------------- | prev = 0xc1231234 | | prev = 0xc5675678 | -----------
cpu\u memory\u rw\u debug()
函数
特别是,我使用某种启发式方法在内核内存中搜索struct module
链表。
假设此列表中元素的相关部分如下所示:
--------------------- ---------------------
| prev = 0xc1231234 | | prev = 0xc5675678 |
--------------------- ---------------------
| next = 0xc1122334 | | next = 0xc5566778 |
--------------------- ---------------------
| etc. | | etc. |
--------------------- ---------------------
当QEMU模拟x86或ARM时,cpu\u memory\u rw\u debug()
可以访问上一个/下一个指针,它们实际上指向上一个/下一个列表元素
然而,当QEMU模拟MIPS时,我观察到以下奇怪的行为:虽然列表中的每个元素中的prev/next指针看起来都是有效的内核指针,但我无法通过cpu\u memory\u rw\u debug()
访问它们的指针对象,因为查找相应的物理地址失败:访问权限正常,虚拟CPU处于内核模式,但tlb->map\u address()
失败
由于我无法遍历链表,我试图一个接一个地查找元素——只是想看看它们的上一个/下一个指针是什么样子——实际上我找到了所有元素,但它们都位于0xAxxxxxxx
地址,而不是0xcxxxxxx
,正如上一个/next所暗示的那样
执行物理地址查找的函数r4k\u map\u address()
如下所示(仅相关摘录):
#定义KSEG0_基准0x80000000UL
#定义KSEG1_基0xA0000000UL
#定义KSEG2_基0xC0000000UL
#定义KSEG3_基0xE0000000UL
//..............
if(地址<(int32_t)KSEG1_基){
/*kseg0*/
if(内核模式){
*物理=地址-(int32_t)KSEG0_基;
*prot=页面读取|页面写入;
}否则{
ret=TLBRET_BADADDR;
}
}else if(地址<(int32_t)KSEG2_基){
/*kseg1*/
if(内核模式){
*物理=地址-(int32_t)KSEG1_基;
*prot=页面读取|页面写入;
}否则{
ret=TLBRET_BADADDR;
}
}else if(地址<(int32_t)KSEG3_BASE){
/*sseg(kseg2)*/
if(主管模式| |内核模式){
ret=env->tlb->映射地址(环境、物理、保护、真实地址、rw、访问类型);
}否则{
ret=TLBRET_BADADDR;
}
也就是说,在MIPS上,0xC0000000…0xE0000000范围的映射不同于较低的内核范围。
如果我将TLB访问替换为*physical=address-(int32_t)KSEG1_BASE
直接映射,我就可以实现这些功能,但这肯定不是解决方案
它看起来像是QEMU相关的问题还是MIPS相关的问题?我希望有任何想法或调试方向。底线是
cpu\u内存\u rw\u调试()
在QEMU系统MIPS中无法可靠工作
原因是QEMU模拟MIPS软件管理的TLB。通过这种方法,每当TLB缓存中不存在虚拟->物理地址映射时,QEMU模拟“TLB未命中”异常,该异常应由操作系统处理。操作系统负责遍历页面目录并填充TLB--QEMU(就像真正的MIPS一样)我不会那么做的
虽然这种方法适用于来宾代码,但它会导致无法使用
要使用cpu\u memory\u rw\u debug()读取来宾虚拟内存
-it
对你来说不可靠
至于为什么内核结构实际上驻留在KSEG2中,而KSEG1中观察到了这一点,这只是因为KSEG1和KSEG2的一些虚拟范围对应于相同的物理页面。底线是,
cpu\u memory\u rw\u debug()
在qemu系统mips中无法可靠工作
原因是QEMU模拟MIPS软件管理的TLB。通过这种方法,每当TLB缓存中不存在虚拟->物理地址映射时,QEMU模拟“TLB未命中”异常,该异常应由操作系统处理。操作系统负责遍历页面目录并填充TLB--QEMU(就像真正的MIPS一样)我不会那么做的
虽然这种方法适用于来宾代码,但它会导致无法使用
要使用cpu\u memory\u rw\u debug()读取来宾虚拟内存
-it
对你来说不可靠
至于为什么内核结构实际上驻留在KSEG2中,而在KSEG1中观察到了这个问题,这只是因为KSEG1和KSEG2的一些虚拟范围对应于相同的物理页面
#define KSEG0_BASE 0x80000000UL
#define KSEG1_BASE 0xA0000000UL
#define KSEG2_BASE 0xC0000000UL
#define KSEG3_BASE 0xE0000000UL
//..............
if (address < (int32_t)KSEG1_BASE) {
/* kseg0 */
if (kernel_mode) {
*physical = address - (int32_t)KSEG0_BASE;
*prot = PAGE_READ | PAGE_WRITE;
} else {
ret = TLBRET_BADADDR;
}
} else if (address < (int32_t)KSEG2_BASE) {
/* kseg1 */
if (kernel_mode) {
*physical = address - (int32_t)KSEG1_BASE;
*prot = PAGE_READ | PAGE_WRITE;
} else {
ret = TLBRET_BADADDR;
}
} else if (address < (int32_t)KSEG3_BASE) {
/* sseg (kseg2) */
if (supervisor_mode || kernel_mode) {
ret = env->tlb->map_address(env, physical, prot, real_address, rw, access_type);
} else {
ret = TLBRET_BADADDR;
}