|
@@ -92,6 +92,9 @@ static bool kvm_rebooting;
|
|
|
|
|
|
static bool largepages_enabled = true;
|
|
|
|
|
|
+struct page *hwpoison_page;
|
|
|
+pfn_t hwpoison_pfn;
|
|
|
+
|
|
|
inline int kvm_is_mmio_pfn(pfn_t pfn)
|
|
|
{
|
|
|
if (pfn_valid(pfn)) {
|
|
@@ -810,16 +813,22 @@ EXPORT_SYMBOL_GPL(kvm_disable_largepages);
|
|
|
|
|
|
int is_error_page(struct page *page)
|
|
|
{
|
|
|
- return page == bad_page;
|
|
|
+ return page == bad_page || page == hwpoison_page;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(is_error_page);
|
|
|
|
|
|
int is_error_pfn(pfn_t pfn)
|
|
|
{
|
|
|
- return pfn == bad_pfn;
|
|
|
+ return pfn == bad_pfn || pfn == hwpoison_pfn;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(is_error_pfn);
|
|
|
|
|
|
+int is_hwpoison_pfn(pfn_t pfn)
|
|
|
+{
|
|
|
+ return pfn == hwpoison_pfn;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(is_hwpoison_pfn);
|
|
|
+
|
|
|
static inline unsigned long bad_hva(void)
|
|
|
{
|
|
|
return PAGE_OFFSET;
|
|
@@ -945,6 +954,11 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr)
|
|
|
if (unlikely(npages != 1)) {
|
|
|
struct vm_area_struct *vma;
|
|
|
|
|
|
+ if (is_hwpoison_address(addr)) {
|
|
|
+ get_page(hwpoison_page);
|
|
|
+ return page_to_pfn(hwpoison_page);
|
|
|
+ }
|
|
|
+
|
|
|
down_read(¤t->mm->mmap_sem);
|
|
|
vma = find_vma(current->mm, addr);
|
|
|
|
|
@@ -2197,6 +2211,15 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
|
|
|
|
|
|
bad_pfn = page_to_pfn(bad_page);
|
|
|
|
|
|
+ hwpoison_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
|
|
+
|
|
|
+ if (hwpoison_page == NULL) {
|
|
|
+ r = -ENOMEM;
|
|
|
+ goto out_free_0;
|
|
|
+ }
|
|
|
+
|
|
|
+ hwpoison_pfn = page_to_pfn(hwpoison_page);
|
|
|
+
|
|
|
if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) {
|
|
|
r = -ENOMEM;
|
|
|
goto out_free_0;
|
|
@@ -2269,6 +2292,8 @@ out_free_1:
|
|
|
out_free_0a:
|
|
|
free_cpumask_var(cpus_hardware_enabled);
|
|
|
out_free_0:
|
|
|
+ if (hwpoison_page)
|
|
|
+ __free_page(hwpoison_page);
|
|
|
__free_page(bad_page);
|
|
|
out:
|
|
|
kvm_arch_exit();
|
|
@@ -2290,6 +2315,7 @@ void kvm_exit(void)
|
|
|
kvm_arch_hardware_unsetup();
|
|
|
kvm_arch_exit();
|
|
|
free_cpumask_var(cpus_hardware_enabled);
|
|
|
+ __free_page(hwpoison_page);
|
|
|
__free_page(bad_page);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(kvm_exit);
|