⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pagetab.c

📁 realview22.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
/* pagetab.c - Module to provide page tables for MMU and PU based processors
 * Copyright (C) Advanced RISC Machines Limited, 1998-1999.
 * Copyright (C) ARM Limited, 1999-2001. All rights reserved.
 *
 * RCS $Revision: 1.10.2.11.18.6 $
 * Checkin $Date: 2004/10/28 15:25:48 $
 * Revising $Author: ljameson $
 */

#define MODEL_NAME Pagetab

#include <string.h>
#include "minperip.h"
#include "armul_cnf.h"

#ifndef NDEBUG
# if 1
# else
#  define VERBOSE_RESET
#  define VERBOSE
# endif
#endif


enum PT_CP15TypeE {
  PT_UNKNOWN, PT_PU, PT_MMU, PT_TCRAM, PT_OTHER
  };
char const *const PT_CP15TypeNames[1+PT_OTHER] =
  {
    "UNKNOWN", "PU", "MMU", "TCRAM", "OTHER"
  };


enum access {
  NO_ACCESS,
  NO_USR_W,
  SVC_RW,
  ALL_ACCESS
  };

enum entrytype {
  INVALID,
  PAGE,
  SECTION
  };

/* The U_BIT is implementation defined.
 * On ARMV6 it SBZ, and is XN if subpages enabled.
 * On ARM720T it SBO, and is Updateable on older MMU's.
 */
#define U_BIT 16
#define C_BIT 8
#define B_BIT 4

#define L1Entry(type,addr,dom,ucb,acc) \
  ((type==SECTION) ? (((addr)&0xfff00000)|((acc)<<10)|  \
                      ((dom)<<5)|(ucb)|(type)) :        \
   (type==PAGE) ? (((addr)&0xfffffc00)|((dom)<<5)|      \
                   ((ucb)&U_BIT)|(type)) :              \
   0)

static struct {
  tag_t option;
  ARMword bit;
  int def;
} ctl_flags[] = {
  ARMulCnf_MMU,         ARM_MMU_M, TRUE,
  ARMulCnf_AlignFaults, ARM_MMU_A, FALSE,
  ARMulCnf_Cache,       ARM_MMU_C, TRUE,
  ARMulCnf_WriteBuffer, ARM_MMU_W, TRUE,
  ARMulCnf_Prog32,      ARM_MMU_P, TRUE,
  ARMulCnf_Data32,      ARM_MMU_D, TRUE,
  ARMulCnf_LateAbort,   ARM_MMU_L, TRUE,
/* - most users of page-tables will allow the debugger to choose ByteSex. */
/*   ARMulCnf_BigEnd,      ARM_MMU_B, FALSE, */
  ARMulCnf_SystemProt,  ARM_MMU_S, FALSE,
  ARMulCnf_ROMProt,     ARM_MMU_R, FALSE,
  ARMulCnf_BranchPredict, ARM_MMU_Z, TRUE,
  ARMulCnf_ICache,      ARM_MMU_I, TRUE,
  ARMulCnf_HighExceptionVectors, ARM_MMU_V, FALSE
  };


BEGIN_STATE_DECL(Pagetab)
    toolconf clone;
/*    GenericAccessCallback *ih_gac;  */
    bool hasMMU, hasPU, hasTCRAM, hasV6MPU;

    bool Set_Endian,   
         sh_Bigend32;
    bool_int sh_Bigend8, Set_Endian8;

    bool_int Set_Unaligned, sh_Unaligned;

    bool_int pt_verbose;
    enum PT_CP15TypeE pt_CP15TYPE;

    ARMword pt_arch;

END_STATE_DECL(Pagetab)


static void
bitAssignWM(ARMword *d, ARMword mask /* e.g. ARM_MMU_B */, bool_int s)
{
  if (s)
    *d |= mask;
  else
    *d &= ~mask;
}



static void disable_MMU(PagetabState *tab)
{
    ARMword cp15ctrl[8]; /* Reg1 can have 2 words in XScale */



    /* Read what's there already. */
    ARMulif_CPRead(&tab->coredesc,15,1,&cp15ctrl[0]);
    
    cp15ctrl[0] &= ~ARM_MMU_M;
    
    ARMulif_CPWrite(&tab->coredesc,15,1,&cp15ctrl[0]);

#ifdef VERBOSE_RESET
    printf("Pagetab.c:disable_MMU write %08lx to CP15 reg1.\n",
           (unsigned long)cp15ctrl[0]);
#endif
}

/* !!! NB pagetab->clone doesn't allow us to read the
 * Architecture from the Processor, so +++ we do this earlier. */
static void pagetab_MMU(PagetabState *tab)
{
  toolconf config = tab->clone;
  const char *option;
/*  ARMword value; */
  ARMword PTBase=ToolConf_DLookupUInt(config, ARMulCnf_PageTableBase,
                             0x40000000) & 0xffffc000; /* align */

  ARMword page;
  ARMword entry;
  unsigned int i;
  ARMword arch = tab->pt_arch;
#if 0
  Hostif_ConsolePrint(tab->hostif,"\nPagetab MMU for Architecture %u\n",
                      (unsigned)arch);
#endif
  disable_MMU(tab);
  {
  ARMWord DACvalue=ToolConf_DLookupUInt(config, ARMulCnf_DAC, 0x3);
  ARMulif_CPWrite(&tab->coredesc,15,3,&DACvalue);
  }
  
  {
  /* ARMV6 has > 1 words here. We choose to only write the first TTB. */
  ARMword data[16];
  memset(data,0,sizeof(data));
  ARMulif_CPRead(&tab->coredesc,15,2,&data[0]);
  data[0]=PTBase;
  ARMulif_CPWrite(&tab->coredesc,15,2,&data[0]);
  }
  
  /* start with all pages flat, cacheable, bufferable. 
   * -- formerly claimed to be uncacheable, read/write, unbufferable */
  {
  unsigned main_ucb = (arch < 5) ? (U_BIT|C_BIT|B_BIT) : (C_BIT|B_BIT);
  entry=L1Entry(SECTION,0,0,main_ucb,ALL_ACCESS);
  }
  for (i=0, page=PTBase; i<4096; i++, page+=4) {
    if (ARMulif_WriteWord(&tab->coredesc, page, entry | (i<<20)))
    {
        Hostif_ConsolePrint(tab->hostif,"\nPagetab failed to write memory "
                            "at %08lx\n",
                            (unsigned long)page);
        return;
    };
  }

  for (i=0; i<100; i++) {
    char buffer[32];
    ARMword low,physical,mask;
    ARMword page;
    toolconf region;
    int j,n;

    sprintf(buffer,"REGION[%d]",i);
    region=ToolConf_FlatChild(config,(tag_t)buffer);
    if (region==NULL) break;    /* stop */

    option=ToolConf_Lookup(region,ARMulCnf_VirtualBase);
    if (option) {
      low=option ? strtoul(option,NULL,0) : 0;
      physical=ToolConf_DLookupUInt(region, ARMulCnf_PhysicalBase, low);
    } else {
      low=physical=ToolConf_DLookupUInt(region, ARMulCnf_PhysicalBase,0);
    }

    option = ToolConf_Lookup(region, ARMulCnf_Size);
    if (option != NULL) {
      unsigned long size = ToolConf_Power(option, TRUE);
      if (size == 0) {          /* assume 4GB */
        n = 4096;
      } else {
        n = size >> 20;
      }
    } else {
      /* backwards compatability */
      n = ToolConf_DLookupUInt(region, ARMulCnf_Pages, 4096);
    }
    mask=0;
    option=ToolConf_Lookup(region,ARMulCnf_Cacheable);
    mask=ToolConf_AddFlag(option,mask,C_BIT,TRUE);
    option=ToolConf_Lookup(region,ARMulCnf_Bufferable);
    mask=ToolConf_AddFlag(option,mask,B_BIT,TRUE);
    if (arch < 5) {
        option=ToolConf_Lookup(region,ARMulCnf_Updateable);
        mask=ToolConf_AddFlag(option,mask,U_BIT,TRUE);
    }

    /* Support V6TEX in 1MB sections to enable AllocateOnWrite in ARMV6
     * and test that ARM1136 doesn't do allocate-on-write! */
    if (arch > 5) {
        ARMword tex = ToolConf_DLookupUInt(region, ARMulCnf_V6TEX, 0) & 0x7;
#if 0
        Hostif_ConsolePrint(tab->hostif,"\nPagetab MMU has TEX:0x%x\n",
                      (unsigned)tex);
#endif

        mask |= (tex) << 12;
    }
    mask |= (ToolConf_DLookupUInt(region, ARMulCnf_Domain, 0) & 0xf) << 5;
    mask |= (ToolConf_DLookupUInt(region, ARMulCnf_AccessPermissions,
                                  ALL_ACCESS) & 3) << 10;

    /* set TRANSLATE=NO to generate translation faults */
    if (ToolConf_DLookupBool(region, ARMulCnf_Translate, TRUE))
      mask |= SECTION;
    
    low&=0xfff00000;
    if (arch < 6)
        mask=(physical & 0xfff00000) | (mask & 0xdfe);
    else
        mask=(physical & 0xfff00000) | (mask & 0x7dfe); /* Allow TEX */

    j=low>>20;          /* index of first section */
    n+=j; if (n>4096) n=4096;
    for (page=(PTBase+j*4); j<n; j++, mask+=0x100000, page+=4) {
      ARMulif_WriteWord(&tab->coredesc,page,mask);
    }
  }
  /* now enable the caches, etc. */
  { 
    ARMword cp15ctrl[16]; /* Reg1 can have 2 words in XScale */
    /* Read what's there already. */
    ARMulif_CPRead(&tab->coredesc,15,1,&cp15ctrl[0]);
#ifdef VERBOSE_RESET
    printf("Pagetab.c:pagetab_MMU reads %08lx from CP15 reg1.\n",
           (unsigned long)cp15ctrl[0]);
#endif
    for (i=0;i<sizeof(ctl_flags)/sizeof(ctl_flags[0]);i++) 
    {
        bool b = 
            ToolConf_DLookupBool(config,ctl_flags[i].option,BOOLIFY(ctl_flags[i].def));
#ifdef VERBOSE_RESET
    printf("Pagetab.c:pagetab_MMU, %08lx in CP15 reg1, "
           "bool=%u, bit = %08lx.\n",
           (unsigned long)cp15ctrl[0], (unsigned)b, 
           (unsigned long)ctl_flags[i].bit
        );

#endif
      if (b)
        cp15ctrl[0]|=ctl_flags[i].bit;
      else
        cp15ctrl[0]&= ~(ctl_flags[i].bit);
    }
    /* !Todo: This should only apply to processors which support FastBus, e.g. by
     * checking for HAS_FASTBUS=True. For now, it does no harm!
     */
    if (!(ToolConf_DLookupBool(config, ARMulCnf_FastBus, FALSE)))
        cp15ctrl[0] |= 0x40000000;
    else
         cp15ctrl[0] &= ~0x40000000;

    if(tab->hasTCRAM)
    {
        if ((ToolConf_DLookupBool(config, ARMulCnf_TCIRAM, FALSE)))
        {
            ARMWord value[4];
            ARMulif_CPRead(&tab->coredesc,15,9,&value[0]);
            value[3] |= 1;
            ARMulif_CPWrite(&tab->coredesc,15,9,&value[0]);
        }
        if ((ToolConf_DLookupBool(config, ARMulCnf_TCDRAM, FALSE))) {
            ARMWord value[4];
            ARMulif_CPRead(&tab->coredesc,15,9,&value[0]);
            value[2] |= 1;
            ARMulif_CPWrite(&tab->coredesc,15,9,&value[0]);
        }
    }
#ifdef VERBOSE_RESET
    printf("Pagetab.c:pagetab_MMU before setting endian, %08lx for CP15 reg1.\n",
           (unsigned long)cp15ctrl[0]);
#endif
    if (tab->Set_Endian)
    {
#ifdef VERBOSE_RESET
        printf("Setting endian to %u\n",tab->sh_Bigend32);
#endif
        bitAssignWM(&cp15ctrl[0], ARM_MMU_B, tab->sh_Bigend32);
    }
    if (tab->Set_Endian8)
    {
        bitAssignWM(&cp15ctrl[0],(1<<ARM_MMU_EE_pos), tab->sh_Bigend8);
        bitAssignWM(&cp15ctrl[0],(1<<ARM_MMU_U_pos), tab->sh_Unaligned);
        {
            ARMword psr = ARMulif_GetCPSR(&tab->coredesc);
            if (tab->sh_Bigend8)
            {
                psr |= (1 << ARM_PSR_E_pos);
            }
            else
            {
                psr &= ~(1 << ARM_PSR_E_pos);
            }
            ARMulif_SetCPSR(&tab->coredesc, psr);
        }
    }
    if (tab->Set_Unaligned)
    {
        bitAssignWM(&cp15ctrl[0], (1<<ARM_MMU_U_pos), tab->sh_Unaligned);
    }
    
 
#ifdef VERBOSE_RESET
    printf("Pagetab.c:pagetab_MMU writes %08lx to CP15 reg1.\n",
           (unsigned long)cp15ctrl[0]);
#endif
    ARMulif_CPWrite(&tab->coredesc,15,1,&cp15ctrl[0]);
  }
}

static void pagetab_ProtectionUnit(PagetabState *tab)
{
  toolconf config = tab->clone;
  const char *option;


    /* Variables to hold the values eventually sent to copro 15. 
       They are all different sizes, but for simplicity's sake they
       are stored as longs.
     */
    unsigned long Config_reg=0;
    unsigned long Cacheable_reg=0;
    unsigned long WriteBuffer_reg=0;
    unsigned long Protection_reg=0;
    unsigned long Region_regs[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    ARMword start;
    ARMword size;
    toolconf region;
    char buffer[32];
    int i, j, x;

    disable_MMU(tab); /* Disables the PU. */


    for (i = 1; i < 4; i++) {   /* a bitmask, 'DI' */
        /* For each type of region. Highest priority comes last and ovewrites */
        for (j = 0; j < 8; j++) {
            switch (i) {
            case 1:
                sprintf(buffer,"IREGION[%d]",j);
                break;
            case 2:
                sprintf(buffer,"DREGION[%d]",j);
                break;
            case 3:
                sprintf(buffer,"REGION[%d]",j);
                break;
            }
            region = ToolConf_Child(config,(tag_t)buffer);
            if (region != NULL) {
                start = ToolConf_DLookupUInt(region, ARMulCnf_PhysicalBase, 0);

                option = ToolConf_Lookup(region, ARMulCnf_Size);
                if (option != NULL) {
                  size = ToolConf_Power(option, TRUE);
                } else {
                  int n = ToolConf_DLookupUInt(region, ARMulCnf_Pages, 4096);
                  size = n << 20;
                }

                /* to get the 5 bit size value from the actual size,
                 * we have to do a linear search, to find the most 
                 * significant bit set.(Any other bit is ignored)
                 */
                for (x = 31; x >= 12; x--) {
                    /* Any value for size less than 0x1000 is considered 0 i.e. 4G */
                    if (size & (1 << x)) break;
                }
                size = (x < 12) ? 0x1f : x-1;

                /* for the moment I am assuming if we get this far we want the region enabled */
                option = ToolConf_Lookup(region, ARMulCnf_Translate);
                if (i & 2) {    /* D side */
                  Region_regs[j] = ToolConf_AddFlag(option, (size << 1) | (start << 12), 1, TRUE);
                }
                if (i & 1) {    /* I side */
                  Region_regs[j+8] = ToolConf_AddFlag(option, (size << 1) | (start << 12), 1, TRUE);
                }

                option = ToolConf_Lookup(region, ARMulCnf_Cacheable);
                if (i & 2) {    /* D side */
                  Cacheable_reg |= ToolConf_AddFlag(option, Cacheable_reg, 1<<j, TRUE);
                }
                if (i & 1) {    /* I side */
                  Cacheable_reg |= ToolConf_AddFlag(option, Cacheable_reg, 1<<(j+8), TRUE);/* I side */
                }
                if (i & 2) {    /* D side */
                  option = ToolConf_Lookup(region, ARMulCnf_Bufferable);
                  WriteBuffer_reg = ToolConf_AddFlag(option, WriteBuffer_reg, 1<<j, TRUE);
                }

                if (i & 1) {    /* I side */
                  Protection_reg |= (ToolConf_DLookupUInt(region, ARMulCnf_AccessPermissions, ALL_ACCESS) & 3) << (j*2);
                }
                if (i & 2) {    /* D side */
                  Protection_reg |= (ToolConf_DLookupUInt(region, ARMulCnf_AccessPermissions, ALL_ACCESS) & 3) << ((j*2) + 16);
                }
            }
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -