diff options
| -rw-r--r-- | arch/x86/kernel/cpu/amd.c | 16 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/resctrl/monitor.c | 14 | ||||
| -rw-r--r-- | arch/x86/mm/pat/set_memory.c | 2 | ||||
| -rw-r--r-- | arch/x86/mm/tlb.c | 24 | 
4 files changed, 47 insertions, 9 deletions
| diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 5398db4dedb4..ccaa51ce63f6 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -1355,11 +1355,23 @@ static __init int print_s5_reset_status_mmio(void)  		return 0;  	value = ioread32(addr); -	iounmap(addr);  	/* Value with "all bits set" is an error response and should be ignored. */ -	if (value == U32_MAX) +	if (value == U32_MAX) { +		iounmap(addr);  		return 0; +	} + +	/* +	 * Clear all reason bits so they won't be retained if the next reset +	 * does not update the register. Besides, some bits are never cleared by +	 * hardware so it's software's responsibility to clear them. +	 * +	 * Writing the value back effectively clears all reason bits as they are +	 * write-1-to-clear. +	 */ +	iowrite32(value, addr); +	iounmap(addr);  	for (i = 0; i < ARRAY_SIZE(s5_reset_reason_txt); i++) {  		if (!(value & BIT(i))) diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c index c8945610d455..2cd25a0d4637 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -242,7 +242,9 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d,  			   u32 unused, u32 rmid, enum resctrl_event_id eventid,  			   u64 *val, void *ignored)  { +	struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d);  	int cpu = cpumask_any(&d->hdr.cpu_mask); +	struct arch_mbm_state *am;  	u64 msr_val;  	u32 prmid;  	int ret; @@ -251,12 +253,16 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_mon_domain *d,  	prmid = logical_rmid_to_physical_rmid(cpu, rmid);  	ret = __rmid_read_phys(prmid, eventid, &msr_val); -	if (ret) -		return ret; -	*val = get_corrected_val(r, d, rmid, eventid, msr_val); +	if (!ret) { +		*val = get_corrected_val(r, d, rmid, eventid, msr_val); +	} else if (ret == -EINVAL) { +		am = get_arch_mbm_state(hw_dom, rmid, eventid); +		if (am) +			am->prev_msr = 0; +	} -	return 0; +	return ret;  }  static int __cntr_id_read(u32 cntr_id, u64 *val) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index d2d54b8c4dbb..970981893c9b 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -446,7 +446,7 @@ static void cpa_flush(struct cpa_data *cpa, int cache)  	}  	start = fix_addr(__cpa_addr(cpa, 0)); -	end =   fix_addr(__cpa_addr(cpa, cpa->numpages)); +	end =   start + cpa->numpages * PAGE_SIZE;  	if (cpa->force_flush_all)  		end = TLB_FLUSH_ALL; diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 39f80111e6f1..5d221709353e 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -911,11 +911,31 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next,  		 * CR3 and cpu_tlbstate.loaded_mm are not all in sync.  		 */  		this_cpu_write(cpu_tlbstate.loaded_mm, LOADED_MM_SWITCHING); -		barrier(); -		/* Start receiving IPIs and then read tlb_gen (and LAM below) */ +		/* +		 * Make sure this CPU is set in mm_cpumask() such that we'll +		 * receive invalidation IPIs. +		 * +		 * Rely on the smp_mb() implied by cpumask_set_cpu()'s atomic +		 * operation, or explicitly provide one. Such that: +		 * +		 * switch_mm_irqs_off()				flush_tlb_mm_range() +		 *   smp_store_release(loaded_mm, SWITCHING);     atomic64_inc_return(tlb_gen) +		 *   smp_mb(); // here                            // smp_mb() implied +		 *   atomic64_read(tlb_gen);                      this_cpu_read(loaded_mm); +		 * +		 * we properly order against flush_tlb_mm_range(), where the +		 * loaded_mm load can happen in mative_flush_tlb_multi() -> +		 * should_flush_tlb(). +		 * +		 * This way switch_mm() must see the new tlb_gen or +		 * flush_tlb_mm_range() must see the new loaded_mm, or both. +		 */  		if (next != &init_mm && !cpumask_test_cpu(cpu, mm_cpumask(next)))  			cpumask_set_cpu(cpu, mm_cpumask(next)); +		else +			smp_mb(); +  		next_tlb_gen = atomic64_read(&next->context.tlb_gen);  		ns = choose_new_asid(next, next_tlb_gen); | 
