Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 329817
b: refs/heads/master
c: a276632
h: refs/heads/master
i:
  329815: 57adba1
v: v3
  • Loading branch information
Xiao Guangrong authored and Avi Kivity committed Jul 26, 2012
1 parent 6f190ea commit 75e572e
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 76 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2b4b5af8f8e7296bc27c52023ab6bb8f53db3a2b
refs/heads/master: a2766325cf9f9e36d1225145f1ce1b066f001837
3 changes: 2 additions & 1 deletion trunk/include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ void kvm_arch_flush_shadow(struct kvm *kvm);
int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages,
int nr_pages);

struct page *get_bad_page(void);
struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn);
unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn);
void kvm_release_page_clean(struct page *page);
Expand Down Expand Up @@ -576,7 +577,7 @@ void kvm_arch_sync_events(struct kvm *kvm);
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu);
void kvm_vcpu_kick(struct kvm_vcpu *vcpu);

int kvm_is_mmio_pfn(pfn_t pfn);
bool kvm_is_mmio_pfn(pfn_t pfn);

struct kvm_irq_ack_notifier {
struct hlist_node link;
Expand Down
3 changes: 1 addition & 2 deletions trunk/virt/kvm/async_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu)
if (!work)
return -ENOMEM;

work->page = bad_page;
get_page(bad_page);
work->page = get_bad_page();
INIT_LIST_HEAD(&work->queue); /* for list_del to work */

spin_lock(&vcpu->async_pf.lock);
Expand Down
121 changes: 49 additions & 72 deletions trunk/virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,11 @@ EXPORT_SYMBOL_GPL(kvm_rebooting);

static bool largepages_enabled = true;

struct page *bad_page;
static pfn_t bad_pfn;

static struct page *hwpoison_page;
static pfn_t hwpoison_pfn;

static struct page *fault_page;
static pfn_t fault_pfn;

inline int kvm_is_mmio_pfn(pfn_t pfn)
bool kvm_is_mmio_pfn(pfn_t pfn)
{
if (is_error_pfn(pfn))
return false;

if (pfn_valid(pfn)) {
int reserved;
struct page *tail = pfn_to_page(pfn);
Expand Down Expand Up @@ -939,34 +933,55 @@ EXPORT_SYMBOL_GPL(kvm_disable_largepages);

int is_error_page(struct page *page)
{
return page == bad_page || page == hwpoison_page || page == fault_page;
return IS_ERR(page);
}
EXPORT_SYMBOL_GPL(is_error_page);

int is_error_pfn(pfn_t pfn)
{
return pfn == bad_pfn || pfn == hwpoison_pfn || pfn == fault_pfn;
return IS_ERR_VALUE(pfn);
}
EXPORT_SYMBOL_GPL(is_error_pfn);

static pfn_t get_bad_pfn(void)
{
return -ENOENT;
}

pfn_t get_fault_pfn(void)
{
return -EFAULT;
}
EXPORT_SYMBOL_GPL(get_fault_pfn);

static pfn_t get_hwpoison_pfn(void)
{
return -EHWPOISON;
}

int is_hwpoison_pfn(pfn_t pfn)
{
return pfn == hwpoison_pfn;
return pfn == -EHWPOISON;
}
EXPORT_SYMBOL_GPL(is_hwpoison_pfn);

int is_noslot_pfn(pfn_t pfn)
{
return pfn == bad_pfn;
return pfn == -ENOENT;
}
EXPORT_SYMBOL_GPL(is_noslot_pfn);

int is_invalid_pfn(pfn_t pfn)
{
return pfn == hwpoison_pfn || pfn == fault_pfn;
return !is_noslot_pfn(pfn) && is_error_pfn(pfn);
}
EXPORT_SYMBOL_GPL(is_invalid_pfn);

struct page *get_bad_page(void)
{
return ERR_PTR(-ENOENT);
}

static inline unsigned long bad_hva(void)
{
return PAGE_OFFSET;
Expand Down Expand Up @@ -1038,13 +1053,6 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
}
EXPORT_SYMBOL_GPL(gfn_to_hva);

pfn_t get_fault_pfn(void)
{
get_page(fault_page);
return fault_pfn;
}
EXPORT_SYMBOL_GPL(get_fault_pfn);

int get_user_page_nowait(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int write, struct page **page)
{
Expand Down Expand Up @@ -1122,8 +1130,7 @@ static pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async,
if (npages == -EHWPOISON ||
(!async && check_user_page_hwpoison(addr))) {
up_read(&current->mm->mmap_sem);
get_page(hwpoison_page);
return page_to_pfn(hwpoison_page);
return get_hwpoison_pfn();
}

vma = find_vma_intersection(current->mm, addr, addr+1);
Expand Down Expand Up @@ -1161,10 +1168,8 @@ static pfn_t __gfn_to_pfn(struct kvm *kvm, gfn_t gfn, bool atomic, bool *async,
*async = false;

addr = gfn_to_hva(kvm, gfn);
if (kvm_is_error_hva(addr)) {
get_page(bad_page);
return page_to_pfn(bad_page);
}
if (kvm_is_error_hva(addr))
return get_bad_pfn();

return hva_to_pfn(addr, atomic, async, write_fault, writable);
}
Expand Down Expand Up @@ -1218,37 +1223,45 @@ int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages,
}
EXPORT_SYMBOL_GPL(gfn_to_page_many_atomic);

static struct page *kvm_pfn_to_page(pfn_t pfn)
{
WARN_ON(kvm_is_mmio_pfn(pfn));

if (is_error_pfn(pfn) || kvm_is_mmio_pfn(pfn))
return get_bad_page();

return pfn_to_page(pfn);
}

struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
{
pfn_t pfn;

pfn = gfn_to_pfn(kvm, gfn);
if (!kvm_is_mmio_pfn(pfn))
return pfn_to_page(pfn);

WARN_ON(kvm_is_mmio_pfn(pfn));

get_page(bad_page);
return bad_page;
return kvm_pfn_to_page(pfn);
}

EXPORT_SYMBOL_GPL(gfn_to_page);

void kvm_release_page_clean(struct page *page)
{
kvm_release_pfn_clean(page_to_pfn(page));
if (!is_error_page(page))
kvm_release_pfn_clean(page_to_pfn(page));
}
EXPORT_SYMBOL_GPL(kvm_release_page_clean);

void kvm_release_pfn_clean(pfn_t pfn)
{
if (!kvm_is_mmio_pfn(pfn))
if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
put_page(pfn_to_page(pfn));
}
EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);

void kvm_release_page_dirty(struct page *page)
{
WARN_ON(is_error_page(page));

kvm_release_pfn_dirty(page_to_pfn(page));
}
EXPORT_SYMBOL_GPL(kvm_release_page_dirty);
Expand Down Expand Up @@ -2771,33 +2784,6 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
if (r)
goto out_fail;

bad_page = alloc_page(GFP_KERNEL | __GFP_ZERO);

if (bad_page == NULL) {
r = -ENOMEM;
goto out;
}

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);

fault_page = alloc_page(GFP_KERNEL | __GFP_ZERO);

if (fault_page == NULL) {
r = -ENOMEM;
goto out_free_0;
}

fault_pfn = page_to_pfn(fault_page);

if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) {
r = -ENOMEM;
goto out_free_0;
Expand Down Expand Up @@ -2872,12 +2858,6 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
out_free_0a:
free_cpumask_var(cpus_hardware_enabled);
out_free_0:
if (fault_page)
__free_page(fault_page);
if (hwpoison_page)
__free_page(hwpoison_page);
__free_page(bad_page);
out:
kvm_arch_exit();
out_fail:
return r;
Expand All @@ -2897,8 +2877,5 @@ void kvm_exit(void)
kvm_arch_hardware_unsetup();
kvm_arch_exit();
free_cpumask_var(cpus_hardware_enabled);
__free_page(fault_page);
__free_page(hwpoison_page);
__free_page(bad_page);
}
EXPORT_SYMBOL_GPL(kvm_exit);

0 comments on commit 75e572e

Please sign in to comment.