- 论坛徽章:
- 9
|
本帖最后由 Buddy_Zhang1 于 2018-01-19 15:44 编辑
下面函数用于介绍 逻辑地址,虚拟地址,线性地址和物理地址的转换过程:
github 地址:https://github.com/BiscuitOS/BiscuitOS
原理来自 Intel X86 官方手册 -- 系统编程卷 -- Segmentation and Paging Section
- /*
- * Logical Address Mechanism on MMU
- *
- * (C) 2018.01 BiscuitOS <buddy.zhang@aliyun.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
- #include <linux/kernel.h>
- #include <linux/head.h>
- #include <linux/sched.h>
- #include <test/debug.h>
- static char var[50] = "BiscuitOS";
- /*
- * Logical address convent to physical address
- */
- static void logic_to_physic(void)
- {
- struct logic_addr la;
- unsigned long virtual, linear, physic;
- unsigned long base, limit;
- unsigned long cs, ds, cr3, cr4;
- unsigned char cpl, dpl;
- struct desc_struct *desc;
- unsigned long PDE, PTE;
- /* Obtain specific segment selector */
- __asm__ ("movl %%cs, %0\n\r"
- "movl %%ds, %1"
- : "=r" (cs), "=r" (ds));
- /* Establish a logical address */
- la.offset = (unsigned long)&var;
- la.sel = ds;
- /* Obtain virtual address */
- virtual = la.offset;
- /* violation COW */
- var[48] = 'A';
- /* Uses the offset in the segment selector to locate the segment
- * descriptor for the segment in the GDT or LDT and reads it into
- * the processor. (This step is needed only when a new segment selector
- * is loaded into a segment register.) */
- if ((la.sel >> 2) & 0x1)
- desc = ¤t->ldt[la.sel >> 3];
- else
- desc = &gdt[la.sel >> 3];
- /* Examines the segment descriptor to check the access rights and range
- * of the segment to insure that the segment is accessible and that
- * offset is within the limit of the segment */
- base = get_base(*desc);
- limit = get_limit(*desc) * 4096;
- if (la.offset > limit)
- panic("Out of segment\n");
- cpl = cs & 0x3;
- dpl = desc->b >> 13 & 0x3;
- if (cpl > dpl)
- panic("Trigger #GP");
- /* Obtain linear address on flat-protect model */
- linear = base + la.offset;
-
- /* Obtain physical address of pgdir from CR3 register, the contents of
- * 'cr3' is point to the physical of pg_dir, so refers it as a pointer. */
- __asm__ ("movl %%cr3, %0" : "=r" (cr3));
- /* A 4-KByte naturally aligned page directory is located at the
- * physical address specified in bits 31:12 of CR3. A page directory
- * comprises 1024 32-bit entries (PDEs). A PDE is selected using
- * the physical address defined as follow:
- *
- * -- Bits 39:32 are all 0
- * -- Bits 31:12 are from CR3.
- * -- Bits 11:2 are bits 31:22 of the linear address
- * -- Bits 1:0 are 0.
- *
- * Becasue a PDE is identified using bits 31:22 of the linear address,
- * it control access to a 4-Mbytes region of the linear-address space.
- * Use of the PDE depends on CR4.PSE and PDE's PS flag (bit 7)*/
- PDE = ((unsigned char)(((cr3 >> 12) & 0xFFFFF) << 12) +
- (((linear >> 22) & 0x3FF) << 2)) & 0xFFFFFFFC;
- /* Another way to compute PDE:
- * PDE = (unsigned long *)cr3[linear >> 22] */
- __asm__ ("movl %%cr4, %0" : "=r" (cr4));
- if (((cr4 >> 4) & 0x1) && ((PDE >> 4) & 0x1)) {
- /* If CR4.PSE = 1 and the PDE's PS flag is 1, the PDE maps a 4-MByte
- * page. The final physical address is computed as follows:
- *
- * -- Bits 39:32 are bits 20:13 of the PDE.
- * -- Bits 31:22 are bits 31:22 of the PDE.
- * -- Bits 21:0 are from the original linear address.
- */
- PTE = 0x0; /* No complete on BiscuitOS */
- } else if (!((cr4 >> 4) & 0x1) && !((PDE >> 4) & 0x1)) {
- /* If CR4.PSE = 0 or the PDE's PS flag is 0, a 4-KByte naturally
- * aligned page table is located at the physical address specified
- * in bits 31:12 of the PDE. A page table comprises 1024 32-bit
- * entries (PTEs). A PTE is selected using the physical address
- * defined as follows:
- *
- * -- Bits 39:32 are all 0
- * -- Bits 31:12 are from the PDE.
- * -- Bits 11:2 are bits 21:12 of the linear address.
- * -- Bits 1:0 are 0.
- */
- PTE = (unsigned long)((unsigned char *)(
- ((*(unsigned long *)PDE >> 12) & 0xFFFFF) << 12) +
- (((linear >> 12) & 0x3FF) << 2)) & 0xFFFFFFFC;
- /* Anther way to compute PTE:
- * PTE = (unsigned long *)PDE[(linear >> 12) & 0x3FF] */
- }
- /* Because a PTE is identified using bits 31:12 of the linear address,
- * every PTE maps a 4-KByte page. The final physical address is
- * computed as follows:
- *
- * -- Bits 39:32 are all 0
- * -- Bits 31:12 are from the PTE.
- * -- Bits 11:0 are from the original linear address.
- */
- physic = (unsigned long)(unsigned char *)(
- ((*(unsigned long *)PTE >> 12) & 0xFFFFF) << 12) +
- (linear & 0xFFF);
- printk("Logical Address: %#x:%#x\n", la.sel, la.offset);
- printk("Virtual Address: %#x\n", virtual);
- printk("Linear Address: %#x\n", linear);
- printk("Physic Address: %#x\n", physic);
- printk("Original: %s\n", la.offset);
- printk("Translate: %s\n", physic);
- }
复制代码 |
评分
-
查看全部评分
|