s390x/mmu: Implement Instruction-Execution-Protection Facility
IEP support in the mmu is fairly easy. Set the right permissions for TLB entries and properly report an exception. Make sure to handle EDAT-2 by setting bit 56/60/61 of the TEID (TEC) to the right values. Let's keep s390_cpu_get_phys_page_debug() working even if IEP is active. Switch MMU_DATA_LOAD - this has no other effects any more as the ASC to be used is now fully selected outside of mmu_translate(). Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: David Hildenbrand <david@redhat.com>
This commit is contained in:
parent
3dc29061f3
commit
3a06f98192
@ -315,6 +315,7 @@ extern const VMStateDescription vmstate_s390_cpu;
|
||||
#define CR0_EDAT 0x0000000000800000ULL
|
||||
#define CR0_AFP 0x0000000000040000ULL
|
||||
#define CR0_VECTOR 0x0000000000020000ULL
|
||||
#define CR0_IEP 0x0000000000100000ULL
|
||||
#define CR0_EMERGENCY_SIGNAL_SC 0x0000000000004000ULL
|
||||
#define CR0_EXTERNAL_CALL_SC 0x0000000000002000ULL
|
||||
#define CR0_CKC_SC 0x0000000000000800ULL
|
||||
|
@ -63,7 +63,11 @@ hwaddr s390_cpu_get_phys_page_debug(CPUState *cs, vaddr vaddr)
|
||||
asc = PSW_ASC_PRIMARY;
|
||||
}
|
||||
|
||||
if (mmu_translate(env, vaddr, MMU_INST_FETCH, asc, &raddr, &prot, false)) {
|
||||
/*
|
||||
* We want to read code even if IEP is active. Use MMU_DATA_LOAD instead
|
||||
* of MMU_INST_FETCH.
|
||||
*/
|
||||
if (mmu_translate(env, vaddr, MMU_DATA_LOAD, asc, &raddr, &prot, false)) {
|
||||
return -1;
|
||||
}
|
||||
return raddr;
|
||||
|
@ -121,6 +121,8 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
|
||||
const bool edat1 = (env->cregs[0] & CR0_EDAT) &&
|
||||
s390_has_feat(S390_FEAT_EDAT);
|
||||
const bool edat2 = edat1 && s390_has_feat(S390_FEAT_EDAT_2);
|
||||
const bool iep = (env->cregs[0] & CR0_IEP) &&
|
||||
s390_has_feat(S390_FEAT_INSTRUCTION_EXEC_PROT);
|
||||
const int asce_tl = asce & ASCE_TABLE_LENGTH;
|
||||
const int asce_p = asce & ASCE_PRIVATE_SPACE;
|
||||
hwaddr gaddr = asce & ASCE_ORIGIN;
|
||||
@ -225,6 +227,9 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
|
||||
*flags &= ~PAGE_WRITE;
|
||||
}
|
||||
if (edat2 && (entry & REGION3_ENTRY_FC)) {
|
||||
if (iep && (entry & REGION3_ENTRY_IEP)) {
|
||||
*flags &= ~PAGE_EXEC;
|
||||
}
|
||||
*raddr = (entry & REGION3_ENTRY_RFAA) |
|
||||
(vaddr & ~REGION3_ENTRY_RFAA);
|
||||
return 0;
|
||||
@ -252,6 +257,9 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
|
||||
*flags &= ~PAGE_WRITE;
|
||||
}
|
||||
if (edat1 && (entry & SEGMENT_ENTRY_FC)) {
|
||||
if (iep && (entry & SEGMENT_ENTRY_IEP)) {
|
||||
*flags &= ~PAGE_EXEC;
|
||||
}
|
||||
*raddr = (entry & SEGMENT_ENTRY_SFAA) |
|
||||
(vaddr & ~SEGMENT_ENTRY_SFAA);
|
||||
return 0;
|
||||
@ -272,6 +280,9 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
|
||||
if (entry & PAGE_ENTRY_P) {
|
||||
*flags &= ~PAGE_WRITE;
|
||||
}
|
||||
if (iep && (entry & PAGE_ENTRY_IEP)) {
|
||||
*flags &= ~PAGE_EXEC;
|
||||
}
|
||||
|
||||
*raddr = entry & TARGET_PAGE_MASK;
|
||||
return 0;
|
||||
@ -430,6 +441,16 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check for Instruction-Execution-Protection */
|
||||
if (unlikely(rw == MMU_INST_FETCH && !(*flags & PAGE_EXEC))) {
|
||||
if (exc) {
|
||||
/* IEP sets bit 56 and 61 */
|
||||
tec |= 0x84;
|
||||
trigger_access_exception(env, PGM_PROTECTION, ilen, tec);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
nodat:
|
||||
/* Convert real address -> absolute address */
|
||||
*raddr = mmu_real2abs(env, *raddr);
|
||||
|
Loading…
Reference in New Issue
Block a user