diff options
author | Anthony Liguori <aliguori@us.ibm.com> | 2008-04-02 15:46:56 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-04-27 05:01:15 -0400 |
commit | 35149e2129fe34fc8cb5917e1ecf5156b0fa3415 (patch) | |
tree | b67cb16fa6054769ee476fce99a32601b126af10 /include | |
parent | fdae862f91728aec6dd8fd62cd2398868c906b6b (diff) |
KVM: MMU: Don't assume struct page for x86
This patch introduces a gfn_to_pfn() function and corresponding functions like
kvm_release_pfn_dirty(). Using these new functions, we can modify the x86
MMU to no longer assume that it can always get a struct page for any given gfn.
We don't want to eliminate gfn_to_page() entirely because a number of places
assume they can do gfn_to_page() and then kmap() the results. When we support
IO memory, gfn_to_page() will fail for IO pages although gfn_to_pfn() will
succeed.
This does not implement support for avoiding reference counting for reserved
RAM or for IO memory. However, it should make those things pretty straight
forward.
Since we're only introducing new common symbols, I don't think it will break
the non-x86 architectures but I haven't tested those. I've tested Intel,
AMD, NPT, and hugetlbfs with Windows and Linux guests.
[avi: fix overflow when shifting left pfns by adding casts]
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-x86/kvm_host.h | 4 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 12 | ||||
-rw-r--r-- | include/linux/kvm_types.h | 2 |
3 files changed, 16 insertions, 2 deletions
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index b9230490d777..de3eccfb767c 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h | |||
@@ -248,8 +248,8 @@ struct kvm_vcpu_arch { | |||
248 | u64 *last_pte_updated; | 248 | u64 *last_pte_updated; |
249 | 249 | ||
250 | struct { | 250 | struct { |
251 | gfn_t gfn; /* presumed gfn during guest pte update */ | 251 | gfn_t gfn; /* presumed gfn during guest pte update */ |
252 | struct page *page; /* page corresponding to that gfn */ | 252 | pfn_t pfn; /* pfn corresponding to that gfn */ |
253 | int largepage; | 253 | int largepage; |
254 | } update_pte; | 254 | } update_pte; |
255 | 255 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index a2ceb51b4274..578c3638bbba 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -150,8 +150,10 @@ static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; } | |||
150 | struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva); | 150 | struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva); |
151 | 151 | ||
152 | extern struct page *bad_page; | 152 | extern struct page *bad_page; |
153 | extern pfn_t bad_pfn; | ||
153 | 154 | ||
154 | int is_error_page(struct page *page); | 155 | int is_error_page(struct page *page); |
156 | int is_error_pfn(pfn_t pfn); | ||
155 | int kvm_is_error_hva(unsigned long addr); | 157 | int kvm_is_error_hva(unsigned long addr); |
156 | int kvm_set_memory_region(struct kvm *kvm, | 158 | int kvm_set_memory_region(struct kvm *kvm, |
157 | struct kvm_userspace_memory_region *mem, | 159 | struct kvm_userspace_memory_region *mem, |
@@ -168,6 +170,16 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); | |||
168 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); | 170 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); |
169 | void kvm_release_page_clean(struct page *page); | 171 | void kvm_release_page_clean(struct page *page); |
170 | void kvm_release_page_dirty(struct page *page); | 172 | void kvm_release_page_dirty(struct page *page); |
173 | void kvm_set_page_dirty(struct page *page); | ||
174 | void kvm_set_page_accessed(struct page *page); | ||
175 | |||
176 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn); | ||
177 | void kvm_release_pfn_dirty(pfn_t); | ||
178 | void kvm_release_pfn_clean(pfn_t pfn); | ||
179 | void kvm_set_pfn_dirty(pfn_t pfn); | ||
180 | void kvm_set_pfn_accessed(pfn_t pfn); | ||
181 | void kvm_get_pfn(pfn_t pfn); | ||
182 | |||
171 | int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, | 183 | int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, |
172 | int len); | 184 | int len); |
173 | int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data, | 185 | int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data, |
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h index 1c4e46decb22..9b6f395c9625 100644 --- a/include/linux/kvm_types.h +++ b/include/linux/kvm_types.h | |||
@@ -38,6 +38,8 @@ typedef unsigned long hva_t; | |||
38 | typedef u64 hpa_t; | 38 | typedef u64 hpa_t; |
39 | typedef unsigned long hfn_t; | 39 | typedef unsigned long hfn_t; |
40 | 40 | ||
41 | typedef hfn_t pfn_t; | ||
42 | |||
41 | struct kvm_pio_request { | 43 | struct kvm_pio_request { |
42 | unsigned long count; | 44 | unsigned long count; |
43 | int cur_count; | 45 | int cur_count; |