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>
master
Peter Maydell 2012-07-12 10:59:05 +00:00
parent 3cc0cd61f4
commit de9b05b807
3 changed files with 26 additions and 12 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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;