再讀核心儲存管理(7):icache支援

來源:互聯網
上載者:User
 

快樂蝦http://blog.csdn.net/lights_joy/lights@hb165.com   本文適用於ADI bf561 DSPuclinux-2008r1-rc8 (移植到vdsp5)Visual DSP++ 5.0   歡迎轉載,但請保留作者資訊 

1.1    icache支援 1.1.1   寄存器配置初始化在核心中,如果要支援icache,必須首先定義一個宏:#define       CONFIG_BFIN_ICACHE               1對icache的初始化配置在arch/blackfin/kernel/cplb-nompu/cacheinit.c的bfin_icache_init函數完成:#if defined(CONFIG_BFIN_ICACHE)void bfin_icache_init(void){     unsigned long *table = icplb_table;     unsigned long ctrl;     int i;      for (i = 0; i < MAX_CPLBS; i++) {         unsigned long addr = *table++;         unsigned long data = *table++;         if (addr == (unsigned long)-1)              break;         bfin_write32(ICPLB_ADDR0 + i * 4, addr);         bfin_write32(ICPLB_DATA0 + i * 4, data);     }     ctrl = bfin_read_IMEM_CONTROL();     ctrl |= IMC | ENICPLB;     bfin_write_IMEM_CONTROL(ctrl);     SSYNC();}#endif在這裡,MAX_CPLBS的定義為:#define MAX_CPLBS (16 * 2)之所以定義為16*2是因為它把ICPLB_ADDR和ICPLB_DATA交叉存放在一個數組中,因此需要*2。icplb_table則是一個全域變數,其定義為:u_long icplb_table[MAX_CPLBS + 1];最後一個CPLB元素的值為-1(不一定是數組的最後一個元素),用作上述函數中for迴圈的允出準則。那麼icplb_table的值從哪來呢?答案在cplbinit.c。 1.1.2   icplb_table的產生icplb_table的產生是由generate_cpl_tables實現的。以下代碼刪除了與icplb初始化化無關的部分:void __init generate_cpl_tables(void){      u16 i, j, process;     u32 a_start, a_end, as, ae, as_1m;      struct cplb_tab *t_i = NULL;     struct s_cplb cplb;      cplb.init_i.size = MAX_CPLBS;     cplb.init_i.pos = 0;     cplb.init_i.tab = icplb_table;      for (i = ZERO_P; i < ARRAY_SIZE(cplb_data); ++i) {         if (!cplb_data[i].valid)              continue;          as = cplb_data[i].start % SIZE_4M;         ae = cplb_data[i].end % SIZE_4M;          if (as)              a_start = cplb_data[i].start + (SIZE_4M - (as));         else              a_start = cplb_data[i].start;          a_end = cplb_data[i].end - ae;          for (j = INITIAL_T; j <= SWITCH_T; j++) {               switch (j) {              case INITIAL_T:                   if (cplb_data[i].attr & INITIAL_T) {                       t_i = &cplb.init_i;                       t_d = &cplb.init_d;                       process = 1;                   } else                       process = 0;                   break;              default:                       process = 0;                   break;              }               if (!process)                   continue;              if (cplb_data[i].attr & I_CPLB)                   __fill_code_cplbtab(t_i, i, a_start, a_end);          }     } /* close tables */      close_cplbtab(&cplb.init_i);     cplb.init_i.tab[cplb.init_i.pos] = -1;}在這裡cplb_data是在檔案頭中定義的一個10個元素的數組,它詳細說明了每塊記憶體的屬性,如大小,類型等等。當程式運行到__fill_code_cplbtab時,以下幾塊將被填入ICPLB的數組中:     {         .start = L1_CODE_START,         .end = L1_CODE_START + L1_CODE_LENGTH,         .psize = SIZE_4M,         .attr = INITIAL_T | SWITCH_T | I_CPLB,         .i_conf = L1_IMEMORY,         .d_conf = 0,         .valid = 1,         .name = "L1 I-Memory",     },     {         .start = 0,         .end = 0, /* dynamic */         .psize = 0,         .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,         .i_conf = SDRAM_IGENERIC,         .d_conf = SDRAM_DGENERIC,         .valid = 1,         .name = "Kernel Memory",     },其中,Kernel Memory這個塊的.end已經設定為SDRAM的結束位置。 1.1.3   __fill_code_cplbtab這個函數的實現為:/* helper function */static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end){     if (cplb_data[i].psize) {         fill_cplbtab(t,                   cplb_data[i].start,                   cplb_data[i].end,                   cplb_data[i].psize,                   cplb_data[i].i_conf);     #if defined(CONFIG_BFIN_ICACHE)         if (ANOMALY_05000263 && i == SDRAM_KERN) {              fill_cplbtab(t,                       cplb_data[i].start,                       cplb_data[i].end,                       SIZE_4M,                       cplb_data[i].i_conf);         } else#endif} else {              fill_cplbtab(t,                       cplb_data[i].start,                       a_start,                       SIZE_1M,                       cplb_data[i].i_conf);              fill_cplbtab(t,                       a_start,                       a_end,                       SIZE_4M,                       cplb_data[i].i_conf);              fill_cplbtab(t, a_end,                       cplb_data[i].end,                       SIZE_1M,                       cplb_data[i].i_conf);         }}static unsigned short __initfill_cplbtab(struct cplb_tab *table,          unsigned long start, unsigned long end,          unsigned long block_size, unsigned long cplb_data){     int i;      switch (block_size) {     case SIZE_4M:         i = 3;         break;     case SIZE_1M:         i = 2;         break;     case SIZE_4K:         i = 1;         break;     case SIZE_1K:     default:         i = 0;         break;     }      cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);      while ((start < end) && (table->pos < table->size)) {          table->tab[table->pos++] = start;          if (lock_kernel_check(start, start + block_size) == IN_KERNEL)              table->tab[table->pos++] =                  cplb_data | CPLB_LOCK | CPLB_DIRTY;         else              table->tab[table->pos++] = cplb_data;          start += block_size;     }     return 0;} 1.1.3.1             L1 I-Memory當     {         .start = L1_CODE_START,         .end = L1_CODE_START + L1_CODE_LENGTH,         .psize = SIZE_4M,         .attr = INITIAL_T | SWITCH_T | I_CPLB,         .i_conf = L1_IMEMORY,         .d_conf = 0,         .valid = 1,         .name = "L1 I-Memory",     },這個塊傳遞進來時,它將直接調用         fill_cplbtab(t,                   cplb_data[i].start,                   cplb_data[i].end,                   cplb_data[i].psize,                   cplb_data[i].i_conf);從fill_cplbtab這個函數可以看出此時ICPLB_ADDR的值將為L1_CODE_START,也就是0xffa0 0000,而ICPLB_DATA的值將為0x0003 0007,這個值的意義是:16位和17位的值為11,即頁面大小為4M。第0位,也即CPLB_VALID,為1,表示Valid CPLB Entry。第1位,也即CPLB_LOCK,為1,表示CPLB Entry Should not be replaced。第2位,也即CPLB_USER_RD,為1,表示User mode read access permitted。 1.1.3.2             Kernel Memory當     {         .start = 0,         .end = 0, /* dynamic */         .psize = 0,         .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,         .i_conf = SDRAM_IGENERIC,         .d_conf = SDRAM_DGENERIC,         .valid = 1,         .name = "Kernel Memory",     },這個塊傳進來的時候,它將調用              fill_cplbtab(t,                       cplb_data[i].start,                       cplb_data[i].end,                       SIZE_4M,                       cplb_data[i].i_conf);此時將產生15個SDRAM的塊,每個都是4M,且從0開始遞增。此時它們的CPLB_DATA值將為0x0003 1205,這個值的意義是:16位和17位的值為11,即頁面大小為4M。第0位,也即CPLB_VALID,為1,表示Valid CPLB Entry。第1位,也即CPLB_LOCK,為0,表示CPLB Entry can be replaced。第2位,也即CPLB_USER_RD,為1,表示User mode read access permitted。第9位,也即CPLB_MEM_LEV,為1,表示Determins Line Buffer, Low Priority。第12位,也即CPLB_L1_CHBL,為1,表示Cacherable in l1。 1.1.4   換頁問題很明顯,在初始化的時候,當SDRAM>32M時,icache是無法覆蓋整個儲存空間的,此時,uclinux核心必然會發生I-fetch CPLB miss異常。uclinux核心對這種異常情況的處理由_cplb_mgr完成,這個函數在arch/blackfin/kernel/cplb-nompu/cplbmgr.S中,它將在整個儲存地區的配置列表中尋找一個合適的塊,替換掉ICACHE_DATA15和ICACHE_ADDR15,即它總是替換最新的一個頁。在這裡,整個儲存地區配置的列表儲存在一個叫ipdt_table的數組中,看看他的定義:u_long ipdt_table[MAX_SWITCH_I_CPLBS + 1] PDT_ATTR;/** Number of required instruction CPLB switchtable entries* MEMSIZE / 4 (we mostly install 4M page size CPLBs* approx 12 for smaller 1MB page size CPLBs for allignment purposes* 1 for L1 Instruction Memory* possibly 1 for L2 Instruction Memory* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO*/ #define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1 + 1) * 2)這個數組同樣是交叉儲存了ICPLB_ADDR和ICPLB_DATA的值,它的初始化同樣由generate_cpl_tables函數完成,與icplb_table的初始化類似。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.