Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 45818
b: refs/heads/master
c: 7993ba4
h: refs/heads/master
v: v3
  • Loading branch information
Avi Kivity authored and Linus Torvalds committed Jan 26, 2007
1 parent 99abca6 commit 649c7ee
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 41 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6f00e68f210c0407dd666743ce61ae543cfd509d
refs/heads/master: 7993ba43db1c07245ada067791f91dbf018095ac
10 changes: 0 additions & 10 deletions trunk/drivers/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -992,16 +992,6 @@ static inline int fix_read_pf(u64 *shadow_ent)
return 0;
}

static int may_access(u64 pte, int write, int user)
{

if (user && !(pte & PT_USER_MASK))
return 0;
if (write && !(pte & PT_WRITABLE_MASK))
return 0;
return 1;
}

static void paging_free(struct kvm_vcpu *vcpu)
{
nonpaging_free(vcpu);
Expand Down
68 changes: 38 additions & 30 deletions trunk/drivers/kvm/paging_tmpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ struct guest_walker {
pt_element_t *ptep;
pt_element_t inherited_ar;
gfn_t gfn;
u32 error_code;
};

/*
* Fetch a guest pte for a guest virtual address
*/
static void FNAME(walk_addr)(struct guest_walker *walker,
struct kvm_vcpu *vcpu, gva_t addr)
static int FNAME(walk_addr)(struct guest_walker *walker,
struct kvm_vcpu *vcpu, gva_t addr,
int write_fault, int user_fault)
{
hpa_t hpa;
struct kvm_memory_slot *slot;
Expand All @@ -86,7 +88,7 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
walker->ptep = &vcpu->pdptrs[(addr >> 30) & 3];
root = *walker->ptep;
if (!(root & PT_PRESENT_MASK))
return;
goto not_present;
--walker->level;
}
#endif
Expand All @@ -111,11 +113,18 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
ASSERT(((unsigned long)walker->table & PAGE_MASK) ==
((unsigned long)ptep & PAGE_MASK));

if (is_present_pte(*ptep) && !(*ptep & PT_ACCESSED_MASK))
*ptep |= PT_ACCESSED_MASK;

if (!is_present_pte(*ptep))
break;
goto not_present;

if (write_fault && !is_writeble_pte(*ptep))
if (user_fault || is_write_protection(vcpu))
goto access_error;

if (user_fault && !(*ptep & PT_USER_MASK))
goto access_error;

if (!(*ptep & PT_ACCESSED_MASK))
*ptep |= PT_ACCESSED_MASK; /* avoid rmw */

if (walker->level == PT_PAGE_TABLE_LEVEL) {
walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
Expand Down Expand Up @@ -146,6 +155,21 @@ static void FNAME(walk_addr)(struct guest_walker *walker,
}
walker->ptep = ptep;
pgprintk("%s: pte %llx\n", __FUNCTION__, (u64)*ptep);
return 1;

not_present:
walker->error_code = 0;
goto err;

access_error:
walker->error_code = PFERR_PRESENT_MASK;

err:
if (write_fault)
walker->error_code |= PFERR_WRITE_MASK;
if (user_fault)
walker->error_code |= PFERR_USER_MASK;
return 0;
}

static void FNAME(release_walker)(struct guest_walker *walker)
Expand Down Expand Up @@ -347,7 +371,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
u32 error_code)
{
int write_fault = error_code & PFERR_WRITE_MASK;
int pte_present = error_code & PFERR_PRESENT_MASK;
int user_fault = error_code & PFERR_USER_MASK;
struct guest_walker walker;
u64 *shadow_pte;
Expand All @@ -365,19 +388,19 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
/*
* Look up the shadow pte for the faulting address.
*/
FNAME(walk_addr)(&walker, vcpu, addr);
shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
r = FNAME(walk_addr)(&walker, vcpu, addr, write_fault, user_fault);

/*
* The page is not mapped by the guest. Let the guest handle it.
*/
if (!shadow_pte) {
pgprintk("%s: not mapped\n", __FUNCTION__);
inject_page_fault(vcpu, addr, error_code);
if (!r) {
pgprintk("%s: guest page fault\n", __FUNCTION__);
inject_page_fault(vcpu, addr, walker.error_code);
FNAME(release_walker)(&walker);
return 0;
}

shadow_pte = FNAME(fetch)(vcpu, addr, &walker);
pgprintk("%s: shadow pte %p %llx\n", __FUNCTION__,
shadow_pte, *shadow_pte);

Expand All @@ -399,22 +422,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 (may_access(*shadow_pte, write_fault, user_fault))
return 1;
pgprintk("%s: io work, no access\n", __FUNCTION__);
inject_page_fault(vcpu, addr,
error_code | PFERR_PRESENT_MASK);
kvm_mmu_audit(vcpu, "post page fault (io)");
return 0;
}

/*
* pte not present, guest page fault.
*/
if (pte_present && !fixed && !write_pt) {
inject_page_fault(vcpu, addr, error_code);
kvm_mmu_audit(vcpu, "post page fault (guest)");
return 0;
return 1;
}

++kvm_stat.pf_fixed;
Expand All @@ -429,7 +437,7 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
pt_element_t guest_pte;
gpa_t gpa;

FNAME(walk_addr)(&walker, vcpu, vaddr);
FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0);
guest_pte = *walker.ptep;
FNAME(release_walker)(&walker);

Expand Down

0 comments on commit 649c7ee

Please sign in to comment.