All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Daney <ddaney.cavm@gmail.com>
To: "Steven J. Hill" <Steven.Hill@imgtec.com>
Cc: linux-mips@linux-mips.org, ralf@linux-mips.org
Subject: Re: [PATCH v2] MIPS: Allow ASID size to be determined at boot time.
Date: Thu, 29 Aug 2013 09:23:01 -0700	[thread overview]
Message-ID: <521F7565.9000708@gmail.com> (raw)
In-Reply-To: <1377785632-13113-1-git-send-email-Steven.Hill@imgtec.com>

On 08/29/2013 07:13 AM, Steven J. Hill wrote:
> From: "Steven J. Hill" <Steven.Hill@imgtec.com>
>
> Original patch by Ralf Baechle and removed by Harold Koerfgen
> with commit f67e4ffc79905482c3b9b8c8dd65197bac7eb508. Allows
> for more generic kernels since ASID size is determinted during
> boot. This patch is required for new Aptiv cores. Tested on
> Malta, SEAD-3, microMIPS, Aptiv, and ERLite-3 (Cavium) platforms.
>

What are the advantages of this patch over something like:

unsigned long ASID_INC __read_mostly;
unsigned long ASID_MASK __read_mostly;
unsigned long ASID_FIRST_VERSION __read_mostly;
.
.
.

void setup_asid(void)
{
  /* Assign system specific values for ASID parameters, all written in C */
}

Unless you can document real performance bottlenecks with doing 
everything in C, this whole thing looks like an unnecessary Rube 
Goldberg Apparatus.

David Daney

> Signed-off-by: Steven J. Hill <Steven.Hill@imgtec.com>
> ---
>   arch/mips/include/asm/kvm_host.h    |    2 +-
>   arch/mips/include/asm/mmu_context.h |   99 ++++++++++++++++++++++++-----------
>   arch/mips/kernel/genex.S            |    2 +-
>   arch/mips/kernel/smtc.c             |    8 +--
>   arch/mips/kernel/traps.c            |    4 +-
>   arch/mips/kvm/kvm_mips_emul.c       |   44 +++++++---------
>   arch/mips/kvm/kvm_tlb.c             |   34 +++++-------
>   arch/mips/lib/dump_tlb.c            |    5 +-
>   arch/mips/lib/r3k_dump_tlb.c        |    6 +--
>   arch/mips/mm/tlb-r3k.c              |   20 +++----
>   arch/mips/mm/tlb-r4k.c              |    2 +-
>   arch/mips/mm/tlb-r8k.c              |    2 +-
>   arch/mips/mm/tlbex.c                |   72 +++++++++++++++++++++++++
>   13 files changed, 195 insertions(+), 105 deletions(-)
>
> diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
> index 4d6fa0b..3f870ad 100644
> --- a/arch/mips/include/asm/kvm_host.h
> +++ b/arch/mips/include/asm/kvm_host.h
> @@ -336,7 +336,7 @@ enum emulation_result {
>   #define VPN2_MASK           0xffffe000
>   #define TLB_IS_GLOBAL(x)    (((x).tlb_lo0 & MIPS3_PG_G) && ((x).tlb_lo1 & MIPS3_PG_G))
>   #define TLB_VPN2(x)         ((x).tlb_hi & VPN2_MASK)
> -#define TLB_ASID(x)         ((x).tlb_hi & ASID_MASK)
> +#define TLB_ASID(x)         ASID_MASK((x).tlb_hi)
>   #define TLB_IS_VALID(x, va) (((va) & (1 << PAGE_SHIFT)) ? ((x).tlb_lo1 & MIPS3_PG_V) : ((x).tlb_lo0 & MIPS3_PG_V))
>
>   struct kvm_mips_tlb {
> diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
> index 3b29079..2d423ef 100644
> --- a/arch/mips/include/asm/mmu_context.h
> +++ b/arch/mips/include/asm/mmu_context.h
> @@ -28,8 +28,10 @@
>
>   #define TLBMISS_HANDLER_SETUP_PGD(pgd)					\
>   do {									\
> -	extern void tlbmiss_handler_setup_pgd(unsigned long);		\
> -	tlbmiss_handler_setup_pgd((unsigned long)(pgd));		\
> +	extern u32 tlbmiss_handler_setup_pgd[];				\
> +	void (*handler)(unsigned long);					\
> +	handler = (void *)tlbmiss_handler_setup_pgd;			\
> +	handler((unsigned long)pgd);					\
>   } while (0)
>
>   #define TLBMISS_HANDLER_SETUP()						\
> @@ -63,45 +65,78 @@ extern unsigned long pgd_current[];
>   	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
>   #endif
>   #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
> -#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
>
> -#define ASID_INC	0x40
> -#define ASID_MASK	0xfc0
> -
> -#elif defined(CONFIG_CPU_R8000)
> -
> -#define ASID_INC	0x10
> -#define ASID_MASK	0xff0
> +#ifdef CONFIG_64BIT
> +#define WORD_ADDR ".dword"
> +#else
> +#define WORD_ADDR ".word"
> +#endif
>
> -#elif defined(CONFIG_MIPS_MT_SMTC)
> +#define ASID_INC(asid)						\
> +({								\
> +	unsigned long __asid = asid;				\
> +	__asm__("1:\taddiu\t%0,1\t\t\t\t# patched\n\t"		\
> +	".section\t__asid_inc,\"a\"\n\t"			\
> +	WORD_ADDR " 1b\n\t"					\
> +	".previous"						\
> +	:"=r" (__asid)						\
> +	:"0" (__asid));						\
> +	__asid;							\
> +})
> +
> +#define ASID_MASK(asid)						\
> +({								\
> +	unsigned long __asid = asid;				\
> +	__asm__("1:\tandi\t%0,%1,0xfc0\t\t\t# patched\n\t"	\
> +	".section\t__asid_mask,\"a\"\n\t"			\
> +	WORD_ADDR " 1b\n\t"					\
> +	".previous"						\
> +	:"=r" (__asid)						\
> +	:"r" (__asid));						\
> +	__asid;							\
> +})
> +
> +#define ASID_VERSION_MASK					\
> +({								\
> +	unsigned long __asid;					\
> +	__asm__("1:\tli\t%0,0xff00\t\t\t\t# patched\n\t"	\
> +	".section\t__asid_version_mask,\"a\"\n\t"		\
> +	WORD_ADDR " 1b\n\t"					\
> +	".previous"						\
> +	:"=r" (__asid));					\
> +	__asid;							\
> +})
> +
> +#define ASID_FIRST_VERSION					\
> +({								\
> +	unsigned long __asid;					\
> +	__asm__("1:\tli\t%0,0x100\t\t\t\t# patched\n\t"		\
> +	".section\t__asid_first_version,\"a\"\n\t"		\
> +	WORD_ADDR " 1b\n\t"					\
> +	".previous"						\
> +	:"=r" (__asid));					\
> +	__asid;							\
> +})
>
> -#define ASID_INC	0x1
> +#ifdef CONFIG_MIPS_MT_SMTC
>   extern unsigned long smtc_asid_mask;
> -#define ASID_MASK	(smtc_asid_mask)
> -#define HW_ASID_MASK	0xff
> -/* End SMTC/34K debug hack */
> -#else /* FIXME: not correct for R6000 */
> -
> -#define ASID_INC	0x1
> -#define ASID_MASK	0xff
> -
> +#define HW_ASID_MASK			0xff
>   #endif
>
> +#define ASID_FIRST_VERSION_R3000	0x1000
> +#define ASID_FIRST_VERSION_R4000	0x100
> +#define ASID_FIRST_VERSION_R8000	0x1000
> +#define ASID_FIRST_VERSION_RM9000	0x1000
> +#define ASID_FIRST_VERSION_99K		0x1000
> +
>   #define cpu_context(cpu, mm)	((mm)->context.asid[cpu])
> -#define cpu_asid(cpu, mm)	(cpu_context((cpu), (mm)) & ASID_MASK)
> +#define cpu_asid(cpu, mm)	ASID_MASK(cpu_context((cpu), (mm)))
>   #define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
>
>   static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
>   {
>   }
>
> -/*
> - *  All unused by hardware upper bits will be considered
> - *  as a software asid extension.
> - */
> -#define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
> -#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
> -
>   #ifndef CONFIG_MIPS_MT_SMTC
>   /* Normal, classic MIPS get_new_mmu_context */
>   static inline void
> @@ -110,7 +145,7 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
>   	extern void kvm_local_flush_tlb_all(void);
>   	unsigned long asid = asid_cache(cpu);
>
> -	if (! ((asid += ASID_INC) & ASID_MASK) ) {
> +	if (!ASID_MASK((asid = ASID_INC(asid)))) {
>   		if (cpu_has_vtag_icache)
>   			flush_icache_all();
>   #ifdef CONFIG_KVM
> @@ -173,7 +208,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
>   	 * free up the ASID value for use and flush any old
>   	 * instances of it from the TLB.
>   	 */
> -	oldasid = (read_c0_entryhi() & ASID_MASK);
> +	oldasid = ASID_MASK(read_c0_entryhi());
>   	if(smtc_live_asid[mytlb][oldasid]) {
>   		smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
>   		if(smtc_live_asid[mytlb][oldasid] == 0)
> @@ -237,7 +272,7 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
>   #ifdef CONFIG_MIPS_MT_SMTC
>   	/* See comments for similar code above */
>   	mtflags = dvpe();
> -	oldasid = read_c0_entryhi() & ASID_MASK;
> +	oldasid = ASID_MASK(read_c0_entryhi());
>   	if(smtc_live_asid[mytlb][oldasid]) {
>   		smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
>   		if(smtc_live_asid[mytlb][oldasid] == 0)
> @@ -282,7 +317,7 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
>   #ifdef CONFIG_MIPS_MT_SMTC
>   		/* See comments for similar code above */
>   		prevvpe = dvpe();
> -		oldasid = (read_c0_entryhi() & ASID_MASK);
> +		oldasid = ASID_MASK(read_c0_entryhi());
>   		if (smtc_live_asid[mytlb][oldasid]) {
>   			smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
>   			if(smtc_live_asid[mytlb][oldasid] == 0)
> diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
> index 31fa856..66c6ef5 100644
> --- a/arch/mips/kernel/genex.S
> +++ b/arch/mips/kernel/genex.S
> @@ -493,7 +493,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
>   	.set	noreorder
>   	/* check if TLB contains a entry for EPC */
>   	MFC0	k1, CP0_ENTRYHI
> -	andi	k1, 0xff	/* ASID_MASK */
> +	andi	k1, 0xff	/* ASID_MASK patched at run-time!! */
>   	MFC0	k0, CP0_EPC
>   	PTR_SRL k0, _PAGE_SHIFT + 1
>   	PTR_SLL k0, _PAGE_SHIFT + 1
> diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
> index dfc1b91..b30cc97 100644
> --- a/arch/mips/kernel/smtc.c
> +++ b/arch/mips/kernel/smtc.c
> @@ -1394,7 +1394,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
>   	asid = asid_cache(cpu);
>
>   	do {
> -		if (!((asid += ASID_INC) & ASID_MASK) ) {
> +		if (!(ASID_MASK(asid = ASID_INC(asid)))) {
>   			if (cpu_has_vtag_icache)
>   				flush_icache_all();
>   			/* Traverse all online CPUs (hack requires contiguous range) */
> @@ -1413,7 +1413,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
>   						mips_ihb();
>   					}
>   					tcstat = read_tc_c0_tcstatus();
> -					smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i);
> +					smtc_live_asid[tlb][ASID_MASK(tcstat)] |= (asiduse)(0x1 << i);
>   					if (!prevhalt)
>   						write_tc_c0_tchalt(0);
>   				}
> @@ -1422,7 +1422,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
>   				asid = ASID_FIRST_VERSION;
>   			local_flush_tlb_all();	/* start new asid cycle */
>   		}
> -	} while (smtc_live_asid[tlb][(asid & ASID_MASK)]);
> +	} while (smtc_live_asid[tlb][ASID_MASK(asid)]);
>
>   	/*
>   	 * SMTC shares the TLB within VPEs and possibly across all VPEs.
> @@ -1460,7 +1460,7 @@ void smtc_flush_tlb_asid(unsigned long asid)
>   		tlb_read();
>   		ehb();
>   		ehi = read_c0_entryhi();
> -		if ((ehi & ASID_MASK) == asid) {
> +		if (ASID_MASK(ehi) == asid) {
>   		    /*
>   		     * Invalidate only entries with specified ASID,
>   		     * makiing sure all entries differ.
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index aec3408..b25f1b5 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -1780,9 +1780,7 @@ void per_cpu_trap_init(bool is_boot_cpu)
>   	}
>   #endif /* CONFIG_MIPS_MT_SMTC */
>
> -	if (!cpu_data[cpu].asid_cache)
> -		cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
> -
> +	asid_cache(cpu) = ASID_FIRST_VERSION;
>   	atomic_inc(&init_mm.mm_count);
>   	current->active_mm = &init_mm;
>   	BUG_ON(current->mm);
> diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
> index 4b6274b..461624e 100644
> --- a/arch/mips/kvm/kvm_mips_emul.c
> +++ b/arch/mips/kvm/kvm_mips_emul.c
> @@ -525,18 +525,14 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
>   				printk("MTCz, cop0->reg[EBASE]: %#lx\n",
>   				       kvm_read_c0_guest_ebase(cop0));
>   			} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
> -				uint32_t nasid =
> -				    vcpu->arch.gprs[rt] & ASID_MASK;
> -				if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0)
> -				    &&
> -				    ((kvm_read_c0_guest_entryhi(cop0) &
> -				      ASID_MASK) != nasid)) {
> -
> -					kvm_debug
> -					    ("MTCz, change ASID from %#lx to %#lx\n",
> -					     kvm_read_c0_guest_entryhi(cop0) &
> -					     ASID_MASK,
> -					     vcpu->arch.gprs[rt] & ASID_MASK);
> +				uint32_t nasid = ASID_MASK(vcpu->arch.gprs[rt]);
> +
> +				if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) &&
> +				    (ASID_MASK(kvm_read_c0_guest_entryhi(cop0))
> +				     != nasid)) {
> +					kvm_debug("MTCz, change ASID from %#lx to %#lx\n",
> +						ASID_MASK(kvm_read_c0_guest_entryhi(cop0)),
> +						ASID_MASK(vcpu->arch.gprs[rt]));
>
>   					/* Blow away the shadow host TLBs */
>   					kvm_mips_flush_host_tlb(1);
> @@ -988,8 +984,7 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
>   		 * resulting handler will do the right thing
>   		 */
>   		index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
> -						  (kvm_read_c0_guest_entryhi
> -						   (cop0) & ASID_MASK));
> +				(ASID_MASK(kvm_read_c0_guest_entryhi(cop0))));
>
>   		if (index < 0) {
>   			vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
> @@ -1153,8 +1148,8 @@ kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc,
>   	struct mips_coproc *cop0 = vcpu->arch.cop0;
>   	struct kvm_vcpu_arch *arch = &vcpu->arch;
>   	enum emulation_result er = EMULATE_DONE;
> -	unsigned long entryhi = (vcpu->arch.  host_cp0_badvaddr & VPN2_MASK) |
> -				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
> +	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
> +				 ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
>
>   	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
>   		/* save old pc */
> @@ -1199,9 +1194,8 @@ kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc,
>   	struct mips_coproc *cop0 = vcpu->arch.cop0;
>   	struct kvm_vcpu_arch *arch = &vcpu->arch;
>   	enum emulation_result er = EMULATE_DONE;
> -	unsigned long entryhi =
> -		(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
> -		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
> +	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
> +				 ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
>
>   	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
>   		/* save old pc */
> @@ -1246,7 +1240,7 @@ kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc,
>   	struct kvm_vcpu_arch *arch = &vcpu->arch;
>   	enum emulation_result er = EMULATE_DONE;
>   	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
> -				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
> +				 ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
>
>   	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
>   		/* save old pc */
> @@ -1290,7 +1284,7 @@ kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc,
>   	struct kvm_vcpu_arch *arch = &vcpu->arch;
>   	enum emulation_result er = EMULATE_DONE;
>   	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
> -		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
> +				 ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
>
>   	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
>   		/* save old pc */
> @@ -1359,7 +1353,7 @@ kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc,
>   {
>   	struct mips_coproc *cop0 = vcpu->arch.cop0;
>   	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
> -				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
> +				 ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
>   	struct kvm_vcpu_arch *arch = &vcpu->arch;
>   	enum emulation_result er = EMULATE_DONE;
>
> @@ -1784,10 +1778,8 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
>   	 * exception. The guest exc handler should then inject an entry into the
>   	 * guest TLB
>   	 */
> -	index = kvm_mips_guest_tlb_lookup(vcpu,
> -					  (va & VPN2_MASK) |
> -					  (kvm_read_c0_guest_entryhi
> -					   (vcpu->arch.cop0) & ASID_MASK));
> +	index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
> +			ASID_MASK(kvm_read_c0_guest_entryhi(vcpu->arch.cop0)));
>   	if (index < 0) {
>   		if (exccode == T_TLB_LD_MISS) {
>   			er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
> diff --git a/arch/mips/kvm/kvm_tlb.c b/arch/mips/kvm/kvm_tlb.c
> index c777dd3..a248c3e 100644
> --- a/arch/mips/kvm/kvm_tlb.c
> +++ b/arch/mips/kvm/kvm_tlb.c
> @@ -53,13 +53,12 @@ EXPORT_SYMBOL(kvm_mips_is_error_pfn);
>
>   uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
>   {
> -	return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
> +	return (ASID_MASK(vcpu->arch.guest_kernel_asid[smp_processor_id()]));
>   }
>
> -
>   uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
>   {
> -	return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
> +	return (ASID_MASK(vcpu->arch.guest_user_asid[smp_processor_id()]));
>   }
>
>   inline uint32_t kvm_mips_get_commpage_asid (struct kvm_vcpu *vcpu)
> @@ -86,7 +85,7 @@ void kvm_mips_dump_host_tlbs(void)
>   	old_pagemask = read_c0_pagemask();
>
>   	printk("HOST TLBs:\n");
> -	printk("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
> +	printk("ASID: %#lx\n", ASID_MASK(read_c0_entryhi()));
>
>   	for (i = 0; i < current_cpu_data.tlbsize; i++) {
>   		write_c0_index(i);
> @@ -445,7 +444,7 @@ int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
>
>   	for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
>   		if (((TLB_VPN2(tlb[i]) & ~tlb[i].tlb_mask) == ((entryhi & VPN2_MASK) & ~tlb[i].tlb_mask)) &&
> -			(TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == (entryhi & ASID_MASK)))) {
> +			(TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == ASID_MASK(entryhi)))) {
>   			index = i;
>   			break;
>   		}
> @@ -538,7 +537,8 @@ int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
>   #ifdef DEBUG
>   	if (idx > 0) {
>   		kvm_debug("%s: Invalidated entryhi %#lx @ idx %d\n", __func__,
> -			  (va & VPN2_MASK) | (vcpu->arch.asid_map[va & ASID_MASK] & ASID_MASK), idx);
> +			  (va & VPN2_MASK) |
> +			  ASID_MASK(vcpu->arch.asid_map[ASID_MASK(va)]), idx);
>   	}
>   #endif
>
> @@ -643,7 +643,7 @@ kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
>   {
>   	unsigned long asid = asid_cache(cpu);
>
> -	if (!((asid += ASID_INC) & ASID_MASK)) {
> +	if (!(ASID_MASK(asid = ASID_INC(asid)))) {
>   		if (cpu_has_vtag_icache) {
>   			flush_icache_all();
>   		}
> @@ -821,8 +821,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>   	if (!newasid) {
>   		/* If we preempted while the guest was executing, then reload the pre-empted ASID */
>   		if (current->flags & PF_VCPU) {
> -			write_c0_entryhi(vcpu->arch.
> -					 preempt_entryhi & ASID_MASK);
> +			write_c0_entryhi(ASID_MASK(vcpu->arch.preempt_entryhi));
>   			ehb();
>   		}
>   	} else {
> @@ -834,13 +833,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
>   		 */
>   		if (current->flags & PF_VCPU) {
>   			if (KVM_GUEST_KERNEL_MODE(vcpu))
> -				write_c0_entryhi(vcpu->arch.
> -						 guest_kernel_asid[cpu] &
> -						 ASID_MASK);
> +				write_c0_entryhi(ASID_MASK(vcpu->arch.guest_kernel_asid[cpu]));
>   			else
> -				write_c0_entryhi(vcpu->arch.
> -						 guest_user_asid[cpu] &
> -						 ASID_MASK);
> +				write_c0_entryhi(ASID_MASK(vcpu->arch.guest_user_asid[cpu]));
>   			ehb();
>   		}
>   	}
> @@ -895,12 +890,9 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
>   		if (index >= 0) {
>   			inst = *(opc);
>   		} else {
> -			index =
> -			    kvm_mips_guest_tlb_lookup(vcpu,
> -						      ((unsigned long) opc & VPN2_MASK)
> -						      |
> -						      (kvm_read_c0_guest_entryhi
> -						       (cop0) & ASID_MASK));
> +			index = kvm_mips_guest_tlb_lookup(vcpu,
> +				((unsigned long) opc & VPN2_MASK) |
> +				ASID_MASK(kvm_read_c0_guest_entryhi(cop0)));
>   			if (index < 0) {
>   				kvm_err
>   				    ("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
> diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
> index 32b9f21..8a12d00 100644
> --- a/arch/mips/lib/dump_tlb.c
> +++ b/arch/mips/lib/dump_tlb.c
> @@ -11,6 +11,7 @@
>   #include <asm/page.h>
>   #include <asm/pgtable.h>
>   #include <asm/tlbdebug.h>
> +#include <asm/mmu_context.h>
>
>   static inline const char *msk2str(unsigned int mask)
>   {
> @@ -55,7 +56,7 @@ static void dump_tlb(int first, int last)
>   	s_pagemask = read_c0_pagemask();
>   	s_entryhi = read_c0_entryhi();
>   	s_index = read_c0_index();
> -	asid = s_entryhi & 0xff;
> +	asid = ASID_MASK(s_entryhi);
>
>   	for (i = first; i <= last; i++) {
>   		write_c0_index(i);
> @@ -85,7 +86,7 @@ static void dump_tlb(int first, int last)
>
>   			printk("va=%0*lx asid=%02lx\n",
>   			       width, (entryhi & ~0x1fffUL),
> -			       entryhi & 0xff);
> +			       ASID_MASK(entryhi));
>   			printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
>   			       width,
>   			       (entrylo0 << 6) & PAGE_MASK, c0,
> diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c
> index 91615c2..ec19a84 100644
> --- a/arch/mips/lib/r3k_dump_tlb.c
> +++ b/arch/mips/lib/r3k_dump_tlb.c
> @@ -21,7 +21,7 @@ static void dump_tlb(int first, int last)
>   	unsigned int asid;
>   	unsigned long entryhi, entrylo0;
>
> -	asid = read_c0_entryhi() & 0xfc0;
> +	asid = ASID_MASK(read_c0_entryhi());
>
>   	for (i = first; i <= last; i++) {
>   		write_c0_index(i<<8);
> @@ -35,7 +35,7 @@ static void dump_tlb(int first, int last)
>
>   		/* Unused entries have a virtual address of KSEG0.  */
>   		if ((entryhi & 0xffffe000) != 0x80000000
> -		    && (entryhi & 0xfc0) == asid) {
> +		    && (ASID_MASK(entryhi) == asid)) {
>   			/*
>   			 * Only print entries in use
>   			 */
> @@ -44,7 +44,7 @@ static void dump_tlb(int first, int last)
>   			printk("va=%08lx asid=%08lx"
>   			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
>   			       (entryhi & 0xffffe000),
> -			       entryhi & 0xfc0,
> +			       ASID_MASK(entryhi),
>   			       entrylo0 & PAGE_MASK,
>   			       (entrylo0 & (1 << 11)) ? 1 : 0,
>   			       (entrylo0 & (1 << 10)) ? 1 : 0,
> diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c
> index 9aca109..8923da6 100644
> --- a/arch/mips/mm/tlb-r3k.c
> +++ b/arch/mips/mm/tlb-r3k.c
> @@ -51,7 +51,7 @@ void local_flush_tlb_all(void)
>   #endif
>
>   	local_irq_save(flags);
> -	old_ctx = read_c0_entryhi() & ASID_MASK;
> +	old_ctx = ASID_MASK(read_c0_entryhi());
>   	write_c0_entrylo0(0);
>   	entry = r3k_have_wired_reg ? read_c0_wired() : 8;
>   	for (; entry < current_cpu_data.tlbsize; entry++) {
> @@ -87,13 +87,13 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
>
>   #ifdef DEBUG_TLB
>   		printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
> -			cpu_context(cpu, mm) & ASID_MASK, start, end);
> +			ASID_MASK(cpu_context(cpu, mm)), start, end);
>   #endif
>   		local_irq_save(flags);
>   		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
>   		if (size <= current_cpu_data.tlbsize) {
> -			int oldpid = read_c0_entryhi() & ASID_MASK;
> -			int newpid = cpu_context(cpu, mm) & ASID_MASK;
> +			int oldpid = ASID_MASK(read_c0_entryhi());
> +			int newpid = ASID_MASK(cpu_context(cpu, mm));
>
>   			start &= PAGE_MASK;
>   			end += PAGE_SIZE - 1;
> @@ -166,10 +166,10 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
>   #ifdef DEBUG_TLB
>   		printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
>   #endif
> -		newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK;
> +		newpid = ASID_MASK(cpu_context(cpu, vma->vm_mm));
>   		page &= PAGE_MASK;
>   		local_irq_save(flags);
> -		oldpid = read_c0_entryhi() & ASID_MASK;
> +		oldpid = ASID_MASK(read_c0_entryhi());
>   		write_c0_entryhi(page | newpid);
>   		BARRIER;
>   		tlb_probe();
> @@ -197,10 +197,10 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
>   	if (current->active_mm != vma->vm_mm)
>   		return;
>
> -	pid = read_c0_entryhi() & ASID_MASK;
> +	pid = ASID_MASK(read_c0_entryhi());
>
>   #ifdef DEBUG_TLB
> -	if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
> +	if ((pid != ASID_MASK(cpu_context(cpu, vma->vm_mm))) || (cpu_context(cpu, vma->vm_mm) == 0)) {
>   		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
>   		       (cpu_context(cpu, vma->vm_mm)), pid);
>   	}
> @@ -241,7 +241,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
>
>   		local_irq_save(flags);
>   		/* Save old context and create impossible VPN2 value */
> -		old_ctx = read_c0_entryhi() & ASID_MASK;
> +		old_ctx = ASID_MASK(read_c0_entryhi());
>   		old_pagemask = read_c0_pagemask();
>   		w = read_c0_wired();
>   		write_c0_wired(w + 1);
> @@ -264,7 +264,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
>   #endif
>
>   		local_irq_save(flags);
> -		old_ctx = read_c0_entryhi() & ASID_MASK;
> +		old_ctx = ASID_MASK(read_c0_entryhi());
>   		write_c0_entrylo0(entrylo0);
>   		write_c0_entryhi(entryhi);
>   		write_c0_index(wired);
> diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
> index 00b26a6..ea5eb69 100644
> --- a/arch/mips/mm/tlb-r4k.c
> +++ b/arch/mips/mm/tlb-r4k.c
> @@ -287,7 +287,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
>
>   	ENTER_CRITICAL(flags);
>
> -	pid = read_c0_entryhi() & ASID_MASK;
> +	pid = ASID_MASK(read_c0_entryhi());
>   	address &= (PAGE_MASK << 1);
>   	write_c0_entryhi(address | pid);
>   	pgdp = pgd_offset(vma->vm_mm, address);
> diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c
> index 6a99733..0d1d092 100644
> --- a/arch/mips/mm/tlb-r8k.c
> +++ b/arch/mips/mm/tlb-r8k.c
> @@ -195,7 +195,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
>   	if (current->active_mm != vma->vm_mm)
>   		return;
>
> -	pid = read_c0_entryhi() & ASID_MASK;
> +	pid = ASID_MASK(read_c0_entryhi());
>
>   	local_irq_save(flags);
>   	address &= PAGE_MASK;
> diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
> index 821b451..ca6166a 100644
> --- a/arch/mips/mm/tlbex.c
> +++ b/arch/mips/mm/tlbex.c
> @@ -29,6 +29,7 @@
>   #include <linux/init.h>
>   #include <linux/cache.h>
>
> +#include <asm/mmu_context.h>
>   #include <asm/cacheflush.h>
>   #include <asm/pgtable.h>
>   #include <asm/war.h>
> @@ -2202,6 +2203,75 @@ static void flush_tlb_handlers(void)
>   #endif
>   }
>
> +/* Fixup an immediate instruction. */
> +static void insn_fixup(unsigned long **start, unsigned long **stop,
> +		       unsigned long i_const)
> +{
> +	unsigned long **p;
> +
> +	for (p = start; p < stop; p++) {
> +#ifndef CONFIG_CPU_MICROMIPS
> +		u32 *ip = (u32 *)*p;
> +
> +		*ip = (*ip & 0xffff0000) | i_const;
> +#else
> +		u16 *ip = ((u16 *)((unsigned long)*p - 1));
> +
> +		if ((*ip & 0xf000) == 0x4000) {		/* ADDIUS5 */
> +			*ip &= 0xfff1;
> +			*ip |= (i_const << 1);
> +		} else if ((*ip & 0xf000) == 0x6000) {	/* ADDIUR1SP */
> +			*ip &= 0xfff1;
> +			*ip |= ((i_const >> 2) << 1);
> +		} else {
> +			ip++;
> +			*ip = i_const;
> +		}
> +#endif
> +	}
> +}
> +
> +#define asid_insn_fixup(section, const)					\
> +do {									\
> +	extern unsigned long *__start_ ## section;			\
> +	extern unsigned long *__stop_ ## section;			\
> +	insn_fixup(&__start_ ## section, &__stop_ ## section, const);	\
> +} while(0)
> +
> +/* Caller is assumed to flush the caches before first context switch. */
> +static void setup_asid(unsigned long inc, unsigned int mask,
> +		       unsigned int version_mask,
> +		       unsigned int first_version)
> +{
> +#ifndef CONFIG_MIPS_MT_SMTC
> +	extern asmlinkage void handle_ri_rdhwr_vivt(void);
> +	unsigned long *vivt_exc;
> +
> +	/* The microMIPS addiu instruction only has a 3-bit immediate value. */
> +	BUG_ON(cpu_has_mmips && (inc > 7));
> +
> +	/* Patch up one instruction in 'genex.s' that uses ASID_MASK. */
> +#ifdef CONFIG_CPU_MICROMIPS
> +	vivt_exc = (unsigned long *)((unsigned long) &handle_ri_rdhwr_vivt - 1);
> +#else
> +	vivt_exc = (unsigned long *) &handle_ri_rdhwr_vivt;
> +#endif
> +	vivt_exc++;
> +	*vivt_exc = (*vivt_exc & 0xffff0000) | mask;
> +
> +	current_cpu_data.asid_cache = first_version;
> +
> +	asid_insn_fixup(__asid_mask, mask);
> +	asid_insn_fixup(__asid_version_mask, version_mask);
> +#else
> +	asid_insn_fixup(__asid_mask, smtc_asid_mask);
> +	asid_insn_fixup(__asid_version_mask,
> +		~(smtc_asid_mask | (smtc_asid_mask - 1)));
> +#endif
> +	asid_insn_fixup(__asid_inc, inc);
> +	asid_insn_fixup(__asid_first_version, first_version);
> +}
> +
>   void build_tlb_refill_handler(void)
>   {
>   	/*
> @@ -2226,6 +2296,7 @@ void build_tlb_refill_handler(void)
>   	case CPU_TX3922:
>   	case CPU_TX3927:
>   #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
> +		setup_asid(0x40, 0xfc0, 0xf000, ASID_FIRST_VERSION_R3000);
>   		if (cpu_has_local_ebase)
>   			build_r3000_tlb_refill_handler();
>   		if (!run_once) {
> @@ -2252,6 +2323,7 @@ void build_tlb_refill_handler(void)
>   		break;
>
>   	default:
> +		setup_asid(0x1, 0xff, 0xff00, ASID_FIRST_VERSION_R4000);
>   		if (!run_once) {
>   			scratch_reg = allocate_kscratch();
>   #ifdef CONFIG_MIPS_PGD_C0_CONTEXT
>

      reply	other threads:[~2013-08-29 16:23 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-29 14:13 [PATCH v2] MIPS: Allow ASID size to be determined at boot time Steven J. Hill
2013-08-29 16:23 ` David Daney [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=521F7565.9000708@gmail.com \
    --to=ddaney.cavm@gmail.com \
    --cc=Steven.Hill@imgtec.com \
    --cc=linux-mips@linux-mips.org \
    --cc=ralf@linux-mips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.