target-arm: Implement privileged-execute-never (PXN)
Implement the privileged-execute-never (PXN) translation table bit. It is implementation-defined whether this is implemented, so we give it its own ARM_FEATURE_ flag. LPAE requires PXN, so add also an LPAE feature flag and the implication logic, as a placeholder for actually implementing LPAE at a later date. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									3cc0cd61f4
								
							
						
					
					
						commit
						de9b05b807
					
				| 
						 | 
				
			
			@ -192,6 +192,9 @@ void arm_cpu_realize(ARMCPU *cpu)
 | 
			
		|||
    if (arm_feature(env, ARM_FEATURE_VFP3)) {
 | 
			
		||||
        set_feature(env, ARM_FEATURE_VFP);
 | 
			
		||||
    }
 | 
			
		||||
    if (arm_feature(env, ARM_FEATURE_LPAE)) {
 | 
			
		||||
        set_feature(env, ARM_FEATURE_PXN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    register_cp_regs_for_features(cpu);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -532,6 +535,7 @@ static void cortex_a15_initfn(Object *obj)
 | 
			
		|||
    set_feature(&cpu->env, ARM_FEATURE_V7MP);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
 | 
			
		||||
    set_feature(&cpu->env, ARM_FEATURE_LPAE);
 | 
			
		||||
    cpu->midr = 0x412fc0f1;
 | 
			
		||||
    cpu->reset_fpsid = 0x410430f0;
 | 
			
		||||
    cpu->mvfr0 = 0x10110222;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -386,6 +386,8 @@ enum arm_features {
 | 
			
		|||
    ARM_FEATURE_CACHE_DIRTY_REG, /* 1136/1176 cache dirty status register */
 | 
			
		||||
    ARM_FEATURE_CACHE_BLOCK_OPS, /* v6 optional cache block operations */
 | 
			
		||||
    ARM_FEATURE_MPIDR, /* has cp15 MPIDR */
 | 
			
		||||
    ARM_FEATURE_PXN, /* has Privileged Execute Never bit */
 | 
			
		||||
    ARM_FEATURE_LPAE, /* has Large Physical Address Extension */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline int arm_feature(CPUARMState *env, int feature)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1935,9 +1935,10 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 | 
			
		|||
    uint32_t table;
 | 
			
		||||
    uint32_t desc;
 | 
			
		||||
    uint32_t xn;
 | 
			
		||||
    uint32_t pxn = 0;
 | 
			
		||||
    int type;
 | 
			
		||||
    int ap;
 | 
			
		||||
    int domain;
 | 
			
		||||
    int domain = 0;
 | 
			
		||||
    int domain_prot;
 | 
			
		||||
    uint32_t phys_addr;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1946,27 +1947,27 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 | 
			
		|||
    table = get_level1_table_address(env, address);
 | 
			
		||||
    desc = ldl_phys(table);
 | 
			
		||||
    type = (desc & 3);
 | 
			
		||||
    if (type == 0) {
 | 
			
		||||
        /* Section translation fault.  */
 | 
			
		||||
    if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
 | 
			
		||||
        /* Section translation fault, or attempt to use the encoding
 | 
			
		||||
         * which is Reserved on implementations without PXN.
 | 
			
		||||
         */
 | 
			
		||||
        code = 5;
 | 
			
		||||
        domain = 0;
 | 
			
		||||
        goto do_fault;
 | 
			
		||||
    } else if (type == 2 && (desc & (1 << 18))) {
 | 
			
		||||
        /* Supersection.  */
 | 
			
		||||
        domain = 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Section or page.  */
 | 
			
		||||
    }
 | 
			
		||||
    if ((type == 1) || !(desc & (1 << 18))) {
 | 
			
		||||
        /* Page or Section.  */
 | 
			
		||||
        domain = (desc >> 5) & 0x0f;
 | 
			
		||||
    }
 | 
			
		||||
    domain_prot = (env->cp15.c3 >> (domain * 2)) & 3;
 | 
			
		||||
    if (domain_prot == 0 || domain_prot == 2) {
 | 
			
		||||
        if (type == 2)
 | 
			
		||||
        if (type != 1) {
 | 
			
		||||
            code = 9; /* Section domain fault.  */
 | 
			
		||||
        else
 | 
			
		||||
        } else {
 | 
			
		||||
            code = 11; /* Page domain fault.  */
 | 
			
		||||
        }
 | 
			
		||||
        goto do_fault;
 | 
			
		||||
    }
 | 
			
		||||
    if (type == 2) {
 | 
			
		||||
    if (type != 1) {
 | 
			
		||||
        if (desc & (1 << 18)) {
 | 
			
		||||
            /* Supersection.  */
 | 
			
		||||
            phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
 | 
			
		||||
| 
						 | 
				
			
			@ -1978,8 +1979,12 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 | 
			
		|||
        }
 | 
			
		||||
        ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
 | 
			
		||||
        xn = desc & (1 << 4);
 | 
			
		||||
        pxn = desc & 1;
 | 
			
		||||
        code = 13;
 | 
			
		||||
    } else {
 | 
			
		||||
        if (arm_feature(env, ARM_FEATURE_PXN)) {
 | 
			
		||||
            pxn = (desc >> 2) & 1;
 | 
			
		||||
        }
 | 
			
		||||
        /* Lookup l2 entry.  */
 | 
			
		||||
        table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
 | 
			
		||||
        desc = ldl_phys(table);
 | 
			
		||||
| 
						 | 
				
			
			@ -2007,6 +2012,9 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
 | 
			
		|||
    if (domain_prot == 3) {
 | 
			
		||||
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 | 
			
		||||
    } else {
 | 
			
		||||
        if (pxn && !is_user) {
 | 
			
		||||
            xn = 1;
 | 
			
		||||
        }
 | 
			
		||||
        if (xn && access_type == 2)
 | 
			
		||||
            goto do_fault;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue