小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Li Haifeng's Blog

 老匹夫 2015-01-03
注:該博文寫的比較凌亂,需要以后再修改。

Linux 的頁表項(xiàng)總體可以劃分為兩部分,一部分是物理映射地址,另一部分是對(duì)物理地址對(duì)應(yīng)的訪問屬性。在Linux/ARM的Kernel中,為各式各樣的內(nèi)存屬性與定義了一下條目 

198  static struct mem_type mem_types[] = {

 199          [MT_DEVICE] = {            /* Strongly ordered / ARMv6 shared device */

 200                  .prot_pte        = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |

 201                                     L_PTE_SHARED,

 202                  .prot_l1         = PMD_TYPE_TABLE,

 203                  .prot_sect       = PROT_SECT_DEVICE | PMD_SECT_S,

 204                  .domain          = DOMAIN_IO,

 205          },

 206          [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared  device */

 207                  .prot_pte        = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED,

 208                  .prot_l1         = PMD_TYPE_TABLE,

 209                  .prot_sect       = PROT_SECT_DEVICE,

 210                  .domain          = DOMAIN_IO,

 211          },

 212          [MT_DEVICE_CACHED] = {    /*  ioremap_cached */

 213                  .prot_pte        = PROT_PTE_DEVICE | L_PTE_MT_DEV_CACHED,

 214                  .prot_l1         = PMD_TYPE_TABLE,

 215                  .prot_sect       = PROT_SECT_DEVICE | PMD_SECT_WB,

 216                  .domain          = DOMAIN_IO,

 217          },

 218          [MT_DEVICE_WC] = {      /*  ioremap_wc */

 219                  .prot_pte        = PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,

 220                  .prot_l1         = PMD_TYPE_TABLE,

 221                  .prot_sect       = PROT_SECT_DEVICE,

 222                  .domain          = DOMAIN_IO,

 223          },

 224          [MT_UNCACHED] = {

 225                  .prot_pte        = PROT_PTE_DEVICE,

 226                  .prot_l1         = PMD_TYPE_TABLE,

 227                  .prot_sect       = PMD_TYPE_SECT | PMD_SECT_XN,

 228                  .domain          = DOMAIN_IO,

 229          },

 230          [MT_CACHECLEAN] = {

 231                  .prot_sect =  PMD_TYPE_SECT | PMD_SECT_XN,

 232                  .domain    =  DOMAIN_KERNEL,

 233          },

 234  #ifndef CONFIG_ARM_LPAE

 235          [MT_MINICLEAN] = {

 236                  .prot_sect =  PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE,

 237                  .domain    =  DOMAIN_KERNEL,

 238          },


 239 #endif

 240         [MT_LOW_VECTORS] = {

 241                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |

 242                                 L_PTE_RDONLY,

 243                 .prot_l1   = PMD_TYPE_TABLE,

 244                 .domain    = DOMAIN_USER,

 245         },

 246         [MT_HIGH_VECTORS] = {

 247                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |

 248                                 L_PTE_USER | L_PTE_RDONLY,

 249                 .prot_l1   = PMD_TYPE_TABLE,

 250                 .domain    = DOMAIN_USER,

 251         },

 252         [MT_MEMORY] = {

 253                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,

 254                 .prot_l1   = PMD_TYPE_TABLE,

 255                 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,

 256                 .domain    = DOMAIN_KERNEL,

 257         },

 258         [MT_ROM] = {

 259                 .prot_sect = PMD_TYPE_SECT,

 260                 .domain    = DOMAIN_KERNEL,

 261         },

 262         [MT_MEMORY_NONCACHED] = {

 263                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |

 264                                 L_PTE_MT_BUFFERABLE,

 265                 .prot_l1   = PMD_TYPE_TABLE,

 266                 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,

 267                 .domain    = DOMAIN_KERNEL,

 268         },

 269         [MT_MEMORY_DTCM] = {

 270                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |

 271                                 L_PTE_XN,

 272                 .prot_l1   = PMD_TYPE_TABLE,

 273                 .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,

 274                 .domain    = DOMAIN_KERNEL,

 275         },

 276         [MT_MEMORY_ITCM] = {

 277                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,

 278                 .prot_l1   = PMD_TYPE_TABLE,

 279                 .domain    = DOMAIN_KERNEL,

 280         },

 281         [MT_MEMORY_SO] = {

 282                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |

 283                                 L_PTE_MT_UNCACHED,

 284                 .prot_l1   = PMD_TYPE_TABLE,

 285                 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |

 286                                 PMD_SECT_UNCACHED | PMD_SECT_XN,

 287                 .domain    = DOMAIN_KERNEL,

 288         },

 289 };

在以后的建立和維護(hù)頁表中,Linux Kernel只是在以上各種類型的基礎(chǔ)上添加或者刪除一些屬性使用。比如252~257行的MT_MEMORY屬性,在初始化的時(shí)候,還會(huì)在build_mem_type_table()函數(shù)中根據(jù)處理器架構(gòu)的不同,“Adjust the PMD section entries according to the CPU in use”,其函數(shù)關(guān)鍵代碼為:

paging_init->build_mem_type_table

 300 static void __init build_mem_type_table(void)

 301 {

 302         struct cachepolicy *cp;

 303         unsigned int cr = get_cr();//System control register

 304         pteval_t user_pgprot, kern_pgprot, vecs_pgprot;

 305         int cpu_arch = cpu_architecture();

 306         int i;

 307 


 322         if (is_smp())

 323                 cachepolicy = CPOLICY_WRITEALLOC;// if write miss, first write block to memory ,then read to cache.


 411         /*

 412          * Now deal with the memory-type mappings

 413          */

 414         cp = &cache_policies[cachepolicy];

 415         vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;


 436         if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {

 447                 if (is_smp()) {
 448                         /*
 449                          * Mark memory with the “shared” attribute
 450                          * for SMP systems
 451                          */
 452                         user_pgprot |= L_PTE_SHARED;
 453                         kern_pgprot |= L_PTE_SHARED;
 454                         vecs_pgprot |= L_PTE_SHARED;
 455                         mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
 456                         mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
 457                         mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
 458                         mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
 459                         mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
 460                         mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
 461                         mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
 462                         mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
 463                 }
 464         }
… 
470         if (cpu_arch >= CPU_ARCH_ARMv6) {


 480         } else {
 481                 mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE;//
 482         }
 483

… 

 496         for (i = 0; i < 16; i++) {


 497                 unsigned long v = pgprot_val(protection_map[i]);

 498                 protection_map[i] = __pgprot(v | user_pgprot);

 499         }

 500 

 501         mem_types[MT_LOW_VECTORS].prot_pte |= vecs_pgprot;

 502         mem_types[MT_HIGH_VECTORS].prot_pte |= vecs_pgprot;

 503 

 504         pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);

 505         pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |

 506                                  L_PTE_DIRTY | kern_pgprot);

 507 

 508         mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;

 509         mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;

 510         mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;

 511         mem_types[MT_MEMORY].prot_pte |= kern_pgprot;

 512         mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask;

 513         mem_types[MT_ROM].prot_sect |= cp->pmd;

 514 

 515         switch (cp->pmd) {

 516         case PMD_SECT_WT:

 517                 mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;

 518                 break;

 519         case PMD_SECT_WB:

 520         case PMD_SECT_WBWA:

 521                 mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;

 522                 break;

 523         }

 524         printk(“Memory policy: ECC %sabled, Data cache %sn”,

 525                 ecc_mask ? “en” : “dis”, cp->policy);

 526 

 527         for (i = 0; i < ARRAY_SIZE(mem_types); i++) {

 528                 struct mem_type *t = &mem_types[i];

 529                 if (t->prot_l1)

 530                         t->prot_l1 |= PMD_DOMAIN(t->domain);

 531                 if (t->prot_sect)

 532                         t->prot_sect |= PMD_DOMAIN(t->domain);

 533         }

 534 }

 535 

414cache_policies的相關(guān)定義:

  68 static struct cachepolicy cache_policies[] __initdata = {

  69         {

  70                 .policy         = “uncached”,

  71                 .cr_mask        = CR_W|CR_C,

  72                 .pmd            = PMD_SECT_UNCACHED,

  73                 .pte            = L_PTE_MT_UNCACHED,

  74         }, {

  75                 .policy         = “buffered”,

  76                 .cr_mask        = CR_C,

  77                 .pmd            = PMD_SECT_BUFFERED,

  78                 .pte            = L_PTE_MT_BUFFERABLE,

  79         }, {

  80                 .policy         = “writethrough”,

  81                 .cr_mask        = 0,

  82                 .pmd            = PMD_SECT_WT,

  83                 .pte            = L_PTE_MT_WRITETHROUGH,

  84         }, {

  85                 .policy         = “writeback”,

  86                 .cr_mask        = 0,

  87                 .pmd            = PMD_SECT_WB,

  88                 .pte            = L_PTE_MT_WRITEBACK,

  89         }, {

  90                 .policy         = “writealloc”,

  91                 .cr_mask        = 0,

  92                 .pmd            = PMD_SECT_WBWA,

  93                 .pte            = L_PTE_MT_WRITEALLOC,

  94         }

  95 };


根據(jù)323行的定義,使用了最后一項(xiàng)即 8994行,所以build_mem_type_table415行的:

vecs_pgprot = kern_pgprot = user_pgprot = cp->pte的值為:L_PTE_MT_WRITEALLOC.


ecc_mask: 未知,貌似是用來校驗(yàn)的。

cp->pmd:PMD_SECT_WBWA


529~533行,設(shè)置了對(duì)應(yīng)的domain

PMD_DOMAIN(t->domain): 

24 #define PMD_DOMAIN(x)           (_AT(pmdval_t, (x)) << 5)

關(guān)于Domain,Linux Kernel 對(duì)Domain的index定義了如下的宏:

arch/arm/include/asm/domain.h
31 #ifndef CONFIG_IO_36


32 #define DOMAIN_KERNEL   0


33 #define DOMAIN_TABLE    0


34 #define DOMAIN_USER     1


35 #define DOMAIN_IO       2


36 #else


37 #define DOMAIN_KERNEL   2


38 #define DOMAIN_TABLE    2


39 #define DOMAIN_USER     1


40 #define DOMAIN_IO       0


41 #endif


42


所以,這個(gè)宏定義的x=DOMAIN_KERNEL=2




根據(jù)build_mem_type_table的修正,假設(shè)在ARM V7的處理器前提下,MT_MEMORY的屬性為:

 252         [MT_MEMORY] = {

 253                 .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY| L_PTE_MT_WRITEALLOC | L_PTE_SHARED,

 254                 .prot_l1   = PMD_TYPE_TABLE | PMD_DOMAIN(t->domain),

 255                 .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE| PMD_SECT_WBWA | ecc_mask|0<<5|PMD_SECT_S,

 256                 .domain    = DOMAIN_KERNEL,

 257         },


以上是Linux Kernel作為軟件,把PTE的屬性和L1以及SECT的屬性都已經(jīng)設(shè)置完成了。


下面,看一下ARM V7提供的硬件機(jī)制:

內(nèi)嵌圖片 1

本文只關(guān)注前兩排,后面的Supersection不關(guān)注。


把上面的MT_MEMORY的屬性中的section部分的值單獨(dú)拿出來:

PMD_TYPE_SECT | PMD_SECT_AP_WRITE| PMD_SECT_WBWA | ecc_mask|0<<5,

PMD_TYPE_SECT:2<<0

PMD_SECT_AP_WRITE:1<<10

PMD_SECT_WBWA:1<<3 | 1<<2 |  1<<12


019對(duì)應(yīng)的二進(jìn)制:

0 0 0 1 0 001 01 0 0000 0 1 1 10

即:


nG S AP[2] Tex[2:0]   AP[1:0] Domain  C B

0  1  0        01           01      0             1 1

AP 001 Privileged access only。即MT_MEMORY的權(quán)限為:進(jìn)程在Kernel Mode下可以任意讀寫,在User Mode下是不可訪問的。

另外,除了訪問權(quán)限的屬性外,還需要提供Shareable, Bufferable, Cacheable的信息。他們的信息由PTE中的TEX位域以及ARM硬件的PRRR和NMRR寄存器提供。


PRRR的全稱是:(Prime Region Remap Register);
NMRR的全稱是:(Normal Memory Remap Register)


對(duì)于ARMV7,Linux Kernel 將其值設(shè)置為:



arch/arm/mm/proc-v7-2level.S

PRRR: 0xff0a81a8

NMRR: 0x40e040e0


分析一下PRRR:

PRRR,可以分為4個(gè)部分,各個(gè)部分共同決定shareable的狀態(tài)。


015位:每?jī)晌蛔鳛橐粋€(gè)unit,說明類型是Normal Memory 還是 Device Memory Strongly-ordered.

16 17位:如果是Device Memory當(dāng)S=0或者1時(shí),對(duì)應(yīng)的區(qū)域是shareable還是non-shareable

18 19位:如果是Normal Memory 當(dāng)S=0或者1時(shí),對(duì)應(yīng)的區(qū)域是shareable還是non-shareable

20~23 SBZ

24~31位:每一位都是指 Outer Shareable 還是Inner Shareable。當(dāng)是1,則為Outer Shareable

Linux PRRR24~31位都是0b1,說明都是inner Shareable.



注1:shareable,用于描述multi-processores的cache的屬性??梢苑譃閕nner shareable和outer shareable. 
若某塊cache是inner shareable的,那么該cache所在的inner domain的observers對(duì)該cache的訪問是transparent或者coherent。 這里transparent的意思是:observers可以對(duì)該cache隨便access,而不會(huì)發(fā)生數(shù)據(jù)不一致的情況。如果某塊cache不是inner shareable,則一定是outer shareable(雖然ARM還定義了non-shareable,但軟件一般不利用這個(gè)概念). 



對(duì)照上文Tex[0]:1 C:1 B:1 決定n7(其映射表實(shí)際上也是一句二進(jìn)制轉(zhuǎn)化為十進(jìn)制來決定的n的值08


所以,此段Memory地址的類型由[1415]位決定。PRRR中對(duì)應(yīng)位的值是0b10,所以為Normal Memory;又由于其S=1的,所以看第[19]位,19位是1,說明是Shareable的;又[31]位是1,說明是Inner Shareable。


因此,Section默認(rèn)的cache狀態(tài):Inner Shareable, Normal Memory


下面分析一下NMRR:

NMRR分為兩部分0~15 16~31.

16~31: Outer Cacheable property

15~0Inner Cacheable property

每?jī)晌蛔饕粋€(gè)unit,其值代表的意義

00  Region is Non-cacheable

01  Region is Write-Back, WriteAllocate

10  Region is WriteThrough, Non-WriteAllocate

11  Region is Write-Back, Non-WriteAllocate.

Linux中,其默認(rèn)的值為0x40e040e0,前16位和16位是一樣的。

對(duì)于Section PGD的值,其默認(rèn)的Tex[0]:1 C:1 B:1,因此:n=7

所以outer cacheableproperty 31:31位,inner cacheableproperty 15:14位。

其值都為0b01,所以outer cacheable  Inner cacheable都是WBWA.


綜上,對(duì)于section的映射,其屬性 outer and inner cache 都是WBWA,而且inner cache shareable的。


下面看一下PTE的屬性


Pte的屬性設(shè)置為:


  .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY| L_PTE_MT_WRITEALLOC | L_PTE_SHARED,



再參考(真正做的操作是黑色粗體部分):

 76 ENTRY(cpu_v7_set_pte_ext)
 77 #ifdef CONFIG_MMU
 78         str     r1, [r0]                        @ linux version
 79
 80         bic     r3, r1, #0x000003f0
 81         bic     r3, r3, #PTE_TYPE_MASK
 82         orr     r3, r3, r2
 83         orr     r3, r3, #PTE_EXT_AP0 | 2
 84
 85         tst     r1, #1 << 4
 86         orrne   r3, r3, #PTE_EXT_TEX(1)
 87
 88         eor     r1, r1, #L_PTE_DIRTY
 89         tst     r1, #L_PTE_RDONLY | L_PTE_DIRTY
 90         orrne   r3, r3, #PTE_EXT_APX
 91
 92         tst     r1, #L_PTE_USER
 93         orrne   r3, r3, #PTE_EXT_AP1
 94 #ifdef CONFIG_CPU_USE_DOMAINS
 95         @ allow kernel read/write access to read-only user pages
 96         tstne   r3, #PTE_EXT_APX
 97         bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
 98 #endif
 99
100         tst     r1, #L_PTE_XN
101         orrne   r3, r3, #PTE_EXT_XN
102
103         tst     r1, #L_PTE_YOUNG
104         tstne   r1, #L_PTE_PRESENT
105         moveq   r3, #0



注意一點(diǎn):

88~90行:如果Linux版本的pte沒有被設(shè)置為dirty(實(shí)際上,可以當(dāng)作write),APX位一定會(huì)被置位的。這樣AP[2:1:0]的值為101,所帶來的結(jié)果是,Privileged read-only. user permissions No access.

此時(shí),若Linux版本的Pte被設(shè)置為L(zhǎng)_PTE_USER,則AP[2:1:0]的值為:111,其效應(yīng)是:Privileged and User read-only(這個(gè)只對(duì)ARM V7有效。在V6中是reserved的)。若88~90行的APX沒有被置位,則AP[2:1:0]的值為:011,其效應(yīng)是:Full access。


所以AP[2…0]的設(shè)置情況是:

1.AP[0]一定置1.

2.若L_PTE_USER設(shè)置了,則AP[1]被設(shè)置。

3.若L_PTE_DIRTY不設(shè)置,則AP[2]必為1,反之,若設(shè)置了L_PTE_RDONLY,則AP[1]也會(huì)置1.若同時(shí)設(shè)置了L_PTE_DIRTY和L_PTE_RDONLY,AP[2]也會(huì)置1(只是這樣的話,貌似互相矛盾了,不過,在設(shè)置的時(shí)候,還是設(shè)置了RDONLY的)


AP對(duì)應(yīng)的權(quán)限表為:

































































AP[2..0]


Privileged


User


Notes


000


No Access


No Access




001


RW


No Access




010


RW


R




011


RW


RW




100


-


-


Reserved


101


R


No Access




110


R


R


Deprecated


111


R


R







最終:




nG S AP[2] TEX[2:0] | AP[1:0] | C | B| 1 | XN

0    1    0       001            01       1  1   1   0


AP[2:1:0]: 001 Privileged access only

Cache的屬性:n=7,所以,查PRRRNMRR


其屬性 outer and inner cache 都是WBWA,而且inner cache shareable的(和Section相同)



唯一不同的是ap[0]的定義。奇怪呢。



注1:添加于2013.09.13

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多