mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-30 05:56:38 +07:00
cb32edf65b
We use pat_enabled in x86-specific code to see if PAT is enabled or not but we're granting full access to it even though readers do not need to set it. If, for instance, we granted access to it to modules later they then could override the variable setting... no bueno. This renames pat_enabled to a new static variable __pat_enabled. Folks are redirected to use pat_enabled() now. Code that sets this can only be internal to pat.c. Apart from the early kernel parameter "nopat" to disable PAT, we also have a few cases that disable it later and make use of a helper pat_disable(). It is wrapped under an ifdef but since that code cannot run unless PAT was enabled its not required to wrap it with ifdefs, unwrap that. Likewise, since "nopat" doesn't really change non-PAT systems just remove that ifdef as well. Although we could add and use an early_param_off(), these helpers don't use __read_mostly but we want to keep __read_mostly for __pat_enabled as this is a hot path -- upon boot, for instance, a simple guest may see ~4k accesses to pat_enabled(). Since __read_mostly early boot params are not that common we don't add a helper for them just yet. Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Walls <awalls@md.metrocast.net> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Christoph Lameter <cl@linux.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Dave Airlie <airlied@redhat.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Doug Ledford <dledford@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Juergen Gross <jgross@suse.com> Cc: Kyle McMartin <kyle@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1430425520-22275-3-git-send-email-mcgrof@do-not-panic.com Link: http://lkml.kernel.org/r/1432628901-18044-13-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
122 lines
3.4 KiB
C
122 lines
3.4 KiB
C
/*
|
|
* Copyright © 2008 Ingo Molnar
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
*/
|
|
|
|
#include <asm/iomap.h>
|
|
#include <asm/pat.h>
|
|
#include <linux/module.h>
|
|
#include <linux/highmem.h>
|
|
|
|
static int is_io_mapping_possible(resource_size_t base, unsigned long size)
|
|
{
|
|
#if !defined(CONFIG_X86_PAE) && defined(CONFIG_PHYS_ADDR_T_64BIT)
|
|
/* There is no way to map greater than 1 << 32 address without PAE */
|
|
if (base + size > 0x100000000ULL)
|
|
return 0;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
int iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot)
|
|
{
|
|
enum page_cache_mode pcm = _PAGE_CACHE_MODE_WC;
|
|
int ret;
|
|
|
|
if (!is_io_mapping_possible(base, size))
|
|
return -EINVAL;
|
|
|
|
ret = io_reserve_memtype(base, base + size, &pcm);
|
|
if (ret)
|
|
return ret;
|
|
|
|
*prot = __pgprot(__PAGE_KERNEL | cachemode2protval(pcm));
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(iomap_create_wc);
|
|
|
|
void iomap_free(resource_size_t base, unsigned long size)
|
|
{
|
|
io_free_memtype(base, base + size);
|
|
}
|
|
EXPORT_SYMBOL_GPL(iomap_free);
|
|
|
|
void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
unsigned long vaddr;
|
|
int idx, type;
|
|
|
|
pagefault_disable();
|
|
|
|
type = kmap_atomic_idx_push();
|
|
idx = type + KM_TYPE_NR * smp_processor_id();
|
|
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
|
set_pte(kmap_pte - idx, pfn_pte(pfn, prot));
|
|
arch_flush_lazy_mmu_mode();
|
|
|
|
return (void *)vaddr;
|
|
}
|
|
|
|
/*
|
|
* Map 'pfn' using protections 'prot'
|
|
*/
|
|
void __iomem *
|
|
iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
|
|
{
|
|
/*
|
|
* For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
|
|
* PAGE_KERNEL_WC maps to PWT, which translates to uncached if the
|
|
* MTRR is UC or WC. UC_MINUS gets the real intention, of the
|
|
* user, which is "WC if the MTRR is WC, UC if you can't do that."
|
|
*/
|
|
if (!pat_enabled() && pgprot_val(prot) ==
|
|
(__PAGE_KERNEL | cachemode2protval(_PAGE_CACHE_MODE_WC)))
|
|
prot = __pgprot(__PAGE_KERNEL |
|
|
cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS));
|
|
|
|
return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, prot);
|
|
}
|
|
EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
|
|
|
|
void
|
|
iounmap_atomic(void __iomem *kvaddr)
|
|
{
|
|
unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
|
|
|
|
if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
|
|
vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
|
|
int idx, type;
|
|
|
|
type = kmap_atomic_idx();
|
|
idx = type + KM_TYPE_NR * smp_processor_id();
|
|
|
|
#ifdef CONFIG_DEBUG_HIGHMEM
|
|
WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
|
|
#endif
|
|
/*
|
|
* Force other mappings to Oops if they'll try to access this
|
|
* pte without first remap it. Keeping stale mappings around
|
|
* is a bad idea also, in case the page changes cacheability
|
|
* attributes or becomes a protected page in a hypervisor.
|
|
*/
|
|
kpte_clear_flush(kmap_pte-idx, vaddr);
|
|
kmap_atomic_idx_pop();
|
|
}
|
|
|
|
pagefault_enable();
|
|
}
|
|
EXPORT_SYMBOL_GPL(iounmap_atomic);
|