xref: /openbmc/linux/arch/x86/kernel/cpu/mtrr/mtrr.c (revision c005e2f62f8421b13b9a31adb9db7281f1a19e68)
1e6d8c84aSJoe Perches /*  Generic MTRR (Memory Type Range Register) driver.
2e6d8c84aSJoe Perches 
3e6d8c84aSJoe Perches     Copyright (C) 1997-2000  Richard Gooch
4e6d8c84aSJoe Perches     Copyright (c) 2002	     Patrick Mochel
5e6d8c84aSJoe Perches 
6e6d8c84aSJoe Perches     This library is free software; you can redistribute it and/or
7e6d8c84aSJoe Perches     modify it under the terms of the GNU Library General Public
8e6d8c84aSJoe Perches     License as published by the Free Software Foundation; either
9e6d8c84aSJoe Perches     version 2 of the License, or (at your option) any later version.
10e6d8c84aSJoe Perches 
11e6d8c84aSJoe Perches     This library is distributed in the hope that it will be useful,
12e6d8c84aSJoe Perches     but WITHOUT ANY WARRANTY; without even the implied warranty of
13e6d8c84aSJoe Perches     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14e6d8c84aSJoe Perches     Library General Public License for more details.
15e6d8c84aSJoe Perches 
16e6d8c84aSJoe Perches     You should have received a copy of the GNU Library General Public
17e6d8c84aSJoe Perches     License along with this library; if not, write to the Free
18e6d8c84aSJoe Perches     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19e6d8c84aSJoe Perches 
20e6d8c84aSJoe Perches     Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
21e6d8c84aSJoe Perches     The postal address is:
22e6d8c84aSJoe Perches       Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
23e6d8c84aSJoe Perches 
24e6d8c84aSJoe Perches     Source: "Pentium Pro Family Developer's Manual, Volume 3:
25e6d8c84aSJoe Perches     Operating System Writer's Guide" (Intel document number 242692),
26e6d8c84aSJoe Perches     section 11.11.7
27e6d8c84aSJoe Perches 
28e6d8c84aSJoe Perches     This was cleaned and made readable by Patrick Mochel <mochel@osdl.org>
29e6d8c84aSJoe Perches     on 6-7 March 2002.
30e6d8c84aSJoe Perches     Source: Intel Architecture Software Developers Manual, Volume 3:
31e6d8c84aSJoe Perches     System Programming Guide; Section 9.11. (1997 edition - PPro).
32e6d8c84aSJoe Perches */
33e6d8c84aSJoe Perches 
34e6d8c84aSJoe Perches #include <linux/types.h> /* FIXME: kvm_para.h needs this */
35e6d8c84aSJoe Perches 
36e6d8c84aSJoe Perches #include <linux/stop_machine.h>
37e6d8c84aSJoe Perches #include <linux/kvm_para.h>
38e6d8c84aSJoe Perches #include <linux/uaccess.h>
39e6d8c84aSJoe Perches #include <linux/export.h>
40e6d8c84aSJoe Perches #include <linux/mutex.h>
41e6d8c84aSJoe Perches #include <linux/init.h>
42e6d8c84aSJoe Perches #include <linux/sort.h>
43e6d8c84aSJoe Perches #include <linux/cpu.h>
44e6d8c84aSJoe Perches #include <linux/pci.h>
45e6d8c84aSJoe Perches #include <linux/smp.h>
46e6d8c84aSJoe Perches #include <linux/syscore_ops.h>
470afe832eSLinus Torvalds #include <linux/rcupdate.h>
48e6d8c84aSJoe Perches 
4945fa71f1SJuergen Gross #include <asm/cacheinfo.h>
50e6d8c84aSJoe Perches #include <asm/cpufeature.h>
51e6d8c84aSJoe Perches #include <asm/e820/api.h>
52e6d8c84aSJoe Perches #include <asm/mtrr.h>
53e6d8c84aSJoe Perches #include <asm/msr.h>
54eb243d1dSIngo Molnar #include <asm/memtype.h>
55e6d8c84aSJoe Perches 
56e6d8c84aSJoe Perches #include "mtrr.h"
57e6d8c84aSJoe Perches 
58e6d8c84aSJoe Perches /* arch_phys_wc_add returns an MTRR register index plus this offset. */
59e6d8c84aSJoe Perches #define MTRR_TO_PHYS_WC_OFFSET 1000
60e6d8c84aSJoe Perches 
61e6d8c84aSJoe Perches u32 num_var_ranges;
62e6d8c84aSJoe Perches 
63e6d8c84aSJoe Perches unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
64061b984aSJuergen Gross DEFINE_MUTEX(mtrr_mutex);
65e6d8c84aSJoe Perches 
66e6d8c84aSJoe Perches const struct mtrr_ops *mtrr_if;
67e6d8c84aSJoe Perches 
68e6d8c84aSJoe Perches /*  Returns non-zero if we have the write-combining memory type  */
have_wrcomb(void)69e6d8c84aSJoe Perches static int have_wrcomb(void)
70e6d8c84aSJoe Perches {
71e6d8c84aSJoe Perches 	struct pci_dev *dev;
72e6d8c84aSJoe Perches 
73e6d8c84aSJoe Perches 	dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8, NULL);
74e6d8c84aSJoe Perches 	if (dev != NULL) {
75e6d8c84aSJoe Perches 		/*
76e6d8c84aSJoe Perches 		 * ServerWorks LE chipsets < rev 6 have problems with
77e6d8c84aSJoe Perches 		 * write-combining. Don't allow it and leave room for other
78e6d8c84aSJoe Perches 		 * chipsets to be tagged
79e6d8c84aSJoe Perches 		 */
80e6d8c84aSJoe Perches 		if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
81e6d8c84aSJoe Perches 		    dev->device == PCI_DEVICE_ID_SERVERWORKS_LE &&
82e6d8c84aSJoe Perches 		    dev->revision <= 5) {
83e6d8c84aSJoe Perches 			pr_info("Serverworks LE rev < 6 detected. Write-combining disabled.\n");
84e6d8c84aSJoe Perches 			pci_dev_put(dev);
85e6d8c84aSJoe Perches 			return 0;
86e6d8c84aSJoe Perches 		}
87e6d8c84aSJoe Perches 		/*
88e6d8c84aSJoe Perches 		 * Intel 450NX errata # 23. Non ascending cacheline evictions to
89e6d8c84aSJoe Perches 		 * write combining memory may resulting in data corruption
90e6d8c84aSJoe Perches 		 */
91e6d8c84aSJoe Perches 		if (dev->vendor == PCI_VENDOR_ID_INTEL &&
92e6d8c84aSJoe Perches 		    dev->device == PCI_DEVICE_ID_INTEL_82451NX) {
93e6d8c84aSJoe Perches 			pr_info("Intel 450NX MMC detected. Write-combining disabled.\n");
94e6d8c84aSJoe Perches 			pci_dev_put(dev);
95e6d8c84aSJoe Perches 			return 0;
96e6d8c84aSJoe Perches 		}
97e6d8c84aSJoe Perches 		pci_dev_put(dev);
98e6d8c84aSJoe Perches 	}
99e6d8c84aSJoe Perches 	return mtrr_if->have_wrcomb ? mtrr_if->have_wrcomb() : 0;
100e6d8c84aSJoe Perches }
101e6d8c84aSJoe Perches 
init_table(void)102e6d8c84aSJoe Perches static void __init init_table(void)
103e6d8c84aSJoe Perches {
104e6d8c84aSJoe Perches 	int i, max;
105e6d8c84aSJoe Perches 
106e6d8c84aSJoe Perches 	max = num_var_ranges;
107e6d8c84aSJoe Perches 	for (i = 0; i < max; i++)
108e6d8c84aSJoe Perches 		mtrr_usage_table[i] = 1;
109e6d8c84aSJoe Perches }
110e6d8c84aSJoe Perches 
111e6d8c84aSJoe Perches struct set_mtrr_data {
112e6d8c84aSJoe Perches 	unsigned long	smp_base;
113e6d8c84aSJoe Perches 	unsigned long	smp_size;
114e6d8c84aSJoe Perches 	unsigned int	smp_reg;
115e6d8c84aSJoe Perches 	mtrr_type	smp_type;
116e6d8c84aSJoe Perches };
117e6d8c84aSJoe Perches 
118e6d8c84aSJoe Perches /**
119e6d8c84aSJoe Perches  * mtrr_rendezvous_handler - Work done in the synchronization handler. Executed
120e6d8c84aSJoe Perches  * by all the CPUs.
121e6d8c84aSJoe Perches  * @info: pointer to mtrr configuration data
122e6d8c84aSJoe Perches  *
123e6d8c84aSJoe Perches  * Returns nothing.
124e6d8c84aSJoe Perches  */
mtrr_rendezvous_handler(void * info)125e6d8c84aSJoe Perches static int mtrr_rendezvous_handler(void *info)
126e6d8c84aSJoe Perches {
127e6d8c84aSJoe Perches 	struct set_mtrr_data *data = info;
128e6d8c84aSJoe Perches 
129e6d8c84aSJoe Perches 	mtrr_if->set(data->smp_reg, data->smp_base,
130e6d8c84aSJoe Perches 		     data->smp_size, data->smp_type);
131e6d8c84aSJoe Perches 	return 0;
132e6d8c84aSJoe Perches }
133e6d8c84aSJoe Perches 
types_compatible(mtrr_type type1,mtrr_type type2)134e6d8c84aSJoe Perches static inline int types_compatible(mtrr_type type1, mtrr_type type2)
135e6d8c84aSJoe Perches {
136e6d8c84aSJoe Perches 	return type1 == MTRR_TYPE_UNCACHABLE ||
137e6d8c84aSJoe Perches 	       type2 == MTRR_TYPE_UNCACHABLE ||
138e6d8c84aSJoe Perches 	       (type1 == MTRR_TYPE_WRTHROUGH && type2 == MTRR_TYPE_WRBACK) ||
139e6d8c84aSJoe Perches 	       (type1 == MTRR_TYPE_WRBACK && type2 == MTRR_TYPE_WRTHROUGH);
140e6d8c84aSJoe Perches }
141e6d8c84aSJoe Perches 
142e6d8c84aSJoe Perches /**
143e6d8c84aSJoe Perches  * set_mtrr - update mtrrs on all processors
144e6d8c84aSJoe Perches  * @reg:	mtrr in question
145e6d8c84aSJoe Perches  * @base:	mtrr base
146e6d8c84aSJoe Perches  * @size:	mtrr size
147e6d8c84aSJoe Perches  * @type:	mtrr type
148e6d8c84aSJoe Perches  *
149e6d8c84aSJoe Perches  * This is kinda tricky, but fortunately, Intel spelled it out for us cleanly:
150e6d8c84aSJoe Perches  *
151e6d8c84aSJoe Perches  * 1. Queue work to do the following on all processors:
152e6d8c84aSJoe Perches  * 2. Disable Interrupts
153e6d8c84aSJoe Perches  * 3. Wait for all procs to do so
154e6d8c84aSJoe Perches  * 4. Enter no-fill cache mode
155e6d8c84aSJoe Perches  * 5. Flush caches
156e6d8c84aSJoe Perches  * 6. Clear PGE bit
157e6d8c84aSJoe Perches  * 7. Flush all TLBs
158e6d8c84aSJoe Perches  * 8. Disable all range registers
159e6d8c84aSJoe Perches  * 9. Update the MTRRs
160e6d8c84aSJoe Perches  * 10. Enable all range registers
161e6d8c84aSJoe Perches  * 11. Flush all TLBs and caches again
162e6d8c84aSJoe Perches  * 12. Enter normal cache mode and reenable caching
163e6d8c84aSJoe Perches  * 13. Set PGE
164e6d8c84aSJoe Perches  * 14. Wait for buddies to catch up
165e6d8c84aSJoe Perches  * 15. Enable interrupts.
166e6d8c84aSJoe Perches  *
167e6d8c84aSJoe Perches  * What does that mean for us? Well, stop_machine() will ensure that
168e6d8c84aSJoe Perches  * the rendezvous handler is started on each CPU. And in lockstep they
169e6d8c84aSJoe Perches  * do the state transition of disabling interrupts, updating MTRR's
170e6d8c84aSJoe Perches  * (the CPU vendors may each do it differently, so we call mtrr_if->set()
171e6d8c84aSJoe Perches  * callback and let them take care of it.) and enabling interrupts.
172e6d8c84aSJoe Perches  *
173e6d8c84aSJoe Perches  * Note that the mechanism is the same for UP systems, too; all the SMP stuff
174e6d8c84aSJoe Perches  * becomes nops.
175e6d8c84aSJoe Perches  */
set_mtrr(unsigned int reg,unsigned long base,unsigned long size,mtrr_type type)17634cf2d19SJuergen Gross static void set_mtrr(unsigned int reg, unsigned long base, unsigned long size,
17734cf2d19SJuergen Gross 		     mtrr_type type)
178e6d8c84aSJoe Perches {
179e6d8c84aSJoe Perches 	struct set_mtrr_data data = { .smp_reg = reg,
180e6d8c84aSJoe Perches 				      .smp_base = base,
181e6d8c84aSJoe Perches 				      .smp_size = size,
182e6d8c84aSJoe Perches 				      .smp_type = type
183e6d8c84aSJoe Perches 				    };
184e6d8c84aSJoe Perches 
185e6d8c84aSJoe Perches 	stop_machine_cpuslocked(mtrr_rendezvous_handler, &data, cpu_online_mask);
186061b984aSJuergen Gross 
187061b984aSJuergen Gross 	generic_rebuild_map();
188e6d8c84aSJoe Perches }
189e6d8c84aSJoe Perches 
190e6d8c84aSJoe Perches /**
191e6d8c84aSJoe Perches  * mtrr_add_page - Add a memory type region
192e6d8c84aSJoe Perches  * @base: Physical base address of region in pages (in units of 4 kB!)
193e6d8c84aSJoe Perches  * @size: Physical size of region in pages (4 kB)
194e6d8c84aSJoe Perches  * @type: Type of MTRR desired
195e6d8c84aSJoe Perches  * @increment: If this is true do usage counting on the region
196e6d8c84aSJoe Perches  *
197e6d8c84aSJoe Perches  * Memory type region registers control the caching on newer Intel and
198e6d8c84aSJoe Perches  * non Intel processors. This function allows drivers to request an
199e6d8c84aSJoe Perches  * MTRR is added. The details and hardware specifics of each processor's
200e6d8c84aSJoe Perches  * implementation are hidden from the caller, but nevertheless the
201e6d8c84aSJoe Perches  * caller should expect to need to provide a power of two size on an
202e6d8c84aSJoe Perches  * equivalent power of two boundary.
203e6d8c84aSJoe Perches  *
204e6d8c84aSJoe Perches  * If the region cannot be added either because all regions are in use
205e6d8c84aSJoe Perches  * or the CPU cannot support it a negative value is returned. On success
206e6d8c84aSJoe Perches  * the register number for this entry is returned, but should be treated
207e6d8c84aSJoe Perches  * as a cookie only.
208e6d8c84aSJoe Perches  *
209e6d8c84aSJoe Perches  * On a multiprocessor machine the changes are made to all processors.
210e6d8c84aSJoe Perches  * This is required on x86 by the Intel processors.
211e6d8c84aSJoe Perches  *
212e6d8c84aSJoe Perches  * The available types are
213e6d8c84aSJoe Perches  *
214e6d8c84aSJoe Perches  * %MTRR_TYPE_UNCACHABLE - No caching
215e6d8c84aSJoe Perches  *
216e6d8c84aSJoe Perches  * %MTRR_TYPE_WRBACK - Write data back in bursts whenever
217e6d8c84aSJoe Perches  *
218e6d8c84aSJoe Perches  * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
219e6d8c84aSJoe Perches  *
220e6d8c84aSJoe Perches  * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
221e6d8c84aSJoe Perches  *
222e6d8c84aSJoe Perches  * BUGS: Needs a quiet flag for the cases where drivers do not mind
223e6d8c84aSJoe Perches  * failures and do not wish system log messages to be sent.
224e6d8c84aSJoe Perches  */
mtrr_add_page(unsigned long base,unsigned long size,unsigned int type,bool increment)225e6d8c84aSJoe Perches int mtrr_add_page(unsigned long base, unsigned long size,
226e6d8c84aSJoe Perches 		  unsigned int type, bool increment)
227e6d8c84aSJoe Perches {
228e6d8c84aSJoe Perches 	unsigned long lbase, lsize;
229e6d8c84aSJoe Perches 	int i, replace, error;
230e6d8c84aSJoe Perches 	mtrr_type ltype;
231e6d8c84aSJoe Perches 
232e6d8c84aSJoe Perches 	if (!mtrr_enabled())
233e6d8c84aSJoe Perches 		return -ENXIO;
234e6d8c84aSJoe Perches 
235e6d8c84aSJoe Perches 	error = mtrr_if->validate_add_page(base, size, type);
236e6d8c84aSJoe Perches 	if (error)
237e6d8c84aSJoe Perches 		return error;
238e6d8c84aSJoe Perches 
239e6d8c84aSJoe Perches 	if (type >= MTRR_NUM_TYPES) {
240e6d8c84aSJoe Perches 		pr_warn("type: %u invalid\n", type);
241e6d8c84aSJoe Perches 		return -EINVAL;
242e6d8c84aSJoe Perches 	}
243e6d8c84aSJoe Perches 
244e6d8c84aSJoe Perches 	/* If the type is WC, check that this processor supports it */
245e6d8c84aSJoe Perches 	if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) {
246e6d8c84aSJoe Perches 		pr_warn("your processor doesn't support write-combining\n");
247e6d8c84aSJoe Perches 		return -ENOSYS;
248e6d8c84aSJoe Perches 	}
249e6d8c84aSJoe Perches 
250e6d8c84aSJoe Perches 	if (!size) {
251e6d8c84aSJoe Perches 		pr_warn("zero sized request\n");
252e6d8c84aSJoe Perches 		return -EINVAL;
253e6d8c84aSJoe Perches 	}
254e6d8c84aSJoe Perches 
255e6d8c84aSJoe Perches 	if ((base | (base + size - 1)) >>
256e6d8c84aSJoe Perches 	    (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) {
257e6d8c84aSJoe Perches 		pr_warn("base or size exceeds the MTRR width\n");
258e6d8c84aSJoe Perches 		return -EINVAL;
259e6d8c84aSJoe Perches 	}
260e6d8c84aSJoe Perches 
261e6d8c84aSJoe Perches 	error = -EINVAL;
262e6d8c84aSJoe Perches 	replace = -1;
263e6d8c84aSJoe Perches 
264e6d8c84aSJoe Perches 	/* No CPU hotplug when we change MTRR entries */
2651a351eefSSebastian Andrzej Siewior 	cpus_read_lock();
266e6d8c84aSJoe Perches 
267e6d8c84aSJoe Perches 	/* Search for existing MTRR  */
268e6d8c84aSJoe Perches 	mutex_lock(&mtrr_mutex);
269e6d8c84aSJoe Perches 	for (i = 0; i < num_var_ranges; ++i) {
270e6d8c84aSJoe Perches 		mtrr_if->get(i, &lbase, &lsize, &ltype);
271e6d8c84aSJoe Perches 		if (!lsize || base > lbase + lsize - 1 ||
272e6d8c84aSJoe Perches 		    base + size - 1 < lbase)
273e6d8c84aSJoe Perches 			continue;
274e6d8c84aSJoe Perches 		/*
275e6d8c84aSJoe Perches 		 * At this point we know there is some kind of
276e6d8c84aSJoe Perches 		 * overlap/enclosure
277e6d8c84aSJoe Perches 		 */
278e6d8c84aSJoe Perches 		if (base < lbase || base + size - 1 > lbase + lsize - 1) {
279e6d8c84aSJoe Perches 			if (base <= lbase &&
280e6d8c84aSJoe Perches 			    base + size - 1 >= lbase + lsize - 1) {
281e6d8c84aSJoe Perches 				/*  New region encloses an existing region  */
282e6d8c84aSJoe Perches 				if (type == ltype) {
283e6d8c84aSJoe Perches 					replace = replace == -1 ? i : -2;
284e6d8c84aSJoe Perches 					continue;
285e6d8c84aSJoe Perches 				} else if (types_compatible(type, ltype))
286e6d8c84aSJoe Perches 					continue;
287e6d8c84aSJoe Perches 			}
288e6d8c84aSJoe Perches 			pr_warn("0x%lx000,0x%lx000 overlaps existing 0x%lx000,0x%lx000\n", base, size, lbase,
289e6d8c84aSJoe Perches 				lsize);
290e6d8c84aSJoe Perches 			goto out;
291e6d8c84aSJoe Perches 		}
292e6d8c84aSJoe Perches 		/* New region is enclosed by an existing region */
293e6d8c84aSJoe Perches 		if (ltype != type) {
294e6d8c84aSJoe Perches 			if (types_compatible(type, ltype))
295e6d8c84aSJoe Perches 				continue;
296e6d8c84aSJoe Perches 			pr_warn("type mismatch for %lx000,%lx000 old: %s new: %s\n",
297e6d8c84aSJoe Perches 				base, size, mtrr_attrib_to_str(ltype),
298e6d8c84aSJoe Perches 				mtrr_attrib_to_str(type));
299e6d8c84aSJoe Perches 			goto out;
300e6d8c84aSJoe Perches 		}
301e6d8c84aSJoe Perches 		if (increment)
302e6d8c84aSJoe Perches 			++mtrr_usage_table[i];
303e6d8c84aSJoe Perches 		error = i;
304e6d8c84aSJoe Perches 		goto out;
305e6d8c84aSJoe Perches 	}
306e6d8c84aSJoe Perches 	/* Search for an empty MTRR */
307e6d8c84aSJoe Perches 	i = mtrr_if->get_free_region(base, size, replace);
308e6d8c84aSJoe Perches 	if (i >= 0) {
30934cf2d19SJuergen Gross 		set_mtrr(i, base, size, type);
310e6d8c84aSJoe Perches 		if (likely(replace < 0)) {
311e6d8c84aSJoe Perches 			mtrr_usage_table[i] = 1;
312e6d8c84aSJoe Perches 		} else {
313e6d8c84aSJoe Perches 			mtrr_usage_table[i] = mtrr_usage_table[replace];
314e6d8c84aSJoe Perches 			if (increment)
315e6d8c84aSJoe Perches 				mtrr_usage_table[i]++;
316e6d8c84aSJoe Perches 			if (unlikely(replace != i)) {
31734cf2d19SJuergen Gross 				set_mtrr(replace, 0, 0, 0);
318e6d8c84aSJoe Perches 				mtrr_usage_table[replace] = 0;
319e6d8c84aSJoe Perches 			}
320e6d8c84aSJoe Perches 		}
321e6d8c84aSJoe Perches 	} else {
322e6d8c84aSJoe Perches 		pr_info("no more MTRRs available\n");
323e6d8c84aSJoe Perches 	}
324e6d8c84aSJoe Perches 	error = i;
325e6d8c84aSJoe Perches  out:
326e6d8c84aSJoe Perches 	mutex_unlock(&mtrr_mutex);
3271a351eefSSebastian Andrzej Siewior 	cpus_read_unlock();
328e6d8c84aSJoe Perches 	return error;
329e6d8c84aSJoe Perches }
330e6d8c84aSJoe Perches 
mtrr_check(unsigned long base,unsigned long size)331e6d8c84aSJoe Perches static int mtrr_check(unsigned long base, unsigned long size)
332e6d8c84aSJoe Perches {
333e6d8c84aSJoe Perches 	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
334e6d8c84aSJoe Perches 		pr_warn("size and base must be multiples of 4 kiB\n");
3357c1dee73SBorislav Petkov (AMD) 		Dprintk("size: 0x%lx  base: 0x%lx\n", size, base);
336e6d8c84aSJoe Perches 		dump_stack();
337e6d8c84aSJoe Perches 		return -1;
338e6d8c84aSJoe Perches 	}
339e6d8c84aSJoe Perches 	return 0;
340e6d8c84aSJoe Perches }
341e6d8c84aSJoe Perches 
342e6d8c84aSJoe Perches /**
343e6d8c84aSJoe Perches  * mtrr_add - Add a memory type region
344e6d8c84aSJoe Perches  * @base: Physical base address of region
345e6d8c84aSJoe Perches  * @size: Physical size of region
346e6d8c84aSJoe Perches  * @type: Type of MTRR desired
347e6d8c84aSJoe Perches  * @increment: If this is true do usage counting on the region
348e6d8c84aSJoe Perches  *
349e6d8c84aSJoe Perches  * Memory type region registers control the caching on newer Intel and
350e6d8c84aSJoe Perches  * non Intel processors. This function allows drivers to request an
351e6d8c84aSJoe Perches  * MTRR is added. The details and hardware specifics of each processor's
352e6d8c84aSJoe Perches  * implementation are hidden from the caller, but nevertheless the
353e6d8c84aSJoe Perches  * caller should expect to need to provide a power of two size on an
354e6d8c84aSJoe Perches  * equivalent power of two boundary.
355e6d8c84aSJoe Perches  *
356e6d8c84aSJoe Perches  * If the region cannot be added either because all regions are in use
357e6d8c84aSJoe Perches  * or the CPU cannot support it a negative value is returned. On success
358e6d8c84aSJoe Perches  * the register number for this entry is returned, but should be treated
359e6d8c84aSJoe Perches  * as a cookie only.
360e6d8c84aSJoe Perches  *
361e6d8c84aSJoe Perches  * On a multiprocessor machine the changes are made to all processors.
362e6d8c84aSJoe Perches  * This is required on x86 by the Intel processors.
363e6d8c84aSJoe Perches  *
364e6d8c84aSJoe Perches  * The available types are
365e6d8c84aSJoe Perches  *
366e6d8c84aSJoe Perches  * %MTRR_TYPE_UNCACHABLE - No caching
367e6d8c84aSJoe Perches  *
368e6d8c84aSJoe Perches  * %MTRR_TYPE_WRBACK - Write data back in bursts whenever
369e6d8c84aSJoe Perches  *
370e6d8c84aSJoe Perches  * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
371e6d8c84aSJoe Perches  *
372e6d8c84aSJoe Perches  * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
373e6d8c84aSJoe Perches  *
374e6d8c84aSJoe Perches  * BUGS: Needs a quiet flag for the cases where drivers do not mind
375e6d8c84aSJoe Perches  * failures and do not wish system log messages to be sent.
376e6d8c84aSJoe Perches  */
mtrr_add(unsigned long base,unsigned long size,unsigned int type,bool increment)377e6d8c84aSJoe Perches int mtrr_add(unsigned long base, unsigned long size, unsigned int type,
378e6d8c84aSJoe Perches 	     bool increment)
379e6d8c84aSJoe Perches {
380e6d8c84aSJoe Perches 	if (!mtrr_enabled())
381e6d8c84aSJoe Perches 		return -ENODEV;
382e6d8c84aSJoe Perches 	if (mtrr_check(base, size))
383e6d8c84aSJoe Perches 		return -EINVAL;
384e6d8c84aSJoe Perches 	return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
385e6d8c84aSJoe Perches 			     increment);
386e6d8c84aSJoe Perches }
387e6d8c84aSJoe Perches 
388e6d8c84aSJoe Perches /**
389e6d8c84aSJoe Perches  * mtrr_del_page - delete a memory type region
390e6d8c84aSJoe Perches  * @reg: Register returned by mtrr_add
391e6d8c84aSJoe Perches  * @base: Physical base address
392e6d8c84aSJoe Perches  * @size: Size of region
393e6d8c84aSJoe Perches  *
394e6d8c84aSJoe Perches  * If register is supplied then base and size are ignored. This is
395e6d8c84aSJoe Perches  * how drivers should call it.
396e6d8c84aSJoe Perches  *
397e6d8c84aSJoe Perches  * Releases an MTRR region. If the usage count drops to zero the
398e6d8c84aSJoe Perches  * register is freed and the region returns to default state.
399e6d8c84aSJoe Perches  * On success the register is returned, on failure a negative error
400e6d8c84aSJoe Perches  * code.
401e6d8c84aSJoe Perches  */
mtrr_del_page(int reg,unsigned long base,unsigned long size)402e6d8c84aSJoe Perches int mtrr_del_page(int reg, unsigned long base, unsigned long size)
403e6d8c84aSJoe Perches {
404e6d8c84aSJoe Perches 	int i, max;
405e6d8c84aSJoe Perches 	mtrr_type ltype;
406e6d8c84aSJoe Perches 	unsigned long lbase, lsize;
407e6d8c84aSJoe Perches 	int error = -EINVAL;
408e6d8c84aSJoe Perches 
409e6d8c84aSJoe Perches 	if (!mtrr_enabled())
410e6d8c84aSJoe Perches 		return -ENODEV;
411e6d8c84aSJoe Perches 
412e6d8c84aSJoe Perches 	max = num_var_ranges;
413e6d8c84aSJoe Perches 	/* No CPU hotplug when we change MTRR entries */
4141a351eefSSebastian Andrzej Siewior 	cpus_read_lock();
415e6d8c84aSJoe Perches 	mutex_lock(&mtrr_mutex);
416e6d8c84aSJoe Perches 	if (reg < 0) {
417e6d8c84aSJoe Perches 		/*  Search for existing MTRR  */
418e6d8c84aSJoe Perches 		for (i = 0; i < max; ++i) {
419e6d8c84aSJoe Perches 			mtrr_if->get(i, &lbase, &lsize, &ltype);
420e6d8c84aSJoe Perches 			if (lbase == base && lsize == size) {
421e6d8c84aSJoe Perches 				reg = i;
422e6d8c84aSJoe Perches 				break;
423e6d8c84aSJoe Perches 			}
424e6d8c84aSJoe Perches 		}
425e6d8c84aSJoe Perches 		if (reg < 0) {
4267c1dee73SBorislav Petkov (AMD) 			Dprintk("no MTRR for %lx000,%lx000 found\n", base, size);
427e6d8c84aSJoe Perches 			goto out;
428e6d8c84aSJoe Perches 		}
429e6d8c84aSJoe Perches 	}
430e6d8c84aSJoe Perches 	if (reg >= max) {
431e6d8c84aSJoe Perches 		pr_warn("register: %d too big\n", reg);
432e6d8c84aSJoe Perches 		goto out;
433e6d8c84aSJoe Perches 	}
434e6d8c84aSJoe Perches 	mtrr_if->get(reg, &lbase, &lsize, &ltype);
435e6d8c84aSJoe Perches 	if (lsize < 1) {
436e6d8c84aSJoe Perches 		pr_warn("MTRR %d not used\n", reg);
437e6d8c84aSJoe Perches 		goto out;
438e6d8c84aSJoe Perches 	}
439e6d8c84aSJoe Perches 	if (mtrr_usage_table[reg] < 1) {
440e6d8c84aSJoe Perches 		pr_warn("reg: %d has count=0\n", reg);
441e6d8c84aSJoe Perches 		goto out;
442e6d8c84aSJoe Perches 	}
443e6d8c84aSJoe Perches 	if (--mtrr_usage_table[reg] < 1)
44434cf2d19SJuergen Gross 		set_mtrr(reg, 0, 0, 0);
445e6d8c84aSJoe Perches 	error = reg;
446e6d8c84aSJoe Perches  out:
447e6d8c84aSJoe Perches 	mutex_unlock(&mtrr_mutex);
4481a351eefSSebastian Andrzej Siewior 	cpus_read_unlock();
449e6d8c84aSJoe Perches 	return error;
450e6d8c84aSJoe Perches }
451e6d8c84aSJoe Perches 
452e6d8c84aSJoe Perches /**
453e6d8c84aSJoe Perches  * mtrr_del - delete a memory type region
454e6d8c84aSJoe Perches  * @reg: Register returned by mtrr_add
455e6d8c84aSJoe Perches  * @base: Physical base address
456e6d8c84aSJoe Perches  * @size: Size of region
457e6d8c84aSJoe Perches  *
458e6d8c84aSJoe Perches  * If register is supplied then base and size are ignored. This is
459e6d8c84aSJoe Perches  * how drivers should call it.
460e6d8c84aSJoe Perches  *
461e6d8c84aSJoe Perches  * Releases an MTRR region. If the usage count drops to zero the
462e6d8c84aSJoe Perches  * register is freed and the region returns to default state.
463e6d8c84aSJoe Perches  * On success the register is returned, on failure a negative error
464e6d8c84aSJoe Perches  * code.
465e6d8c84aSJoe Perches  */
mtrr_del(int reg,unsigned long base,unsigned long size)466e6d8c84aSJoe Perches int mtrr_del(int reg, unsigned long base, unsigned long size)
467e6d8c84aSJoe Perches {
468e6d8c84aSJoe Perches 	if (!mtrr_enabled())
469e6d8c84aSJoe Perches 		return -ENODEV;
470e6d8c84aSJoe Perches 	if (mtrr_check(base, size))
471e6d8c84aSJoe Perches 		return -EINVAL;
472e6d8c84aSJoe Perches 	return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
473e6d8c84aSJoe Perches }
474e6d8c84aSJoe Perches 
475e6d8c84aSJoe Perches /**
476e6d8c84aSJoe Perches  * arch_phys_wc_add - add a WC MTRR and handle errors if PAT is unavailable
477e6d8c84aSJoe Perches  * @base: Physical base address
478e6d8c84aSJoe Perches  * @size: Size of region
479e6d8c84aSJoe Perches  *
480e6d8c84aSJoe Perches  * If PAT is available, this does nothing.  If PAT is unavailable, it
481e6d8c84aSJoe Perches  * attempts to add a WC MTRR covering size bytes starting at base and
482e6d8c84aSJoe Perches  * logs an error if this fails.
483e6d8c84aSJoe Perches  *
484e6d8c84aSJoe Perches  * The called should provide a power of two size on an equivalent
485e6d8c84aSJoe Perches  * power of two boundary.
486e6d8c84aSJoe Perches  *
487e6d8c84aSJoe Perches  * Drivers must store the return value to pass to mtrr_del_wc_if_needed,
488e6d8c84aSJoe Perches  * but drivers should not try to interpret that return value.
489e6d8c84aSJoe Perches  */
arch_phys_wc_add(unsigned long base,unsigned long size)490e6d8c84aSJoe Perches int arch_phys_wc_add(unsigned long base, unsigned long size)
491e6d8c84aSJoe Perches {
492e6d8c84aSJoe Perches 	int ret;
493e6d8c84aSJoe Perches 
494e6d8c84aSJoe Perches 	if (pat_enabled() || !mtrr_enabled())
495e6d8c84aSJoe Perches 		return 0;  /* Success!  (We don't need to do anything.) */
496e6d8c84aSJoe Perches 
497e6d8c84aSJoe Perches 	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
498e6d8c84aSJoe Perches 	if (ret < 0) {
499e6d8c84aSJoe Perches 		pr_warn("Failed to add WC MTRR for [%p-%p]; performance may suffer.",
500e6d8c84aSJoe Perches 			(void *)base, (void *)(base + size - 1));
501e6d8c84aSJoe Perches 		return ret;
502e6d8c84aSJoe Perches 	}
503e6d8c84aSJoe Perches 	return ret + MTRR_TO_PHYS_WC_OFFSET;
504e6d8c84aSJoe Perches }
505e6d8c84aSJoe Perches EXPORT_SYMBOL(arch_phys_wc_add);
506e6d8c84aSJoe Perches 
507e6d8c84aSJoe Perches /*
508e6d8c84aSJoe Perches  * arch_phys_wc_del - undoes arch_phys_wc_add
509e6d8c84aSJoe Perches  * @handle: Return value from arch_phys_wc_add
510e6d8c84aSJoe Perches  *
511e6d8c84aSJoe Perches  * This cleans up after mtrr_add_wc_if_needed.
512e6d8c84aSJoe Perches  *
513e6d8c84aSJoe Perches  * The API guarantees that mtrr_del_wc_if_needed(error code) and
514e6d8c84aSJoe Perches  * mtrr_del_wc_if_needed(0) do nothing.
515e6d8c84aSJoe Perches  */
arch_phys_wc_del(int handle)516e6d8c84aSJoe Perches void arch_phys_wc_del(int handle)
517e6d8c84aSJoe Perches {
518e6d8c84aSJoe Perches 	if (handle >= 1) {
519e6d8c84aSJoe Perches 		WARN_ON(handle < MTRR_TO_PHYS_WC_OFFSET);
520e6d8c84aSJoe Perches 		mtrr_del(handle - MTRR_TO_PHYS_WC_OFFSET, 0, 0);
521e6d8c84aSJoe Perches 	}
522e6d8c84aSJoe Perches }
523e6d8c84aSJoe Perches EXPORT_SYMBOL(arch_phys_wc_del);
524e6d8c84aSJoe Perches 
525e6d8c84aSJoe Perches /*
526e6d8c84aSJoe Perches  * arch_phys_wc_index - translates arch_phys_wc_add's return value
527e6d8c84aSJoe Perches  * @handle: Return value from arch_phys_wc_add
528e6d8c84aSJoe Perches  *
529e6d8c84aSJoe Perches  * This will turn the return value from arch_phys_wc_add into an mtrr
530e6d8c84aSJoe Perches  * index suitable for debugging.
531e6d8c84aSJoe Perches  *
532e6d8c84aSJoe Perches  * Note: There is no legitimate use for this function, except possibly
533e6d8c84aSJoe Perches  * in printk line.  Alas there is an illegitimate use in some ancient
534e6d8c84aSJoe Perches  * drm ioctls.
535e6d8c84aSJoe Perches  */
arch_phys_wc_index(int handle)536e6d8c84aSJoe Perches int arch_phys_wc_index(int handle)
537e6d8c84aSJoe Perches {
538e6d8c84aSJoe Perches 	if (handle < MTRR_TO_PHYS_WC_OFFSET)
539e6d8c84aSJoe Perches 		return -1;
540e6d8c84aSJoe Perches 	else
541e6d8c84aSJoe Perches 		return handle - MTRR_TO_PHYS_WC_OFFSET;
542e6d8c84aSJoe Perches }
543e6d8c84aSJoe Perches EXPORT_SYMBOL_GPL(arch_phys_wc_index);
544e6d8c84aSJoe Perches 
545e6d8c84aSJoe Perches int __initdata changed_by_mtrr_cleanup;
546e6d8c84aSJoe Perches 
547e6d8c84aSJoe Perches /**
548f6b98064SJuergen Gross  * mtrr_bp_init - initialize MTRRs on the boot CPU
549e6d8c84aSJoe Perches  *
550e6d8c84aSJoe Perches  * This needs to be called early; before any of the other CPUs are
551e6d8c84aSJoe Perches  * initialized (i.e. before smp_init()).
552e6d8c84aSJoe Perches  */
mtrr_bp_init(void)553e6d8c84aSJoe Perches void __init mtrr_bp_init(void)
554e6d8c84aSJoe Perches {
55529055dc7SJuergen Gross 	bool generic_mtrrs = cpu_feature_enabled(X86_FEATURE_MTRR);
5567882b69eSJuergen Gross 	const char *why = "(not available)";
55703409069SJuergen Gross 	unsigned long config, dummy;
558e6d8c84aSJoe Perches 
559d053b481SJuergen Gross 	phys_hi_rsvd = GENMASK(31, boot_cpu_data.x86_phys_bits - 32);
560e6d8c84aSJoe Perches 
56129055dc7SJuergen Gross 	if (!generic_mtrrs && mtrr_state.enabled) {
56229055dc7SJuergen Gross 		/*
56329055dc7SJuergen Gross 		 * Software overwrite of MTRR state, only for generic case.
56429055dc7SJuergen Gross 		 * Note that X86_FEATURE_MTRR has been reset in this case.
56529055dc7SJuergen Gross 		 */
56629055dc7SJuergen Gross 		init_table();
567061b984aSJuergen Gross 		mtrr_build_map();
56829055dc7SJuergen Gross 		pr_info("MTRRs set to read-only\n");
56929055dc7SJuergen Gross 
57029055dc7SJuergen Gross 		return;
57129055dc7SJuergen Gross 	}
57229055dc7SJuergen Gross 
573b5d3c728SJuergen Gross 	if (generic_mtrrs)
574e6d8c84aSJoe Perches 		mtrr_if = &generic_mtrr_ops;
575b5d3c728SJuergen Gross 	else
576b5d3c728SJuergen Gross 		mtrr_set_if();
577e6d8c84aSJoe Perches 
5782c15679eSJuergen Gross 	if (mtrr_enabled()) {
57903409069SJuergen Gross 		/* Get the number of variable MTRR ranges. */
58003409069SJuergen Gross 		if (mtrr_if == &generic_mtrr_ops)
58103409069SJuergen Gross 			rdmsr(MSR_MTRRcap, config, dummy);
58203409069SJuergen Gross 		else
58303409069SJuergen Gross 			config = mtrr_if->var_regs;
58403409069SJuergen Gross 		num_var_ranges = config & MTRR_CAP_VCNT;
58503409069SJuergen Gross 
586e6d8c84aSJoe Perches 		init_table();
58745fa71f1SJuergen Gross 		if (mtrr_if == &generic_mtrr_ops) {
588e6d8c84aSJoe Perches 			/* BIOS may override */
5892c15679eSJuergen Gross 			if (get_mtrr_state()) {
590adfe7512SJuergen Gross 				memory_caching_control |= CACHE_MTRR;
591f6b98064SJuergen Gross 				changed_by_mtrr_cleanup = mtrr_cleanup();
592061b984aSJuergen Gross 				mtrr_build_map();
5932c15679eSJuergen Gross 			} else {
5942c15679eSJuergen Gross 				mtrr_if = NULL;
5957882b69eSJuergen Gross 				why = "by BIOS";
596e6d8c84aSJoe Perches 			}
597e6d8c84aSJoe Perches 		}
598e6d8c84aSJoe Perches 	}
599e6d8c84aSJoe Perches 
600adfe7512SJuergen Gross 	if (!mtrr_enabled())
6017882b69eSJuergen Gross 		pr_info("MTRRs disabled %s\n", why);
602e6d8c84aSJoe Perches }
603e6d8c84aSJoe Perches 
604e6d8c84aSJoe Perches /**
6054a2d2ed9SMauro Carvalho Chehab  * mtrr_save_state - Save current fixed-range MTRR state of the first
6064a2d2ed9SMauro Carvalho Chehab  *	cpu in cpu_online_mask.
607e6d8c84aSJoe Perches  */
mtrr_save_state(void)608e6d8c84aSJoe Perches void mtrr_save_state(void)
609e6d8c84aSJoe Perches {
610e6d8c84aSJoe Perches 	int first_cpu;
611e6d8c84aSJoe Perches 
612*8a90d3fcSAndi Kleen 	if (!mtrr_enabled() || !mtrr_state.have_fixed)
613e6d8c84aSJoe Perches 		return;
614e6d8c84aSJoe Perches 
615e6d8c84aSJoe Perches 	first_cpu = cpumask_first(cpu_online_mask);
616e6d8c84aSJoe Perches 	smp_call_function_single(first_cpu, mtrr_save_fixed_ranges, NULL, 1);
617e6d8c84aSJoe Perches }
618e6d8c84aSJoe Perches 
mtrr_init_finalize(void)619b5d3c728SJuergen Gross static int __init mtrr_init_finalize(void)
620e6d8c84aSJoe Perches {
621061b984aSJuergen Gross 	/*
622061b984aSJuergen Gross 	 * Map might exist if mtrr_overwrite_state() has been called or if
623061b984aSJuergen Gross 	 * mtrr_enabled() returns true.
624061b984aSJuergen Gross 	 */
625061b984aSJuergen Gross 	mtrr_copy_map();
626061b984aSJuergen Gross 
627e6d8c84aSJoe Perches 	if (!mtrr_enabled())
628e6d8c84aSJoe Perches 		return 0;
629e6d8c84aSJoe Perches 
63045fa71f1SJuergen Gross 	if (memory_caching_control & CACHE_MTRR) {
631e6d8c84aSJoe Perches 		if (!changed_by_mtrr_cleanup)
632e6d8c84aSJoe Perches 			mtrr_state_warn();
633e6d8c84aSJoe Perches 		return 0;
634e6d8c84aSJoe Perches 	}
635e6d8c84aSJoe Perches 
636b5d3c728SJuergen Gross 	mtrr_register_syscore();
637e6d8c84aSJoe Perches 
638e6d8c84aSJoe Perches 	return 0;
639e6d8c84aSJoe Perches }
640b5d3c728SJuergen Gross subsys_initcall(mtrr_init_finalize);
641