Thanks, applied all.
On 5/4/10, Igor V. Kovalenko <igor.v.kovale...@gmail.com> wrote:
> From: Igor V. Kovalenko <igor.v.kovale...@gmail.com>
>
> - match global tte against any context
> - show global tte in MMU dump
>
> v0->v1: added default case to switch statement in demap_tlb
> - should fix gcc warning about uninitialized context variable
>
> Signed-off-by: Igor V. Kovalenko <igor.v.kovale...@gmail.com>
> ---
> target-sparc/cpu.h | 18 ++++++++++++++++
> target-sparc/helper.c | 33 ++++++++++++-----------------
> target-sparc/op_helper.c | 53
> ++++++++++++++++++++++++++++++++++++++--------
> 3 files changed, 76 insertions(+), 28 deletions(-)
>
> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
> index 0e7f390..b705728 100644
> --- a/target-sparc/cpu.h
> +++ b/target-sparc/cpu.h
> @@ -513,6 +513,24 @@ static inline void cpu_set_cwp(CPUSPARCState *env1, int
> new_cwp)
> /* sun4m.c, sun4u.c */
> void cpu_check_irqs(CPUSPARCState *env);
>
> +#if defined (TARGET_SPARC64)
> +
> +static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
> +{
> + return (x & mask) == (y & mask);
> +}
> +
> +#define MMU_CONTEXT_BITS 13
> +#define MMU_CONTEXT_MASK ((1 << MMU_CONTEXT_BITS) - 1)
> +
> +static inline int tlb_compare_context(const SparcTLBEntry *tlb,
> + uint64_t context)
> +{
> + return compare_masked(context, tlb->tag, MMU_CONTEXT_MASK);
> +}
> +
> +#endif
> +
> static inline void PUT_PSR(CPUSPARCState *env1, target_ulong val)
> {
> env1->psr = val & PSR_ICC;
> diff --git a/target-sparc/helper.c b/target-sparc/helper.c
> index 1f0f7d4..4ece01b 100644
> --- a/target-sparc/helper.c
> +++ b/target-sparc/helper.c
> @@ -381,17 +381,11 @@ static inline target_phys_addr_t
> ultrasparc_truncate_physical(uint64_t x)
> * UltraSparc IIi I/DMMUs
> */
>
> -static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
> -{
> - return (x & mask) == (y & mask);
> -}
> -
> // Returns true if TTE tag is valid and matches virtual address value in
> context
> // requires virtual address mask value calculated from TTE entry size
> static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
> uint64_t address, uint64_t context,
> - target_phys_addr_t *physical,
> - int is_nucleus)
> + target_phys_addr_t *physical)
> {
> uint64_t mask;
>
> @@ -413,8 +407,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry
> *tlb,
>
> // valid, context match, virtual address match?
> if (TTE_IS_VALID(tlb->tte) &&
> - ((is_nucleus && compare_masked(0, tlb->tag, 0x1fff))
> - || TTE_IS_GLOBAL(tlb->tte) || compare_masked(context, tlb->tag,
> 0x1fff))
> + (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
> && compare_masked(address, tlb->tag, mask))
> {
> // decode physical address
> @@ -431,7 +424,6 @@ static int get_physical_address_data(CPUState *env,
> {
> unsigned int i;
> uint64_t context;
> - int is_nucleus;
>
> if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
> *physical = ultrasparc_truncate_physical(address);
> @@ -439,14 +431,16 @@ static int get_physical_address_data(CPUState *env,
> return 0;
> }
>
> - context = env->dmmu.mmu_primary_context & 0x1fff;
> - is_nucleus = env->tl > 0;
> + if (env->tl == 0) {
> + context = env->dmmu.mmu_primary_context & 0x1fff;
> + } else {
> + context = 0;
> + }
>
> for (i = 0; i < 64; i++) {
> // ctx match, vaddr match, valid?
> if (ultrasparc_tag_match(&env->dtlb[i],
> - address, context, physical,
> - is_nucleus)) {
> + address, context, physical)) {
> // access ok?
> if (((env->dtlb[i].tte & 0x4) && is_user) ||
> (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
> @@ -492,7 +486,6 @@ static int get_physical_address_code(CPUState *env,
> {
> unsigned int i;
> uint64_t context;
> - int is_nucleus;
>
> if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
> /* IMMU disabled */
> @@ -501,14 +494,16 @@ static int get_physical_address_code(CPUState *env,
> return 0;
> }
>
> - context = env->dmmu.mmu_primary_context & 0x1fff;
> - is_nucleus = env->tl > 0;
> + if (env->tl == 0) {
> + context = env->dmmu.mmu_primary_context & 0x1fff;
> + } else {
> + context = 0;
> + }
>
> for (i = 0; i < 64; i++) {
> // ctx match, vaddr match, valid?
> if (ultrasparc_tag_match(&env->itlb[i],
> - address, context, physical,
> - is_nucleus)) {
> + address, context, physical)) {
> // access ok?
> if ((env->itlb[i].tte & 0x4) && is_user) {
> if (env->immu.sfsr) /* Fault status register */
> diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
> index b27778b..245eba7 100644
> --- a/target-sparc/op_helper.c
> +++ b/target-sparc/op_helper.c
> @@ -129,24 +129,59 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong
> demap_addr,
> {
> unsigned int i;
> target_ulong mask;
> + uint64_t context;
> +
> + int is_demap_context = (demap_addr >> 6) & 1;
> +
> + // demap context
> + switch ((demap_addr >> 4) & 3) {
> + case 0: // primary
> + context = env1->dmmu.mmu_primary_context;
> + break;
> + case 1: // secondary
> + context = env1->dmmu.mmu_secondary_context;
> + break;
> + case 2: // nucleus
> + context = 0;
> + break;
> + case 3: // reserved
> + default:
> + return;
> + }
>
> for (i = 0; i < 64; i++) {
> if (TTE_IS_VALID(tlb[i].tte)) {
>
> - mask = 0xffffffffffffe000ULL;
> - mask <<= 3 * ((tlb[i].tte >> 61) & 3);
> + if (is_demap_context) {
> + // will remove non-global entries matching context value
> + if (TTE_IS_GLOBAL(tlb[i].tte) ||
> + !tlb_compare_context(&tlb[i], context)) {
> + continue;
> + }
> + } else {
> + // demap page
> + // will remove any entry matching VA
> + mask = 0xffffffffffffe000ULL;
> + mask <<= 3 * ((tlb[i].tte >> 61) & 3);
>
> - if ((demap_addr & mask) == (tlb[i].tag & mask)) {
> - replace_tlb_entry(&tlb[i], 0, 0, env1);
> + if (!compare_masked(demap_addr, tlb[i].tag, mask)) {
> + continue;
> + }
> +
> + // entry should be global or matching context value
> + if (!TTE_IS_GLOBAL(tlb[i].tte) &&
> + !tlb_compare_context(&tlb[i], context)) {
> + continue;
> + }
> + }
> +
> + replace_tlb_entry(&tlb[i], 0, 0, env1);
> #ifdef DEBUG_MMU
> - DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu,
> i);
> - dump_mmu(env1);
> + DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
> + dump_mmu(env1);
> #endif
> - }
> - //return;
> }
> }
> -
> }
>
> static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
>
>
>
>