* [PATCH 02/54] KVM: Remove gpa_to_hpa()
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 03/54] KVM: MMU: Rename variables of type 'struct kvm_mmu_page *' Avi Kivity
` (51 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Converting last uses along the way.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm.h | 1 -
drivers/kvm/mmu.c | 21 +++------------------
2 files changed, 3 insertions(+), 19 deletions(-)
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 31315bc..1fd8158 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -375,7 +375,6 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
struct module *module);
void kvm_exit(void);
-hpa_t gpa_to_hpa(struct kvm *kvm, gpa_t gpa);
#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)
static inline int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; }
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 6aa0319..9b75b10 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -868,26 +868,13 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
__set_bit(slot, &page_head->slot_bitmap);
}
-hpa_t gpa_to_hpa(struct kvm *kvm, gpa_t gpa)
-{
- struct page *page;
- hpa_t hpa;
-
- ASSERT((gpa & HPA_ERR_MASK) == 0);
- page = gfn_to_page(kvm, gpa >> PAGE_SHIFT);
- hpa = ((hpa_t)page_to_pfn(page) << PAGE_SHIFT) | (gpa & (PAGE_SIZE-1));
- if (is_error_page(page))
- return hpa | HPA_ERR_MASK;
- return hpa;
-}
-
struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
{
gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, gva);
if (gpa == UNMAPPED_GVA)
return NULL;
- return pfn_to_page(gpa_to_hpa(vcpu->kvm, gpa) >> PAGE_SHIFT);
+ return gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
}
static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
@@ -1611,8 +1598,8 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
audit_mappings_page(vcpu, ent, va, level - 1);
} else {
gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, va);
- hpa_t hpa = gpa_to_hpa(vcpu, gpa);
- struct page *page;
+ struct page *page = gpa_to_page(vcpu, gpa);
+ hpa_t hpa = page_to_phys(page);
if (is_shadow_present_pte(ent)
&& (ent & PT64_BASE_ADDR_MASK) != hpa)
@@ -1625,8 +1612,6 @@ static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte,
&& !is_error_hpa(hpa))
printk(KERN_ERR "audit: (%s) notrap shadow,"
" valid guest gva %lx\n", audit_msg, va);
- page = pfn_to_page((gpa & PT64_BASE_ADDR_MASK)
- >> PAGE_SHIFT);
kvm_release_page_clean(page);
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 03/54] KVM: MMU: Rename variables of type 'struct kvm_mmu_page *'
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2008-01-01 15:35 ` [PATCH 02/54] KVM: Remove gpa_to_hpa() Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 04/54] KVM: MMU: Rename 'release_page' Avi Kivity
` (50 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
These are traditionally named 'page', but even more traditionally, that name
is reserved for variables that point to a 'struct page'. Rename them to 'sp'
(for "shadow page").
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 300 ++++++++++++++++++++++++++---------------------------
1 files changed, 146 insertions(+), 154 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 9b75b10..86896da 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -367,7 +367,7 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn)
*/
static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
{
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
struct kvm_rmap_desc *desc;
unsigned long *rmapp;
int i;
@@ -375,8 +375,8 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
if (!is_rmap_pte(*spte))
return;
gfn = unalias_gfn(vcpu->kvm, gfn);
- page = page_header(__pa(spte));
- page->gfns[spte - page->spt] = gfn;
+ sp = page_header(__pa(spte));
+ sp->gfns[spte - sp->spt] = gfn;
rmapp = gfn_to_rmap(vcpu->kvm, gfn);
if (!*rmapp) {
rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte);
@@ -429,20 +429,20 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
{
struct kvm_rmap_desc *desc;
struct kvm_rmap_desc *prev_desc;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
struct page *release_page;
unsigned long *rmapp;
int i;
if (!is_rmap_pte(*spte))
return;
- page = page_header(__pa(spte));
+ sp = page_header(__pa(spte));
release_page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
if (is_writeble_pte(*spte))
kvm_release_page_dirty(release_page);
else
kvm_release_page_clean(release_page);
- rmapp = gfn_to_rmap(kvm, page->gfns[spte - page->spt]);
+ rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt]);
if (!*rmapp) {
printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
BUG();
@@ -537,14 +537,13 @@ static int is_empty_shadow_page(u64 *spt)
}
#endif
-static void kvm_mmu_free_page(struct kvm *kvm,
- struct kvm_mmu_page *page_head)
+static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
- ASSERT(is_empty_shadow_page(page_head->spt));
- list_del(&page_head->link);
- __free_page(virt_to_page(page_head->spt));
- __free_page(virt_to_page(page_head->gfns));
- kfree(page_head);
+ ASSERT(is_empty_shadow_page(sp->spt));
+ list_del(&sp->link);
+ __free_page(virt_to_page(sp->spt));
+ __free_page(virt_to_page(sp->gfns));
+ kfree(sp);
++kvm->n_free_mmu_pages;
}
@@ -556,27 +555,26 @@ static unsigned kvm_page_table_hashfn(gfn_t gfn)
static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
u64 *parent_pte)
{
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
if (!vcpu->kvm->n_free_mmu_pages)
return NULL;
- page = mmu_memory_cache_alloc(&vcpu->mmu_page_header_cache,
- sizeof *page);
- page->spt = mmu_memory_cache_alloc(&vcpu->mmu_page_cache, PAGE_SIZE);
- page->gfns = mmu_memory_cache_alloc(&vcpu->mmu_page_cache, PAGE_SIZE);
- set_page_private(virt_to_page(page->spt), (unsigned long)page);
- list_add(&page->link, &vcpu->kvm->active_mmu_pages);
- ASSERT(is_empty_shadow_page(page->spt));
- page->slot_bitmap = 0;
- page->multimapped = 0;
- page->parent_pte = parent_pte;
+ sp = mmu_memory_cache_alloc(&vcpu->mmu_page_header_cache, sizeof *sp);
+ sp->spt = mmu_memory_cache_alloc(&vcpu->mmu_page_cache, PAGE_SIZE);
+ sp->gfns = mmu_memory_cache_alloc(&vcpu->mmu_page_cache, PAGE_SIZE);
+ set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
+ list_add(&sp->link, &vcpu->kvm->active_mmu_pages);
+ ASSERT(is_empty_shadow_page(sp->spt));
+ sp->slot_bitmap = 0;
+ sp->multimapped = 0;
+ sp->parent_pte = parent_pte;
--vcpu->kvm->n_free_mmu_pages;
- return page;
+ return sp;
}
static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *page, u64 *parent_pte)
+ struct kvm_mmu_page *sp, u64 *parent_pte)
{
struct kvm_pte_chain *pte_chain;
struct hlist_node *node;
@@ -584,20 +582,20 @@ static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu,
if (!parent_pte)
return;
- if (!page->multimapped) {
- u64 *old = page->parent_pte;
+ if (!sp->multimapped) {
+ u64 *old = sp->parent_pte;
if (!old) {
- page->parent_pte = parent_pte;
+ sp->parent_pte = parent_pte;
return;
}
- page->multimapped = 1;
+ sp->multimapped = 1;
pte_chain = mmu_alloc_pte_chain(vcpu);
- INIT_HLIST_HEAD(&page->parent_ptes);
- hlist_add_head(&pte_chain->link, &page->parent_ptes);
+ INIT_HLIST_HEAD(&sp->parent_ptes);
+ hlist_add_head(&pte_chain->link, &sp->parent_ptes);
pte_chain->parent_ptes[0] = old;
}
- hlist_for_each_entry(pte_chain, node, &page->parent_ptes, link) {
+ hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link) {
if (pte_chain->parent_ptes[NR_PTE_CHAIN_ENTRIES-1])
continue;
for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i)
@@ -608,23 +606,23 @@ static void mmu_page_add_parent_pte(struct kvm_vcpu *vcpu,
}
pte_chain = mmu_alloc_pte_chain(vcpu);
BUG_ON(!pte_chain);
- hlist_add_head(&pte_chain->link, &page->parent_ptes);
+ hlist_add_head(&pte_chain->link, &sp->parent_ptes);
pte_chain->parent_ptes[0] = parent_pte;
}
-static void mmu_page_remove_parent_pte(struct kvm_mmu_page *page,
+static void mmu_page_remove_parent_pte(struct kvm_mmu_page *sp,
u64 *parent_pte)
{
struct kvm_pte_chain *pte_chain;
struct hlist_node *node;
int i;
- if (!page->multimapped) {
- BUG_ON(page->parent_pte != parent_pte);
- page->parent_pte = NULL;
+ if (!sp->multimapped) {
+ BUG_ON(sp->parent_pte != parent_pte);
+ sp->parent_pte = NULL;
return;
}
- hlist_for_each_entry(pte_chain, node, &page->parent_ptes, link)
+ hlist_for_each_entry(pte_chain, node, &sp->parent_ptes, link)
for (i = 0; i < NR_PTE_CHAIN_ENTRIES; ++i) {
if (!pte_chain->parent_ptes[i])
break;
@@ -640,9 +638,9 @@ static void mmu_page_remove_parent_pte(struct kvm_mmu_page *page,
if (i == 0) {
hlist_del(&pte_chain->link);
mmu_free_pte_chain(pte_chain);
- if (hlist_empty(&page->parent_ptes)) {
- page->multimapped = 0;
- page->parent_pte = NULL;
+ if (hlist_empty(&sp->parent_ptes)) {
+ sp->multimapped = 0;
+ sp->parent_pte = NULL;
}
}
return;
@@ -650,22 +648,21 @@ static void mmu_page_remove_parent_pte(struct kvm_mmu_page *page,
BUG();
}
-static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm,
- gfn_t gfn)
+static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
{
unsigned index;
struct hlist_head *bucket;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
struct hlist_node *node;
pgprintk("%s: looking for gfn %lx\n", __FUNCTION__, gfn);
index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
bucket = &kvm->mmu_page_hash[index];
- hlist_for_each_entry(page, node, bucket, hash_link)
- if (page->gfn == gfn && !page->role.metaphysical) {
+ hlist_for_each_entry(sp, node, bucket, hash_link)
+ if (sp->gfn == gfn && !sp->role.metaphysical) {
pgprintk("%s: found role %x\n",
- __FUNCTION__, page->role.word);
- return page;
+ __FUNCTION__, sp->role.word);
+ return sp;
}
return NULL;
}
@@ -682,7 +679,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
unsigned index;
unsigned quadrant;
struct hlist_head *bucket;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
struct hlist_node *node;
role.word = 0;
@@ -699,35 +696,35 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
gfn, role.word);
index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
bucket = &vcpu->kvm->mmu_page_hash[index];
- hlist_for_each_entry(page, node, bucket, hash_link)
- if (page->gfn == gfn && page->role.word == role.word) {
- mmu_page_add_parent_pte(vcpu, page, parent_pte);
+ hlist_for_each_entry(sp, node, bucket, hash_link)
+ if (sp->gfn == gfn && sp->role.word == role.word) {
+ mmu_page_add_parent_pte(vcpu, sp, parent_pte);
pgprintk("%s: found\n", __FUNCTION__);
- return page;
+ return sp;
}
- page = kvm_mmu_alloc_page(vcpu, parent_pte);
- if (!page)
- return page;
+ sp = kvm_mmu_alloc_page(vcpu, parent_pte);
+ if (!sp)
+ return sp;
pgprintk("%s: adding gfn %lx role %x\n", __FUNCTION__, gfn, role.word);
- page->gfn = gfn;
- page->role = role;
- hlist_add_head(&page->hash_link, bucket);
- vcpu->mmu.prefetch_page(vcpu, page);
+ sp->gfn = gfn;
+ sp->role = role;
+ hlist_add_head(&sp->hash_link, bucket);
+ vcpu->mmu.prefetch_page(vcpu, sp);
if (!metaphysical)
rmap_write_protect(vcpu->kvm, gfn);
- return page;
+ return sp;
}
static void kvm_mmu_page_unlink_children(struct kvm *kvm,
- struct kvm_mmu_page *page)
+ struct kvm_mmu_page *sp)
{
unsigned i;
u64 *pt;
u64 ent;
- pt = page->spt;
+ pt = sp->spt;
- if (page->role.level == PT_PAGE_TABLE_LEVEL) {
+ if (sp->role.level == PT_PAGE_TABLE_LEVEL) {
for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
if (is_shadow_present_pte(pt[i]))
rmap_remove(kvm, &pt[i]);
@@ -749,10 +746,9 @@ static void kvm_mmu_page_unlink_children(struct kvm *kvm,
kvm_flush_remote_tlbs(kvm);
}
-static void kvm_mmu_put_page(struct kvm_mmu_page *page,
- u64 *parent_pte)
+static void kvm_mmu_put_page(struct kvm_mmu_page *sp, u64 *parent_pte)
{
- mmu_page_remove_parent_pte(page, parent_pte);
+ mmu_page_remove_parent_pte(sp, parent_pte);
}
static void kvm_mmu_reset_last_pte_updated(struct kvm *kvm)
@@ -764,32 +760,31 @@ static void kvm_mmu_reset_last_pte_updated(struct kvm *kvm)
kvm->vcpus[i]->last_pte_updated = NULL;
}
-static void kvm_mmu_zap_page(struct kvm *kvm,
- struct kvm_mmu_page *page)
+static void kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
u64 *parent_pte;
++kvm->stat.mmu_shadow_zapped;
- while (page->multimapped || page->parent_pte) {
- if (!page->multimapped)
- parent_pte = page->parent_pte;
+ while (sp->multimapped || sp->parent_pte) {
+ if (!sp->multimapped)
+ parent_pte = sp->parent_pte;
else {
struct kvm_pte_chain *chain;
- chain = container_of(page->parent_ptes.first,
+ chain = container_of(sp->parent_ptes.first,
struct kvm_pte_chain, link);
parent_pte = chain->parent_ptes[0];
}
BUG_ON(!parent_pte);
- kvm_mmu_put_page(page, parent_pte);
+ kvm_mmu_put_page(sp, parent_pte);
set_shadow_pte(parent_pte, shadow_trap_nonpresent_pte);
}
- kvm_mmu_page_unlink_children(kvm, page);
- if (!page->root_count) {
- hlist_del(&page->hash_link);
- kvm_mmu_free_page(kvm, page);
+ kvm_mmu_page_unlink_children(kvm, sp);
+ if (!sp->root_count) {
+ hlist_del(&sp->hash_link);
+ kvm_mmu_free_page(kvm, sp);
} else
- list_move(&page->link, &kvm->active_mmu_pages);
+ list_move(&sp->link, &kvm->active_mmu_pages);
kvm_mmu_reset_last_pte_updated(kvm);
}
@@ -831,7 +826,7 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn)
{
unsigned index;
struct hlist_head *bucket;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
struct hlist_node *node, *n;
int r;
@@ -839,11 +834,11 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn)
r = 0;
index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
bucket = &kvm->mmu_page_hash[index];
- hlist_for_each_entry_safe(page, node, n, bucket, hash_link)
- if (page->gfn == gfn && !page->role.metaphysical) {
+ hlist_for_each_entry_safe(sp, node, n, bucket, hash_link)
+ if (sp->gfn == gfn && !sp->role.metaphysical) {
pgprintk("%s: gfn %lx role %x\n", __FUNCTION__, gfn,
- page->role.word);
- kvm_mmu_zap_page(kvm, page);
+ sp->role.word);
+ kvm_mmu_zap_page(kvm, sp);
r = 1;
}
return r;
@@ -851,21 +846,20 @@ static int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn)
static void mmu_unshadow(struct kvm *kvm, gfn_t gfn)
{
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
- while ((page = kvm_mmu_lookup_page(kvm, gfn)) != NULL) {
- pgprintk("%s: zap %lx %x\n",
- __FUNCTION__, gfn, page->role.word);
- kvm_mmu_zap_page(kvm, page);
+ while ((sp = kvm_mmu_lookup_page(kvm, gfn)) != NULL) {
+ pgprintk("%s: zap %lx %x\n", __FUNCTION__, gfn, sp->role.word);
+ kvm_mmu_zap_page(kvm, sp);
}
}
static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
{
int slot = memslot_id(kvm, gfn_to_memslot(kvm, gfn));
- struct kvm_mmu_page *page_head = page_header(__pa(pte));
+ struct kvm_mmu_page *sp = page_header(__pa(pte));
- __set_bit(slot, &page_head->slot_bitmap);
+ __set_bit(slot, &sp->slot_bitmap);
}
struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
@@ -951,7 +945,7 @@ static void nonpaging_prefetch_page(struct kvm_vcpu *vcpu,
static void mmu_free_roots(struct kvm_vcpu *vcpu)
{
int i;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
if (!VALID_PAGE(vcpu->mmu.root_hpa))
return;
@@ -959,8 +953,8 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
if (vcpu->mmu.shadow_root_level == PT64_ROOT_LEVEL) {
hpa_t root = vcpu->mmu.root_hpa;
- page = page_header(root);
- --page->root_count;
+ sp = page_header(root);
+ --sp->root_count;
vcpu->mmu.root_hpa = INVALID_PAGE;
return;
}
@@ -970,8 +964,8 @@ static void mmu_free_roots(struct kvm_vcpu *vcpu)
if (root) {
root &= PT64_BASE_ADDR_MASK;
- page = page_header(root);
- --page->root_count;
+ sp = page_header(root);
+ --sp->root_count;
}
vcpu->mmu.pae_root[i] = INVALID_PAGE;
}
@@ -982,7 +976,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
{
int i;
gfn_t root_gfn;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
root_gfn = vcpu->cr3 >> PAGE_SHIFT;
@@ -991,10 +985,10 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
hpa_t root = vcpu->mmu.root_hpa;
ASSERT(!VALID_PAGE(root));
- page = kvm_mmu_get_page(vcpu, root_gfn, 0,
- PT64_ROOT_LEVEL, 0, 0, NULL);
- root = __pa(page->spt);
- ++page->root_count;
+ sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
+ PT64_ROOT_LEVEL, 0, 0, NULL);
+ root = __pa(sp->spt);
+ ++sp->root_count;
vcpu->mmu.root_hpa = root;
return;
}
@@ -1011,11 +1005,11 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
root_gfn = vcpu->pdptrs[i] >> PAGE_SHIFT;
} else if (vcpu->mmu.root_level == 0)
root_gfn = 0;
- page = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
- PT32_ROOT_LEVEL, !is_paging(vcpu),
- 0, NULL);
- root = __pa(page->spt);
- ++page->root_count;
+ sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
+ PT32_ROOT_LEVEL, !is_paging(vcpu),
+ 0, NULL);
+ root = __pa(sp->spt);
+ ++sp->root_count;
vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK;
}
vcpu->mmu.root_hpa = __pa(vcpu->mmu.pae_root);
@@ -1196,7 +1190,7 @@ void kvm_mmu_unload(struct kvm_vcpu *vcpu)
}
static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *page,
+ struct kvm_mmu_page *sp,
u64 *spte)
{
u64 pte;
@@ -1204,7 +1198,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
pte = *spte;
if (is_shadow_present_pte(pte)) {
- if (page->role.level == PT_PAGE_TABLE_LEVEL)
+ if (sp->role.level == PT_PAGE_TABLE_LEVEL)
rmap_remove(vcpu->kvm, spte);
else {
child = page_header(pte & PT64_BASE_ADDR_MASK);
@@ -1215,23 +1209,21 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
}
static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
- struct kvm_mmu_page *page,
+ struct kvm_mmu_page *sp,
u64 *spte,
const void *new, int bytes,
int offset_in_pte)
{
- if (page->role.level != PT_PAGE_TABLE_LEVEL) {
+ if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
++vcpu->kvm->stat.mmu_pde_zapped;
return;
}
++vcpu->kvm->stat.mmu_pte_updated;
- if (page->role.glevels == PT32_ROOT_LEVEL)
- paging32_update_pte(vcpu, page, spte, new, bytes,
- offset_in_pte);
+ if (sp->role.glevels == PT32_ROOT_LEVEL)
+ paging32_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte);
else
- paging64_update_pte(vcpu, page, spte, new, bytes,
- offset_in_pte);
+ paging64_update_pte(vcpu, sp, spte, new, bytes, offset_in_pte);
}
static bool need_remote_flush(u64 old, u64 new)
@@ -1266,7 +1258,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
const u8 *new, int bytes)
{
gfn_t gfn = gpa >> PAGE_SHIFT;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
struct hlist_node *node, *n;
struct hlist_head *bucket;
unsigned index;
@@ -1296,10 +1288,10 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
}
index = kvm_page_table_hashfn(gfn) % KVM_NUM_MMU_PAGES;
bucket = &vcpu->kvm->mmu_page_hash[index];
- hlist_for_each_entry_safe(page, node, n, bucket, hash_link) {
- if (page->gfn != gfn || page->role.metaphysical)
+ hlist_for_each_entry_safe(sp, node, n, bucket, hash_link) {
+ if (sp->gfn != gfn || sp->role.metaphysical)
continue;
- pte_size = page->role.glevels == PT32_ROOT_LEVEL ? 4 : 8;
+ pte_size = sp->role.glevels == PT32_ROOT_LEVEL ? 4 : 8;
misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1);
misaligned |= bytes < 4;
if (misaligned || flooded) {
@@ -1314,15 +1306,15 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
* page.
*/
pgprintk("misaligned: gpa %llx bytes %d role %x\n",
- gpa, bytes, page->role.word);
- kvm_mmu_zap_page(vcpu->kvm, page);
+ gpa, bytes, sp->role.word);
+ kvm_mmu_zap_page(vcpu->kvm, sp);
++vcpu->kvm->stat.mmu_flooded;
continue;
}
page_offset = offset;
- level = page->role.level;
+ level = sp->role.level;
npte = 1;
- if (page->role.glevels == PT32_ROOT_LEVEL) {
+ if (sp->role.glevels == PT32_ROOT_LEVEL) {
page_offset <<= 1; /* 32->64 */
/*
* A 32-bit pde maps 4MB while the shadow pdes map
@@ -1336,14 +1328,14 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
}
quadrant = page_offset >> PAGE_SHIFT;
page_offset &= ~PAGE_MASK;
- if (quadrant != page->role.quadrant)
+ if (quadrant != sp->role.quadrant)
continue;
}
- spte = &page->spt[page_offset / sizeof(*spte)];
+ spte = &sp->spt[page_offset / sizeof(*spte)];
while (npte--) {
entry = *spte;
- mmu_pte_write_zap_pte(vcpu, page, spte);
- mmu_pte_write_new_pte(vcpu, page, spte, new, bytes,
+ mmu_pte_write_zap_pte(vcpu, sp, spte);
+ mmu_pte_write_new_pte(vcpu, sp, spte, new, bytes,
page_offset & (pte_size - 1));
mmu_pte_write_flush_tlb(vcpu, entry, *spte);
++spte;
@@ -1362,11 +1354,11 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu)
{
while (vcpu->kvm->n_free_mmu_pages < KVM_REFILL_PAGES) {
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
- page = container_of(vcpu->kvm->active_mmu_pages.prev,
- struct kvm_mmu_page, link);
- kvm_mmu_zap_page(vcpu->kvm, page);
+ sp = container_of(vcpu->kvm->active_mmu_pages.prev,
+ struct kvm_mmu_page, link);
+ kvm_mmu_zap_page(vcpu->kvm, sp);
++vcpu->kvm->stat.mmu_recycled;
}
}
@@ -1413,12 +1405,12 @@ EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
static void free_mmu_pages(struct kvm_vcpu *vcpu)
{
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
while (!list_empty(&vcpu->kvm->active_mmu_pages)) {
- page = container_of(vcpu->kvm->active_mmu_pages.next,
- struct kvm_mmu_page, link);
- kvm_mmu_zap_page(vcpu->kvm, page);
+ sp = container_of(vcpu->kvm->active_mmu_pages.next,
+ struct kvm_mmu_page, link);
+ kvm_mmu_zap_page(vcpu->kvm, sp);
}
free_page((unsigned long)vcpu->mmu.pae_root);
}
@@ -1480,16 +1472,16 @@ void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
{
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
- list_for_each_entry(page, &kvm->active_mmu_pages, link) {
+ list_for_each_entry(sp, &kvm->active_mmu_pages, link) {
int i;
u64 *pt;
- if (!test_bit(slot, &page->slot_bitmap))
+ if (!test_bit(slot, &sp->slot_bitmap))
continue;
- pt = page->spt;
+ pt = sp->spt;
for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
/* avoid RMW */
if (pt[i] & PT_WRITABLE_MASK)
@@ -1499,10 +1491,10 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
void kvm_mmu_zap_all(struct kvm *kvm)
{
- struct kvm_mmu_page *page, *node;
+ struct kvm_mmu_page *sp, *node;
- list_for_each_entry_safe(page, node, &kvm->active_mmu_pages, link)
- kvm_mmu_zap_page(kvm, page);
+ list_for_each_entry_safe(sp, node, &kvm->active_mmu_pages, link)
+ kvm_mmu_zap_page(kvm, sp);
kvm_flush_remote_tlbs(kvm);
}
@@ -1668,13 +1660,13 @@ static int count_rmaps(struct kvm_vcpu *vcpu)
static int count_writable_mappings(struct kvm_vcpu *vcpu)
{
int nmaps = 0;
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
int i;
- list_for_each_entry(page, &vcpu->kvm->active_mmu_pages, link) {
- u64 *pt = page->spt;
+ list_for_each_entry(sp, &vcpu->kvm->active_mmu_pages, link) {
+ u64 *pt = sp->spt;
- if (page->role.level != PT_PAGE_TABLE_LEVEL)
+ if (sp->role.level != PT_PAGE_TABLE_LEVEL)
continue;
for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
@@ -1702,23 +1694,23 @@ static void audit_rmap(struct kvm_vcpu *vcpu)
static void audit_write_protection(struct kvm_vcpu *vcpu)
{
- struct kvm_mmu_page *page;
+ struct kvm_mmu_page *sp;
struct kvm_memory_slot *slot;
unsigned long *rmapp;
gfn_t gfn;
- list_for_each_entry(page, &vcpu->kvm->active_mmu_pages, link) {
- if (page->role.metaphysical)
+ list_for_each_entry(sp, &vcpu->kvm->active_mmu_pages, link) {
+ if (sp->role.metaphysical)
continue;
- slot = gfn_to_memslot(vcpu->kvm, page->gfn);
- gfn = unalias_gfn(vcpu->kvm, page->gfn);
+ slot = gfn_to_memslot(vcpu->kvm, sp->gfn);
+ gfn = unalias_gfn(vcpu->kvm, sp->gfn);
rmapp = &slot->rmap[gfn - slot->base_gfn];
if (*rmapp)
printk(KERN_ERR "%s: (%s) shadow page has writable"
" mappings: gfn %lx role %x\n",
- __FUNCTION__, audit_msg, page->gfn,
- page->role.word);
+ __FUNCTION__, audit_msg, sp->gfn,
+ sp->role.word);
}
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 04/54] KVM: MMU: Rename 'release_page'
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2008-01-01 15:35 ` [PATCH 02/54] KVM: Remove gpa_to_hpa() Avi Kivity
2008-01-01 15:35 ` [PATCH 03/54] KVM: MMU: Rename variables of type 'struct kvm_mmu_page *' Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 05/54] KVM: Disallow fork() and similar games when using a VM Avi Kivity
` (49 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Rename the awkwardly named variable.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 86896da..0cb6580 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -430,18 +430,18 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
struct kvm_rmap_desc *desc;
struct kvm_rmap_desc *prev_desc;
struct kvm_mmu_page *sp;
- struct page *release_page;
+ struct page *page;
unsigned long *rmapp;
int i;
if (!is_rmap_pte(*spte))
return;
sp = page_header(__pa(spte));
- release_page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
+ page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
if (is_writeble_pte(*spte))
- kvm_release_page_dirty(release_page);
+ kvm_release_page_dirty(page);
else
- kvm_release_page_clean(release_page);
+ kvm_release_page_clean(page);
rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt]);
if (!*rmapp) {
printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte);
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 05/54] KVM: Disallow fork() and similar games when using a VM
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (2 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 04/54] KVM: MMU: Rename 'release_page' Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 06/54] KVM: Enhance guest cpuid management Avi Kivity
` (48 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
We don't want the meaning of guest userspace changing under our feet.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm.h | 1 +
drivers/kvm/kvm_main.c | 9 +++++++++
kernel/fork.c | 1 +
3 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 1fd8158..be18620 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -305,6 +305,7 @@ struct kvm_vm_stat {
struct kvm {
struct mutex lock; /* protects everything except vcpus */
+ struct mm_struct *mm; /* userspace tied to this vm */
int naliases;
struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS];
int nmemslots;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 411b2bd..a9e1c77 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -165,6 +165,8 @@ static struct kvm *kvm_create_vm(void)
if (IS_ERR(kvm))
goto out;
+ kvm->mm = current->mm;
+ atomic_inc(&kvm->mm->mm_count);
kvm_io_bus_init(&kvm->pio_bus);
mutex_init(&kvm->lock);
kvm_io_bus_init(&kvm->mmio_bus);
@@ -202,12 +204,15 @@ void kvm_free_physmem(struct kvm *kvm)
static void kvm_destroy_vm(struct kvm *kvm)
{
+ struct mm_struct *mm = kvm->mm;
+
spin_lock(&kvm_lock);
list_del(&kvm->vm_list);
spin_unlock(&kvm_lock);
kvm_io_bus_destroy(&kvm->pio_bus);
kvm_io_bus_destroy(&kvm->mmio_bus);
kvm_arch_destroy_vm(kvm);
+ mmdrop(mm);
}
static int kvm_vm_release(struct inode *inode, struct file *filp)
@@ -818,6 +823,8 @@ static long kvm_vcpu_ioctl(struct file *filp,
void __user *argp = (void __user *)arg;
int r;
+ if (vcpu->kvm->mm != current->mm)
+ return -EIO;
switch (ioctl) {
case KVM_RUN:
r = -EINVAL;
@@ -976,6 +983,8 @@ static long kvm_vm_ioctl(struct file *filp,
void __user *argp = (void __user *)arg;
int r;
+ if (kvm->mm != current->mm)
+ return -EIO;
switch (ioctl) {
case KVM_CREATE_VCPU:
r = kvm_vm_ioctl_create_vcpu(kvm, arg);
diff --git a/kernel/fork.c b/kernel/fork.c
index 8dd8ff2..591c8df 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -392,6 +392,7 @@ void fastcall __mmdrop(struct mm_struct *mm)
destroy_context(mm);
free_mm(mm);
}
+EXPORT_SYMBOL_GPL(__mmdrop);
/*
* Decrement the use count and release all resources for an mm.
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 06/54] KVM: Enhance guest cpuid management
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (3 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 05/54] KVM: Disallow fork() and similar games when using a VM Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 07/54] KVM: VMX: Remove the secondary execute control dependency on irqchip Avi Kivity
` (47 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Dan Kenigsberg <danken-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
The current cpuid management suffers from several problems, which inhibit
passing through the host feature set to the guest:
- No way to tell which features the host supports
While some features can be supported with no changes to kvm, others
need explicit support. That means kvm needs to vet the feature set
before it is passed to the guest.
- No support for indexed or stateful cpuid entries
Some cpuid entries depend on ecx as well as on eax, or on internal
state in the processor (running cpuid multiple times with the same
input returns different output). The current cpuid machinery only
supports keying on eax.
- No support for save/restore/migrate
The internal state above needs to be exposed to userspace so it can
be saved or migrated.
This patch adds extended cpuid support by means of three new ioctls:
- KVM_GET_SUPPORTED_CPUID: get all cpuid entries the host (and kvm)
supports
- KVM_SET_CPUID2: sets the vcpu's cpuid table
- KVM_GET_CPUID2: gets the vcpu's cpuid table, including hidden state
[avi: fix original KVM_SET_CPUID not removing nx on non-nx hosts as it did
before]
Signed-off-by: Dan Kenigsberg <danken-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86.c | 331 +++++++++++++++++++++++++++++++++++++++++++++++--
drivers/kvm/x86.h | 2 +-
include/asm-x86/kvm.h | 21 +++
include/linux/kvm.h | 4 +
4 files changed, 348 insertions(+), 10 deletions(-)
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 15e1203..7237cb2 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -646,6 +646,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_MMU_SHADOW_CACHE_CONTROL:
case KVM_CAP_USER_MEMORY:
case KVM_CAP_SET_TSS_ADDR:
+ case KVM_CAP_EXT_CPUID:
r = 1;
break;
default:
@@ -708,13 +709,19 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
kvm_put_guest_fpu(vcpu);
}
-static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
+static int is_efer_nx(void)
{
u64 efer;
- int i;
- struct kvm_cpuid_entry *e, *entry;
rdmsrl(MSR_EFER, efer);
+ return efer & EFER_NX;
+}
+
+static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
+{
+ int i;
+ struct kvm_cpuid_entry2 *e, *entry;
+
entry = NULL;
for (i = 0; i < vcpu->cpuid_nent; ++i) {
e = &vcpu->cpuid_entries[i];
@@ -723,16 +730,57 @@ static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
break;
}
}
- if (entry && (entry->edx & (1 << 20)) && !(efer & EFER_NX)) {
+ if (entry && (entry->edx & (1 << 20)) && !is_efer_nx()) {
entry->edx &= ~(1 << 20);
printk(KERN_INFO "kvm: guest NX capability removed\n");
}
}
+/* when an old userspace process fills a new kernel module */
static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
struct kvm_cpuid *cpuid,
struct kvm_cpuid_entry __user *entries)
{
+ int r, i;
+ struct kvm_cpuid_entry *cpuid_entries;
+
+ r = -E2BIG;
+ if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
+ goto out;
+ r = -ENOMEM;
+ cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent);
+ if (!cpuid_entries)
+ goto out;
+ r = -EFAULT;
+ if (copy_from_user(cpuid_entries, entries,
+ cpuid->nent * sizeof(struct kvm_cpuid_entry)))
+ goto out_free;
+ for (i = 0; i < cpuid->nent; i++) {
+ vcpu->cpuid_entries[i].function = cpuid_entries[i].function;
+ vcpu->cpuid_entries[i].eax = cpuid_entries[i].eax;
+ vcpu->cpuid_entries[i].ebx = cpuid_entries[i].ebx;
+ vcpu->cpuid_entries[i].ecx = cpuid_entries[i].ecx;
+ vcpu->cpuid_entries[i].edx = cpuid_entries[i].edx;
+ vcpu->cpuid_entries[i].index = 0;
+ vcpu->cpuid_entries[i].flags = 0;
+ vcpu->cpuid_entries[i].padding[0] = 0;
+ vcpu->cpuid_entries[i].padding[1] = 0;
+ vcpu->cpuid_entries[i].padding[2] = 0;
+ }
+ vcpu->cpuid_nent = cpuid->nent;
+ cpuid_fix_nx_cap(vcpu);
+ r = 0;
+
+out_free:
+ vfree(cpuid_entries);
+out:
+ return r;
+}
+
+static int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
+ struct kvm_cpuid2 *cpuid,
+ struct kvm_cpuid_entry2 __user *entries)
+{
int r;
r = -E2BIG;
@@ -740,16 +788,198 @@ static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
goto out;
r = -EFAULT;
if (copy_from_user(&vcpu->cpuid_entries, entries,
- cpuid->nent * sizeof(struct kvm_cpuid_entry)))
+ cpuid->nent * sizeof(struct kvm_cpuid_entry2)))
goto out;
vcpu->cpuid_nent = cpuid->nent;
- cpuid_fix_nx_cap(vcpu);
return 0;
out:
return r;
}
+static int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
+ struct kvm_cpuid2 *cpuid,
+ struct kvm_cpuid_entry2 __user *entries)
+{
+ int r;
+
+ r = -E2BIG;
+ if (cpuid->nent < vcpu->cpuid_nent)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user(entries, &vcpu->cpuid_entries,
+ vcpu->cpuid_nent * sizeof(struct kvm_cpuid_entry2)))
+ goto out;
+ return 0;
+
+out:
+ cpuid->nent = vcpu->cpuid_nent;
+ return r;
+}
+
+static inline u32 bit(int bitno)
+{
+ return 1 << (bitno & 31);
+}
+
+static void do_cpuid_1_ent(struct kvm_cpuid_entry2 *entry, u32 function,
+ u32 index)
+{
+ entry->function = function;
+ entry->index = index;
+ cpuid_count(entry->function, entry->index,
+ &entry->eax, &entry->ebx, &entry->ecx, &entry->edx);
+ entry->flags = 0;
+}
+
+static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
+ u32 index, int *nent, int maxnent)
+{
+ const u32 kvm_supported_word0_x86_features = bit(X86_FEATURE_FPU) |
+ bit(X86_FEATURE_VME) | bit(X86_FEATURE_DE) |
+ bit(X86_FEATURE_PSE) | bit(X86_FEATURE_TSC) |
+ bit(X86_FEATURE_MSR) | bit(X86_FEATURE_PAE) |
+ bit(X86_FEATURE_CX8) | bit(X86_FEATURE_APIC) |
+ bit(X86_FEATURE_SEP) | bit(X86_FEATURE_PGE) |
+ bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PSE36) |
+ bit(X86_FEATURE_CLFLSH) | bit(X86_FEATURE_MMX) |
+ bit(X86_FEATURE_FXSR) | bit(X86_FEATURE_XMM) |
+ bit(X86_FEATURE_XMM2) | bit(X86_FEATURE_SELFSNOOP);
+ const u32 kvm_supported_word1_x86_features = bit(X86_FEATURE_FPU) |
+ bit(X86_FEATURE_VME) | bit(X86_FEATURE_DE) |
+ bit(X86_FEATURE_PSE) | bit(X86_FEATURE_TSC) |
+ bit(X86_FEATURE_MSR) | bit(X86_FEATURE_PAE) |
+ bit(X86_FEATURE_CX8) | bit(X86_FEATURE_APIC) |
+ bit(X86_FEATURE_PGE) |
+ bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PSE36) |
+ bit(X86_FEATURE_MMX) | bit(X86_FEATURE_FXSR) |
+ bit(X86_FEATURE_SYSCALL) |
+ (bit(X86_FEATURE_NX) && is_efer_nx()) |
+#ifdef CONFIG_X86_64
+ bit(X86_FEATURE_LM) |
+#endif
+ bit(X86_FEATURE_MMXEXT) |
+ bit(X86_FEATURE_3DNOWEXT) |
+ bit(X86_FEATURE_3DNOW);
+ const u32 kvm_supported_word3_x86_features =
+ bit(X86_FEATURE_XMM3) | bit(X86_FEATURE_CX16);
+ const u32 kvm_supported_word6_x86_features =
+ bit(X86_FEATURE_LAHF_LM) | bit(X86_FEATURE_CMP_LEGACY);
+
+ /* all func 2 cpuid_count() should be called on the same cpu */
+ get_cpu();
+ do_cpuid_1_ent(entry, function, index);
+ ++*nent;
+
+ switch (function) {
+ case 0:
+ entry->eax = min(entry->eax, (u32)0xb);
+ break;
+ case 1:
+ entry->edx &= kvm_supported_word0_x86_features;
+ entry->ecx &= kvm_supported_word3_x86_features;
+ break;
+ /* function 2 entries are STATEFUL. That is, repeated cpuid commands
+ * may return different values. This forces us to get_cpu() before
+ * issuing the first command, and also to emulate this annoying behavior
+ * in kvm_emulate_cpuid() using KVM_CPUID_FLAG_STATE_READ_NEXT */
+ case 2: {
+ int t, times = entry->eax & 0xff;
+
+ entry->flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
+ for (t = 1; t < times && *nent < maxnent; ++t) {
+ do_cpuid_1_ent(&entry[t], function, 0);
+ entry[t].flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
+ ++*nent;
+ }
+ break;
+ }
+ /* function 4 and 0xb have additional index. */
+ case 4: {
+ int index, cache_type;
+
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ /* read more entries until cache_type is zero */
+ for (index = 1; *nent < maxnent; ++index) {
+ cache_type = entry[index - 1].eax & 0x1f;
+ if (!cache_type)
+ break;
+ do_cpuid_1_ent(&entry[index], function, index);
+ entry[index].flags |=
+ KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ ++*nent;
+ }
+ break;
+ }
+ case 0xb: {
+ int index, level_type;
+
+ entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ /* read more entries until level_type is zero */
+ for (index = 1; *nent < maxnent; ++index) {
+ level_type = entry[index - 1].ecx & 0xff;
+ if (!level_type)
+ break;
+ do_cpuid_1_ent(&entry[index], function, index);
+ entry[index].flags |=
+ KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
+ ++*nent;
+ }
+ break;
+ }
+ case 0x80000000:
+ entry->eax = min(entry->eax, 0x8000001a);
+ break;
+ case 0x80000001:
+ entry->edx &= kvm_supported_word1_x86_features;
+ entry->ecx &= kvm_supported_word6_x86_features;
+ break;
+ }
+ put_cpu();
+}
+
+static int kvm_vm_ioctl_get_supported_cpuid(struct kvm *kvm,
+ struct kvm_cpuid2 *cpuid,
+ struct kvm_cpuid_entry2 __user *entries)
+{
+ struct kvm_cpuid_entry2 *cpuid_entries;
+ int limit, nent = 0, r = -E2BIG;
+ u32 func;
+
+ if (cpuid->nent < 1)
+ goto out;
+ r = -ENOMEM;
+ cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent);
+ if (!cpuid_entries)
+ goto out;
+
+ do_cpuid_ent(&cpuid_entries[0], 0, 0, &nent, cpuid->nent);
+ limit = cpuid_entries[0].eax;
+ for (func = 1; func <= limit && nent < cpuid->nent; ++func)
+ do_cpuid_ent(&cpuid_entries[nent], func, 0,
+ &nent, cpuid->nent);
+ r = -E2BIG;
+ if (nent >= cpuid->nent)
+ goto out_free;
+
+ do_cpuid_ent(&cpuid_entries[nent], 0x80000000, 0, &nent, cpuid->nent);
+ limit = cpuid_entries[nent - 1].eax;
+ for (func = 0x80000001; func <= limit && nent < cpuid->nent; ++func)
+ do_cpuid_ent(&cpuid_entries[nent], func, 0,
+ &nent, cpuid->nent);
+ r = -EFAULT;
+ if (copy_to_user(entries, cpuid_entries,
+ nent * sizeof(struct kvm_cpuid_entry2)))
+ goto out_free;
+ cpuid->nent = nent;
+ r = 0;
+
+out_free:
+ vfree(cpuid_entries);
+out:
+ return r;
+}
+
static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
struct kvm_lapic_state *s)
{
@@ -816,6 +1046,36 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
goto out;
break;
}
+ case KVM_SET_CPUID2: {
+ struct kvm_cpuid2 __user *cpuid_arg = argp;
+ struct kvm_cpuid2 cpuid;
+
+ r = -EFAULT;
+ if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
+ goto out;
+ r = kvm_vcpu_ioctl_set_cpuid2(vcpu, &cpuid,
+ cpuid_arg->entries);
+ if (r)
+ goto out;
+ break;
+ }
+ case KVM_GET_CPUID2: {
+ struct kvm_cpuid2 __user *cpuid_arg = argp;
+ struct kvm_cpuid2 cpuid;
+
+ r = -EFAULT;
+ if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
+ goto out;
+ r = kvm_vcpu_ioctl_get_cpuid2(vcpu, &cpuid,
+ cpuid_arg->entries);
+ if (r)
+ goto out;
+ r = -EFAULT;
+ if (copy_to_user(cpuid_arg, &cpuid, sizeof cpuid))
+ goto out;
+ r = 0;
+ break;
+ }
case KVM_GET_MSRS:
r = msr_io(vcpu, argp, kvm_get_msr, 1);
break;
@@ -1111,6 +1371,24 @@ long kvm_arch_vm_ioctl(struct file *filp,
r = 0;
break;
}
+ case KVM_GET_SUPPORTED_CPUID: {
+ struct kvm_cpuid2 __user *cpuid_arg = argp;
+ struct kvm_cpuid2 cpuid;
+
+ r = -EFAULT;
+ if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
+ goto out;
+ r = kvm_vm_ioctl_get_supported_cpuid(kvm, &cpuid,
+ cpuid_arg->entries);
+ if (r)
+ goto out;
+
+ r = -EFAULT;
+ if (copy_to_user(cpuid_arg, &cpuid, sizeof cpuid))
+ goto out;
+ r = 0;
+ break;
+ }
default:
;
}
@@ -1908,14 +2186,47 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
}
}
+static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
+{
+ struct kvm_cpuid_entry2 *e = &vcpu->cpuid_entries[i];
+ int j, nent = vcpu->cpuid_nent;
+
+ e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
+ /* when no next entry is found, the current entry[i] is reselected */
+ for (j = i + 1; j == i; j = (j + 1) % nent) {
+ struct kvm_cpuid_entry2 *ej = &vcpu->cpuid_entries[j];
+ if (ej->function == e->function) {
+ ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
+ return j;
+ }
+ }
+ return 0; /* silence gcc, even though control never reaches here */
+}
+
+/* find an entry with matching function, matching index (if needed), and that
+ * should be read next (if it's stateful) */
+static int is_matching_cpuid_entry(struct kvm_cpuid_entry2 *e,
+ u32 function, u32 index)
+{
+ if (e->function != function)
+ return 0;
+ if ((e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) && e->index != index)
+ return 0;
+ if ((e->flags & KVM_CPUID_FLAG_STATEFUL_FUNC) &&
+ !(e->flags & KVM_CPUID_FLAG_STATE_READ_NEXT))
+ return 0;
+ return 1;
+}
+
void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
{
int i;
- u32 function;
- struct kvm_cpuid_entry *e, *best;
+ u32 function, index;
+ struct kvm_cpuid_entry2 *e, *best;
kvm_x86_ops->cache_regs(vcpu);
function = vcpu->regs[VCPU_REGS_RAX];
+ index = vcpu->regs[VCPU_REGS_RCX];
vcpu->regs[VCPU_REGS_RAX] = 0;
vcpu->regs[VCPU_REGS_RBX] = 0;
vcpu->regs[VCPU_REGS_RCX] = 0;
@@ -1923,7 +2234,9 @@ void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
best = NULL;
for (i = 0; i < vcpu->cpuid_nent; ++i) {
e = &vcpu->cpuid_entries[i];
- if (e->function == function) {
+ if (is_matching_cpuid_entry(e, function, index)) {
+ if (e->flags & KVM_CPUID_FLAG_STATEFUL_FUNC)
+ move_to_next_stateful_cpuid_entry(vcpu, i);
best = e;
break;
}
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index b1528c9..78ab1e1 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -149,7 +149,7 @@ struct kvm_vcpu {
int halt_request; /* real mode on Intel only */
int cpuid_nent;
- struct kvm_cpuid_entry cpuid_entries[KVM_MAX_CPUID_ENTRIES];
+ struct kvm_cpuid_entry2 cpuid_entries[KVM_MAX_CPUID_ENTRIES];
/* emulate context */
diff --git a/include/asm-x86/kvm.h b/include/asm-x86/kvm.h
index 4837d75..17afa81 100644
--- a/include/asm-x86/kvm.h
+++ b/include/asm-x86/kvm.h
@@ -151,5 +151,26 @@ struct kvm_cpuid {
struct kvm_cpuid_entry entries[0];
};
+struct kvm_cpuid_entry2 {
+ __u32 function;
+ __u32 index;
+ __u32 flags;
+ __u32 eax;
+ __u32 ebx;
+ __u32 ecx;
+ __u32 edx;
+ __u32 padding[3];
+};
+
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1
+#define KVM_CPUID_FLAG_STATEFUL_FUNC 2
+#define KVM_CPUID_FLAG_STATE_READ_NEXT 4
+
+/* for KVM_SET_CPUID2 */
+struct kvm_cpuid2 {
+ __u32 nent;
+ __u32 padding;
+ struct kvm_cpuid_entry2 entries[0];
+};
#endif
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index fd4f900..b751552 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -224,6 +224,7 @@ struct kvm_signal_mask {
#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2
#define KVM_CAP_USER_MEMORY 3
#define KVM_CAP_SET_TSS_ADDR 4
+#define KVM_CAP_EXT_CPUID 5
/*
* ioctls for VM fds
@@ -241,6 +242,7 @@ struct kvm_signal_mask {
#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
+#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x48, struct kvm_cpuid2)
/* Device model IOC */
#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
@@ -266,5 +268,7 @@ struct kvm_signal_mask {
#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu)
#define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state)
#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state)
+#define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2)
+#define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2)
#endif
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 07/54] KVM: VMX: Remove the secondary execute control dependency on irqchip
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (4 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 06/54] KVM: Enhance guest cpuid management Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 08/54] KVM: Portability: Move unalias_gfn to arch dependent file Avi Kivity
` (46 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Sheng Yang <sheng.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
The state of SECONDARY_VM_EXEC_CONTROL shouldn't depend on in-kernel IRQ chip,
this patch fix this.
Signed-off-by: Sheng Yang <sheng.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/vmx.c | 17 +++++++----------
1 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index fbe792d..8e43feb 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -193,11 +193,6 @@ static inline int cpu_has_secondary_exec_ctrls(void)
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS);
}
-static inline int vm_need_secondary_exec_ctrls(struct kvm *kvm)
-{
- return ((cpu_has_secondary_exec_ctrls()) && (irqchip_in_kernel(kvm)));
-}
-
static inline int cpu_has_vmx_virtualize_apic_accesses(void)
{
return (vmcs_config.cpu_based_2nd_exec_ctrl &
@@ -1524,13 +1519,15 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
CPU_BASED_CR8_LOAD_EXITING;
#endif
}
- if (!vm_need_secondary_exec_ctrls(vmx->vcpu.kvm))
- exec_control &= ~CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
- if (vm_need_secondary_exec_ctrls(vmx->vcpu.kvm))
- vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
- vmcs_config.cpu_based_2nd_exec_ctrl);
+ if (cpu_has_secondary_exec_ctrls()) {
+ exec_control = vmcs_config.cpu_based_2nd_exec_ctrl;
+ if (!vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
+ exec_control &=
+ ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
+ }
vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, !!bypass_guest_pf);
vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, !!bypass_guest_pf);
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 08/54] KVM: Portability: Move unalias_gfn to arch dependent file
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (5 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 07/54] KVM: VMX: Remove the secondary execute control dependency on irqchip Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 09/54] KVM: x86 emulator: Make a distinction between repeat prefixes F3 and F2 Avi Kivity
` (45 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Zhang Xiantao
From: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Non-x86 archs don't need this mechanism. Move it to arch, and
keep its interface in common.
Signed-off-by: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Acked-by: Carsten Otte <cotte-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm_main.c | 14 --------------
drivers/kvm/x86.c | 14 ++++++++++++++
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index a9e1c77..003a43c 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -408,20 +408,6 @@ int kvm_is_error_hva(unsigned long addr)
}
EXPORT_SYMBOL_GPL(kvm_is_error_hva);
-gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
-{
- int i;
- struct kvm_mem_alias *alias;
-
- for (i = 0; i < kvm->naliases; ++i) {
- alias = &kvm->aliases[i];
- if (gfn >= alias->base_gfn
- && gfn < alias->base_gfn + alias->npages)
- return alias->target_gfn + gfn - alias->base_gfn;
- }
- return gfn;
-}
-
static struct kvm_memory_slot *__gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
{
int i;
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 7237cb2..2be5936 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -1119,6 +1119,20 @@ static int kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
return kvm->n_alloc_mmu_pages;
}
+gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
+{
+ int i;
+ struct kvm_mem_alias *alias;
+
+ for (i = 0; i < kvm->naliases; ++i) {
+ alias = &kvm->aliases[i];
+ if (gfn >= alias->base_gfn
+ && gfn < alias->base_gfn + alias->npages)
+ return alias->target_gfn + gfn - alias->base_gfn;
+ }
+ return gfn;
+}
+
/*
* Set a new alias region. Aliases map a portion of physical memory into
* another portion. This is useful for memory windows, for example the PC
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 09/54] KVM: x86 emulator: Make a distinction between repeat prefixes F3 and F2
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (6 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 08/54] KVM: Portability: Move unalias_gfn to arch dependent file Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 10/54] KVM: x86 emulator: address size and operand size overrides are sticky Avi Kivity
` (44 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Guillaume Thouvenin
From: Guillaume Thouvenin <guillaume.thouvenin-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
cmps and scas instructions accept repeat prefixes F3 and F2. So in
order to emulate those prefixed instructions we need to be able to know
if prefixes are REP/REPE/REPZ or REPNE/REPNZ. Currently kvm doesn't make
this distinction. This patch introduces this distinction.
Signed-off-by: Guillaume Thouvenin <guillaume.thouvenin-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 4 +++-
drivers/kvm/x86_emulate.h | 4 ++++
2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 6e7f774..9f8d59a 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -824,8 +824,10 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
c->lock_prefix = 1;
break;
case 0xf2: /* REPNE/REPNZ */
+ c->rep_prefix = REPNE_PREFIX;
+ break;
case 0xf3: /* REP/REPE/REPZ */
- c->rep_prefix = 1;
+ c->rep_prefix = REPE_PREFIX;
break;
default:
goto done_prefixes;
diff --git a/drivers/kvm/x86_emulate.h b/drivers/kvm/x86_emulate.h
index 4603b2b..644086e 100644
--- a/drivers/kvm/x86_emulate.h
+++ b/drivers/kvm/x86_emulate.h
@@ -162,6 +162,10 @@ struct x86_emulate_ctxt {
struct decode_cache decode;
};
+/* Repeat String Operation Prefix */
+#define REPE_PREFIX 1
+#define REPNE_PREFIX 2
+
/* Execution mode, passed to the emulator. */
#define X86EMUL_MODE_REAL 0 /* Real mode. */
#define X86EMUL_MODE_PROT16 2 /* 16-bit protected mode. */
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 10/54] KVM: x86 emulator: address size and operand size overrides are sticky
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (7 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 09/54] KVM: x86 emulator: Make a distinction between repeat prefixes F3 and F2 Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 11/54] KVM: Remove misleading check for mmio during event injection Avi Kivity
` (43 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Current implementation is to toggle, which is incorrect. Patch ported from
corresponding Xen code.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 19 ++++++++++++-------
1 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 9f8d59a..3be506a 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -758,6 +758,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
struct decode_cache *c = &ctxt->decode;
int rc = 0;
int mode = ctxt->mode;
+ int def_op_bytes, def_ad_bytes;
/* Shadow copy of register state. Committed on successful emulation. */
@@ -768,34 +769,38 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
switch (mode) {
case X86EMUL_MODE_REAL:
case X86EMUL_MODE_PROT16:
- c->op_bytes = c->ad_bytes = 2;
+ def_op_bytes = def_ad_bytes = 2;
break;
case X86EMUL_MODE_PROT32:
- c->op_bytes = c->ad_bytes = 4;
+ def_op_bytes = def_ad_bytes = 4;
break;
#ifdef CONFIG_X86_64
case X86EMUL_MODE_PROT64:
- c->op_bytes = 4;
- c->ad_bytes = 8;
+ def_op_bytes = 4;
+ def_ad_bytes = 8;
break;
#endif
default:
return -1;
}
+ c->op_bytes = def_op_bytes;
+ c->ad_bytes = def_ad_bytes;
+
/* Legacy prefixes. */
for (;;) {
switch (c->b = insn_fetch(u8, 1, c->eip)) {
case 0x66: /* operand-size override */
- c->op_bytes ^= 6; /* switch between 2/4 bytes */
+ /* switch between 2/4 bytes */
+ c->op_bytes = def_op_bytes ^ 6;
break;
case 0x67: /* address-size override */
if (mode == X86EMUL_MODE_PROT64)
/* switch between 4/8 bytes */
- c->ad_bytes ^= 12;
+ c->ad_bytes = def_ad_bytes ^ 12;
else
/* switch between 2/4 bytes */
- c->ad_bytes ^= 6;
+ c->ad_bytes = def_ad_bytes ^ 6;
break;
case 0x2e: /* CS override */
c->override_base = &ctxt->cs_base;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 11/54] KVM: Remove misleading check for mmio during event injection
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (8 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 10/54] KVM: x86 emulator: address size and operand size overrides are sticky Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 12/54] KVM: MMU: mark pages that were inserted to the shadow pages table as accessed Avi Kivity
` (42 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
mmio was already handled in kvm_arch_vcpu_ioctl_run(), so no need to check
again.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 2be5936..5e58156 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -2344,7 +2344,7 @@ again:
if (irqchip_in_kernel(vcpu->kvm))
kvm_x86_ops->inject_pending_irq(vcpu);
- else if (!vcpu->mmio_read_completed)
+ else
kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
vcpu->guest_mode = 1;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 12/54] KVM: MMU: mark pages that were inserted to the shadow pages table as accessed
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (9 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 11/54] KVM: Remove misleading check for mmio during event injection Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 13/54] KVM: x86 emulator: Rename 'cr2' to 'memop' Avi Kivity
` (41 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Izik Eidus <izike-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
Mark guest pages as accessed when removed from the shadow page tables for
better lru processing.
Signed-off-by: Izik Eidus <izike-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 0cb6580..9b9d1b6 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -26,6 +26,7 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/module.h>
+#include <linux/swap.h>
#include <asm/page.h>
#include <asm/cmpxchg.h>
@@ -438,6 +439,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte)
return;
sp = page_header(__pa(spte));
page = pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT);
+ mark_page_accessed(page);
if (is_writeble_pte(*spte))
kvm_release_page_dirty(page);
else
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 13/54] KVM: x86 emulator: Rename 'cr2' to 'memop'
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (10 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 12/54] KVM: MMU: mark pages that were inserted to the shadow pages table as accessed Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 14/54] KVM: x86 emulator: cmps instruction Avi Kivity
` (40 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Sheng Yang <sheng.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Previous patches have removed the dependency on cr2; we can now stop passing
it to the emulator and rename uses to 'memop'.
Signed-off-by: Sheng Yang <sheng.yang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86.c | 1 -
drivers/kvm/x86_emulate.c | 18 +++++++++---------
drivers/kvm/x86_emulate.h | 1 -
3 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 5e58156..12f1d6f 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -1702,7 +1702,6 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
vcpu->emulate_ctxt.vcpu = vcpu;
vcpu->emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
- vcpu->emulate_ctxt.cr2 = cr2;
vcpu->emulate_ctxt.mode =
(vcpu->emulate_ctxt.eflags & X86_EFLAGS_VM)
? X86EMUL_MODE_REAL : cs_l
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 3be506a..22fdf0a 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1127,13 +1127,13 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt,
static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops,
- unsigned long cr2)
+ unsigned long memop)
{
struct decode_cache *c = &ctxt->decode;
u64 old, new;
int rc;
- rc = ops->read_emulated(cr2, &old, 8, ctxt->vcpu);
+ rc = ops->read_emulated(memop, &old, 8, ctxt->vcpu);
if (rc != 0)
return rc;
@@ -1148,7 +1148,7 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
new = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
(u32) c->regs[VCPU_REGS_RBX];
- rc = ops->cmpxchg_emulated(cr2, &old, &new, 8, ctxt->vcpu);
+ rc = ops->cmpxchg_emulated(memop, &old, &new, 8, ctxt->vcpu);
if (rc != 0)
return rc;
ctxt->eflags |= EFLG_ZF;
@@ -1211,7 +1211,7 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
int
x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
{
- unsigned long cr2 = ctxt->cr2;
+ unsigned long memop = 0;
u64 msr_data;
unsigned long saved_eip = 0;
struct decode_cache *c = &ctxt->decode;
@@ -1226,10 +1226,10 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
saved_eip = c->eip;
if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
- cr2 = c->modrm_ea;
+ memop = c->modrm_ea;
if (c->src.type == OP_MEM) {
- c->src.ptr = (unsigned long *)cr2;
+ c->src.ptr = (unsigned long *)memop;
c->src.val = 0;
rc = ops->read_emulated((unsigned long)c->src.ptr,
&c->src.val,
@@ -1245,7 +1245,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
if (c->dst.type == OP_MEM) {
- c->dst.ptr = (unsigned long *)cr2;
+ c->dst.ptr = (unsigned long *)memop;
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
c->dst.val = 0;
if (c->d & BitOp) {
@@ -1677,7 +1677,7 @@ twobyte_insn:
&ctxt->eflags);
break;
case 7: /* invlpg*/
- emulate_invlpg(ctxt->vcpu, cr2);
+ emulate_invlpg(ctxt->vcpu, memop);
break;
default:
goto cannot_emulate;
@@ -1848,7 +1848,7 @@ twobyte_special_insn:
break;
}
case 0xc7: /* Grp9 (cmpxchg8b) */
- rc = emulate_grp9(ctxt, ops, cr2);
+ rc = emulate_grp9(ctxt, ops, memop);
if (rc != 0)
goto done;
break;
diff --git a/drivers/kvm/x86_emulate.h b/drivers/kvm/x86_emulate.h
index 644086e..7db91b9 100644
--- a/drivers/kvm/x86_emulate.h
+++ b/drivers/kvm/x86_emulate.h
@@ -145,7 +145,6 @@ struct x86_emulate_ctxt {
/* Linear faulting address (if emulating a page-faulting instruction). */
unsigned long eflags;
- unsigned long cr2;
/* Emulated execution mode, represented by an X86EMUL_MODE value. */
int mode;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 14/54] KVM: x86 emulator: cmps instruction
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (11 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 13/54] KVM: x86 emulator: Rename 'cr2' to 'memop' Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 15/54] KVM: Add ifdef in irqchip struct for x86 only structures Avi Kivity
` (39 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Guillaume Thouvenin
From: Guillaume Thouvenin <guillaume.thouvenin-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
Add emulation for the cmps instruction. This lets OpenBSD boot on kvm.
Signed-off-by: Guillaume Thouvenin <guillaume.thouvenin-Z51IpKcfGtLk1uMJSBkQmQ@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 58 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 22fdf0a..84e5366 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1535,10 +1535,31 @@ special_insn:
break;
}
if (c->rep_prefix) {
+ /* All REP prefixes have the same first termination condition */
if (c->regs[VCPU_REGS_RCX] == 0) {
ctxt->vcpu->rip = c->eip;
goto done;
}
+ /* The second termination condition only applies for REPE
+ * and REPNE. Test if the repeat string operation prefix is
+ * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
+ * corresponding termination condition according to:
+ * - if REPE/REPZ and ZF = 0 then done
+ * - if REPNE/REPNZ and ZF = 1 then done
+ */
+ if ((c->b == 0xa6) || (c->b == 0xa7) ||
+ (c->b == 0xae) || (c->b == 0xaf)) {
+ if ((c->rep_prefix == REPE_PREFIX) &&
+ ((ctxt->eflags & EFLG_ZF) == 0)) {
+ ctxt->vcpu->rip = c->eip;
+ goto done;
+ }
+ if ((c->rep_prefix == REPNE_PREFIX) &&
+ ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
+ ctxt->vcpu->rip = c->eip;
+ goto done;
+ }
+ }
c->regs[VCPU_REGS_RCX]--;
c->eip = ctxt->vcpu->rip;
}
@@ -1564,8 +1585,41 @@ special_insn:
: c->dst.bytes);
break;
case 0xa6 ... 0xa7: /* cmps */
- DPRINTF("Urk! I don't handle CMPS.\n");
- goto cannot_emulate;
+ c->src.type = OP_NONE; /* Disable writeback. */
+ c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+ c->src.ptr = (unsigned long *)register_address(
+ c->override_base ? *c->override_base :
+ ctxt->ds_base,
+ c->regs[VCPU_REGS_RSI]);
+ if ((rc = ops->read_emulated((unsigned long)c->src.ptr,
+ &c->src.val,
+ c->src.bytes,
+ ctxt->vcpu)) != 0)
+ goto done;
+
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
+ c->dst.ptr = (unsigned long *)register_address(
+ ctxt->es_base,
+ c->regs[VCPU_REGS_RDI]);
+ if ((rc = ops->read_emulated((unsigned long)c->dst.ptr,
+ &c->dst.val,
+ c->dst.bytes,
+ ctxt->vcpu)) != 0)
+ goto done;
+
+ DPRINTF("cmps: mem1=0x%p mem2=0x%p\n", c->src.ptr, c->dst.ptr);
+
+ emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
+
+ register_address_increment(c->regs[VCPU_REGS_RSI],
+ (ctxt->eflags & EFLG_DF) ? -c->src.bytes
+ : c->src.bytes);
+ register_address_increment(c->regs[VCPU_REGS_RDI],
+ (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
+ : c->dst.bytes);
+
+ break;
case 0xaa ... 0xab: /* stos */
c->dst.type = OP_MEM;
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 15/54] KVM: Add ifdef in irqchip struct for x86 only structures
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (12 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 14/54] KVM: x86 emulator: cmps instruction Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 16/54] KVM: x86 emulator: Move rep processing before instruction execution Avi Kivity
` (38 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Jerone Young
From: Jerone Young <jyoung5-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
This patch fixes a small issue where sturctures:
kvm_pic_state
kvm_ioapic_state
are defined inside x86 specific code and may or may not
be defined in anyway for other architectures. The problem
caused is one cannot compile userspace apps (ex. libkvm)
for other archs since a size cannot be determined for these
structures.
Signed-off-by: Jerone Young <jyoung5-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
include/linux/Kbuild | 2 +-
include/linux/kvm.h | 2 ++
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 9abf5a8..805c2a7 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -98,7 +98,6 @@ header-y += iso_fs.h
header-y += ixjuser.h
header-y += jffs2.h
header-y += keyctl.h
-header-y += kvm.h
header-y += limits.h
header-y += lock_dlm_plock.h
header-y += magic.h
@@ -254,6 +253,7 @@ unifdef-y += kd.h
unifdef-y += kernelcapi.h
unifdef-y += kernel.h
unifdef-y += keyboard.h
+unifdef-y += kvm.h
unifdef-y += llc.h
unifdef-y += loop.h
unifdef-y += lp.h
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index b751552..f0bebd6 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -51,8 +51,10 @@ struct kvm_irqchip {
__u32 pad;
union {
char dummy[512]; /* reserving space */
+#ifdef CONFIG_X86
struct kvm_pic_state pic;
struct kvm_ioapic_state ioapic;
+#endif
} chip;
};
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 16/54] KVM: x86 emulator: Move rep processing before instruction execution
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (13 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 15/54] KVM: Add ifdef in irqchip struct for x86 only structures Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 17/54] KVM: x86 emulator: unify two switches Avi Kivity
` (37 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Currently rep processing is handled somewhere in the middle of instruction
processing. Move it to a sensible place.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 70 +++++++++++++++++++++++----------------------
1 files changed, 36 insertions(+), 34 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 84e5366..53377f0 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -64,6 +64,7 @@
#define Mov (1<<7)
#define BitOp (1<<8)
#define MemAbs (1<<9) /* Memory operand is absolute displacement */
+#define String (1<<10) /* String instruction (rep capable) */
static u16 opcode_table[256] = {
/* 0x00 - 0x07 */
@@ -133,12 +134,12 @@ static u16 opcode_table[256] = {
/* 0xA0 - 0xA7 */
ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
- ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
- ByteOp | ImplicitOps, ImplicitOps,
+ ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
+ ByteOp | ImplicitOps | String, ImplicitOps | String,
/* 0xA8 - 0xAF */
- 0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
- ByteOp | ImplicitOps | Mov, ImplicitOps | Mov,
- ByteOp | ImplicitOps, ImplicitOps,
+ 0, 0, ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
+ ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String,
+ ByteOp | ImplicitOps | String, ImplicitOps | String,
/* 0xB0 - 0xBF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xC0 - 0xC7 */
@@ -1228,6 +1229,36 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
if (((c->d & ModRM) && (c->modrm_mod != 3)) || (c->d & MemAbs))
memop = c->modrm_ea;
+ if (c->rep_prefix && (c->d & String)) {
+ /* All REP prefixes have the same first termination condition */
+ if (c->regs[VCPU_REGS_RCX] == 0) {
+ ctxt->vcpu->rip = c->eip;
+ goto done;
+ }
+ /* The second termination condition only applies for REPE
+ * and REPNE. Test if the repeat string operation prefix is
+ * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
+ * corresponding termination condition according to:
+ * - if REPE/REPZ and ZF = 0 then done
+ * - if REPNE/REPNZ and ZF = 1 then done
+ */
+ if ((c->b == 0xa6) || (c->b == 0xa7) ||
+ (c->b == 0xae) || (c->b == 0xaf)) {
+ if ((c->rep_prefix == REPE_PREFIX) &&
+ ((ctxt->eflags & EFLG_ZF) == 0)) {
+ ctxt->vcpu->rip = c->eip;
+ goto done;
+ }
+ if ((c->rep_prefix == REPNE_PREFIX) &&
+ ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
+ ctxt->vcpu->rip = c->eip;
+ goto done;
+ }
+ }
+ c->regs[VCPU_REGS_RCX]--;
+ c->eip = ctxt->vcpu->rip;
+ }
+
if (c->src.type == OP_MEM) {
c->src.ptr = (unsigned long *)memop;
c->src.val = 0;
@@ -1534,35 +1565,6 @@ special_insn:
c->dst.type = OP_NONE; /* Disable writeback. */
break;
}
- if (c->rep_prefix) {
- /* All REP prefixes have the same first termination condition */
- if (c->regs[VCPU_REGS_RCX] == 0) {
- ctxt->vcpu->rip = c->eip;
- goto done;
- }
- /* The second termination condition only applies for REPE
- * and REPNE. Test if the repeat string operation prefix is
- * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
- * corresponding termination condition according to:
- * - if REPE/REPZ and ZF = 0 then done
- * - if REPNE/REPNZ and ZF = 1 then done
- */
- if ((c->b == 0xa6) || (c->b == 0xa7) ||
- (c->b == 0xae) || (c->b == 0xaf)) {
- if ((c->rep_prefix == REPE_PREFIX) &&
- ((ctxt->eflags & EFLG_ZF) == 0)) {
- ctxt->vcpu->rip = c->eip;
- goto done;
- }
- if ((c->rep_prefix == REPNE_PREFIX) &&
- ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
- ctxt->vcpu->rip = c->eip;
- goto done;
- }
- }
- c->regs[VCPU_REGS_RCX]--;
- c->eip = ctxt->vcpu->rip;
- }
switch (c->b) {
case 0xa4 ... 0xa5: /* movs */
c->dst.type = OP_MEM;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 17/54] KVM: x86 emulator: unify two switches
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (14 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 16/54] KVM: x86 emulator: Move rep processing before instruction execution Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 18/54] KVM: x86 emulator: unify four switch statements into two Avi Kivity
` (36 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
The rep prefix cleanup left two switch () statements next to each other.
Unify them.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 50 ++++++++++++++++++++------------------------
1 files changed, 23 insertions(+), 27 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 53377f0..499d1ad 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1541,31 +1541,6 @@ special_insn:
case 0x9d: /* popf */
c->dst.ptr = (unsigned long *) &ctxt->eflags;
goto pop_instruction;
- case 0xc3: /* ret */
- c->dst.ptr = &c->eip;
- goto pop_instruction;
- case 0xf4: /* hlt */
- ctxt->vcpu->halt_request = 1;
- goto done;
- case 0xf5: /* cmc */
- /* complement carry flag from eflags reg */
- ctxt->eflags ^= EFLG_CF;
- c->dst.type = OP_NONE; /* Disable writeback. */
- break;
- case 0xf8: /* clc */
- ctxt->eflags &= ~EFLG_CF;
- c->dst.type = OP_NONE; /* Disable writeback. */
- break;
- case 0xfa: /* cli */
- ctxt->eflags &= ~X86_EFLAGS_IF;
- c->dst.type = OP_NONE; /* Disable writeback. */
- break;
- case 0xfb: /* sti */
- ctxt->eflags |= X86_EFLAGS_IF;
- c->dst.type = OP_NONE; /* Disable writeback. */
- break;
- }
- switch (c->b) {
case 0xa4 ... 0xa5: /* movs */
c->dst.type = OP_MEM;
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
@@ -1652,6 +1627,9 @@ special_insn:
case 0xae ... 0xaf: /* scas */
DPRINTF("Urk! I don't handle SCAS.\n");
goto cannot_emulate;
+ case 0xc3: /* ret */
+ c->dst.ptr = &c->eip;
+ goto pop_instruction;
case 0xe8: /* call (near) */ {
long int rel;
switch (c->op_bytes) {
@@ -1676,8 +1654,26 @@ special_insn:
JMP_REL(c->src.val);
c->dst.type = OP_NONE; /* Disable writeback. */
break;
-
-
+ case 0xf4: /* hlt */
+ ctxt->vcpu->halt_request = 1;
+ goto done;
+ case 0xf5: /* cmc */
+ /* complement carry flag from eflags reg */
+ ctxt->eflags ^= EFLG_CF;
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
+ case 0xf8: /* clc */
+ ctxt->eflags &= ~EFLG_CF;
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
+ case 0xfa: /* cli */
+ ctxt->eflags &= ~X86_EFLAGS_IF;
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
+ case 0xfb: /* sti */
+ ctxt->eflags |= X86_EFLAGS_IF;
+ c->dst.type = OP_NONE; /* Disable writeback. */
+ break;
}
goto writeback;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 18/54] KVM: x86 emulator: unify four switch statements into two
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (15 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 17/54] KVM: x86 emulator: unify two switches Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 19/54] KVM: Portability: Move KVM_INTERRUPT vcpu ioctl to x86.c Avi Kivity
` (35 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Unify the special instruction switch with the regular instruction switch,
and the two byte special instruction switch with the regular two byte
instruction switch. That makes it much easier to find an instruction or
the place an instruction needs to be added in.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 342 ++++++++++++++++++++++-----------------------
1 files changed, 168 insertions(+), 174 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 499d1ad..3e3eba7 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1294,6 +1294,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
}
c->dst.orig_val = c->dst.val;
+special_insn:
+
if (c->twobyte)
goto twobyte_insn;
@@ -1378,6 +1380,52 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
goto cannot_emulate;
c->dst.val = (s32) c->src.val;
break;
+ case 0x6a: /* push imm8 */
+ c->src.val = 0L;
+ c->src.val = insn_fetch(s8, 1, c->eip);
+ emulate_push(ctxt);
+ break;
+ case 0x6c: /* insb */
+ case 0x6d: /* insw/insd */
+ if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
+ 1,
+ (c->d & ByteOp) ? 1 : c->op_bytes,
+ c->rep_prefix ?
+ address_mask(c->regs[VCPU_REGS_RCX]) : 1,
+ (ctxt->eflags & EFLG_DF),
+ register_address(ctxt->es_base,
+ c->regs[VCPU_REGS_RDI]),
+ c->rep_prefix,
+ c->regs[VCPU_REGS_RDX]) == 0) {
+ c->eip = saved_eip;
+ return -1;
+ }
+ return 0;
+ case 0x6e: /* outsb */
+ case 0x6f: /* outsw/outsd */
+ if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
+ 0,
+ (c->d & ByteOp) ? 1 : c->op_bytes,
+ c->rep_prefix ?
+ address_mask(c->regs[VCPU_REGS_RCX]) : 1,
+ (ctxt->eflags & EFLG_DF),
+ register_address(c->override_base ?
+ *c->override_base :
+ ctxt->ds_base,
+ c->regs[VCPU_REGS_RSI]),
+ c->rep_prefix,
+ c->regs[VCPU_REGS_RDX]) == 0) {
+ c->eip = saved_eip;
+ return -1;
+ }
+ return 0;
+ case 0x70 ... 0x7f: /* jcc (short) */ {
+ int rel = insn_fetch(s8, 1, c->eip);
+
+ if (test_cc(c->b, ctxt->eflags))
+ JMP_REL(rel);
+ break;
+ }
case 0x80 ... 0x83: /* Grp1 */
switch (c->modrm_reg) {
case 0:
@@ -1434,106 +1482,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
if (rc != 0)
goto done;
break;
- case 0xa0 ... 0xa1: /* mov */
- c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
- c->dst.val = c->src.val;
- break;
- case 0xa2 ... 0xa3: /* mov */
- c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX];
- break;
- case 0xc0 ... 0xc1:
- emulate_grp2(ctxt);
- break;
- case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
- mov:
- c->dst.val = c->src.val;
- break;
- case 0xd0 ... 0xd1: /* Grp2 */
- c->src.val = 1;
- emulate_grp2(ctxt);
- break;
- case 0xd2 ... 0xd3: /* Grp2 */
- c->src.val = c->regs[VCPU_REGS_RCX];
- emulate_grp2(ctxt);
- break;
- case 0xf6 ... 0xf7: /* Grp3 */
- rc = emulate_grp3(ctxt, ops);
- if (rc != 0)
- goto done;
- break;
- case 0xfe ... 0xff: /* Grp4/Grp5 */
- rc = emulate_grp45(ctxt, ops);
- if (rc != 0)
- goto done;
- break;
- }
-
-writeback:
- rc = writeback(ctxt, ops);
- if (rc != 0)
- goto done;
-
- /* Commit shadow register state. */
- memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs);
- ctxt->vcpu->rip = c->eip;
-
-done:
- if (rc == X86EMUL_UNHANDLEABLE) {
- c->eip = saved_eip;
- return -1;
- }
- return 0;
-
-special_insn:
- if (c->twobyte)
- goto twobyte_special_insn;
- switch (c->b) {
- case 0x6a: /* push imm8 */
- c->src.val = 0L;
- c->src.val = insn_fetch(s8, 1, c->eip);
- emulate_push(ctxt);
- break;
- case 0x6c: /* insb */
- case 0x6d: /* insw/insd */
- if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
- 1,
- (c->d & ByteOp) ? 1 : c->op_bytes,
- c->rep_prefix ?
- address_mask(c->regs[VCPU_REGS_RCX]) : 1,
- (ctxt->eflags & EFLG_DF),
- register_address(ctxt->es_base,
- c->regs[VCPU_REGS_RDI]),
- c->rep_prefix,
- c->regs[VCPU_REGS_RDX]) == 0) {
- c->eip = saved_eip;
- return -1;
- }
- return 0;
- case 0x6e: /* outsb */
- case 0x6f: /* outsw/outsd */
- if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
- 0,
- (c->d & ByteOp) ? 1 : c->op_bytes,
- c->rep_prefix ?
- address_mask(c->regs[VCPU_REGS_RCX]) : 1,
- (ctxt->eflags & EFLG_DF),
- register_address(c->override_base ?
- *c->override_base :
- ctxt->ds_base,
- c->regs[VCPU_REGS_RSI]),
- c->rep_prefix,
- c->regs[VCPU_REGS_RDX]) == 0) {
- c->eip = saved_eip;
- return -1;
- }
- return 0;
- case 0x70 ... 0x7f: /* jcc (short) */ {
- int rel = insn_fetch(s8, 1, c->eip);
-
- if (test_cc(c->b, ctxt->eflags))
- JMP_REL(rel);
- break;
- }
case 0x9c: /* pushf */
c->src.val = (unsigned long) ctxt->eflags;
emulate_push(ctxt);
@@ -1541,6 +1489,13 @@ special_insn:
case 0x9d: /* popf */
c->dst.ptr = (unsigned long *) &ctxt->eflags;
goto pop_instruction;
+ case 0xa0 ... 0xa1: /* mov */
+ c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
+ c->dst.val = c->src.val;
+ break;
+ case 0xa2 ... 0xa3: /* mov */
+ c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX];
+ break;
case 0xa4 ... 0xa5: /* movs */
c->dst.type = OP_MEM;
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
@@ -1627,9 +1582,24 @@ special_insn:
case 0xae ... 0xaf: /* scas */
DPRINTF("Urk! I don't handle SCAS.\n");
goto cannot_emulate;
+ case 0xc0 ... 0xc1:
+ emulate_grp2(ctxt);
+ break;
case 0xc3: /* ret */
c->dst.ptr = &c->eip;
goto pop_instruction;
+ case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
+ mov:
+ c->dst.val = c->src.val;
+ break;
+ case 0xd0 ... 0xd1: /* Grp2 */
+ c->src.val = 1;
+ emulate_grp2(ctxt);
+ break;
+ case 0xd2 ... 0xd3: /* Grp2 */
+ c->src.val = c->regs[VCPU_REGS_RCX];
+ emulate_grp2(ctxt);
+ break;
case 0xe8: /* call (near) */ {
long int rel;
switch (c->op_bytes) {
@@ -1662,6 +1632,11 @@ special_insn:
ctxt->eflags ^= EFLG_CF;
c->dst.type = OP_NONE; /* Disable writeback. */
break;
+ case 0xf6 ... 0xf7: /* Grp3 */
+ rc = emulate_grp3(ctxt, ops);
+ if (rc != 0)
+ goto done;
+ break;
case 0xf8: /* clc */
ctxt->eflags &= ~EFLG_CF;
c->dst.type = OP_NONE; /* Disable writeback. */
@@ -1674,8 +1649,28 @@ special_insn:
ctxt->eflags |= X86_EFLAGS_IF;
c->dst.type = OP_NONE; /* Disable writeback. */
break;
+ case 0xfe ... 0xff: /* Grp4/Grp5 */
+ rc = emulate_grp45(ctxt, ops);
+ if (rc != 0)
+ goto done;
+ break;
}
- goto writeback;
+
+writeback:
+ rc = writeback(ctxt, ops);
+ if (rc != 0)
+ goto done;
+
+ /* Commit shadow register state. */
+ memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs);
+ ctxt->vcpu->rip = c->eip;
+
+done:
+ if (rc == X86EMUL_UNHANDLEABLE) {
+ c->eip = saved_eip;
+ return -1;
+ }
+ return 0;
twobyte_insn:
switch (c->b) {
@@ -1737,6 +1732,23 @@ twobyte_insn:
/* Disable writeback. */
c->dst.type = OP_NONE;
break;
+ case 0x06:
+ emulate_clts(ctxt->vcpu);
+ c->dst.type = OP_NONE;
+ break;
+ case 0x08: /* invd */
+ case 0x09: /* wbinvd */
+ case 0x0d: /* GrpP (prefetch) */
+ case 0x18: /* Grp16 (prefetch/nop) */
+ c->dst.type = OP_NONE;
+ break;
+ case 0x20: /* mov cr, reg */
+ if (c->modrm_mod != 3)
+ goto cannot_emulate;
+ c->regs[c->modrm_rm] =
+ realmode_get_cr(ctxt->vcpu, c->modrm_reg);
+ c->dst.type = OP_NONE; /* no writeback */
+ break;
case 0x21: /* mov from dr to reg */
if (c->modrm_mod != 3)
goto cannot_emulate;
@@ -1745,6 +1757,13 @@ twobyte_insn:
goto cannot_emulate;
c->dst.type = OP_NONE; /* no writeback */
break;
+ case 0x22: /* mov reg, cr */
+ if (c->modrm_mod != 3)
+ goto cannot_emulate;
+ realmode_set_cr(ctxt->vcpu,
+ c->modrm_reg, c->modrm_val, &ctxt->eflags);
+ c->dst.type = OP_NONE;
+ break;
case 0x23: /* mov from reg to dr */
if (c->modrm_mod != 3)
goto cannot_emulate;
@@ -1754,11 +1773,58 @@ twobyte_insn:
goto cannot_emulate;
c->dst.type = OP_NONE; /* no writeback */
break;
+ case 0x30:
+ /* wrmsr */
+ msr_data = (u32)c->regs[VCPU_REGS_RAX]
+ | ((u64)c->regs[VCPU_REGS_RDX] << 32);
+ rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data);
+ if (rc) {
+ kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
+ c->eip = ctxt->vcpu->rip;
+ }
+ rc = X86EMUL_CONTINUE;
+ c->dst.type = OP_NONE;
+ break;
+ case 0x32:
+ /* rdmsr */
+ rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data);
+ if (rc) {
+ kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
+ c->eip = ctxt->vcpu->rip;
+ } else {
+ c->regs[VCPU_REGS_RAX] = (u32)msr_data;
+ c->regs[VCPU_REGS_RDX] = msr_data >> 32;
+ }
+ rc = X86EMUL_CONTINUE;
+ c->dst.type = OP_NONE;
+ break;
case 0x40 ... 0x4f: /* cmov */
c->dst.val = c->dst.orig_val = c->src.val;
if (!test_cc(c->b, ctxt->eflags))
c->dst.type = OP_NONE; /* no writeback */
break;
+ case 0x80 ... 0x8f: /* jnz rel, etc*/ {
+ long int rel;
+
+ switch (c->op_bytes) {
+ case 2:
+ rel = insn_fetch(s16, 2, c->eip);
+ break;
+ case 4:
+ rel = insn_fetch(s32, 4, c->eip);
+ break;
+ case 8:
+ rel = insn_fetch(s64, 8, c->eip);
+ break;
+ default:
+ DPRINTF("jnz: Invalid op_bytes\n");
+ goto cannot_emulate;
+ }
+ if (test_cc(c->b, ctxt->eflags))
+ JMP_REL(rel);
+ c->dst.type = OP_NONE;
+ break;
+ }
case 0xa3:
bt: /* bt */
c->dst.type = OP_NONE;
@@ -1828,85 +1894,13 @@ twobyte_insn:
c->dst.val = (c->op_bytes == 4) ? (u32) c->src.val :
(u64) c->src.val;
break;
- }
- goto writeback;
-
-twobyte_special_insn:
- switch (c->b) {
- case 0x06:
- emulate_clts(ctxt->vcpu);
- break;
- case 0x08: /* invd */
- break;
- case 0x09: /* wbinvd */
- break;
- case 0x0d: /* GrpP (prefetch) */
- case 0x18: /* Grp16 (prefetch/nop) */
- break;
- case 0x20: /* mov cr, reg */
- if (c->modrm_mod != 3)
- goto cannot_emulate;
- c->regs[c->modrm_rm] =
- realmode_get_cr(ctxt->vcpu, c->modrm_reg);
- break;
- case 0x22: /* mov reg, cr */
- if (c->modrm_mod != 3)
- goto cannot_emulate;
- realmode_set_cr(ctxt->vcpu,
- c->modrm_reg, c->modrm_val, &ctxt->eflags);
- break;
- case 0x30:
- /* wrmsr */
- msr_data = (u32)c->regs[VCPU_REGS_RAX]
- | ((u64)c->regs[VCPU_REGS_RDX] << 32);
- rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data);
- if (rc) {
- kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
- c->eip = ctxt->vcpu->rip;
- }
- rc = X86EMUL_CONTINUE;
- break;
- case 0x32:
- /* rdmsr */
- rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data);
- if (rc) {
- kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
- c->eip = ctxt->vcpu->rip;
- } else {
- c->regs[VCPU_REGS_RAX] = (u32)msr_data;
- c->regs[VCPU_REGS_RDX] = msr_data >> 32;
- }
- rc = X86EMUL_CONTINUE;
- break;
- case 0x80 ... 0x8f: /* jnz rel, etc*/ {
- long int rel;
-
- switch (c->op_bytes) {
- case 2:
- rel = insn_fetch(s16, 2, c->eip);
- break;
- case 4:
- rel = insn_fetch(s32, 4, c->eip);
- break;
- case 8:
- rel = insn_fetch(s64, 8, c->eip);
- break;
- default:
- DPRINTF("jnz: Invalid op_bytes\n");
- goto cannot_emulate;
- }
- if (test_cc(c->b, ctxt->eflags))
- JMP_REL(rel);
- break;
- }
case 0xc7: /* Grp9 (cmpxchg8b) */
rc = emulate_grp9(ctxt, ops, memop);
if (rc != 0)
goto done;
+ c->dst.type = OP_NONE;
break;
}
- /* Disable writeback. */
- c->dst.type = OP_NONE;
goto writeback;
cannot_emulate:
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 19/54] KVM: Portability: Move KVM_INTERRUPT vcpu ioctl to x86.c
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (16 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 18/54] KVM: x86 emulator: unify four switch statements into two Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 20/54] KVM: Correct kvm_init() error paths not freeing bad_pge Avi Kivity
` (34 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Zhang Xiantao
From: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Other archs doesn't need it.
Signed-off-by: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm_main.c | 29 -----------------------------
drivers/kvm/x86.c | 29 +++++++++++++++++++++++++++++
2 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 003a43c..ef961cc 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -665,23 +665,6 @@ void kvm_resched(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_resched);
-static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
- struct kvm_interrupt *irq)
-{
- if (irq->irq < 0 || irq->irq >= 256)
- return -EINVAL;
- if (irqchip_in_kernel(vcpu->kvm))
- return -ENXIO;
- vcpu_load(vcpu);
-
- set_bit(irq->irq, vcpu->irq_pending);
- set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary);
-
- vcpu_put(vcpu);
-
- return 0;
-}
-
static struct page *kvm_vcpu_nopage(struct vm_area_struct *vma,
unsigned long address,
int *type)
@@ -883,18 +866,6 @@ static long kvm_vcpu_ioctl(struct file *filp,
r = 0;
break;
}
- case KVM_INTERRUPT: {
- struct kvm_interrupt irq;
-
- r = -EFAULT;
- if (copy_from_user(&irq, argp, sizeof irq))
- goto out;
- r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
- if (r)
- goto out;
- r = 0;
- break;
- }
case KVM_DEBUG_GUEST: {
struct kvm_debug_guest dbg;
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 12f1d6f..c9e4b67 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -1001,6 +1001,23 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
return 0;
}
+static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
+ struct kvm_interrupt *irq)
+{
+ if (irq->irq < 0 || irq->irq >= 256)
+ return -EINVAL;
+ if (irqchip_in_kernel(vcpu->kvm))
+ return -ENXIO;
+ vcpu_load(vcpu);
+
+ set_bit(irq->irq, vcpu->irq_pending);
+ set_bit(irq->irq / BITS_PER_LONG, &vcpu->irq_summary);
+
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -1034,6 +1051,18 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = 0;
break;
}
+ case KVM_INTERRUPT: {
+ struct kvm_interrupt irq;
+
+ r = -EFAULT;
+ if (copy_from_user(&irq, argp, sizeof irq))
+ goto out;
+ r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
case KVM_SET_CPUID: {
struct kvm_cpuid __user *cpuid_arg = argp;
struct kvm_cpuid cpuid;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 20/54] KVM: Correct kvm_init() error paths not freeing bad_pge.
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (17 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 19/54] KVM: Portability: Move KVM_INTERRUPT vcpu ioctl to x86.c Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 21/54] KVM: Export include/linux/kvm.h only if $ARCH actually supports KVM Avi Kivity
` (33 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Zhang Xiantao
From: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm_main.c | 28 +++++++++++++++-------------
1 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index ef961cc..b56ee34 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1311,7 +1311,7 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
r = kvm_arch_init(opaque);
if (r)
- goto out4;
+ goto out_fail;
bad_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
@@ -1322,29 +1322,29 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
r = kvm_arch_hardware_setup();
if (r < 0)
- goto out;
+ goto out_free_0;
for_each_online_cpu(cpu) {
smp_call_function_single(cpu,
kvm_arch_check_processor_compat,
&r, 0, 1);
if (r < 0)
- goto out_free_0;
+ goto out_free_1;
}
on_each_cpu(hardware_enable, NULL, 0, 1);
r = register_cpu_notifier(&kvm_cpu_notifier);
if (r)
- goto out_free_1;
+ goto out_free_2;
register_reboot_notifier(&kvm_reboot_notifier);
r = sysdev_class_register(&kvm_sysdev_class);
if (r)
- goto out_free_2;
+ goto out_free_3;
r = sysdev_register(&kvm_sysdev);
if (r)
- goto out_free_3;
+ goto out_free_4;
/* A kmem cache lets us meet the alignment requirements of fx_save. */
kvm_vcpu_cache = kmem_cache_create("kvm_vcpu", vcpu_size,
@@ -1352,7 +1352,7 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
0, NULL);
if (!kvm_vcpu_cache) {
r = -ENOMEM;
- goto out_free_4;
+ goto out_free_5;
}
kvm_chardev_ops.owner = module;
@@ -1370,21 +1370,23 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
out_free:
kmem_cache_destroy(kvm_vcpu_cache);
-out_free_4:
+out_free_5:
sysdev_unregister(&kvm_sysdev);
-out_free_3:
+out_free_4:
sysdev_class_unregister(&kvm_sysdev_class);
-out_free_2:
+out_free_3:
unregister_reboot_notifier(&kvm_reboot_notifier);
unregister_cpu_notifier(&kvm_cpu_notifier);
-out_free_1:
+out_free_2:
on_each_cpu(hardware_disable, NULL, 0, 1);
-out_free_0:
+out_free_1:
kvm_arch_hardware_unsetup();
+out_free_0:
+ __free_page(bad_page);
out:
kvm_arch_exit();
kvm_exit_debug();
-out4:
+out_fail:
return r;
}
EXPORT_SYMBOL_GPL(kvm_init);
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 21/54] KVM: Export include/linux/kvm.h only if $ARCH actually supports KVM
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (18 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 20/54] KVM: Correct kvm_init() error paths not freeing bad_pge Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
[not found] ` <1199201780-14001-22-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2008-01-01 15:35 ` [PATCH 22/54] KVM: SVM: Remove KVM specific defines for MSR_EFER Avi Kivity
` (32 subsequent siblings)
52 siblings, 1 reply; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Currently, make headers_check barfs due to <asm/kvm.h>, which <linux/kvm.h>
includes, not existing. Rather than add a zillion <asm/kvm.h>s, export kvm.h
only if the arch actually supports it.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
arch/x86/Kconfig | 4 ++++
drivers/kvm/Kconfig | 4 ++--
include/linux/Kbuild | 2 +-
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 80b7ba4..e029a93 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -116,6 +116,10 @@ config ARCH_SUPPORTS_OPROFILE
bool
default y
+config ARCH_SUPPORTS_KVM
+ bool
+ default y
+
config ZONE_DMA32
bool
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index 6569206..4086080 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig VIRTUALIZATION
bool "Virtualization"
- depends on X86
+ depends on ARCH_SUPPORTS_KVM || X86
default y
---help---
Say Y here to get to see options for using your Linux host to run other
@@ -16,7 +16,7 @@ if VIRTUALIZATION
config KVM
tristate "Kernel-based Virtual Machine (KVM) support"
- depends on X86 && EXPERIMENTAL
+ depends on ARCH_SUPPORTS_KVM && EXPERIMENTAL
select PREEMPT_NOTIFIERS
select ANON_INODES
---help---
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 805c2a7..d70fa26 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -253,7 +253,7 @@ unifdef-y += kd.h
unifdef-y += kernelcapi.h
unifdef-y += kernel.h
unifdef-y += keyboard.h
-unifdef-y += kvm.h
+unifdef-$(CONFIG_ARCH_SUPPORTS_KVM) += kvm.h
unifdef-y += llc.h
unifdef-y += loop.h
unifdef-y += lp.h
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 22/54] KVM: SVM: Remove KVM specific defines for MSR_EFER
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (19 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 21/54] KVM: Export include/linux/kvm.h only if $ARCH actually supports KVM Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 23/54] KVM: Replace kvm_lapic with kvm_vcpu in ioapic/lapic interface Avi Kivity
` (31 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Carlo Marcelo Arenas Belon
From: Carlo Marcelo Arenas Belon <carenas-kLeDWSohozoJb6fo7hG9ng@public.gmane.org>
This patch removes the KVM specific defines for MSR_EFER that were being used
in the svm support file and migrates all references to use instead the ones
from the kernel headers that are used everywhere else and that have the same
values.
Signed-off-by: Carlo Marcelo Arenas Belon <carenas-kLeDWSohozoJb6fo7hG9ng@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/svm.c | 17 +++++++----------
1 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 928fb35..04e6b39 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -42,9 +42,6 @@ MODULE_LICENSE("GPL");
#define SEG_TYPE_LDT 2
#define SEG_TYPE_BUSY_TSS16 3
-#define KVM_EFER_LMA (1 << 10)
-#define KVM_EFER_LME (1 << 8)
-
#define SVM_FEATURE_NPT (1 << 0)
#define SVM_FEATURE_LBRV (1 << 1)
#define SVM_DEATURE_SVML (1 << 2)
@@ -184,8 +181,8 @@ static inline void flush_guest_tlb(struct kvm_vcpu *vcpu)
static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
{
- if (!(efer & KVM_EFER_LMA))
- efer &= ~KVM_EFER_LME;
+ if (!(efer & EFER_LMA))
+ efer &= ~EFER_LME;
to_svm(vcpu)->vmcb->save.efer = efer | MSR_EFER_SVME_MASK;
vcpu->shadow_efer = efer;
@@ -777,15 +774,15 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
struct vcpu_svm *svm = to_svm(vcpu);
#ifdef CONFIG_X86_64
- if (vcpu->shadow_efer & KVM_EFER_LME) {
+ if (vcpu->shadow_efer & EFER_LME) {
if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
- vcpu->shadow_efer |= KVM_EFER_LMA;
- svm->vmcb->save.efer |= KVM_EFER_LMA | KVM_EFER_LME;
+ vcpu->shadow_efer |= EFER_LMA;
+ svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
}
if (is_paging(vcpu) && !(cr0 & X86_CR0_PG)) {
- vcpu->shadow_efer &= ~KVM_EFER_LMA;
- svm->vmcb->save.efer &= ~(KVM_EFER_LMA | KVM_EFER_LME);
+ vcpu->shadow_efer &= ~EFER_LMA;
+ svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
}
}
#endif
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 23/54] KVM: Replace kvm_lapic with kvm_vcpu in ioapic/lapic interface
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (20 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 22/54] KVM: SVM: Remove KVM specific defines for MSR_EFER Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 24/54] KVM: Replace dest_Lowest_Prio and dest_Fixed with self-defined macros Avi Kivity
` (30 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Zhang Xiantao
From: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
This patch replaces lapic structure with kvm_vcpu in ioapic.c, making ioapic
independent of the local apic, as required by ia64.
Signed-off-by: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/ioapic.c | 18 ++++++++----------
drivers/kvm/irq.h | 5 +++--
drivers/kvm/lapic.c | 23 ++++++++++++++++++-----
3 files changed, 29 insertions(+), 17 deletions(-)
diff --git a/drivers/kvm/ioapic.c b/drivers/kvm/ioapic.c
index cf1d50b..3629867 100644
--- a/drivers/kvm/ioapic.c
+++ b/drivers/kvm/ioapic.c
@@ -136,7 +136,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
}
static void ioapic_inj_irq(struct kvm_ioapic *ioapic,
- struct kvm_lapic *target,
+ struct kvm_vcpu *vcpu,
u8 vector, u8 trig_mode, u8 delivery_mode)
{
ioapic_debug("irq %d trig %d deliv %d\n", vector, trig_mode,
@@ -145,7 +145,7 @@ static void ioapic_inj_irq(struct kvm_ioapic *ioapic,
ASSERT((delivery_mode == dest_Fixed) ||
(delivery_mode == dest_LowestPrio));
- kvm_apic_set_irq(target, vector, trig_mode);
+ kvm_apic_set_irq(vcpu, vector, trig_mode);
}
static u32 ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest,
@@ -196,7 +196,6 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
u8 vector = ioapic->redirtbl[irq].fields.vector;
u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode;
u32 deliver_bitmask;
- struct kvm_lapic *target;
struct kvm_vcpu *vcpu;
int vcpu_id;
@@ -212,13 +211,13 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
switch (delivery_mode) {
case dest_LowestPrio:
- target =
- kvm_apic_round_robin(ioapic->kvm, vector, deliver_bitmask);
- if (target != NULL)
- ioapic_inj_irq(ioapic, target, vector,
+ vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
+ deliver_bitmask);
+ if (vcpu != NULL)
+ ioapic_inj_irq(ioapic, vcpu, vector,
trig_mode, delivery_mode);
else
- ioapic_debug("null round robin: "
+ ioapic_debug("null lowest prio vcpu: "
"mask=%x vector=%x delivery_mode=%x\n",
deliver_bitmask, vector, dest_LowestPrio);
break;
@@ -229,8 +228,7 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
deliver_bitmask &= ~(1 << vcpu_id);
vcpu = ioapic->kvm->vcpus[vcpu_id];
if (vcpu) {
- target = vcpu->apic;
- ioapic_inj_irq(ioapic, target, vector,
+ ioapic_inj_irq(ioapic, vcpu, vector,
trig_mode, delivery_mode);
}
}
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 5ad3cfd..78a34dd 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -145,14 +145,15 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu);
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
-struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
+
+struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
unsigned long bitmap);
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector);
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
-int kvm_apic_set_irq(struct kvm_lapic *apic, u8 vec, u8 trig);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
int kvm_ioapic_init(struct kvm *kvm);
void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index 64f74bd..5efa6c0 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -185,8 +185,10 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_lapic_find_highest_irr);
-int kvm_apic_set_irq(struct kvm_lapic *apic, u8 vec, u8 trig)
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
{
+ struct kvm_lapic *apic = vcpu->apic;
+
if (!apic_test_and_set_irr(vec, apic)) {
/* a new pending irq is set in IRR */
if (trig)
@@ -394,7 +396,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
return result;
}
-struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
+static struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
unsigned long bitmap)
{
int last;
@@ -422,6 +424,17 @@ struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
return apic;
}
+struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
+ unsigned long bitmap)
+{
+ struct kvm_lapic *apic;
+
+ apic = kvm_apic_round_robin(kvm, vector, bitmap);
+ if (apic)
+ return apic->vcpu;
+ return NULL;
+}
+
static void apic_set_eoi(struct kvm_lapic *apic)
{
int vector = apic_find_highest_isr(apic);
@@ -453,7 +466,7 @@ static void apic_send_ipi(struct kvm_lapic *apic)
unsigned int delivery_mode = icr_low & APIC_MODE_MASK;
unsigned int vector = icr_low & APIC_VECTOR_MASK;
- struct kvm_lapic *target;
+ struct kvm_vcpu *target;
struct kvm_vcpu *vcpu;
unsigned long lpr_map = 0;
int i;
@@ -480,9 +493,9 @@ static void apic_send_ipi(struct kvm_lapic *apic)
}
if (delivery_mode == APIC_DM_LOWEST) {
- target = kvm_apic_round_robin(vcpu->kvm, vector, lpr_map);
+ target = kvm_get_lowest_prio_vcpu(vcpu->kvm, vector, lpr_map);
if (target != NULL)
- __apic_accept_irq(target, delivery_mode,
+ __apic_accept_irq(target->apic, delivery_mode,
vector, level, trig_mode);
}
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 24/54] KVM: Replace dest_Lowest_Prio and dest_Fixed with self-defined macros
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (21 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 23/54] KVM: Replace kvm_lapic with kvm_vcpu in ioapic/lapic interface Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 25/54] KVM: Extend ioapic code to support iosapic Avi Kivity
` (29 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Zhang Xiantao
From: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Change
dest_Loest_Prio -> IOAPIC_LOWEST_PRIORITY
dest_Fixed -> IOAPIC_FIXED
the original names are x86 specific, while the ioapic code will be reused
for ia64.
Signed-off-by: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/ioapic.c | 13 +++++--------
drivers/kvm/irq.h | 8 ++++++++
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/kvm/ioapic.c b/drivers/kvm/ioapic.c
index 3629867..0feae6f 100644
--- a/drivers/kvm/ioapic.c
+++ b/drivers/kvm/ioapic.c
@@ -36,11 +36,8 @@
#include <linux/hrtimer.h>
#include <linux/io.h>
#include <asm/processor.h>
-#include <asm/msr.h>
#include <asm/page.h>
#include <asm/current.h>
-#include <asm/apicdef.h>
-#include <asm/io_apic.h>
#include "irq.h"
#if 0
#define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg)
@@ -142,8 +139,8 @@ static void ioapic_inj_irq(struct kvm_ioapic *ioapic,
ioapic_debug("irq %d trig %d deliv %d\n", vector, trig_mode,
delivery_mode);
- ASSERT((delivery_mode == dest_Fixed) ||
- (delivery_mode == dest_LowestPrio));
+ ASSERT((delivery_mode == IOAPIC_FIXED) ||
+ (delivery_mode == IOAPIC_LOWEST_PRIORITY));
kvm_apic_set_irq(vcpu, vector, trig_mode);
}
@@ -210,7 +207,7 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
}
switch (delivery_mode) {
- case dest_LowestPrio:
+ case IOAPIC_LOWEST_PRIORITY:
vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
deliver_bitmask);
if (vcpu != NULL)
@@ -219,9 +216,9 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
else
ioapic_debug("null lowest prio vcpu: "
"mask=%x vector=%x delivery_mode=%x\n",
- deliver_bitmask, vector, dest_LowestPrio);
+ deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY);
break;
- case dest_Fixed:
+ case IOAPIC_FIXED:
for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
if (!(deliver_bitmask & (1 << vcpu_id)))
continue;
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 78a34dd..75f5f18 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -79,6 +79,14 @@ void kvm_pic_update_irq(struct kvm_pic *s);
#define IOAPIC_REG_VERSION 0x01
#define IOAPIC_REG_ARB_ID 0x02 /* x86 IOAPIC only */
+/*ioapic delivery mode*/
+#define IOAPIC_FIXED 0x0
+#define IOAPIC_LOWEST_PRIORITY 0x1
+#define IOAPIC_PMI 0x2
+#define IOAPIC_NMI 0x4
+#define IOAPIC_INIT 0x5
+#define IOAPIC_EXTINT 0x7
+
struct kvm_ioapic {
u64 base_address;
u32 ioregsel;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 25/54] KVM: Extend ioapic code to support iosapic
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (22 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 24/54] KVM: Replace dest_Lowest_Prio and dest_Fixed with self-defined macros Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 26/54] KVM: Portability: Move address types to their own header file Avi Kivity
` (28 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Zhang Xiantao
From: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
iosapic supports an additional mmio EOI register compared to ioapic.
Signed-off-by: Zhang Xiantao <xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/ioapic.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/ioapic.c b/drivers/kvm/ioapic.c
index 0feae6f..e7debfa 100644
--- a/drivers/kvm/ioapic.c
+++ b/drivers/kvm/ioapic.c
@@ -360,6 +360,11 @@ static void ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len,
case IOAPIC_REG_WINDOW:
ioapic_write_indirect(ioapic, data);
break;
+#ifdef CONFIG_IA64
+ case IOAPIC_REG_EOI:
+ kvm_ioapic_update_eoi(ioapic, data);
+ break;
+#endif
default:
break;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 26/54] KVM: Portability: Move address types to their own header file
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (23 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 25/54] KVM: Extend ioapic code to support iosapic Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 27/54] KVM: Portability: Move IO device definitions to its " Avi Kivity
` (27 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Hollis Blanchard
From: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Acked-by: Carsten Otte <cotte-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm.h | 21 ++-------------------
drivers/kvm/types.h | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 19 deletions(-)
create mode 100644 drivers/kvm/types.h
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index be18620..3b0ba5a 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -20,6 +20,8 @@
#include <linux/kvm.h>
#include <linux/kvm_para.h>
+#include "types.h"
+
#define KVM_MAX_VCPUS 4
#define KVM_ALIAS_SLOTS 4
#define KVM_MEMORY_SLOTS 8
@@ -39,25 +41,6 @@
*/
#define KVM_REQ_TLB_FLUSH 0
-/*
- * Address types:
- *
- * gva - guest virtual address
- * gpa - guest physical address
- * gfn - guest frame number
- * hva - host virtual address
- * hpa - host physical address
- * hfn - host frame number
- */
-
-typedef unsigned long gva_t;
-typedef u64 gpa_t;
-typedef unsigned long gfn_t;
-
-typedef unsigned long hva_t;
-typedef u64 hpa_t;
-typedef unsigned long hfn_t;
-
#define NR_PTE_CHAIN_ENTRIES 5
struct kvm_pte_chain {
diff --git a/drivers/kvm/types.h b/drivers/kvm/types.h
new file mode 100644
index 0000000..6ad7623
--- /dev/null
+++ b/drivers/kvm/types.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __KVM_TYPES_H__
+#define __KVM_TYPES_H__
+
+#include <asm/types.h>
+
+/*
+ * Address types:
+ *
+ * gva - guest virtual address
+ * gpa - guest physical address
+ * gfn - guest frame number
+ * hva - host virtual address
+ * hpa - host physical address
+ * hfn - host frame number
+ */
+
+typedef unsigned long gva_t;
+typedef u64 gpa_t;
+typedef unsigned long gfn_t;
+
+typedef unsigned long hva_t;
+typedef u64 hpa_t;
+typedef unsigned long hfn_t;
+
+#endif /* __KVM_TYPES_H__ */
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 27/54] KVM: Portability: Move IO device definitions to its own header file
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (24 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 26/54] KVM: Portability: Move address types to their own header file Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 28/54] KVM: Portability: Stop including x86-specific headers in kvm_main.c Avi Kivity
` (26 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Hollis Blanchard
From: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Acked-by: Carsten Otte <cotte-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/iodev.h | 63 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/kvm/irq.h | 1 +
drivers/kvm/kvm.h | 42 --------------------------------
drivers/kvm/kvm_main.c | 1 +
4 files changed, 65 insertions(+), 42 deletions(-)
create mode 100644 drivers/kvm/iodev.h
diff --git a/drivers/kvm/iodev.h b/drivers/kvm/iodev.h
new file mode 100644
index 0000000..eb9e8a7
--- /dev/null
+++ b/drivers/kvm/iodev.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KVM_IODEV_H__
+#define __KVM_IODEV_H__
+
+#include "types.h"
+
+struct kvm_io_device {
+ void (*read)(struct kvm_io_device *this,
+ gpa_t addr,
+ int len,
+ void *val);
+ void (*write)(struct kvm_io_device *this,
+ gpa_t addr,
+ int len,
+ const void *val);
+ int (*in_range)(struct kvm_io_device *this, gpa_t addr);
+ void (*destructor)(struct kvm_io_device *this);
+
+ void *private;
+};
+
+static inline void kvm_iodevice_read(struct kvm_io_device *dev,
+ gpa_t addr,
+ int len,
+ void *val)
+{
+ dev->read(dev, addr, len, val);
+}
+
+static inline void kvm_iodevice_write(struct kvm_io_device *dev,
+ gpa_t addr,
+ int len,
+ const void *val)
+{
+ dev->write(dev, addr, len, val);
+}
+
+static inline int kvm_iodevice_inrange(struct kvm_io_device *dev, gpa_t addr)
+{
+ return dev->in_range(dev, addr);
+}
+
+static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
+{
+ if (dev->destructor)
+ dev->destructor(dev);
+}
+
+#endif /* __KVM_IODEV_H__ */
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 75f5f18..803b9c7 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -23,6 +23,7 @@
#define __IRQ_H
#include "kvm.h"
+#include "iodev.h"
typedef void irq_request_func(void *opaque, int level);
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 3b0ba5a..a1b7d1c 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -168,48 +168,6 @@ struct kvm_vcpu_stat {
u32 insn_emulation_fail;
};
-struct kvm_io_device {
- void (*read)(struct kvm_io_device *this,
- gpa_t addr,
- int len,
- void *val);
- void (*write)(struct kvm_io_device *this,
- gpa_t addr,
- int len,
- const void *val);
- int (*in_range)(struct kvm_io_device *this, gpa_t addr);
- void (*destructor)(struct kvm_io_device *this);
-
- void *private;
-};
-
-static inline void kvm_iodevice_read(struct kvm_io_device *dev,
- gpa_t addr,
- int len,
- void *val)
-{
- dev->read(dev, addr, len, val);
-}
-
-static inline void kvm_iodevice_write(struct kvm_io_device *dev,
- gpa_t addr,
- int len,
- const void *val)
-{
- dev->write(dev, addr, len, val);
-}
-
-static inline int kvm_iodevice_inrange(struct kvm_io_device *dev, gpa_t addr)
-{
- return dev->in_range(dev, addr);
-}
-
-static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
-{
- if (dev->destructor)
- dev->destructor(dev);
-}
-
/*
* It would be nice to use something smarter than a linear search, TBD...
* Thankfully we dont expect many devices to register (famous last words :),
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index b56ee34..8d4a06d 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -18,6 +18,7 @@
#include "kvm.h"
#include "x86.h"
#include "irq.h"
+#include "iodev.h"
#include <linux/kvm.h>
#include <linux/module.h>
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 28/54] KVM: Portability: Stop including x86-specific headers in kvm_main.c
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (25 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 27/54] KVM: Portability: Move IO device definitions to its " Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 29/54] KVM: Portability: Create kvm_arch_vcpu_runnable() function Avi Kivity
` (25 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Hollis Blanchard
From: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/i8259.c | 1 +
drivers/kvm/irq.h | 7 ++++++-
drivers/kvm/kvm.h | 9 ++++-----
drivers/kvm/kvm_main.c | 3 ---
drivers/kvm/x86.h | 8 ++++++++
5 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/kvm/i8259.c b/drivers/kvm/i8259.c
index f0dc2ee..b3cad63 100644
--- a/drivers/kvm/i8259.c
+++ b/drivers/kvm/i8259.c
@@ -27,6 +27,7 @@
*/
#include <linux/mm.h>
#include "irq.h"
+#include "kvm.h"
/*
* set irq level. If an edge is detected, then the IRR is set to 1
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 803b9c7..730a87c 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -22,9 +22,14 @@
#ifndef __IRQ_H
#define __IRQ_H
-#include "kvm.h"
+#include <linux/mm_types.h>
+#include <linux/hrtimer.h>
+#include <asm/kvm.h>
#include "iodev.h"
+struct kvm;
+struct kvm_vcpu;
+
typedef void irq_request_func(void *opaque, int level);
struct kvm_kpic_state {
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index a1b7d1c..0d3555b 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -288,11 +288,6 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
return pic_irqchip(kvm) != NULL;
}
-struct descriptor_table {
- u16 limit;
- unsigned long base;
-} __attribute__((packed));
-
/* The guest did something we don't support. */
#define pr_unimpl(vcpu, fmt, ...) \
do { \
@@ -457,4 +452,8 @@ struct kvm_stats_debugfs_item {
};
extern struct kvm_stats_debugfs_item debugfs_entries[];
+#if defined(CONFIG_X86)
+#include "x86.h"
+#endif
+
#endif
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 8d4a06d..7785c90 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -16,8 +16,6 @@
*/
#include "kvm.h"
-#include "x86.h"
-#include "irq.h"
#include "iodev.h"
#include <linux/kvm.h>
@@ -46,7 +44,6 @@
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <asm/desc.h>
#include <asm/pgtable.h>
MODULE_AUTHOR("Qumranet");
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index 78ab1e1..4b7acc7 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -12,6 +12,7 @@
#define KVM_X86_H
#include "kvm.h"
+#include "irq.h"
#include <linux/types.h>
#include <linux/mm.h>
@@ -19,6 +20,8 @@
#include <linux/kvm.h>
#include <linux/kvm_para.h>
+#include <asm/desc.h>
+
#define CR3_PAE_RESERVED_BITS ((X86_CR3_PWT | X86_CR3_PCD) - 1)
#define CR3_NONPAE_RESERVED_BITS ((PAGE_SIZE-1) & ~(X86_CR3_PWT | X86_CR3_PCD))
#define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS|0xFFFFFF0000000000ULL)
@@ -156,6 +159,11 @@ struct kvm_vcpu {
struct x86_emulate_ctxt emulate_ctxt;
};
+struct descriptor_table {
+ u16 limit;
+ unsigned long base;
+} __attribute__((packed));
+
struct kvm_x86_ops {
int (*cpu_has_kvm_support)(void); /* __init */
int (*disabled_by_bios)(void); /* __init */
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 29/54] KVM: Portability: Create kvm_arch_vcpu_runnable() function
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (26 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 28/54] KVM: Portability: Stop including x86-specific headers in kvm_main.c Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 30/54] KVM: Convert KVM from ->nopage() to ->fault() Avi Kivity
` (24 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Hollis Blanchard
From: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
This abstracts the detail of x86 hlt and INIT modes into a function.
Signed-off-by: Hollis Blanchard <hollisb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Acked-by: Carsten Otte <cotte-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm_main.c | 3 +--
drivers/kvm/x86.h | 7 +++++++
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 7785c90..3d1023c 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -643,8 +643,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
*/
while (!kvm_cpu_has_interrupt(vcpu)
&& !signal_pending(current)
- && vcpu->mp_state != VCPU_MP_STATE_RUNNABLE
- && vcpu->mp_state != VCPU_MP_STATE_SIPI_RECEIVED) {
+ && !kvm_arch_vcpu_runnable(vcpu)) {
set_current_state(TASK_INTERRUPTIBLE);
vcpu_put(vcpu);
schedule();
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index 4b7acc7..eed7964 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -471,4 +471,11 @@ static inline u32 get_rdx_init_val(void)
#define TSS_IOPB_SIZE (65536 / 8)
#define TSS_REDIRECTION_SIZE (256 / 8)
#define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 1)
+
+static inline int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+ return vcpu->mp_state == VCPU_MP_STATE_RUNNABLE
+ || vcpu->mp_state == VCPU_MP_STATE_SIPI_RECEIVED;
+}
+
#endif
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 30/54] KVM: Convert KVM from ->nopage() to ->fault()
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (27 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 29/54] KVM: Portability: Create kvm_arch_vcpu_runnable() function Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 31/54] KVM: MMU: Remove unused prev_shadow_ent variable from fetch() Avi Kivity
` (23 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: npiggin-l3A5Bk7waGM@public.gmane.org
From: npiggin-l3A5Bk7waGM@public.gmane.org <npiggin-l3A5Bk7waGM@public.gmane.org>
Signed-off-by: Nick Piggin <npiggin-l3A5Bk7waGM@public.gmane.org>
Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Cc: avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm_main.c | 42 +++++++++++++++---------------------------
1 files changed, 15 insertions(+), 27 deletions(-)
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 3d1023c..cfb27ef 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -662,30 +662,24 @@ void kvm_resched(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_resched);
-static struct page *kvm_vcpu_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type)
+static int kvm_vcpu_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct kvm_vcpu *vcpu = vma->vm_file->private_data;
- unsigned long pgoff;
struct page *page;
- pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
- if (pgoff == 0)
+ if (vmf->pgoff == 0)
page = virt_to_page(vcpu->run);
- else if (pgoff == KVM_PIO_PAGE_OFFSET)
+ else if (vmf->pgoff == KVM_PIO_PAGE_OFFSET)
page = virt_to_page(vcpu->pio_data);
else
- return NOPAGE_SIGBUS;
+ return VM_FAULT_SIGBUS;
get_page(page);
- if (type != NULL)
- *type = VM_FAULT_MINOR;
-
- return page;
+ vmf->page = page;
+ return 0;
}
static struct vm_operations_struct kvm_vcpu_vm_ops = {
- .nopage = kvm_vcpu_nopage,
+ .fault = kvm_vcpu_fault,
};
static int kvm_vcpu_mmap(struct file *file, struct vm_area_struct *vma)
@@ -976,31 +970,25 @@ out:
return r;
}
-static struct page *kvm_vm_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type)
+static int kvm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct kvm *kvm = vma->vm_file->private_data;
- unsigned long pgoff;
struct page *page;
- pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
- if (!kvm_is_visible_gfn(kvm, pgoff))
- return NOPAGE_SIGBUS;
+ if (!kvm_is_visible_gfn(kvm, vmf->pgoff))
+ return VM_FAULT_SIGBUS;
/* current->mm->mmap_sem is already held so call lockless version */
- page = __gfn_to_page(kvm, pgoff);
+ page = __gfn_to_page(kvm, vmf->pgoff);
if (is_error_page(page)) {
kvm_release_page_clean(page);
- return NOPAGE_SIGBUS;
+ return VM_FAULT_SIGBUS;
}
- if (type != NULL)
- *type = VM_FAULT_MINOR;
-
- return page;
+ vmf->page = page;
+ return 0;
}
static struct vm_operations_struct kvm_vm_vm_ops = {
- .nopage = kvm_vm_nopage,
+ .fault = kvm_vm_fault,
};
static int kvm_vm_mmap(struct file *file, struct vm_area_struct *vma)
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 31/54] KVM: MMU: Remove unused prev_shadow_ent variable from fetch()
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (28 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 30/54] KVM: Convert KVM from ->nopage() to ->fault() Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 32/54] KVM: Generalize exception injection mechanism Avi Kivity
` (22 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Marcelo Tosatti
From: Marcelo Tosatti <marcelo-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>
Signed-off-by: Marcelo Tosatti <mtosatti-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/paging_tmpl.h | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index b24bc7c..3c40a59 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -300,7 +300,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
hpa_t shadow_addr;
int level;
u64 *shadow_ent;
- u64 *prev_shadow_ent = NULL;
if (!is_present_pte(walker->pte))
return NULL;
@@ -326,7 +325,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
if (level == PT_PAGE_TABLE_LEVEL)
break;
shadow_addr = *shadow_ent & PT64_BASE_ADDR_MASK;
- prev_shadow_ent = shadow_ent;
continue;
}
@@ -355,7 +353,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
| PT_WRITABLE_MASK | PT_USER_MASK;
*shadow_ent = shadow_pte;
- prev_shadow_ent = shadow_ent;
}
FNAME(set_pte)(vcpu, walker->pte, shadow_ent,
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 32/54] KVM: Generalize exception injection mechanism
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (29 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 31/54] KVM: MMU: Remove unused prev_shadow_ent variable from fetch() Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:35 ` [PATCH 33/54] KVM: Replace page fault injection by the generalized exception queue Avi Kivity
` (21 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Instead of each subarch doing its own thing, add an API for queuing an
injection, and manage failed exception injection centerally (i.e., if
an inject failed due to a shadow page fault, we need to requeue it).
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/svm.c | 21 +++++++++++++++++++++
drivers/kvm/vmx.c | 20 ++++++++++++++++++++
drivers/kvm/x86.c | 33 ++++++++++++++++++++++++++++++++-
drivers/kvm/x86.h | 13 +++++++++++++
4 files changed, 86 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 04e6b39..f4c61c8 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -188,6 +188,25 @@ static void svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
vcpu->shadow_efer = efer;
}
+static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
+ bool has_error_code, u32 error_code)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ svm->vmcb->control.event_inj = nr
+ | SVM_EVTINJ_VALID
+ | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0)
+ | SVM_EVTINJ_TYPE_EXEPT;
+ svm->vmcb->control.event_inj_err = error_code;
+}
+
+static bool svm_exception_injected(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
+}
+
static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -1712,6 +1731,8 @@ static struct kvm_x86_ops svm_x86_ops = {
.patch_hypercall = svm_patch_hypercall,
.get_irq = svm_get_irq,
.set_irq = svm_set_irq,
+ .queue_exception = svm_queue_exception,
+ .exception_injected = svm_exception_injected,
.inject_pending_irq = svm_intr_assist,
.inject_pending_vectors = do_interrupt_requests,
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 8e43feb..1ec1c28 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -595,6 +595,24 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
vcpu->interrupt_window_open = 1;
}
+static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
+ bool has_error_code, u32 error_code)
+{
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ nr | INTR_TYPE_EXCEPTION
+ | (has_error_code ? INTR_INFO_DELIEVER_CODE_MASK : 0)
+ | INTR_INFO_VALID_MASK);
+ if (has_error_code)
+ vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+}
+
+static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
+}
+
static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
{
printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n",
@@ -2641,6 +2659,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
.patch_hypercall = vmx_patch_hypercall,
.get_irq = vmx_get_irq,
.set_irq = vmx_inject_irq,
+ .queue_exception = vmx_queue_exception,
+ .exception_injected = vmx_exception_injected,
.inject_pending_irq = vmx_intr_assist,
.inject_pending_vectors = do_interrupt_requests,
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index c9e4b67..11440d1 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -133,6 +133,32 @@ static void inject_gp(struct kvm_vcpu *vcpu)
kvm_x86_ops->inject_gp(vcpu, 0);
}
+void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
+{
+ WARN_ON(vcpu->exception.pending);
+ vcpu->exception.pending = true;
+ vcpu->exception.has_error_code = false;
+ vcpu->exception.nr = nr;
+}
+EXPORT_SYMBOL_GPL(kvm_queue_exception);
+
+void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
+{
+ WARN_ON(vcpu->exception.pending);
+ vcpu->exception.pending = true;
+ vcpu->exception.has_error_code = true;
+ vcpu->exception.nr = nr;
+ vcpu->exception.error_code = error_code;
+}
+EXPORT_SYMBOL_GPL(kvm_queue_exception_e);
+
+static void __queue_exception(struct kvm_vcpu *vcpu)
+{
+ kvm_x86_ops->queue_exception(vcpu, vcpu->exception.nr,
+ vcpu->exception.has_error_code,
+ vcpu->exception.error_code);
+}
+
/*
* Load the pae pdptrs. Return true is they are all valid.
*/
@@ -2370,7 +2396,9 @@ again:
goto out;
}
- if (irqchip_in_kernel(vcpu->kvm))
+ if (vcpu->exception.pending)
+ __queue_exception(vcpu);
+ else if (irqchip_in_kernel(vcpu->kvm))
kvm_x86_ops->inject_pending_irq(vcpu);
else
kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
@@ -2409,6 +2437,9 @@ again:
profile_hit(KVM_PROFILING, (void *)vcpu->rip);
}
+ if (vcpu->exception.pending && kvm_x86_ops->exception_injected(vcpu))
+ vcpu->exception.pending = false;
+
r = kvm_x86_ops->handle_exit(kvm_run, vcpu);
if (r > 0) {
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index eed7964..1e71668 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -139,6 +139,13 @@ struct kvm_vcpu {
struct kvm_pio_request pio;
void *pio_data;
+ struct kvm_queued_exception {
+ bool pending;
+ bool has_error_code;
+ u8 nr;
+ u32 error_code;
+ } exception;
+
struct {
int active;
u8 save_iopl;
@@ -224,6 +231,9 @@ struct kvm_x86_ops {
unsigned char *hypercall_addr);
int (*get_irq)(struct kvm_vcpu *vcpu);
void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
+ void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
+ bool has_error_code, u32 error_code);
+ bool (*exception_injected)(struct kvm_vcpu *vcpu);
void (*inject_pending_irq)(struct kvm_vcpu *vcpu);
void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
struct kvm_run *run);
@@ -294,6 +304,9 @@ void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l);
int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
+void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
+void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
+
void fx_init(struct kvm_vcpu *vcpu);
int emulator_read_std(unsigned long addr,
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 33/54] KVM: Replace page fault injection by the generalized exception queue
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (30 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 32/54] KVM: Generalize exception injection mechanism Avi Kivity
@ 2008-01-01 15:35 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 34/54] KVM: Replace #GP " Avi Kivity
` (20 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:35 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 2 +-
drivers/kvm/svm.c | 35 -----------------------------------
drivers/kvm/vmx.c | 32 --------------------------------
drivers/kvm/x86.c | 17 ++++++++++++++++-
drivers/kvm/x86.h | 4 ++--
5 files changed, 19 insertions(+), 71 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 9b9d1b6..62a7415 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -1081,7 +1081,7 @@ static void inject_page_fault(struct kvm_vcpu *vcpu,
u64 addr,
u32 err_code)
{
- kvm_x86_ops->inject_page_fault(vcpu, addr, err_code);
+ kvm_inject_page_fault(vcpu, addr, err_code);
}
static void paging_free(struct kvm_vcpu *vcpu)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index f4c61c8..ce77f15 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -225,12 +225,6 @@ static void inject_ud(struct kvm_vcpu *vcpu)
UD_VECTOR;
}
-static int is_page_fault(uint32_t info)
-{
- info &= SVM_EVTINJ_VEC_MASK | SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
- return info == (PF_VECTOR | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT);
-}
-
static int is_external_interrupt(u32 info)
{
info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
@@ -1624,34 +1618,6 @@ static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
}
}
-static void svm_inject_page_fault(struct kvm_vcpu *vcpu,
- unsigned long addr,
- uint32_t err_code)
-{
- struct vcpu_svm *svm = to_svm(vcpu);
- uint32_t exit_int_info = svm->vmcb->control.exit_int_info;
-
- ++vcpu->stat.pf_guest;
-
- if (is_page_fault(exit_int_info)) {
-
- svm->vmcb->control.event_inj_err = 0;
- svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
- SVM_EVTINJ_VALID_ERR |
- SVM_EVTINJ_TYPE_EXEPT |
- DF_VECTOR;
- return;
- }
- vcpu->cr2 = addr;
- svm->vmcb->save.cr2 = addr;
- svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
- SVM_EVTINJ_VALID_ERR |
- SVM_EVTINJ_TYPE_EXEPT |
- PF_VECTOR;
- svm->vmcb->control.event_inj_err = err_code;
-}
-
-
static int is_disabled(void)
{
u64 vm_cr;
@@ -1721,7 +1687,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.set_rflags = svm_set_rflags,
.tlb_flush = svm_flush_tlb,
- .inject_page_fault = svm_inject_page_fault,
.inject_gp = svm_inject_gp,
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 1ec1c28..20e9dfc 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -2487,37 +2487,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
asm("int $2");
}
-static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
- unsigned long addr,
- u32 err_code)
-{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
- u32 vect_info = vmx->idt_vectoring_info;
-
- ++vcpu->stat.pf_guest;
-
- if (is_page_fault(vect_info)) {
- printk(KERN_DEBUG "inject_page_fault: "
- "double fault 0x%lx @ 0x%lx\n",
- addr, vmcs_readl(GUEST_RIP));
- vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, 0);
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- DF_VECTOR |
- INTR_TYPE_EXCEPTION |
- INTR_INFO_DELIEVER_CODE_MASK |
- INTR_INFO_VALID_MASK);
- return;
- }
- vcpu->cr2 = addr;
- vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, err_code);
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- PF_VECTOR |
- INTR_TYPE_EXCEPTION |
- INTR_INFO_DELIEVER_CODE_MASK |
- INTR_INFO_VALID_MASK);
-
-}
-
static void vmx_free_vmcs(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2649,7 +2618,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.set_rflags = vmx_set_rflags,
.tlb_flush = vmx_flush_tlb,
- .inject_page_fault = vmx_inject_page_fault,
.inject_gp = vmx_inject_gp,
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 11440d1..dc007a3 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -142,6 +142,21 @@ void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
}
EXPORT_SYMBOL_GPL(kvm_queue_exception);
+void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long addr,
+ u32 error_code)
+{
+ ++vcpu->stat.pf_guest;
+ if (vcpu->exception.pending && vcpu->exception.nr == PF_VECTOR) {
+ printk(KERN_DEBUG "kvm: inject_page_fault:"
+ " double fault 0x%lx\n", addr);
+ vcpu->exception.nr = DF_VECTOR;
+ vcpu->exception.error_code = 0;
+ return;
+ }
+ vcpu->cr2 = addr;
+ kvm_queue_exception_e(vcpu, PF_VECTOR, error_code);
+}
+
void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code)
{
WARN_ON(vcpu->exception.pending);
@@ -1601,7 +1616,7 @@ static int emulator_write_emulated_onepage(unsigned long addr,
gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
if (gpa == UNMAPPED_GVA) {
- kvm_x86_ops->inject_page_fault(vcpu, addr, 2);
+ kvm_inject_page_fault(vcpu, addr, 2);
return X86EMUL_PROPAGATE_FAULT;
}
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index 1e71668..d3ac4e2 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -219,8 +219,6 @@ struct kvm_x86_ops {
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
void (*tlb_flush)(struct kvm_vcpu *vcpu);
- void (*inject_page_fault)(struct kvm_vcpu *vcpu,
- unsigned long addr, u32 err_code);
void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code);
@@ -306,6 +304,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
+void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2,
+ u32 error_code);
void fx_init(struct kvm_vcpu *vcpu);
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 34/54] KVM: Replace #GP injection by the generalized exception queue
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (31 preceding siblings ...)
2008-01-01 15:35 ` [PATCH 33/54] KVM: Replace page fault injection by the generalized exception queue Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 35/54] KVM: Use generalized exception queue for injecting #UD Avi Kivity
` (19 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/svm.c | 17 ++---------------
drivers/kvm/vmx.c | 18 ++----------------
drivers/kvm/x86.c | 43 +++++++++++++++++++------------------------
drivers/kvm/x86.h | 7 +++++--
drivers/kvm/x86_emulate.c | 4 ++--
5 files changed, 30 insertions(+), 59 deletions(-)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index ce77f15..b896614 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -207,17 +207,6 @@ static bool svm_exception_injected(struct kvm_vcpu *vcpu)
return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
}
-static void svm_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
-{
- struct vcpu_svm *svm = to_svm(vcpu);
-
- svm->vmcb->control.event_inj = SVM_EVTINJ_VALID |
- SVM_EVTINJ_VALID_ERR |
- SVM_EVTINJ_TYPE_EXEPT |
- GP_VECTOR;
- svm->vmcb->control.event_inj_err = error_code;
-}
-
static void inject_ud(struct kvm_vcpu *vcpu)
{
to_svm(vcpu)->vmcb->control.event_inj = SVM_EVTINJ_VALID |
@@ -1115,7 +1104,7 @@ static int rdmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
u64 data;
if (svm_get_msr(&svm->vcpu, ecx, &data))
- svm_inject_gp(&svm->vcpu, 0);
+ kvm_inject_gp(&svm->vcpu, 0);
else {
svm->vmcb->save.rax = data & 0xffffffff;
svm->vcpu.regs[VCPU_REGS_RDX] = data >> 32;
@@ -1176,7 +1165,7 @@ static int wrmsr_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
| ((u64)(svm->vcpu.regs[VCPU_REGS_RDX] & -1u) << 32);
svm->next_rip = svm->vmcb->save.rip + 2;
if (svm_set_msr(&svm->vcpu, ecx, data))
- svm_inject_gp(&svm->vcpu, 0);
+ kvm_inject_gp(&svm->vcpu, 0);
else
skip_emulated_instruction(&svm->vcpu);
return 1;
@@ -1688,8 +1677,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.tlb_flush = svm_flush_tlb,
- .inject_gp = svm_inject_gp,
-
.run = svm_vcpu_run,
.handle_exit = handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 20e9dfc..92660db 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -613,18 +613,6 @@ static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
}
-static void vmx_inject_gp(struct kvm_vcpu *vcpu, unsigned error_code)
-{
- printk(KERN_DEBUG "inject_general_protection: rip 0x%lx\n",
- vmcs_readl(GUEST_RIP));
- vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- GP_VECTOR |
- INTR_TYPE_EXCEPTION |
- INTR_INFO_DELIEVER_CODE_MASK |
- INTR_INFO_VALID_MASK);
-}
-
static void vmx_inject_ud(struct kvm_vcpu *vcpu)
{
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
@@ -2083,7 +2071,7 @@ static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
u64 data;
if (vmx_get_msr(vcpu, ecx, &data)) {
- vmx_inject_gp(vcpu, 0);
+ kvm_inject_gp(vcpu, 0);
return 1;
}
@@ -2101,7 +2089,7 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
| ((u64)(vcpu->regs[VCPU_REGS_RDX] & -1u) << 32);
if (vmx_set_msr(vcpu, ecx, data) != 0) {
- vmx_inject_gp(vcpu, 0);
+ kvm_inject_gp(vcpu, 0);
return 1;
}
@@ -2619,8 +2607,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.tlb_flush = vmx_flush_tlb,
- .inject_gp = vmx_inject_gp,
-
.run = vmx_vcpu_run,
.handle_exit = kvm_handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index dc007a3..6deb052 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -128,11 +128,6 @@ void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data)
}
EXPORT_SYMBOL_GPL(kvm_set_apic_base);
-static void inject_gp(struct kvm_vcpu *vcpu)
-{
- kvm_x86_ops->inject_gp(vcpu, 0);
-}
-
void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr)
{
WARN_ON(vcpu->exception.pending);
@@ -232,20 +227,20 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
if (cr0 & CR0_RESERVED_BITS) {
printk(KERN_DEBUG "set_cr0: 0x%lx #GP, reserved bits 0x%lx\n",
cr0, vcpu->cr0);
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) {
printk(KERN_DEBUG "set_cr0: #GP, CD == 0 && NW == 1\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) {
printk(KERN_DEBUG "set_cr0: #GP, set PG flag "
"and a clear PE flag\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
@@ -257,14 +252,14 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
if (!is_pae(vcpu)) {
printk(KERN_DEBUG "set_cr0: #GP, start paging "
"in long mode while PAE is disabled\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
if (cs_l) {
printk(KERN_DEBUG "set_cr0: #GP, start paging "
"in long mode while CS.L == 1\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
@@ -273,7 +268,7 @@ void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
if (is_pae(vcpu) && !load_pdptrs(vcpu, vcpu->cr3)) {
printk(KERN_DEBUG "set_cr0: #GP, pdptrs "
"reserved bits\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
@@ -299,7 +294,7 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
{
if (cr4 & CR4_RESERVED_BITS) {
printk(KERN_DEBUG "set_cr4: #GP, reserved bits\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
@@ -307,19 +302,19 @@ void set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
if (!(cr4 & X86_CR4_PAE)) {
printk(KERN_DEBUG "set_cr4: #GP, clearing PAE while "
"in long mode\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
} else if (is_paging(vcpu) && !is_pae(vcpu) && (cr4 & X86_CR4_PAE)
&& !load_pdptrs(vcpu, vcpu->cr3)) {
printk(KERN_DEBUG "set_cr4: #GP, pdptrs reserved bits\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
if (cr4 & X86_CR4_VMXE) {
printk(KERN_DEBUG "set_cr4: #GP, setting VMXE\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
kvm_x86_ops->set_cr4(vcpu, cr4);
@@ -340,7 +335,7 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
if (is_long_mode(vcpu)) {
if (cr3 & CR3_L_MODE_RESERVED_BITS) {
printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
} else {
@@ -348,13 +343,13 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
if (cr3 & CR3_PAE_RESERVED_BITS) {
printk(KERN_DEBUG
"set_cr3: #GP, reserved bits\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
if (is_paging(vcpu) && !load_pdptrs(vcpu, cr3)) {
printk(KERN_DEBUG "set_cr3: #GP, pdptrs "
"reserved bits\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
}
@@ -375,7 +370,7 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
* to debug) behavior on the guest side.
*/
if (unlikely(!gfn_to_memslot(vcpu->kvm, cr3 >> PAGE_SHIFT)))
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
else {
vcpu->cr3 = cr3;
vcpu->mmu.new_cr3(vcpu);
@@ -388,7 +383,7 @@ void set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8)
{
if (cr8 & CR8_RESERVED_BITS) {
printk(KERN_DEBUG "set_cr8: #GP, reserved bits 0x%lx\n", cr8);
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
if (irqchip_in_kernel(vcpu->kvm))
@@ -436,14 +431,14 @@ static void set_efer(struct kvm_vcpu *vcpu, u64 efer)
if (efer & EFER_RESERVED_BITS) {
printk(KERN_DEBUG "set_efer: 0x%llx #GP, reserved bits\n",
efer);
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
if (is_paging(vcpu)
&& (vcpu->shadow_efer & EFER_LME) != (efer & EFER_LME)) {
printk(KERN_DEBUG "set_efer: #GP, change LME while paging\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return;
}
@@ -2047,7 +2042,7 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
* String I/O in reverse. Yuck. Kill the guest, fix later.
*/
pr_unimpl(vcpu, "guest string pio down\n");
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
return 1;
}
vcpu->run->io.count = now;
@@ -2062,7 +2057,7 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
vcpu->pio.guest_pages[i] = page;
mutex_unlock(&vcpu->kvm->lock);
if (!page) {
- inject_gp(vcpu);
+ kvm_inject_gp(vcpu, 0);
free_pio_guest_pages(vcpu);
return 1;
}
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
index d3ac4e2..78396d6 100644
--- a/drivers/kvm/x86.h
+++ b/drivers/kvm/x86.h
@@ -220,8 +220,6 @@ struct kvm_x86_ops {
void (*tlb_flush)(struct kvm_vcpu *vcpu);
- void (*inject_gp)(struct kvm_vcpu *vcpu, unsigned err_code);
-
void (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run);
int (*handle_exit)(struct kvm_run *run, struct kvm_vcpu *vcpu);
void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
@@ -467,6 +465,11 @@ static inline u32 get_rdx_init_val(void)
return 0x600; /* P6 family */
}
+static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
+{
+ kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
+}
+
#define ASM_VMX_VMCLEAR_RAX ".byte 0x66, 0x0f, 0xc7, 0x30"
#define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2"
#define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3"
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 3e3eba7..2e259a8 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1779,7 +1779,7 @@ twobyte_insn:
| ((u64)c->regs[VCPU_REGS_RDX] << 32);
rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data);
if (rc) {
- kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
+ kvm_inject_gp(ctxt->vcpu, 0);
c->eip = ctxt->vcpu->rip;
}
rc = X86EMUL_CONTINUE;
@@ -1789,7 +1789,7 @@ twobyte_insn:
/* rdmsr */
rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data);
if (rc) {
- kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
+ kvm_inject_gp(ctxt->vcpu, 0);
c->eip = ctxt->vcpu->rip;
} else {
c->regs[VCPU_REGS_RAX] = (u32)msr_data;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 35/54] KVM: Use generalized exception queue for injecting #UD
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (32 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 34/54] KVM: Replace #GP " Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 36/54] KVM: x86 emulator: fix eflags preparation for emulation Avi Kivity
` (18 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/svm.c | 12 ++----------
drivers/kvm/vmx.c | 11 +----------
2 files changed, 3 insertions(+), 20 deletions(-)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index b896614..8b1cc60 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -207,13 +207,6 @@ static bool svm_exception_injected(struct kvm_vcpu *vcpu)
return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
}
-static void inject_ud(struct kvm_vcpu *vcpu)
-{
- to_svm(vcpu)->vmcb->control.event_inj = SVM_EVTINJ_VALID |
- SVM_EVTINJ_TYPE_EXEPT |
- UD_VECTOR;
-}
-
static int is_external_interrupt(u32 info)
{
info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
@@ -948,8 +941,7 @@ static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
er = emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0);
if (er != EMULATE_DONE)
- inject_ud(&svm->vcpu);
-
+ kvm_queue_exception(&svm->vcpu, UD_VECTOR);
return 1;
}
@@ -1027,7 +1019,7 @@ static int vmmcall_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
static int invalid_op_interception(struct vcpu_svm *svm,
struct kvm_run *kvm_run)
{
- inject_ud(&svm->vcpu);
+ kvm_queue_exception(&svm->vcpu, UD_VECTOR);
return 1;
}
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 92660db..aa6bf2b 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -613,14 +613,6 @@ static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
return !(vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK);
}
-static void vmx_inject_ud(struct kvm_vcpu *vcpu)
-{
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- UD_VECTOR |
- INTR_TYPE_EXCEPTION |
- INTR_INFO_VALID_MASK);
-}
-
/*
* Swap MSR entry in host/guest MSR entry array.
*/
@@ -1866,8 +1858,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (is_invalid_opcode(intr_info)) {
er = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
if (er != EMULATE_DONE)
- vmx_inject_ud(vcpu);
-
+ kvm_queue_exception(vcpu, UD_VECTOR);
return 1;
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 36/54] KVM: x86 emulator: fix eflags preparation for emulation
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (33 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 35/54] KVM: Use generalized exception queue for injecting #UD Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 37/54] KVM: VMX: Avoid exit when setting cr8 if the local apic is in the kernel Avi Kivity
` (17 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
We prepare eflags for the emulated instruction, then clobber it with an 'andl'.
Fix by popping eflags as the last thing in the sequence.
Patch taken from Xen (16143:959b4b92b6bf)
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 30 +++++++++++++++---------------
1 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 2e259a8..f423b0e 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -256,21 +256,21 @@ static u16 twobyte_table[256] = {
#define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF)
/* Before executing instruction: restore necessary bits in EFLAGS. */
-#define _PRE_EFLAGS(_sav, _msk, _tmp) \
- /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); */ \
- "push %"_sav"; " \
- "movl %"_msk",%"_LO32 _tmp"; " \
- "andl %"_LO32 _tmp",("_STK"); " \
- "pushf; " \
- "notl %"_LO32 _tmp"; " \
- "andl %"_LO32 _tmp",("_STK"); " \
- "pop %"_tmp"; " \
- "orl %"_LO32 _tmp",("_STK"); " \
- "popf; " \
- /* _sav &= ~msk; */ \
- "movl %"_msk",%"_LO32 _tmp"; " \
- "notl %"_LO32 _tmp"; " \
- "andl %"_LO32 _tmp",%"_sav"; "
+#define _PRE_EFLAGS(_sav, _msk, _tmp) \
+ /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); _sav &= ~_msk; */ \
+ "movl %"_sav",%"_LO32 _tmp"; " \
+ "push %"_tmp"; " \
+ "push %"_tmp"; " \
+ "movl %"_msk",%"_LO32 _tmp"; " \
+ "andl %"_LO32 _tmp",("_STK"); " \
+ "pushf; " \
+ "notl %"_LO32 _tmp"; " \
+ "andl %"_LO32 _tmp",("_STK"); " \
+ "andl %"_LO32 _tmp","__stringify(BITS_PER_LONG/4)"("_STK"); " \
+ "pop %"_tmp"; " \
+ "orl %"_LO32 _tmp",("_STK"); " \
+ "popf; " \
+ "pop %"_sav"; "
/* After executing instruction: write-back necessary bits in EFLAGS. */
#define _POST_EFLAGS(_sav, _msk, _tmp) \
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 37/54] KVM: VMX: Avoid exit when setting cr8 if the local apic is in the kernel
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (34 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 36/54] KVM: x86 emulator: fix eflags preparation for emulation Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 38/54] KVM: SVM: Emulate read/write access to cr8 Avi Kivity
` (16 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
With apic in userspace, we must exit to userspace after a cr8 write in order
to update the tpr. But if the apic is in the kernel, the exit is unnecessary.
Noticed by Joerg Roedel.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/vmx.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index aa6bf2b..548e3a5 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1973,6 +1973,8 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
vcpu_load_rsp_rip(vcpu);
set_cr8(vcpu, vcpu->regs[reg]);
skip_emulated_instruction(vcpu);
+ if (irqchip_in_kernel(vcpu->kvm))
+ return 1;
kvm_run->exit_reason = KVM_EXIT_SET_TPR;
return 0;
};
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 38/54] KVM: SVM: Emulate read/write access to cr8
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (35 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 37/54] KVM: VMX: Avoid exit when setting cr8 if the local apic is in the kernel Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 39/54] KVM: x86 emulator: Fix stack instructions on 64-bit mode Avi Kivity
` (15 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Joerg Roedel
From: Joerg Roedel <jroedel-Ug2OvFXVNAT2eFz/2MeuCQ@public.gmane.org>
This patch adds code to emulate the access to the cr8 register to the x86
instruction emulator in kvm. This is needed on svm, where there is no
hardware decode for control register access.
Signed-off-by: Joerg Roedel <joerg.roedel-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Markus Rechberger <markus.rechberger-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 6deb052..9db4e32 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -2236,6 +2236,8 @@ unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
return vcpu->cr3;
case 4:
return vcpu->cr4;
+ case 8:
+ return get_cr8(vcpu);
default:
vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
return 0;
@@ -2259,6 +2261,9 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
case 4:
set_cr4(vcpu, mk_cr_64(vcpu->cr4, val));
break;
+ case 8:
+ set_cr8(vcpu, val & 0xfUL);
+ break;
default:
vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 39/54] KVM: x86 emulator: Fix stack instructions on 64-bit mode
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (36 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 38/54] KVM: SVM: Emulate read/write access to cr8 Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 40/54] KVM: SVM: Trap access to the cr8 register Avi Kivity
` (14 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Stack instructions are always 64-bit on 64-bit mode; many of the
emulated stack instructions did not take that into account. Fix by
adding a 'Stack' bitflag and setting the operand size appropriately
during the decode stage (except for 'push r/m', which is in a group
with a few other instructions, so it gets its own treatment).
This fixes random crashes on Vista x64.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/x86_emulate.c | 27 +++++++++++++++------------
1 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index f423b0e..0a6ab06 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -65,6 +65,7 @@
#define BitOp (1<<8)
#define MemAbs (1<<9) /* Memory operand is absolute displacement */
#define String (1<<10) /* String instruction (rep capable) */
+#define Stack (1<<11) /* Stack instruction (push/pop) */
static u16 opcode_table[256] = {
/* 0x00 - 0x07 */
@@ -104,14 +105,16 @@ static u16 opcode_table[256] = {
/* 0x48 - 0x4F */
DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
/* 0x50 - 0x57 */
- SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg,
+ SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack,
+ SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack,
/* 0x58 - 0x5F */
- DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
+ DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack,
+ DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack,
/* 0x60 - 0x67 */
0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
0, 0, 0, 0,
/* 0x68 - 0x6F */
- 0, 0, ImplicitOps|Mov, 0,
+ 0, 0, ImplicitOps | Mov | Stack, 0,
SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* insb, insw/insd */
SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* outsb, outsw/outsd */
/* 0x70 - 0x77 */
@@ -128,9 +131,10 @@ static u16 opcode_table[256] = {
/* 0x88 - 0x8F */
ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov,
ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
- 0, ModRM | DstReg, 0, DstMem | SrcNone | ModRM | Mov,
+ 0, ModRM | DstReg, 0, DstMem | SrcNone | ModRM | Mov | Stack,
/* 0x90 - 0x9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps, ImplicitOps, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0,
/* 0xA0 - 0xA7 */
ByteOp | DstReg | SrcMem | Mov | MemAbs, DstReg | SrcMem | Mov | MemAbs,
ByteOp | DstMem | SrcReg | Mov | MemAbs, DstMem | SrcReg | Mov | MemAbs,
@@ -144,7 +148,7 @@ static u16 opcode_table[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xC0 - 0xC7 */
ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
- 0, ImplicitOps, 0, 0,
+ 0, ImplicitOps | Stack, 0, 0,
ByteOp | DstMem | SrcImm | ModRM | Mov, DstMem | SrcImm | ModRM | Mov,
/* 0xC8 - 0xCF */
0, 0, 0, 0, 0, 0, 0, 0,
@@ -157,7 +161,8 @@ static u16 opcode_table[256] = {
/* 0xE0 - 0xE7 */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xE8 - 0xEF */
- ImplicitOps, SrcImm|ImplicitOps, 0, SrcImmByte|ImplicitOps, 0, 0, 0, 0,
+ ImplicitOps | Stack, SrcImm|ImplicitOps, 0, SrcImmByte|ImplicitOps,
+ 0, 0, 0, 0,
/* 0xF0 - 0xF7 */
0, 0, 0, 0,
ImplicitOps, ImplicitOps,
@@ -868,6 +873,9 @@ done_prefixes:
}
}
+ if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
+ c->op_bytes = 8;
+
/* ModRM and SIB bytes. */
if (c->d & ModRM)
rc = decode_modrm(ctxt, ops);
@@ -988,11 +996,6 @@ static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
struct decode_cache *c = &ctxt->decode;
int rc;
- /* 64-bit mode: POP always pops a 64-bit operand. */
-
- if (ctxt->mode == X86EMUL_MODE_PROT64)
- c->dst.bytes = 8;
-
rc = ops->read_std(register_address(ctxt->ss_base,
c->regs[VCPU_REGS_RSP]),
&c->dst.val, c->dst.bytes, ctxt->vcpu);
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 40/54] KVM: SVM: Trap access to the cr8 register
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (37 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 39/54] KVM: x86 emulator: Fix stack instructions on 64-bit mode Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 41/54] KVM: MMU: Use cmpxchg for pte updates on walk_addr() Avi Kivity
` (13 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Later we may be able to use the virtual tpr feature, but for now,
just trap it.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/svm.c | 8 ++++++--
drivers/kvm/svm.h | 1 +
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 8b1cc60..677b525 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -449,11 +449,13 @@ static void init_vmcb(struct vmcb *vmcb)
control->intercept_cr_read = INTERCEPT_CR0_MASK |
INTERCEPT_CR3_MASK |
- INTERCEPT_CR4_MASK;
+ INTERCEPT_CR4_MASK |
+ INTERCEPT_CR8_MASK;
control->intercept_cr_write = INTERCEPT_CR0_MASK |
INTERCEPT_CR3_MASK |
- INTERCEPT_CR4_MASK;
+ INTERCEPT_CR4_MASK |
+ INTERCEPT_CR8_MASK;
control->intercept_dr_read = INTERCEPT_DR0_MASK |
INTERCEPT_DR1_MASK |
@@ -1195,10 +1197,12 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_READ_CR0] = emulate_on_interception,
[SVM_EXIT_READ_CR3] = emulate_on_interception,
[SVM_EXIT_READ_CR4] = emulate_on_interception,
+ [SVM_EXIT_READ_CR8] = emulate_on_interception,
/* for now: */
[SVM_EXIT_WRITE_CR0] = emulate_on_interception,
[SVM_EXIT_WRITE_CR3] = emulate_on_interception,
[SVM_EXIT_WRITE_CR4] = emulate_on_interception,
+ [SVM_EXIT_WRITE_CR8] = emulate_on_interception,
[SVM_EXIT_READ_DR0] = emulate_on_interception,
[SVM_EXIT_READ_DR1] = emulate_on_interception,
[SVM_EXIT_READ_DR2] = emulate_on_interception,
diff --git a/drivers/kvm/svm.h b/drivers/kvm/svm.h
index 5fa277c..5fd5049 100644
--- a/drivers/kvm/svm.h
+++ b/drivers/kvm/svm.h
@@ -204,6 +204,7 @@ struct __attribute__ ((__packed__)) vmcb {
#define INTERCEPT_CR0_MASK 1
#define INTERCEPT_CR3_MASK (1 << 3)
#define INTERCEPT_CR4_MASK (1 << 4)
+#define INTERCEPT_CR8_MASK (1 << 8)
#define INTERCEPT_DR0_MASK 1
#define INTERCEPT_DR1_MASK (1 << 1)
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 41/54] KVM: MMU: Use cmpxchg for pte updates on walk_addr()
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (38 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 40/54] KVM: SVM: Trap access to the cr8 register Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 42/54] KVM: MMU: Simplify calculation of pte access Avi Kivity
` (12 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Marcelo Tosatti
From: Marcelo Tosatti <marcelo-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>
In preparation for multi-threaded guest pte walking, use cmpxchg()
when updating guest pte's. This guarantees that the assignment of the
dirty bit can't be lost if two CPU's are faulting the same address
simultaneously.
[avi: fix kunmap_atomic() parameters]
Signed-off-by: Marcelo Tosatti <mtosatti-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/paging_tmpl.h | 36 ++++++++++++++++++++++++++++++++++--
1 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 3c40a59..8086f82 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -34,7 +34,9 @@
#define PT_LEVEL_BITS PT64_LEVEL_BITS
#ifdef CONFIG_X86_64
#define PT_MAX_FULL_LEVELS 4
+ #define CMPXCHG cmpxchg
#else
+ #define CMPXCHG cmpxchg64
#define PT_MAX_FULL_LEVELS 2
#endif
#elif PTTYPE == 32
@@ -48,6 +50,7 @@
#define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
#define PT_LEVEL_BITS PT32_LEVEL_BITS
#define PT_MAX_FULL_LEVELS 2
+ #define CMPXCHG cmpxchg
#else
#error Invalid PTTYPE value
#endif
@@ -78,6 +81,26 @@ static gfn_t gpte_to_gfn_pde(pt_element_t gpte)
return (gpte & PT_DIR_BASE_ADDR_MASK) >> PAGE_SHIFT;
}
+static bool FNAME(cmpxchg_gpte)(struct kvm *kvm,
+ gfn_t table_gfn, unsigned index,
+ pt_element_t orig_pte, pt_element_t new_pte)
+{
+ pt_element_t ret;
+ pt_element_t *table;
+ struct page *page;
+
+ page = gfn_to_page(kvm, table_gfn);
+ table = kmap_atomic(page, KM_USER0);
+
+ ret = CMPXCHG(&table[index], orig_pte, new_pte);
+
+ kunmap_atomic(table, KM_USER0);
+
+ kvm_release_page_dirty(page);
+
+ return (ret != orig_pte);
+}
+
/*
* Fetch a guest pte for a guest virtual address
*/
@@ -91,6 +114,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
gpa_t pte_gpa;
pgprintk("%s: addr %lx\n", __FUNCTION__, addr);
+walk:
walker->level = vcpu->mmu.root_level;
pte = vcpu->cr3;
#if PTTYPE == 64
@@ -135,8 +159,10 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
if (!(pte & PT_ACCESSED_MASK)) {
mark_page_dirty(vcpu->kvm, table_gfn);
+ if (FNAME(cmpxchg_gpte)(vcpu->kvm, table_gfn,
+ index, pte, pte|PT_ACCESSED_MASK))
+ goto walk;
pte |= PT_ACCESSED_MASK;
- kvm_write_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte));
}
if (walker->level == PT_PAGE_TABLE_LEVEL) {
@@ -159,9 +185,14 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
}
if (write_fault && !is_dirty_pte(pte)) {
+ bool ret;
+
mark_page_dirty(vcpu->kvm, table_gfn);
+ ret = FNAME(cmpxchg_gpte)(vcpu->kvm, table_gfn, index, pte,
+ pte|PT_DIRTY_MASK);
+ if (ret)
+ goto walk;
pte |= PT_DIRTY_MASK;
- kvm_write_guest(vcpu->kvm, pte_gpa, &pte, sizeof(pte));
kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&pte, sizeof(pte));
}
@@ -484,3 +515,4 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
#undef PT_MAX_FULL_LEVELS
#undef gpte_to_gfn
#undef gpte_to_gfn_pde
+#undef CMPXCHG
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 42/54] KVM: MMU: Simplify calculation of pte access
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (39 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 41/54] KVM: MMU: Use cmpxchg for pte updates on walk_addr() Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 43/54] KVM: MMU: Set nx bit correctly on shadow ptes Avi Kivity
` (11 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
The nx bit is awkwardly placed in the 63rd bit position; furthermore it
has a reversed meaning compared to the other bits, which means we can't use
a bitwise and to calculate compounded access masks.
So, we simplify things by creating a new 3-bit exec/write/user access word,
and doing all calculations in that.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 14 +++++++---
drivers/kvm/paging_tmpl.h | 58 +++++++++++++++++++++++++-------------------
2 files changed, 43 insertions(+), 29 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 62a7415..f8a2137 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -85,7 +85,8 @@ static int dbg = 1;
#define PT_PAGE_SIZE_MASK (1ULL << 7)
#define PT_PAT_MASK (1ULL << 7)
#define PT_GLOBAL_MASK (1ULL << 8)
-#define PT64_NX_MASK (1ULL << 63)
+#define PT64_NX_SHIFT 63
+#define PT64_NX_MASK (1ULL << PT64_NX_SHIFT)
#define PT_PAT_SHIFT 7
#define PT_DIR_PAT_SHIFT 12
@@ -153,6 +154,11 @@ static int dbg = 1;
#define RMAP_EXT 4
+#define ACC_EXEC_MASK 1
+#define ACC_WRITE_MASK PT_WRITABLE_MASK
+#define ACC_USER_MASK PT_USER_MASK
+#define ACC_ALL (ACC_EXEC_MASK | ACC_WRITE_MASK | ACC_USER_MASK)
+
struct kvm_rmap_desc {
u64 *shadow_ptes[RMAP_EXT];
struct kvm_rmap_desc *more;
@@ -921,7 +927,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, struct page *page)
>> PAGE_SHIFT;
new_table = kvm_mmu_get_page(vcpu, pseudo_gfn,
v, level - 1,
- 1, 3, &table[index]);
+ 1, ACC_ALL, &table[index]);
if (!new_table) {
pgprintk("nonpaging_map: ENOMEM\n");
kvm_release_page_clean(page);
@@ -988,7 +994,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
ASSERT(!VALID_PAGE(root));
sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
- PT64_ROOT_LEVEL, 0, 0, NULL);
+ PT64_ROOT_LEVEL, 0, ACC_ALL, NULL);
root = __pa(sp->spt);
++sp->root_count;
vcpu->mmu.root_hpa = root;
@@ -1009,7 +1015,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
root_gfn = 0;
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
PT32_ROOT_LEVEL, !is_paging(vcpu),
- 0, NULL);
+ ACC_ALL, NULL);
root = __pa(sp->spt);
++sp->root_count;
vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK;
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 8086f82..7688cbf 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -66,7 +66,8 @@ struct guest_walker {
int level;
gfn_t table_gfn[PT_MAX_FULL_LEVELS];
pt_element_t pte;
- pt_element_t inherited_ar;
+ unsigned pt_access;
+ unsigned pte_access;
gfn_t gfn;
u32 error_code;
};
@@ -110,7 +111,7 @@ static int FNAME(walk_addr)(struct guest_walker *walker,
{
pt_element_t pte;
gfn_t table_gfn;
- unsigned index;
+ unsigned index, pt_access, pte_access;
gpa_t pte_gpa;
pgprintk("%s: addr %lx\n", __FUNCTION__, addr);
@@ -128,7 +129,7 @@ walk:
ASSERT((!is_long_mode(vcpu) && is_pae(vcpu)) ||
(vcpu->cr3 & CR3_NONPAE_RESERVED_BITS) == 0);
- walker->inherited_ar = PT_USER_MASK | PT_WRITABLE_MASK;
+ pt_access = ACC_ALL;
for (;;) {
index = PT_INDEX(addr, walker->level);
@@ -165,6 +166,14 @@ walk:
pte |= PT_ACCESSED_MASK;
}
+ pte_access = pte & (PT_WRITABLE_MASK | PT_USER_MASK);
+ pte_access |= ACC_EXEC_MASK;
+#if PTTYPE == 64
+ if (is_nx(vcpu))
+ pte_access &= ~(pte >> PT64_NX_SHIFT);
+#endif
+ pte_access &= pt_access;
+
if (walker->level == PT_PAGE_TABLE_LEVEL) {
walker->gfn = gpte_to_gfn(pte);
break;
@@ -180,7 +189,7 @@ walk:
break;
}
- walker->inherited_ar &= pte;
+ pt_access = pte_access;
--walker->level;
}
@@ -197,7 +206,10 @@ walk:
}
walker->pte = pte;
- pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)pte);
+ walker->pt_access = pt_access;
+ walker->pte_access = pte_access;
+ pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
+ __FUNCTION__, (u64)pte, pt_access, pte_access);
return 1;
not_present:
@@ -218,7 +230,8 @@ err:
}
static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
- u64 *shadow_pte, u64 access_bits,
+ u64 *shadow_pte, unsigned pt_access,
+ unsigned pte_access,
int user_fault, int write_fault,
int *ptwrite, struct guest_walker *walker,
gfn_t gfn)
@@ -228,12 +241,11 @@ static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
int was_rmapped = is_rmap_pte(*shadow_pte);
struct page *page;
- pgprintk("%s: spte %llx gpte %llx access %llx write_fault %d"
+ pgprintk("%s: spte %llx gpte %llx access %x write_fault %d"
" user_fault %d gfn %lx\n",
- __FUNCTION__, *shadow_pte, (u64)gpte, access_bits,
+ __FUNCTION__, *shadow_pte, (u64)gpte, pt_access,
write_fault, user_fault, gfn);
- access_bits &= gpte;
/*
* We don't set the accessed bit, since we sometimes want to see
* whether the guest actually used the pte (in order to detect
@@ -242,12 +254,12 @@ static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
spte = PT_PRESENT_MASK | PT_DIRTY_MASK;
spte |= gpte & PT64_NX_MASK;
if (!dirty)
- access_bits &= ~PT_WRITABLE_MASK;
+ pte_access &= ~ACC_WRITE_MASK;
page = gfn_to_page(vcpu->kvm, gfn);
spte |= PT_PRESENT_MASK;
- if (access_bits & PT_USER_MASK)
+ if (pte_access & ACC_USER_MASK)
spte |= PT_USER_MASK;
if (is_error_page(page)) {
@@ -259,7 +271,7 @@ static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
spte |= page_to_phys(page);
- if ((access_bits & PT_WRITABLE_MASK)
+ if ((pte_access & ACC_WRITE_MASK)
|| (write_fault && !is_write_protection(vcpu) && !user_fault)) {
struct kvm_mmu_page *shadow;
@@ -273,7 +285,7 @@ static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
if (shadow) {
pgprintk("%s: found shadow page for %lx, marking ro\n",
__FUNCTION__, gfn);
- access_bits &= ~PT_WRITABLE_MASK;
+ pte_access &= ~ACC_WRITE_MASK;
if (is_writeble_pte(spte)) {
spte &= ~PT_WRITABLE_MASK;
kvm_x86_ops->tlb_flush(vcpu);
@@ -285,7 +297,7 @@ static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
unshadowed:
- if (access_bits & PT_WRITABLE_MASK)
+ if (pte_access & ACC_WRITE_MASK)
mark_page_dirty(vcpu->kvm, gfn);
pgprintk("%s: setting spte %llx\n", __FUNCTION__, spte);
@@ -317,8 +329,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
if (bytes < sizeof(pt_element_t))
return;
pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
- FNAME(set_pte)(vcpu, gpte, spte, PT_USER_MASK | PT_WRITABLE_MASK, 0,
- 0, NULL, NULL, gpte_to_gfn(gpte));
+ FNAME(set_pte)(vcpu, gpte, spte, ACC_ALL, ACC_ALL,
+ 0, 0, NULL, NULL, gpte_to_gfn(gpte));
}
/*
@@ -331,6 +343,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
hpa_t shadow_addr;
int level;
u64 *shadow_ent;
+ unsigned access = walker->pt_access;
if (!is_present_pte(walker->pte))
return NULL;
@@ -349,7 +362,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
u64 shadow_pte;
int metaphysical;
gfn_t table_gfn;
- unsigned hugepage_access = 0;
shadow_ent = ((u64 *)__va(shadow_addr)) + index;
if (is_shadow_present_pte(*shadow_ent)) {
@@ -365,20 +377,15 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
if (level - 1 == PT_PAGE_TABLE_LEVEL
&& walker->level == PT_DIRECTORY_LEVEL) {
metaphysical = 1;
- hugepage_access = walker->pte;
- hugepage_access &= PT_USER_MASK | PT_WRITABLE_MASK;
if (!is_dirty_pte(walker->pte))
- hugepage_access &= ~PT_WRITABLE_MASK;
- hugepage_access >>= PT_WRITABLE_SHIFT;
- if (walker->pte & PT64_NX_MASK)
- hugepage_access |= (1 << 2);
+ access &= ~ACC_WRITE_MASK;
table_gfn = gpte_to_gfn(walker->pte);
} else {
metaphysical = 0;
table_gfn = walker->table_gfn[level - 2];
}
shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
- metaphysical, hugepage_access,
+ metaphysical, access,
shadow_ent);
shadow_addr = __pa(shadow_page->spt);
shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
@@ -387,7 +394,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
}
FNAME(set_pte)(vcpu, walker->pte, shadow_ent,
- walker->inherited_ar, user_fault, write_fault,
+ access, walker->pte_access & access,
+ user_fault, write_fault,
ptwrite, walker, walker->gfn);
return shadow_ent;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 43/54] KVM: MMU: Set nx bit correctly on shadow ptes
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (40 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 42/54] KVM: MMU: Simplify calculation of pte access Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 44/54] KVM: MMU: Move pte access calculation into a helper function Avi Kivity
` (10 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
While the page table walker correctly generates a guest page fault
if a guest tries to execute a non-executable page, the shadow code does
not mark it non-executable. This means that if a guest accesses an nx
page first with a read access, then subsequent code fetch accesses will
succeed.
Fix by setting the nx bit on shadow ptes.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/paging_tmpl.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 7688cbf..59ba752 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -255,6 +255,8 @@ static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
spte |= gpte & PT64_NX_MASK;
if (!dirty)
pte_access &= ~ACC_WRITE_MASK;
+ if (!(pte_access & ACC_EXEC_MASK))
+ spte |= PT64_NX_MASK;
page = gfn_to_page(vcpu->kvm, gfn);
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 44/54] KVM: MMU: Move pte access calculation into a helper function
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (41 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 43/54] KVM: MMU: Set nx bit correctly on shadow ptes Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 45/54] KVM: MMU: Fix inherited permissions for emulated guest pte updates Avi Kivity
` (9 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/paging_tmpl.h | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 59ba752..1fc4f9b 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -102,6 +102,18 @@ static bool FNAME(cmpxchg_gpte)(struct kvm *kvm,
return (ret != orig_pte);
}
+static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte)
+{
+ unsigned access;
+
+ access = (gpte & (PT_WRITABLE_MASK | PT_USER_MASK)) | ACC_EXEC_MASK;
+#if PTTYPE == 64
+ if (is_nx(vcpu))
+ access &= ~(gpte >> PT64_NX_SHIFT);
+#endif
+ return access;
+}
+
/*
* Fetch a guest pte for a guest virtual address
*/
@@ -166,13 +178,7 @@ walk:
pte |= PT_ACCESSED_MASK;
}
- pte_access = pte & (PT_WRITABLE_MASK | PT_USER_MASK);
- pte_access |= ACC_EXEC_MASK;
-#if PTTYPE == 64
- if (is_nx(vcpu))
- pte_access &= ~(pte >> PT64_NX_SHIFT);
-#endif
- pte_access &= pt_access;
+ pte_access = pt_access & FNAME(gpte_access)(vcpu, pte);
if (walker->level == PT_PAGE_TABLE_LEVEL) {
walker->gfn = gpte_to_gfn(pte);
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 45/54] KVM: MMU: Fix inherited permissions for emulated guest pte updates
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (42 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 44/54] KVM: MMU: Move pte access calculation into a helper function Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 46/54] KVM: MMU: No need to pick up nx bit from guest pte Avi Kivity
` (8 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
When we emulate a guest pte write, we fail to apply the correct inherited
permissions from the parent ptes. Now that we store inherited permissions
in the shadow page, we can use that to update the pte permissions correctly.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/kvm.h | 4 ++--
drivers/kvm/mmu.c | 4 ++--
drivers/kvm/paging_tmpl.h | 4 +++-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 0d3555b..ceefb44 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -55,7 +55,7 @@ struct kvm_pte_chain {
* bits 4:7 - page table level for this shadow (1-4)
* bits 8:9 - page table quadrant for 2-level guests
* bit 16 - "metaphysical" - gfn is not a real page (huge page/real mode)
- * bits 17:19 - "access" - the user, writable, and nx bits of a huge page pde
+ * bits 17:19 - common access permissions for all ptes in this shadow page
*/
union kvm_mmu_page_role {
unsigned word;
@@ -65,7 +65,7 @@ union kvm_mmu_page_role {
unsigned quadrant : 2;
unsigned pad_for_nice_hex_output : 6;
unsigned metaphysical : 1;
- unsigned hugepage_access : 3;
+ unsigned access : 3;
};
};
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index f8a2137..cace1e4 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -680,7 +680,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
gva_t gaddr,
unsigned level,
int metaphysical,
- unsigned hugepage_access,
+ unsigned access,
u64 *parent_pte)
{
union kvm_mmu_page_role role;
@@ -694,7 +694,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
role.glevels = vcpu->mmu.root_level;
role.level = level;
role.metaphysical = metaphysical;
- role.hugepage_access = hugepage_access;
+ role.access = access;
if (vcpu->mmu.root_level <= PT32_ROOT_LEVEL) {
quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level));
quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 1fc4f9b..211fef8 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -327,6 +327,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
int offset_in_pte)
{
pt_element_t gpte;
+ unsigned pte_access;
gpte = *(const pt_element_t *)pte;
if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK)) {
@@ -337,7 +338,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
if (bytes < sizeof(pt_element_t))
return;
pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
- FNAME(set_pte)(vcpu, gpte, spte, ACC_ALL, ACC_ALL,
+ pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
+ FNAME(set_pte)(vcpu, gpte, spte, page->role.access, pte_access,
0, 0, NULL, NULL, gpte_to_gfn(gpte));
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 46/54] KVM: MMU: No need to pick up nx bit from guest pte
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (43 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 45/54] KVM: MMU: Fix inherited permissions for emulated guest pte updates Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 47/54] KVM: MMU: Pass pte dirty flag to set_pte() instead of calculating it on-site Avi Kivity
` (7 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
We already set it according to cumulative access permissions.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/paging_tmpl.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 211fef8..179ce9e 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -258,7 +258,6 @@ static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
* demand paging).
*/
spte = PT_PRESENT_MASK | PT_DIRTY_MASK;
- spte |= gpte & PT64_NX_MASK;
if (!dirty)
pte_access &= ~ACC_WRITE_MASK;
if (!(pte_access & ACC_EXEC_MASK))
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 47/54] KVM: MMU: Pass pte dirty flag to set_pte() instead of calculating it on-site
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (44 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 46/54] KVM: MMU: No need to pick up nx bit from guest pte Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 48/54] KVM: MMU: Remove walker argument to set_pte() Avi Kivity
` (6 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
This allows us to remove its dependency on pt_element_t.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/paging_tmpl.h | 17 +++++++----------
1 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 179ce9e..ca8d515 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -235,14 +235,12 @@ err:
return 0;
}
-static void FNAME(set_pte)(struct kvm_vcpu *vcpu, pt_element_t gpte,
- u64 *shadow_pte, unsigned pt_access,
- unsigned pte_access,
- int user_fault, int write_fault,
+static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+ unsigned pt_access, unsigned pte_access,
+ int user_fault, int write_fault, int dirty,
int *ptwrite, struct guest_walker *walker,
gfn_t gfn)
{
- int dirty = gpte & PT_DIRTY_MASK;
u64 spte;
int was_rmapped = is_rmap_pte(*shadow_pte);
struct page *page;
@@ -338,8 +336,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
return;
pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
- FNAME(set_pte)(vcpu, gpte, spte, page->role.access, pte_access,
- 0, 0, NULL, NULL, gpte_to_gfn(gpte));
+ FNAME(set_pte)(vcpu, spte, page->role.access, pte_access, 0, 0,
+ gpte & PT_DIRTY_MASK, NULL, NULL, gpte_to_gfn(gpte));
}
/*
@@ -402,9 +400,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
*shadow_ent = shadow_pte;
}
- FNAME(set_pte)(vcpu, walker->pte, shadow_ent,
- access, walker->pte_access & access,
- user_fault, write_fault,
+ FNAME(set_pte)(vcpu, shadow_ent, access, walker->pte_access & access,
+ user_fault, write_fault, walker->pte & PT_DIRTY_MASK,
ptwrite, walker, walker->gfn);
return shadow_ent;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 48/54] KVM: MMU: Remove walker argument to set_pte()
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (45 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 47/54] KVM: MMU: Pass pte dirty flag to set_pte() instead of calculating it on-site Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 49/54] KVM: MMU: Move set_pte() into guest paging mode independent code Avi Kivity
` (5 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Unused.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/paging_tmpl.h | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index ca8d515..2e5a80a 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -238,8 +238,7 @@ err:
static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 *shadow_pte,
unsigned pt_access, unsigned pte_access,
int user_fault, int write_fault, int dirty,
- int *ptwrite, struct guest_walker *walker,
- gfn_t gfn)
+ int *ptwrite, gfn_t gfn)
{
u64 spte;
int was_rmapped = is_rmap_pte(*shadow_pte);
@@ -337,7 +336,7 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
FNAME(set_pte)(vcpu, spte, page->role.access, pte_access, 0, 0,
- gpte & PT_DIRTY_MASK, NULL, NULL, gpte_to_gfn(gpte));
+ gpte & PT_DIRTY_MASK, NULL, gpte_to_gfn(gpte));
}
/*
@@ -402,7 +401,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
FNAME(set_pte)(vcpu, shadow_ent, access, walker->pte_access & access,
user_fault, write_fault, walker->pte & PT_DIRTY_MASK,
- ptwrite, walker, walker->gfn);
+ ptwrite, walker->gfn);
return shadow_ent;
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 49/54] KVM: MMU: Move set_pte() into guest paging mode independent code
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (46 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 48/54] KVM: MMU: Remove walker argument to set_pte() Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 50/54] KVM: MMU: Adjust mmu_set_spte() debug code for gpte removal Avi Kivity
` (4 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
As set_pte() no longer references either a gpte or the guest walker, we can
move it out of paging mode dependent code (which compiles twice and is
generally nasty).
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 83 ++++++++++++++++++++++++++++++++++++++++
drivers/kvm/paging_tmpl.h | 93 ++------------------------------------------
2 files changed, 88 insertions(+), 88 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index cace1e4..a91e05b 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -879,6 +879,89 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
return gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
}
+static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
+ unsigned pt_access, unsigned pte_access,
+ int user_fault, int write_fault, int dirty,
+ int *ptwrite, gfn_t gfn)
+{
+ u64 spte;
+ int was_rmapped = is_rmap_pte(*shadow_pte);
+ struct page *page;
+
+ pgprintk("%s: spte %llx gpte %llx access %x write_fault %d"
+ " user_fault %d gfn %lx\n",
+ __FUNCTION__, *shadow_pte, (u64)gpte, pt_access,
+ write_fault, user_fault, gfn);
+
+ /*
+ * We don't set the accessed bit, since we sometimes want to see
+ * whether the guest actually used the pte (in order to detect
+ * demand paging).
+ */
+ spte = PT_PRESENT_MASK | PT_DIRTY_MASK;
+ if (!dirty)
+ pte_access &= ~ACC_WRITE_MASK;
+ if (!(pte_access & ACC_EXEC_MASK))
+ spte |= PT64_NX_MASK;
+
+ page = gfn_to_page(vcpu->kvm, gfn);
+
+ spte |= PT_PRESENT_MASK;
+ if (pte_access & ACC_USER_MASK)
+ spte |= PT_USER_MASK;
+
+ if (is_error_page(page)) {
+ set_shadow_pte(shadow_pte,
+ shadow_trap_nonpresent_pte | PT_SHADOW_IO_MARK);
+ kvm_release_page_clean(page);
+ return;
+ }
+
+ spte |= page_to_phys(page);
+
+ if ((pte_access & ACC_WRITE_MASK)
+ || (write_fault && !is_write_protection(vcpu) && !user_fault)) {
+ struct kvm_mmu_page *shadow;
+
+ spte |= PT_WRITABLE_MASK;
+ if (user_fault) {
+ mmu_unshadow(vcpu->kvm, gfn);
+ goto unshadowed;
+ }
+
+ shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn);
+ if (shadow) {
+ pgprintk("%s: found shadow page for %lx, marking ro\n",
+ __FUNCTION__, gfn);
+ pte_access &= ~ACC_WRITE_MASK;
+ if (is_writeble_pte(spte)) {
+ spte &= ~PT_WRITABLE_MASK;
+ kvm_x86_ops->tlb_flush(vcpu);
+ }
+ if (write_fault)
+ *ptwrite = 1;
+ }
+ }
+
+unshadowed:
+
+ if (pte_access & ACC_WRITE_MASK)
+ mark_page_dirty(vcpu->kvm, gfn);
+
+ pgprintk("%s: setting spte %llx\n", __FUNCTION__, spte);
+ set_shadow_pte(shadow_pte, spte);
+ page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
+ if (!was_rmapped) {
+ rmap_add(vcpu, shadow_pte, gfn);
+ if (!is_rmap_pte(*shadow_pte))
+ kvm_release_page_clean(page);
+ }
+ else
+ kvm_release_page_clean(page);
+ if (!ptwrite || !*ptwrite)
+ vcpu->last_pte_updated = shadow_pte;
+}
+
static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
{
}
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 2e5a80a..3ab3fb6 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -235,89 +235,6 @@ err:
return 0;
}
-static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 *shadow_pte,
- unsigned pt_access, unsigned pte_access,
- int user_fault, int write_fault, int dirty,
- int *ptwrite, gfn_t gfn)
-{
- u64 spte;
- int was_rmapped = is_rmap_pte(*shadow_pte);
- struct page *page;
-
- pgprintk("%s: spte %llx gpte %llx access %x write_fault %d"
- " user_fault %d gfn %lx\n",
- __FUNCTION__, *shadow_pte, (u64)gpte, pt_access,
- write_fault, user_fault, gfn);
-
- /*
- * We don't set the accessed bit, since we sometimes want to see
- * whether the guest actually used the pte (in order to detect
- * demand paging).
- */
- spte = PT_PRESENT_MASK | PT_DIRTY_MASK;
- if (!dirty)
- pte_access &= ~ACC_WRITE_MASK;
- if (!(pte_access & ACC_EXEC_MASK))
- spte |= PT64_NX_MASK;
-
- page = gfn_to_page(vcpu->kvm, gfn);
-
- spte |= PT_PRESENT_MASK;
- if (pte_access & ACC_USER_MASK)
- spte |= PT_USER_MASK;
-
- if (is_error_page(page)) {
- set_shadow_pte(shadow_pte,
- shadow_trap_nonpresent_pte | PT_SHADOW_IO_MARK);
- kvm_release_page_clean(page);
- return;
- }
-
- spte |= page_to_phys(page);
-
- if ((pte_access & ACC_WRITE_MASK)
- || (write_fault && !is_write_protection(vcpu) && !user_fault)) {
- struct kvm_mmu_page *shadow;
-
- spte |= PT_WRITABLE_MASK;
- if (user_fault) {
- mmu_unshadow(vcpu->kvm, gfn);
- goto unshadowed;
- }
-
- shadow = kvm_mmu_lookup_page(vcpu->kvm, gfn);
- if (shadow) {
- pgprintk("%s: found shadow page for %lx, marking ro\n",
- __FUNCTION__, gfn);
- pte_access &= ~ACC_WRITE_MASK;
- if (is_writeble_pte(spte)) {
- spte &= ~PT_WRITABLE_MASK;
- kvm_x86_ops->tlb_flush(vcpu);
- }
- if (write_fault)
- *ptwrite = 1;
- }
- }
-
-unshadowed:
-
- if (pte_access & ACC_WRITE_MASK)
- mark_page_dirty(vcpu->kvm, gfn);
-
- pgprintk("%s: setting spte %llx\n", __FUNCTION__, spte);
- set_shadow_pte(shadow_pte, spte);
- page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
- if (!was_rmapped) {
- rmap_add(vcpu, shadow_pte, gfn);
- if (!is_rmap_pte(*shadow_pte))
- kvm_release_page_clean(page);
- }
- else
- kvm_release_page_clean(page);
- if (!ptwrite || !*ptwrite)
- vcpu->last_pte_updated = shadow_pte;
-}
-
static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
u64 *spte, const void *pte, int bytes,
int offset_in_pte)
@@ -335,8 +252,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
return;
pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte, spte);
pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
- FNAME(set_pte)(vcpu, spte, page->role.access, pte_access, 0, 0,
- gpte & PT_DIRTY_MASK, NULL, gpte_to_gfn(gpte));
+ mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
+ gpte & PT_DIRTY_MASK, NULL, gpte_to_gfn(gpte));
}
/*
@@ -399,9 +316,9 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
*shadow_ent = shadow_pte;
}
- FNAME(set_pte)(vcpu, shadow_ent, access, walker->pte_access & access,
- user_fault, write_fault, walker->pte & PT_DIRTY_MASK,
- ptwrite, walker->gfn);
+ mmu_set_spte(vcpu, shadow_ent, access, walker->pte_access & access,
+ user_fault, write_fault, walker->pte & PT_DIRTY_MASK,
+ ptwrite, walker->gfn);
return shadow_ent;
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 50/54] KVM: MMU: Adjust mmu_set_spte() debug code for gpte removal
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (47 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 49/54] KVM: MMU: Move set_pte() into guest paging mode independent code Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 51/54] KVM: MMU: Use mmu_set_spte() for real-mode shadows Avi Kivity
` (3 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index a91e05b..b4dd726 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -888,9 +888,9 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
int was_rmapped = is_rmap_pte(*shadow_pte);
struct page *page;
- pgprintk("%s: spte %llx gpte %llx access %x write_fault %d"
+ pgprintk("%s: spte %llx access %x write_fault %d"
" user_fault %d gfn %lx\n",
- __FUNCTION__, *shadow_pte, (u64)gpte, pt_access,
+ __FUNCTION__, *shadow_pte, pt_access,
write_fault, user_fault, gfn);
/*
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 51/54] KVM: MMU: Use mmu_set_spte() for real-mode shadows
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (48 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 50/54] KVM: MMU: Adjust mmu_set_spte() debug code for gpte removal Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 52/54] KVM: SVM: Exit to userspace if write to cr8 and not using in-kernel apic Avi Kivity
` (2 subsequent siblings)
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
In addition to removing some duplicated code, this also handles the unlikely
case of real-mode code updating a guest page table. This can happen when
one vcpu (in real mode) touches a second vcpu's (in protected mode) page
tables, or if a vcpu switches to real mode, touches page tables, and switches
back.
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 41 ++++++++++-------------------------------
1 files changed, 10 insertions(+), 31 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index b4dd726..ba71e8d 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -966,40 +966,23 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
{
}
-static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, struct page *page)
+static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
{
int level = PT32E_ROOT_LEVEL;
hpa_t table_addr = vcpu->mmu.root_hpa;
+ int pt_write = 0;
for (; ; level--) {
u32 index = PT64_INDEX(v, level);
u64 *table;
- u64 pte;
ASSERT(VALID_PAGE(table_addr));
table = __va(table_addr);
if (level == 1) {
- int was_rmapped;
-
- pte = table[index];
- was_rmapped = is_rmap_pte(pte);
- if (is_shadow_present_pte(pte) && is_writeble_pte(pte)) {
- kvm_release_page_clean(page);
- return 0;
- }
- mark_page_dirty(vcpu->kvm, v >> PAGE_SHIFT);
- page_header_update_slot(vcpu->kvm, table,
- v >> PAGE_SHIFT);
- table[index] = page_to_phys(page)
- | PT_PRESENT_MASK | PT_WRITABLE_MASK
- | PT_USER_MASK;
- if (!was_rmapped)
- rmap_add(vcpu, &table[index], v >> PAGE_SHIFT);
- else
- kvm_release_page_clean(page);
-
- return 0;
+ mmu_set_spte(vcpu, &table[index], ACC_ALL, ACC_ALL,
+ 0, write, 1, &pt_write, gfn);
+ return pt_write || is_io_pte(table[index]);
}
if (table[index] == shadow_trap_nonpresent_pte) {
@@ -1013,7 +996,6 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, struct page *page)
1, ACC_ALL, &table[index]);
if (!new_table) {
pgprintk("nonpaging_map: ENOMEM\n");
- kvm_release_page_clean(page);
return -ENOMEM;
}
@@ -1114,9 +1096,10 @@ static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
u32 error_code)
{
- struct page *page;
+ gfn_t gfn;
int r;
+ pgprintk("%s: gva %lx error %x\n", __FUNCTION__, gva, error_code);
r = mmu_topup_memory_caches(vcpu);
if (r)
return r;
@@ -1124,14 +1107,10 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
ASSERT(vcpu);
ASSERT(VALID_PAGE(vcpu->mmu.root_hpa));
- page = gfn_to_page(vcpu->kvm, gva >> PAGE_SHIFT);
-
- if (is_error_page(page)) {
- kvm_release_page_clean(page);
- return 1;
- }
+ gfn = gva >> PAGE_SHIFT;
- return nonpaging_map(vcpu, gva & PAGE_MASK, page);
+ return nonpaging_map(vcpu, gva & PAGE_MASK,
+ error_code & PFERR_WRITE_MASK, gfn);
}
static void nonpaging_free(struct kvm_vcpu *vcpu)
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 52/54] KVM: SVM: Exit to userspace if write to cr8 and not using in-kernel apic
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (49 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 51/54] KVM: MMU: Use mmu_set_spte() for real-mode shadows Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 53/54] KVM: MMU: Fix SMP shadow instantiation race Avi Kivity
2008-01-01 15:36 ` [PATCH 54/54] KVM: LAPIC: minor debugging compile fix Avi Kivity
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Joerg Roedel <joerg.roedel-5C7GfCeVMHo@public.gmane.org>
With this patch KVM on SVM will exit to userspace if the guest writes to CR8
and the in-kernel APIC is disabled.
Signed-off-by: Joerg Roedel <joerg.roedel-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Markus Rechberger <markus.rechberger-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/svm.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 677b525..9f8564a 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -1048,6 +1048,15 @@ static int emulate_on_interception(struct vcpu_svm *svm,
return 1;
}
+static int cr8_write_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
+ emulate_instruction(&svm->vcpu, NULL, 0, 0, 0);
+ if (irqchip_in_kernel(svm->vcpu.kvm))
+ return 1;
+ kvm_run->exit_reason = KVM_EXIT_SET_TPR;
+ return 0;
+}
+
static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -1202,7 +1211,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_WRITE_CR0] = emulate_on_interception,
[SVM_EXIT_WRITE_CR3] = emulate_on_interception,
[SVM_EXIT_WRITE_CR4] = emulate_on_interception,
- [SVM_EXIT_WRITE_CR8] = emulate_on_interception,
+ [SVM_EXIT_WRITE_CR8] = cr8_write_interception,
[SVM_EXIT_READ_DR0] = emulate_on_interception,
[SVM_EXIT_READ_DR1] = emulate_on_interception,
[SVM_EXIT_READ_DR2] = emulate_on_interception,
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 53/54] KVM: MMU: Fix SMP shadow instantiation race
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (50 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 52/54] KVM: SVM: Exit to userspace if write to cr8 and not using in-kernel apic Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
2008-01-01 15:36 ` [PATCH 54/54] KVM: LAPIC: minor debugging compile fix Avi Kivity
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: Marcelo Tosatti
From: Marcelo Tosatti <marcelo-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>
There is a race where VCPU0 is shadowing a pagetable entry while VCPU1
is updating it, which results in a stale shadow copy.
Fix that by comparing the contents of the cached guest pte with the
current guest pte after write-protecting the guest pagetable.
Signed-off-by: Marcelo Tosatti <mtosatti-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/mmu.c | 12 ++++++++----
drivers/kvm/paging_tmpl.h | 29 +++++++++++++++++++++--------
2 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index ba71e8d..92ac0d1 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -681,7 +681,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
unsigned level,
int metaphysical,
unsigned access,
- u64 *parent_pte)
+ u64 *parent_pte,
+ bool *new_page)
{
union kvm_mmu_page_role role;
unsigned index;
@@ -720,6 +721,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
vcpu->mmu.prefetch_page(vcpu, sp);
if (!metaphysical)
rmap_write_protect(vcpu->kvm, gfn);
+ if (new_page)
+ *new_page = 1;
return sp;
}
@@ -993,7 +996,8 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
>> PAGE_SHIFT;
new_table = kvm_mmu_get_page(vcpu, pseudo_gfn,
v, level - 1,
- 1, ACC_ALL, &table[index]);
+ 1, ACC_ALL, &table[index],
+ NULL);
if (!new_table) {
pgprintk("nonpaging_map: ENOMEM\n");
return -ENOMEM;
@@ -1059,7 +1063,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
ASSERT(!VALID_PAGE(root));
sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
- PT64_ROOT_LEVEL, 0, ACC_ALL, NULL);
+ PT64_ROOT_LEVEL, 0, ACC_ALL, NULL, NULL);
root = __pa(sp->spt);
++sp->root_count;
vcpu->mmu.root_hpa = root;
@@ -1080,7 +1084,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
root_gfn = 0;
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
PT32_ROOT_LEVEL, !is_paging(vcpu),
- ACC_ALL, NULL);
+ ACC_ALL, NULL, NULL);
root = __pa(sp->spt);
++sp->root_count;
vcpu->mmu.pae_root[i] = root | PT_PRESENT_MASK;
diff --git a/drivers/kvm/paging_tmpl.h b/drivers/kvm/paging_tmpl.h
index 3ab3fb6..fb19596 100644
--- a/drivers/kvm/paging_tmpl.h
+++ b/drivers/kvm/paging_tmpl.h
@@ -65,7 +65,8 @@
struct guest_walker {
int level;
gfn_t table_gfn[PT_MAX_FULL_LEVELS];
- pt_element_t pte;
+ pt_element_t ptes[PT_MAX_FULL_LEVELS];
+ gpa_t pte_gpa[PT_MAX_FULL_LEVELS];
unsigned pt_access;
unsigned pte_access;
gfn_t gfn;
@@ -150,6 +151,7 @@ walk:
pte_gpa = gfn_to_gpa(table_gfn);
pte_gpa += index * sizeof(pt_element_t);
walker->table_gfn[walker->level - 1] = table_gfn;
+ walker->pte_gpa[walker->level - 1] = pte_gpa;
pgprintk("%s: table_gfn[%d] %lx\n", __FUNCTION__,
walker->level - 1, table_gfn);
@@ -180,6 +182,8 @@ walk:
pte_access = pt_access & FNAME(gpte_access)(vcpu, pte);
+ walker->ptes[walker->level - 1] = pte;
+
if (walker->level == PT_PAGE_TABLE_LEVEL) {
walker->gfn = gpte_to_gfn(pte);
break;
@@ -209,9 +213,9 @@ walk:
goto walk;
pte |= PT_DIRTY_MASK;
kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&pte, sizeof(pte));
+ walker->ptes[walker->level - 1] = pte;
}
- walker->pte = pte;
walker->pt_access = pt_access;
walker->pte_access = pte_access;
pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
@@ -268,7 +272,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
u64 *shadow_ent;
unsigned access = walker->pt_access;
- if (!is_present_pte(walker->pte))
+ if (!is_present_pte(walker->ptes[walker->level - 1]))
return NULL;
shadow_addr = vcpu->mmu.root_hpa;
@@ -285,6 +289,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
u64 shadow_pte;
int metaphysical;
gfn_t table_gfn;
+ bool new_page = 0;
shadow_ent = ((u64 *)__va(shadow_addr)) + index;
if (is_shadow_present_pte(*shadow_ent)) {
@@ -300,16 +305,23 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
if (level - 1 == PT_PAGE_TABLE_LEVEL
&& walker->level == PT_DIRECTORY_LEVEL) {
metaphysical = 1;
- if (!is_dirty_pte(walker->pte))
+ if (!is_dirty_pte(walker->ptes[level - 1]))
access &= ~ACC_WRITE_MASK;
- table_gfn = gpte_to_gfn(walker->pte);
+ table_gfn = gpte_to_gfn(walker->ptes[level - 1]);
} else {
metaphysical = 0;
table_gfn = walker->table_gfn[level - 2];
}
shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
metaphysical, access,
- shadow_ent);
+ shadow_ent, &new_page);
+ if (new_page && !metaphysical) {
+ pt_element_t curr_pte;
+ kvm_read_guest(vcpu->kvm, walker->pte_gpa[level - 2],
+ &curr_pte, sizeof(curr_pte));
+ if (curr_pte != walker->ptes[level - 2])
+ return NULL;
+ }
shadow_addr = __pa(shadow_page->spt);
shadow_pte = shadow_addr | PT_PRESENT_MASK | PT_ACCESSED_MASK
| PT_WRITABLE_MASK | PT_USER_MASK;
@@ -317,7 +329,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
}
mmu_set_spte(vcpu, shadow_ent, access, walker->pte_access & access,
- user_fault, write_fault, walker->pte & PT_DIRTY_MASK,
+ user_fault, write_fault,
+ walker->ptes[walker->level-1] & PT_DIRTY_MASK,
ptwrite, walker->gfn);
return shadow_ent;
@@ -382,7 +395,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
/*
* mmio: emulate if accessible, otherwise its a guest fault.
*/
- if (is_io_pte(*shadow_pte))
+ if (shadow_pte && is_io_pte(*shadow_pte))
return 1;
++vcpu->stat.pf_fixed;
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread* [PATCH 54/54] KVM: LAPIC: minor debugging compile fix
[not found] ` <1199201780-14001-1-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
` (51 preceding siblings ...)
2008-01-01 15:36 ` [PATCH 53/54] KVM: MMU: Fix SMP shadow instantiation race Avi Kivity
@ 2008-01-01 15:36 ` Avi Kivity
52 siblings, 0 replies; 57+ messages in thread
From: Avi Kivity @ 2008-01-01 15:36 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Joerg Roedel <joerg.roedel-5C7GfCeVMHo@public.gmane.org>
This patch fixes a compile error of the LAPIC code with APIC debugging enabled.
Signed-off-by: Joerg Roedel <joerg.roedel-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Markus Rechberger <markus.rechberger-5C7GfCeVMHo@public.gmane.org>
Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
drivers/kvm/lapic.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index 5efa6c0..466c37f 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -829,7 +829,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
/* with FSB delivery interrupt, we can restart APIC functionality */
apic_debug("apic base msr is 0x%016" PRIx64 ", and base address is "
- "0x%lx.\n", apic->apic_base, apic->base_address);
+ "0x%lx.\n", apic->vcpu->apic_base, apic->base_address);
}
--
1.5.3.7
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
^ permalink raw reply related [flat|nested] 57+ messages in thread