转换后备缓冲区TLB和PDE/PTE的G位

转换后备缓冲区TLB和PDE/PTE的G位前言:这篇作为转换后备缓冲区TLB(TranslationLookasideBuffer)的学习笔记#线性地址解析这里我们拿10-10-12分页来举例子,下面来说明在10-10-12分页下CPU和操作系统是如何通过线性地址找到物理地址的一个概念需要知道,比如一个程序要读取DWORD大小的内

大家好,欢迎来到IT知识分享网。

前言:这篇作为转换后备缓冲区TLB(Translation Lookaside Buffer)的学习笔记

线性地址解析

这里我们拿10-10-12分页来举例子,下面来说明在10-10-12分页下CPU和操作系统是如何通过线性地址找到物理地址的

一个概念需要知道,比如一个程序要读取DWORD大小的内存,其实未必真正读的是4个字节,我们先读的PDE再读PTE 最后才读的4个字节的页。

不考虑PDE大页(PS=1)的情况下,就比如0x12345678,0x1234567C,那么这两个地址,先读0x1234678,那么在10-10-12分页下会先读取C0300000+PDI*4获取PDE,再接着读取C0000000+PDI*4*1024+PTI*4获取PTE,再接着继续读PTE对应的基址+偏移,最终才会找到数据,所以一共读了3次,那么如果在2-9-9-12分页下就会读4次。接着又去读0x1234567C,那么又要读3次

那么如果再考虑下特殊情况,如果跨页(就比如PTE不在同一个)可能更多。

知识点:什么是跨页?

我理解的就是 virtualalloc 分配的都是0x1000 0x1000 ,那是不是如果在0x40000FFF读取四个字节的时候 这种情况下就有另外三个字节会读取到40001000-40001FFF上了 这种就会跨页

所以为了提高效率,只能做记录。

CPU内部做了一个表,来记录这些东西,这个表格是CPU内部的,和寄存器一样快,这个表格:TLB(Translation Lookaside Buffer)。

TLB的结构

转换后备缓冲区TLB和PDE/PTE的G位

说明:

  • ATTR(属性):属性是PDPE PDE PTE三个属性AND起来的. 如果是10-10-12就是PDE and PTE
  • 不同的CPU(根据型号) 这个表的大小不一样.
  • 只要CR3变了,TLB立马刷新,一核一套TLB。

G位知识点

操作系统的高2G映射基本不变,如果CR3改了,TLB刷新 重建高2G以上很浪费。

所以PDE和PTE中有个G标志位,如果G位为1刷新TLB时将不会刷新 PDE/PTE的G位为1的页,这就会导致进程A切换到进程B,而进程A的线性地址0x12345678还是保存到进程B中的TLB表中,那么下次进程B进行找0x12345678,就会去找到进程A线性地址中对应的物理地址

当TLB满了,根据统计信息将不常用的地址废弃,最近最常用的保留。

需要注意的:这个其实就可以之前在做读取高2G的时候,有时候你给的属性的167,原因就是167的G位为1,那么这个情况下刷新TLB的时候就不会刷新你修改过的属性,所以其实还是165(R/W为0)的情况,那么实验的时候10-10-12分页下就需要把这个PDE和PTE的G位修改为0,如果在2-9-9-12分页下只需要修改PTE的G位。

TLB的种类

TLB在X86体系的CPU里的实际应用最早是从Intel的486CPU开始的。

在X86体系的CPU里边,一般都设有如下4组TLB“

  • 第一组:缓存一般页表(4K字节页面)的指令页表缓存(Instruction-TLB);
  • 第二组:缓存一般页表(4K字节页面)的数据页表缓存(Data-TLB);
  • 第三组:缓存大尺寸页表(2M/4M字节页面)的指令页表缓存(Instruction-TLB);
  • 第四组:缓存大尺寸页表(2M/4M字节页面)的数据页表缓存(Data-TLB)

这个我们不能直接控制不了存储指令表还是数据页表的缓存,这个是由内部CPU来决定的,只能间接控制,就比如我们自己用mov eax,0x12345678,这个就是数据缓存,那么CPU可能就会把这条0x12345678的线性地址进行缓存起来,下次读写的时候就直接在TLB读取对应的线性地址的物理地址即可

练习

这篇测试是在2-9-9-12分页模式下进行测试的

步骤0:给0线性地址挂上物理页
步骤1:体验TLB的存在
步骤2:全局页的意义
步骤3:INVLPG指令的意义

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>


int g_value = 0;

// 0x40100A
__declspec(naked) void test()
{
	__asm
	{
		push 0x30;
		pop fs;
		pushad;
		pushfd;
		
		
		// get 0x600000's pte
		mov eax, 0x600000;
		mov ebx, 0xC0000000;
		shr eax, 9;
		and eax, 7FFFF8h;
		mov edx, eax;
		add edx, ebx; // eax = pte

		// edit 0's pte value
		mov ecx, dword ptr ds:[edx]; // ecx = [0x600000's pte]
		// or ecx, 0x100;
		mov dword ptr ds:[ebx], ecx;  // ds:[0] = ecx

		// write 0's phy value
		mov dword ptr ds:[0], 0x12345678;

		xor eax, eax;
		xor ebx, ebx;
		xor ecx, ecx;
		xor edx, edx;
		
		// get 0x700000's pte
		mov eax, 0x700000;
		mov ebx, 0xC0000000;
		shr eax, 9;
		and eax, 7FFFF8h;
		mov edx, eax;
		add edx, ebx; // eax = pte

		// edit 0's pte value
		mov ecx, dword ptr ds:[edx]; // ecx = [0x700000's pte]
		mov dword ptr ds:[ebx], ecx;  // ds:[0] = ecx
		
		popfd;
		popad;	
		iretd;
	}
}

int main()
{
	// for secure, use virtualAlloc to apply memory
	DWORD* p1 = (DWORD*)VirtualAlloc(0x600000, 0x1000, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
	DWORD* p2 = (DWORD*)VirtualAlloc(0x700000, 0x1000, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
	
	if(p1 == NULL || p2 == NULL)
	{
		printf("virtualAlloc Failed!\n");
		system("pause");
		return 0;
	}

	// for fresh phy addr;
	memset(p1, 0, 0x1000);
	memset(p2, 0, 0x1000);
	*p1 = 0x100;
	*p2 = 0x200;

	printf("test func: %x\n", test);
	__asm
	{
		// eq 8003f500 0040EE00`0008100A
		int 0x20;
		push 0x3b;
		pop fs;
	}
	
	printf("%x", *(DWORD*)0);
	system("pause");
	return 0;
}

运行结果如下所示,因为TLB没有刷新,所以TLB中保存的还是p1指向的线性地址中的物理地址

转换后备缓冲区TLB和PDE/PTE的G位

接着模拟刷新CR3来实现线程切换

		mov eax, cr3;
		mov cr3, eax;

转换后备缓冲区TLB和PDE/PTE的G位

结果如下所示,因为G位不是1,所以CR3会导致整个TLB表刷新,那么次是TLB中保存的就是p2指向的线性地址中的物理地址了

转换后备缓冲区TLB和PDE/PTE的G位

接着设置将p1的PTE的G位设置为1,那么进程切换的时候也不会导致这个TLB表中的p1的线性地址记录被刷新

转换后备缓冲区TLB和PDE/PTE的G位

如下图所示,可以看到TLB没有刷新p1所指向的物理地址

转换后备缓冲区TLB和PDE/PTE的G位

那么强制刷新线性地址0对应的TLB,这里用到INVLPG指令

invlpg dword ptr ds:[0];

转换后备缓冲区TLB和PDE/PTE的G位

转换后备缓冲区TLB和PDE/PTE的G位

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/34306.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信