debuggers.hg

view tools/libxc/xc_pagetab.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents 192bc11d7506
children 3ffdb094c2c0
line source
1 /******************************************************************************
2 * xc_pagetab.c
3 *
4 * Function to translate virtual to physical addresses.
5 */
6 #include "xc_private.h"
7 #include <xen/hvm/save.h>
9 #define CR0_PG 0x80000000
10 #define CR4_PAE 0x20
11 #define PTE_PSE 0x80
12 #define EFER_LMA 0x400
15 unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
16 int vcpu, unsigned long long virt)
17 {
18 xc_dominfo_t dominfo;
19 uint64_t paddr, mask, pte = 0;
20 int size, level, pt_levels = 2;
21 void *map;
23 if (xc_domain_getinfo(xc_handle, dom, 1, &dominfo) != 1
24 || dominfo.domid != dom)
25 return 0;
27 /* What kind of paging are we dealing with? */
28 if (dominfo.hvm) {
29 struct hvm_hw_cpu ctx;
30 if (xc_domain_hvm_getcontext_partial(xc_handle, dom,
31 HVM_SAVE_CODE(CPU), vcpu,
32 &ctx, sizeof ctx) != 0)
33 return 0;
34 if (!(ctx.cr0 & CR0_PG))
35 return virt >> PAGE_SHIFT;
36 pt_levels = (ctx.msr_efer&EFER_LMA) ? 4 : (ctx.cr4&CR4_PAE) ? 3 : 2;
37 paddr = ctx.cr3 & ((pt_levels == 3) ? ~0x1full : ~0xfffull);
38 } else {
39 DECLARE_DOMCTL;
40 vcpu_guest_context_any_t ctx;
41 if (xc_vcpu_getcontext(xc_handle, dom, vcpu, &ctx) != 0)
42 return 0;
43 domctl.domain = dom;
44 domctl.cmd = XEN_DOMCTL_get_address_size;
45 if ( do_domctl(xc_handle, &domctl) != 0 )
46 return 0;
47 if (domctl.u.address_size.size == 64) {
48 pt_levels = 4;
49 paddr = ctx.x64.ctrlreg[3] & ~0xfffull;
50 } else {
51 pt_levels = 3;
52 paddr = (((uint64_t) xen_cr3_to_pfn(ctx.x32.ctrlreg[3]))
53 << PAGE_SHIFT);
54 }
55 }
57 if (pt_levels == 4) {
58 virt &= 0x0000ffffffffffffull;
59 mask = 0x0000ff8000000000ull;
60 } else if (pt_levels == 3) {
61 virt &= 0x00000000ffffffffull;
62 mask = 0x0000007fc0000000ull;
63 } else {
64 virt &= 0x00000000ffffffffull;
65 mask = 0x00000000ffc00000ull;
66 }
67 size = (pt_levels == 2 ? 4 : 8);
69 /* Walk the pagetables */
70 for (level = pt_levels; level > 0; level--) {
71 paddr += ((virt & mask) >> (xc_ffs64(mask) - 1)) * size;
72 map = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ,
73 paddr >>PAGE_SHIFT);
74 if (!map)
75 return 0;
76 memcpy(&pte, map + (paddr & (PAGE_SIZE - 1)), size);
77 munmap(map, PAGE_SIZE);
78 if (!(pte & 1))
79 return 0;
80 paddr = pte & 0x000ffffffffff000ull;
81 if (level == 2 && (pte & PTE_PSE)) {
82 mask = ((mask ^ ~-mask) >> 1); /* All bits below first set bit */
83 return ((paddr & ~mask) | (virt & mask)) >> PAGE_SHIFT;
84 }
85 mask >>= (pt_levels == 2 ? 10 : 9);
86 }
87 return paddr >> PAGE_SHIFT;
88 }
90 /*
91 * Local variables:
92 * mode: C
93 * c-set-style: "BSD"
94 * c-basic-offset: 4
95 * tab-width: 4
96 * indent-tabs-mode: nil
97 * End:
98 */