Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "cp15.h"
  2.  
  3.  
  4. #define CPUID_PXA255            0x69052D06UL    //spepping A0
  5. #define CPUID_PXA270            0x69054114UL    //stepping C0
  6.  
  7. static Boolean cp15prvCoprocRegXferFunc(struct ArmCpu* cpu, void* userData, Boolean two, Boolean read, UInt8 op1, UInt8 Rx, UInt8 CRn, UInt8 CRm, UInt8 op2){
  8.        
  9.         ArmCP15* cp15 = userData;
  10.         UInt32 val = 0, tmp;
  11.        
  12.        
  13.         if(!read) val = cpuGetRegExternal(cpu, Rx);
  14.        
  15.         if(op1 != 0 || two) goto fail;                                  //CP15 only accessed with MCR/MRC with op1 == 0
  16.        
  17.         switch(CRn){
  18.                
  19.                 case 0:         //ID codes
  20.                
  21.                         if(!read) goto fail;                            //cannot write to ID codes register
  22.                         if(CRm != 0) goto fail;                         //CRm must be zero for this read
  23.                         if(op2 == 0){                                   //main ID register
  24.                                
  25.                                 val = CPUID_PXA255;
  26.                                 goto success;
  27.                         }
  28.                         else if(op2 == 1){                              //cahce type register - we lie here
  29.                                
  30.                                 val = 0x0B16A16AUL;
  31.                                 goto success;  
  32.                         }
  33.                         break;
  34.                        
  35.                 case 1:         //control register
  36.                
  37.                         if(op2 == 0){
  38.                                 if(read){
  39.                                         val = cp15->control;
  40.                                 }
  41.                                 else{
  42.                                         tmp = val ^ cp15->control;              //see what changed and mask off then chack for what we support changing of
  43.                                         if(tmp & 0x84F0UL){
  44.                                                 err_str("cp15: unknown bits changed 0x");
  45.                                                 err_hex(cp15->control);
  46.                                                 err_str("->0x");
  47.                                                 err_hex(val);
  48.                                                 err_str(", halting\r\n");
  49.                                                 while(true);
  50.                                         }
  51.                                        
  52.                                         if(tmp & 0x00002000UL){                 // V bit
  53.                                                
  54.                                                 cpuSetVectorAddr(cp15->cpu, (val & 0x00002000UL) ? 0xFFFF0000UL : 0x00000000UL);
  55.                                                 cp15->control ^= 0x00002000UL;
  56.                                         }
  57.                                         if(tmp & 0x00000200UL){                 // R bit
  58.                                                
  59.                                                 mmuSetR(cp15->mmu, (val & 0x00000200UL) != 0);
  60.                                                 cp15->control ^= 0x00000200UL;
  61.                                         }
  62.                                         if(tmp & 0x00000100UL){                 // S bit
  63.                                                
  64.                                                 mmuSetS(cp15->mmu, (val & 0x00000100UL) != 0);
  65.                                                 cp15->control ^= 0x00000100UL;
  66.                                         }
  67.                                         if(tmp & 0x00000001UL){                 // M bit
  68.                                                
  69.                                                 mmuSetTTP(cp15->mmu, (val & 0x00000001UL) ? cp15->ttb : MMU_DISABLED_TTP);
  70.                                                 mmuTlbFlush(cp15->mmu);
  71.                                                 cp15->control ^= 0x00000001UL;
  72.                                         }
  73.                                        
  74.                                 }
  75.                         }
  76.                         else if(op2 == 1){      //PXA-specific thing
  77.                                 if(read) val = cp15->ACP;
  78.                                 else cp15->ACP = val;
  79.                         }
  80.                         else break;
  81.                         goto success;
  82.                        
  83.                 case 2:         //translation tabler base
  84.                         if(read) val = cp15->ttb;
  85.                         else{
  86.                                 if(cp15->control & 0x00000001UL){       //mmu is on
  87.                                        
  88.                                         mmuSetTTP(cp15->mmu, val);
  89.                                         mmuTlbFlush(cp15->mmu);
  90.                                 }
  91.                                 cp15->ttb = val;
  92.                         }
  93.                         goto success;
  94.                
  95.                 case 3:         //domain access control
  96.                         if(read) val = mmuGetDomainCfg(cp15->mmu);
  97.                         else mmuSetDomainCfg(cp15->mmu, val);
  98.                         goto success;
  99.                
  100.                 case 5:         //FSR
  101.                         if(read) val = cp15->FSR;
  102.                         else cp15->FSR = val;
  103.                         goto success;
  104.                        
  105.                 case 6:         //FAR
  106.                         if(read) val = cp15->FAR;
  107.                         else cp15->FAR = val;
  108.                         goto success;
  109.                
  110.                 case 7:         //cache ops
  111.                         if((CRm == 5 || CRm == 7)&& op2 == 0) cpuIcacheInval(cp15->cpu);                //invalidate entire {icache(5) or both i and dcache(7)}
  112.                         if((CRm == 5 || CRm == 7) && op2 == 1) cpuIcacheInvalAddr(cp15->cpu, val);      //invalidate {icache(5) or both i and dcache(7)} line, given VA
  113.                         if((CRm == 5 || CRm == 7) && op2 == 2) cpuIcacheInval(cp15->cpu);               //invalidate {icache(5) or both i and dcache(7)} line, given set/index. i dont know how to do this, so flush thee whole thing
  114.                         goto success;
  115.                
  116.                 case 8:         //TLB ops
  117.                         mmuTlbFlush(cp15->mmu);
  118.                         goto success;
  119.                
  120.                 case 9:         //cache lockdown
  121.                         if(CRm == 1 && op2 == 0){
  122.                                 err_str("Attempt to lock 0x");
  123.                                 err_hex(val);
  124.                                 err_str("+32 in icache\r\n");  
  125.                         }
  126.                         else if(CRm == 2 && op2 == 0){
  127.                                 err_str("Dcache now ");
  128.                                 err_str(val ? "in" : "out of");
  129.                                 err_str(" lock mode\r\n");
  130.                         }
  131.                         goto success;
  132.                
  133.                 case 10:        //TLB lockdown
  134.                         goto success;
  135.                
  136.                 case 13:        //FCSE
  137.                         err_str("FCSE not supported\n");
  138.                         break;
  139.                
  140.                 case 15:
  141.                         if(op2 == 0 && CRm == 1){       //CPAR
  142.                                 if(read) val = cpuGetCPAR(cp15->cpu);
  143.                                 else cpuSetCPAR(cp15->cpu, val & 0x3FFF);
  144.                                 goto success;
  145.                         }
  146.                         break;
  147.         }
  148.        
  149. fail:
  150.         //TODO: cause invalid instruction trap in cpu
  151.         return false;
  152.  
  153. success:
  154.        
  155.         if(read) cpuSetReg(cpu, Rx, val);
  156.         return true;
  157. }
  158.  
  159. void cp15Init(ArmCP15* cp15, ArmCpu* cpu, ArmMmu* mmu){
  160.  
  161.         ArmCoprocessor cp;
  162.        
  163.         cp.regXfer = cp15prvCoprocRegXferFunc;
  164.         cp.dataProcessing = NULL;
  165.         cp.memAccess = NULL;
  166.         cp.twoRegF = NULL;
  167.         cp.userData = cp15;
  168.        
  169.         __mem_zero(cp15, sizeof(ArmCP15));
  170.         cp15->cpu = cpu;
  171.         cp15->mmu = mmu;
  172.         cp15->control = 0x00004072UL;
  173.        
  174.         cpuCoprocessorRegister(cpu, 15, &cp);
  175. }
  176.  
  177. void cp15Deinit(ArmCP15* cp15){
  178.        
  179.         cpuCoprocessorUnregister(cp15->cpu, 15);
  180. }
  181.  
  182. void cp15SetFaultStatus(ArmCP15* cp15, UInt32 addr, UInt8 faultStatus){
  183.        
  184.         cp15->FAR = addr;
  185.         cp15->FSR = faultStatus;
  186. }
  187.