mirror of https://gitee.com/openkylin/qemu.git
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