From 9fda787443f81fee1731a83bacbcbb0fdd2def93 Mon Sep 17 00:00:00 2001 From: gatieme Date: Wed, 27 Jul 2016 21:38:16 +0800 Subject: [PATCH] =?UTF-8?q?list/rbtree=E9=81=8D=E5=8E=86=E8=BF=9B=E7=A8=8B?= =?UTF-8?q?=E8=99=9A=E6=8B=9F=E5=9C=B0=E5=9D=80=E7=A9=BA=E9=97=B4vm=5Farea?= =?UTF-8?q?=5Fstruct=E7=9A=84=E5=AD=A6=E4=B9=A0=E4=BB=A3=E7=A0=81=E4=B8=AD?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=BE=93=E5=87=BA=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=98=A0=E5=B0=84=E7=9A=84=E4=BB=A3=E7=A0=81print=5Fvm=5Ffile-?= =?UTF-8?q?-=E9=A9=B1=E5=8A=A8print=5Fvmarea?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- study/kernel/memory/kv2p/1.c | 18 +++ study/kernel/memory/kv2p/Makefile | 14 ++ study/kernel/memory/kv2p/README.md | 148 ++++++++++++++++++ .../kv2p/images/CONFIG_PHYS_ADDR_T_64BIT.png | Bin 0 -> 23543 bytes study/kernel/memory/kv2p/kv2p.c | 44 ++++++ study/kernel/memory/v2p/v2p.c | 1 - 6 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 study/kernel/memory/kv2p/1.c create mode 100644 study/kernel/memory/kv2p/Makefile create mode 100644 study/kernel/memory/kv2p/README.md create mode 100644 study/kernel/memory/kv2p/images/CONFIG_PHYS_ADDR_T_64BIT.png create mode 100644 study/kernel/memory/kv2p/kv2p.c diff --git a/study/kernel/memory/kv2p/1.c b/study/kernel/memory/kv2p/1.c new file mode 100644 index 0000000..207a70e --- /dev/null +++ b/study/kernel/memory/kv2p/1.c @@ -0,0 +1,18 @@ +/* + * Physical vs virtual RAM address space conversion. These are + * private definitions which should NOT be used outside memory.h + * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. + */ +#define __virt_to_phys(x) ({ \ + phys_addr_t __x = (phys_addr_t)(x); \ + __x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET : \ + (__x - kimage_voffset); }) + +#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET) +#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset)) + +/* + * Convert a page to/from a physical address + */ +#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) +#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) \ No newline at end of file diff --git a/study/kernel/memory/kv2p/Makefile b/study/kernel/memory/kv2p/Makefile new file mode 100644 index 0000000..4250a02 --- /dev/null +++ b/study/kernel/memory/kv2p/Makefile @@ -0,0 +1,14 @@ + + +obj-m := kv2p.o + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build + +PWD := $(shell pwd) + +all: + make -C $(KERNELDIR) M=$(PWD) modules + +clean: + make -C $(KERNELDIR) M=$(PWD) clean + diff --git a/study/kernel/memory/kv2p/README.md b/study/kernel/memory/kv2p/README.md new file mode 100644 index 0000000..2b80deb --- /dev/null +++ b/study/kernel/memory/kv2p/README.md @@ -0,0 +1,148 @@ +| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN | +| ------------- |:-------------:|:-------------:|:-------------:|:-------------:|:-------------:| +| 2016-07-21 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux进程管理与调度](http://blog.csdn.net/gatieme/article/category/6225543) | + + + +#1 内核虚拟地址与物理地址的转换 +------- + +| 函数 | 描述 | 底层函数 | +|:---:|:---:|:--------:| +| phys_addr_t virt_to_phys(volatile void *address) | 将内核的虚拟地址转换为物理地址 | \__pa或者 \__virt_to_phys | +| void *phys_to_virt(phys_addr_t x) | 将物理地址转换为虚拟内核 | \__va或者\__phys_to_virt | + +其中phy_addr_t用以表示一个内存地址, 定义在[include/linux/types.h](http://lxr.free-electrons.com/source/include/linux/types.h#L161)中 + +```c +#ifdef CONFIG_PHYS_ADDR_T_64BIT + typedef u64 phys_addr_t; +#else + typedef u32 phys_addr_t; +#endif +``` + +可以通过搜索我们内核的.config文件搜索CONFIG_PHYS_ADDR_T_64BIT这个配置参数 + +```c +cat /usr/src/linux-headers-4.2.0-36-generic/.config | grep CONFIG_PHYS_ADDR_T_64BIT +``` + +![CONFIG_PHYS_ADDR_T_64BIT参数](./images/CONFIG_PHYS_ADDR_T_64BIT.png) + + +#2 virt_to_phys/phys_to_virt实现 +------- + +##2.1 不同架构的实现 +------- + + +| 架构 | 定义 | +|:-------:|:-------:| +| 标准 | [include/asm-generic/io.h, line 724](http://lxr.free-electrons.com/source/include/asm-generic/io.h?v4.7#L724) +| arm | [arch/arm/include/asm/memory.h, line 272](http://lxr.free-electrons.com/source/arch/arm/include/asm/memory.h?v4.7#L272) | +| arm64 | [arch/arm64/include/asm/memory.h](http://lxr.free-electrons.com/source/arch/arm64/include/asm/memory.h?v4.7#L189) | +| x86 |[arch/x86/include/asm/io.h, line 118](http://lxr.free-electrons.com/source/arch/x86/include/asm/io.h?v4.7#L118) + + + +* virt_to_phys函数在内核中是通过\__pa或者\__virt_to_phys函数实现的 + +* phys_to_virt函数在内核中是通过\__va或者\__phys_to_virt函数实现的 + + + + +##2.2 arm64上的实现 + +不同架构的实现有细微差别, 但是其基本思路是一致的 + + +下面我们就以arm64上的实现为例进行讲解, 定义在[arch/arm64/include/asm/memory.h](http://lxr.free-electrons.com/source/arch/arm64/include/asm/memory.h?v4.7#L184) + +```c +/* + * These are *only* valid on the kernel direct mapped RAM memory. + * Note: Drivers should NOT use these. They are the wrong + * translation for translating DMA addresses. Use the driver + * DMA support - see dma-mapping.h. + */ +#define virt_to_phys virt_to_phys +static inline phys_addr_t virt_to_phys(const volatile void *x) +{ + return __virt_to_phys((unsigned long)(x)); +} + +#define phys_to_virt phys_to_virt +static inline void *phys_to_virt(phys_addr_t x) +{ + return (void *)__phys_to_virt(x); +} + +/* + * Drivers should NOT use these either. + */ +#define __pa(x) __virt_to_phys((unsigned long)(x)) +#define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) +#define pfn_to_kaddr(pfn) __va((phys_addr_t)(pfn) << PAGE_SHIFT) +``` + + +可以看到真是的实现是__virt_to_phys和__phys_to_virt函数实现的 + + + +##2.3 __virt_to_phys函数 +------- + +__virt_to_phys函数定义在[arch/arm64/include/asm/memory.h, line 109](http://lxr.free-electrons.com/source/arch/arm64/include/asm/memory.h?v=4.7#L109) + +```c +/* + * Physical vs virtual RAM address space conversion. These are + * private definitions which should NOT be used outside memory.h + * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. + */ +#define __virt_to_phys(x) ({ \ + phys_addr_t __x = (phys_addr_t)(x); \ + __x & BIT(VA_BITS - 1) ? (__x & ~PAGE_OFFSET) + PHYS_OFFSET : \ + (__x - kimage_voffset); }) + +``` + + +##2.4 __phys_to_virt函数 +------- + +__phys_to_virt函数定义在[arch/arm64/include/asm/memory.h, line 114](http://lxr.free-electrons.com/source/arch/arm64/include/asm/memory.h?v=4.7#L114) + + +```c +#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET) +``` + +##2.5 __phys_to_kimg函数 +------- + +```c +#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset)) +``` + +##2.6 page_to_phys和phys_to_page函数 +------- + +```c +/* + * Convert a page to/from a physical address + */ +#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page))) +#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys))) +``` + + + + + + + diff --git a/study/kernel/memory/kv2p/images/CONFIG_PHYS_ADDR_T_64BIT.png b/study/kernel/memory/kv2p/images/CONFIG_PHYS_ADDR_T_64BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..54aec24b98f6f057b655d9662010596804a226cd GIT binary patch literal 23543 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 Hi?IIz@T1*= literal 0 HcmV?d00001 diff --git a/study/kernel/memory/kv2p/kv2p.c b/study/kernel/memory/kv2p/kv2p.c new file mode 100644 index 0000000..f378c94 --- /dev/null +++ b/study/kernel/memory/kv2p/kv2p.c @@ -0,0 +1,44 @@ +/***************************************************************** +文件名:mem.c +输入参数: +pid 接收待查询进程的PID +va 接收待查询的虚拟地址 +*****************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + + +static unsigned long VA; +module_param(VA, ulong, 0644); + + + +static int __init kv2p_init( ) +{ + // use virt_to_phys + // http://lxr.free-electrons.com/source/arch/arm64/include/asm/memory.h?v4.7#L189 + // + virt_to_phys(VA); + + + return 0; +} + + + +static void __exit kv2p_exit(void) +{ + printk(KERN_INFO"Goodbye!\n"); +} + +module_init(kv2p_init); +module_exit(kv2p_exit); diff --git a/study/kernel/memory/v2p/v2p.c b/study/kernel/memory/v2p/v2p.c index 0c18cdc..d3ab710 100644 --- a/study/kernel/memory/v2p/v2p.c +++ b/study/kernel/memory/v2p/v2p.c @@ -133,7 +133,6 @@ static int find_pgd_init(void) static void find_pgd_exit(void) { printk(KERN_INFO"Goodbye!\n"); - } module_init(find_pgd_init);