Background: s390x implements Low-Address Protection (LAP). If LAP is
enabled, writing to effective addresses (before any transaltion)
0-511 and 4096-4607 triggers a protection exception.
So we have subpage protection on the first two pages of every address
space (where the lowcore - the CPU private data resides).
By immediately invalidating the write entry but allowing the caller to
continue, we force every write access onto these first two pages into
the slow path. we will get a tlb fault with the specific accessed
addresses and can then evaluate if protection applies or not.
We have to make sure to ignore the invalid bit if tlb_fill() succeeds.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
accel/tcg/cputlb.c | 5 ++++-
accel/tcg/softmmu_template.h | 4 ++--
include/exec/cpu-all.h | 3 +++
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index bcbcc4db6c..5bc4233961 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -683,6 +683,9 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
} else {
tn.addr_write = address;
}
+ if (prot & PAGE_WRITE_INV) {
+ tn.addr_write |= TLB_INVALID_MASK;
+ }
}
/* Pairs with flag setting in tlb_reset_dirty_range */
@@ -967,7 +970,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
}
- tlb_addr = tlbe->addr_write;
+ tlb_addr = tlbe->addr_write & ~TLB_INVALID_MASK;
}
/* Check notdirty */
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
index d7563292a5..3fc5144316 100644
--- a/accel/tcg/softmmu_template.h
+++ b/accel/tcg/softmmu_template.h
@@ -285,7 +285,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
}
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
}
/* Handle an IO access. */
@@ -361,7 +361,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, MMU_DATA_STORE, mmu_idx, retaddr);
}
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+ tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
}
/* Handle an IO access. */
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index ffe43d5654..24b9509604 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -247,6 +247,9 @@ extern intptr_t qemu_host_page_mask;
/* original state of the write flag (used when tracking self-modifying
code */
#define PAGE_WRITE_ORG 0x0010
+/* Invalidate the TLB entry immediately, helpful for s390x
+ * Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs() */
+#define PAGE_WRITE_INV 0x0040
#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
/* FIXME: Code that sets/uses this is broken and needs to go away. */
#define PAGE_RESERVED 0x0020
--
2.13.5
On 09/27/2017 10:00 AM, David Hildenbrand wrote: > Background: s390x implements Low-Address Protection (LAP). If LAP is > enabled, writing to effective addresses (before any transaltion) > 0-511 and 4096-4607 triggers a protection exception. > > So we have subpage protection on the first two pages of every address > space (where the lowcore - the CPU private data resides). > > By immediately invalidating the write entry but allowing the caller to > continue, we force every write access onto these first two pages into > the slow path. we will get a tlb fault with the specific accessed > addresses and can then evaluate if protection applies or not. > > We have to make sure to ignore the invalid bit if tlb_fill() succeeds. This is similar to a scheme I proposed to PMM wrt handling ARM v8M translation. Reusing TLB_INVALID_MASK would appear to work, but I wonder if it wouldn't be clearer to use another bit. I believe I had proposed a TLB_FORCE_SLOW_MASK. Thoughts, Peter? r~
On 27.09.2017 19:48, Richard Henderson wrote: > On 09/27/2017 10:00 AM, David Hildenbrand wrote: >> Background: s390x implements Low-Address Protection (LAP). If LAP is >> enabled, writing to effective addresses (before any transaltion) >> 0-511 and 4096-4607 triggers a protection exception. >> >> So we have subpage protection on the first two pages of every address >> space (where the lowcore - the CPU private data resides). >> >> By immediately invalidating the write entry but allowing the caller to >> continue, we force every write access onto these first two pages into >> the slow path. we will get a tlb fault with the specific accessed >> addresses and can then evaluate if protection applies or not. >> >> We have to make sure to ignore the invalid bit if tlb_fill() succeeds. > > This is similar to a scheme I proposed to PMM wrt handling ARM v8M translation. > Reusing TLB_INVALID_MASK would appear to work, but I wonder if it wouldn't be > clearer to use another bit. I believe I had proposed a TLB_FORCE_SLOW_MASK. The only downside of another bit is that we have to duplicate all checks. Using TLB_INVALID_MASK avoids this change (because it simply works). Of course, we could come up with something as simple as #define TLB_INVALID_MASK (TLB_INVALID | TLB_FORCE_SLOW) and fixup the few places where TLB_INVALID_MASK really just has to be TLB_INVALID. Have no strong opinion on this. This way requires minimal changes. > > Thoughts, Peter? > > > r~ > -- Thanks, David
On 27.09.2017 19:48, Richard Henderson wrote: > On 09/27/2017 10:00 AM, David Hildenbrand wrote: >> Background: s390x implements Low-Address Protection (LAP). If LAP is >> enabled, writing to effective addresses (before any transaltion) >> 0-511 and 4096-4607 triggers a protection exception. >> >> So we have subpage protection on the first two pages of every address >> space (where the lowcore - the CPU private data resides). >> >> By immediately invalidating the write entry but allowing the caller to >> continue, we force every write access onto these first two pages into >> the slow path. we will get a tlb fault with the specific accessed >> addresses and can then evaluate if protection applies or not. >> >> We have to make sure to ignore the invalid bit if tlb_fill() succeeds. > > This is similar to a scheme I proposed to PMM wrt handling ARM v8M translation. > Reusing TLB_INVALID_MASK would appear to work, but I wonder if it wouldn't be > clearer to use another bit. I believe I had proposed a TLB_FORCE_SLOW_MASK. > > Thoughts, Peter? As two weeks have passed: Any further opinions? Richard, how do you want me to continue with this? Thanks! -- Thanks, David
On 10/16/2017 12:24 AM, David Hildenbrand wrote: > On 27.09.2017 19:48, Richard Henderson wrote: >> On 09/27/2017 10:00 AM, David Hildenbrand wrote: >>> Background: s390x implements Low-Address Protection (LAP). If LAP is >>> enabled, writing to effective addresses (before any transaltion) >>> 0-511 and 4096-4607 triggers a protection exception. >>> >>> So we have subpage protection on the first two pages of every address >>> space (where the lowcore - the CPU private data resides). >>> >>> By immediately invalidating the write entry but allowing the caller to >>> continue, we force every write access onto these first two pages into >>> the slow path. we will get a tlb fault with the specific accessed >>> addresses and can then evaluate if protection applies or not. >>> >>> We have to make sure to ignore the invalid bit if tlb_fill() succeeds. >> >> This is similar to a scheme I proposed to PMM wrt handling ARM v8M translation. >> Reusing TLB_INVALID_MASK would appear to work, but I wonder if it wouldn't be >> clearer to use another bit. I believe I had proposed a TLB_FORCE_SLOW_MASK. >> >> Thoughts, Peter? > > As two weeks have passed: > > Any further opinions? Richard, how do you want me to continue with this? Let's just go ahead with TLB_INVALID_MASK; we'll revisit if it gets to be confusing. r~
© 2016 - 2026 Red Hat, Inc.