|
@@ -93,6 +93,18 @@ void arch_report_meminfo(struct seq_file *m)
|
|
|
static inline void split_page_count(int level) { }
|
|
|
#endif
|
|
|
|
|
|
+static inline int
|
|
|
+within(unsigned long addr, unsigned long start, unsigned long end)
|
|
|
+{
|
|
|
+ return addr >= start && addr < end;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int
|
|
|
+within_inclusive(unsigned long addr, unsigned long start, unsigned long end)
|
|
|
+{
|
|
|
+ return addr >= start && addr <= end;
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
|
|
static inline unsigned long highmap_start_pfn(void)
|
|
@@ -106,20 +118,25 @@ static inline unsigned long highmap_end_pfn(void)
|
|
|
return __pa_symbol(roundup(_brk_end, PMD_SIZE) - 1) >> PAGE_SHIFT;
|
|
|
}
|
|
|
|
|
|
-#endif
|
|
|
-
|
|
|
-static inline int
|
|
|
-within(unsigned long addr, unsigned long start, unsigned long end)
|
|
|
+static bool __cpa_pfn_in_highmap(unsigned long pfn)
|
|
|
{
|
|
|
- return addr >= start && addr < end;
|
|
|
+ /*
|
|
|
+ * Kernel text has an alias mapping at a high address, known
|
|
|
+ * here as "highmap".
|
|
|
+ */
|
|
|
+ return within_inclusive(pfn, highmap_start_pfn(), highmap_end_pfn());
|
|
|
}
|
|
|
|
|
|
-static inline int
|
|
|
-within_inclusive(unsigned long addr, unsigned long start, unsigned long end)
|
|
|
+#else
|
|
|
+
|
|
|
+static bool __cpa_pfn_in_highmap(unsigned long pfn)
|
|
|
{
|
|
|
- return addr >= start && addr <= end;
|
|
|
+ /* There is no highmap on 32-bit */
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* Flushing functions
|
|
|
*/
|
|
@@ -172,7 +189,7 @@ static void __cpa_flush_all(void *arg)
|
|
|
|
|
|
static void cpa_flush_all(unsigned long cache)
|
|
|
{
|
|
|
- BUG_ON(irqs_disabled());
|
|
|
+ BUG_ON(irqs_disabled() && !early_boot_irqs_disabled);
|
|
|
|
|
|
on_each_cpu(__cpa_flush_all, (void *) cache, 1);
|
|
|
}
|
|
@@ -236,7 +253,7 @@ static void cpa_flush_array(unsigned long *start, int numpages, int cache,
|
|
|
unsigned long do_wbinvd = cache && numpages >= 1024; /* 4M threshold */
|
|
|
#endif
|
|
|
|
|
|
- BUG_ON(irqs_disabled());
|
|
|
+ BUG_ON(irqs_disabled() && !early_boot_irqs_disabled);
|
|
|
|
|
|
on_each_cpu(__cpa_flush_all, (void *) do_wbinvd, 1);
|
|
|
|
|
@@ -1183,6 +1200,10 @@ static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
|
|
|
cpa->numpages = 1;
|
|
|
cpa->pfn = __pa(vaddr) >> PAGE_SHIFT;
|
|
|
return 0;
|
|
|
+
|
|
|
+ } else if (__cpa_pfn_in_highmap(cpa->pfn)) {
|
|
|
+ /* Faults in the highmap are OK, so do not warn: */
|
|
|
+ return -EFAULT;
|
|
|
} else {
|
|
|
WARN(1, KERN_WARNING "CPA: called for zero pte. "
|
|
|
"vaddr = %lx cpa->vaddr = %lx\n", vaddr,
|
|
@@ -1335,8 +1356,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
|
|
|
* to touch the high mapped kernel as well:
|
|
|
*/
|
|
|
if (!within(vaddr, (unsigned long)_text, _brk_end) &&
|
|
|
- within_inclusive(cpa->pfn, highmap_start_pfn(),
|
|
|
- highmap_end_pfn())) {
|
|
|
+ __cpa_pfn_in_highmap(cpa->pfn)) {
|
|
|
unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
|
|
|
__START_KERNEL_map - phys_base;
|
|
|
alias_cpa = *cpa;
|