# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID 0bb5205fa6adb7db6787ff12a0987916e35afc70
# Parent 2f4dff8ec8645c00bf411568c2409332c1b02b9c
Add support to xenctx for printing stack traces on x86_32 and x86_64.
To support this add xc_translate_foreign_address to libxc. This function
walks page tables and translates virtual addresses using a given domain
and vcpu page table.
Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>
xen-unstable cset: 8d5d4d58407f7071ee1dc0cc2418ffce508d8c1c
committer: Robert Read <robert@xxxxxxxxxxxxx>
diff -r 2f4dff8ec864 -r 0bb5205fa6ad tools/libxc/Makefile
--- a/tools/libxc/Makefile Fri Dec 30 10:55:19 2005
+++ b/tools/libxc/Makefile Thu Dec 22 06:33:19 2005
@@ -27,6 +27,11 @@
ifeq ($(XEN_TARGET_ARCH),x86_32)
SRCS += xc_ptrace.c
SRCS += xc_ptrace_core.c
+SRCS += xc_pagetab.c
+endif
+
+ifeq ($(XEN_TARGET_ARCH),x86_64)
+SRCS += xc_pagetab.c
endif
BUILD_SRCS :=
diff -r 2f4dff8ec864 -r 0bb5205fa6ad tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Fri Dec 30 10:55:19 2005
+++ b/tools/libxc/xenctrl.h Thu Dec 22 06:33:19 2005
@@ -415,6 +415,19 @@
void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
unsigned long *arr, int num );
+/**
+ * Translates a virtual address in the context of a given domain and
+ * vcpu returning the machine page frame number of the associated
+ * page.
+ *
+ * @parm xc_handle a handle on an open hypervisor interface
+ * @parm dom the domain to perform the translation in
+ * @parm vcpu the vcpu to perform the translation on
+ * @parm virt the virtual address to translate
+ */
+unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
+ int vcpu, unsigned long long virt);
+
int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf,
unsigned long max_pfns);
diff -r 2f4dff8ec864 -r 0bb5205fa6ad tools/xentrace/Makefile
--- a/tools/xentrace/Makefile Fri Dec 30 10:55:19 2005
+++ b/tools/xentrace/Makefile Thu Dec 22 06:33:19 2005
@@ -15,25 +15,29 @@
OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
BIN = xentrace tbctl setsize
+LIBBIN = xenctx
SCRIPTS = xentrace_format
MAN1 = $(wildcard *.1)
MAN8 = $(wildcard *.8)
all: build
-build: $(BIN)
+build: $(BIN) $(LIBBIN)
install: build
[ -d $(DESTDIR)/usr/bin ] || $(INSTALL_DIR) $(DESTDIR)/usr/bin
+ [ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \
+ $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
[ -d $(DESTDIR)/usr/share/man/man1 ] || \
$(INSTALL_DIR) $(DESTDIR)/usr/share/man/man1
[ -d $(DESTDIR)/usr/share/man/man8 ] || \
$(INSTALL_DIR) $(DESTDIR)/usr/share/man/man8
$(INSTALL_PROG) $(BIN) $(SCRIPTS) $(DESTDIR)/usr/bin
+ $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
$(INSTALL_DATA) $(MAN1) $(DESTDIR)/usr/share/man/man1
$(INSTALL_DATA) $(MAN8) $(DESTDIR)/usr/share/man/man8
clean:
- $(RM) *.a *.so *.o *.rpm $(BIN)
+ $(RM) *.a *.so *.o *.rpm $(BIN) $(LIBBIN)
%: %.c $(HDRS) Makefile
$(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl
diff -r 2f4dff8ec864 -r 0bb5205fa6ad tools/xentrace/xenctx.c
--- a/tools/xentrace/xenctx.c Fri Dec 30 10:55:19 2005
+++ b/tools/xentrace/xenctx.c Thu Dec 22 06:33:19 2005
@@ -20,15 +20,184 @@
#include <errno.h>
#include <argp.h>
#include <signal.h>
+#include <string.h>
+#include <getopt.h>
#include "xenctrl.h"
+
+int xc_handle = 0;
+int domid = 0;
+int frame_ptrs = 0;
+int stack_trace = 0;
+
+#if defined (__i386__)
+#define FMT_SIZE_T "%08x"
+#define STACK_POINTER(regs) (regs->esp)
+#define FRAME_POINTER(regs) (regs->ebp)
+#define INSTR_POINTER(regs) (regs->eip)
+#define STACK_ROWS 4
+#define STACK_COLS 8
+#elif defined (__x86_64__)
+#define FMT_SIZE_T "%016lx"
+#define STACK_POINTER(regs) (regs->rsp)
+#define FRAME_POINTER(regs) (regs->rbp)
+#define INSTR_POINTER(regs) (regs->rip)
+#define STACK_ROWS 4
+#define STACK_COLS 4
+#endif
+
+struct symbol {
+ size_t address;
+ char type;
+ char *name;
+ struct symbol *next;
+} *symbol_table = NULL;
+
+size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext;
+
+int is_kernel_text(size_t addr)
+{
+#if defined (__i386__)
+ if (symbol_table == NULL)
+ return (addr > 0xc000000);
+#elif defined (__x86_64__)
+ if (symbol_table == NULL)
+ return (addr > 0xffffffff80000000UL);
+#endif
+
+ if (addr >= kernel_stext &&
+ addr <= kernel_etext)
+ return 1;
+ if (addr >= kernel_sinittext &&
+ addr <= kernel_einittext)
+ return 1;
+ return 0;
+}
+
+void free_symbol(struct symbol *symbol)
+{
+ if (symbol == NULL)
+ return;
+ if (symbol->name)
+ free(symbol->name);
+ free(symbol);
+}
+
+void insert_symbol(struct symbol *symbol)
+{
+ static struct symbol *prev = NULL;
+ struct symbol *s = symbol_table;
+
+ if (s == NULL) {
+ symbol_table = symbol;
+ symbol->next = NULL;
+ return;
+ }
+
+ /* The System.map is usually already sorted... */
+ if (prev
+ && prev->address < symbol->address
+ && (!prev->next || prev->next->address > symbol->address)) {
+ s = prev;
+ } else {
+ /* ... otherwise do crappy/slow search for the correct place */
+ while(s && s->next && s->next->address < symbol->address)
+ s = s->next;
+ }
+
+ symbol->next = s->next;
+ s->next = symbol;
+ prev = symbol;
+}
+
+struct symbol *lookup_symbol(size_t address)
+{
+ struct symbol *s = symbol_table;
+
+ while(s && s->next && s->next->address < address)
+ s = s->next;
+
+ if (s && s->address < address)
+ return s;
+
+ return NULL;
+}
+
+void print_symbol(size_t addr)
+{
+ struct symbol *s;
+
+ if (!is_kernel_text(addr))
+ return;
+
+ s = lookup_symbol(addr);
+
+ if (s==NULL)
+ return;
+
+ if (addr==s->address)
+ printf("%s", s->name);
+ else
+ printf("%s+%#x", s->name, (unsigned int)(addr - s->address));
+}
+
+void read_symbol_table(const char *symtab)
+{
+ char line[256];
+ char *p;
+ struct symbol *symbol;
+ FILE *f;
+
+ f = fopen(symtab, "r");
+ if(f == NULL) {
+ fprintf(stderr, "failed to open symbol table %s\n", symtab);
+ exit(-1);
+ }
+
+ while(!feof(f)) {
+ if(fgets(line,256,f)==NULL)
+ break;
+
+ symbol = malloc(sizeof(*symbol));
+
+ /* need more checks for syntax here... */
+ symbol->address = strtoull(line, &p, 16);
+ p++;
+ symbol->type = *p++;
+ p++;
+
+ /* in the future we should handle the module name
+ * being appended here, this would allow us to use
+ * /proc/kallsyms as our symbol table
+ */
+ if (p[strlen(p)-1] == '\n')
+ p[strlen(p)-1] = '\0';
+ symbol->name = strdup(p);
+
+ insert_symbol(symbol);
+
+ if (strcmp(symbol->name, "_stext") == 0)
+ kernel_stext = symbol->address;
+ else if (strcmp(symbol->name, "_etext") == 0)
+ kernel_etext = symbol->address;
+ else if (strcmp(symbol->name, "_sinittext") == 0)
+ kernel_sinittext = symbol->address;
+ else if (strcmp(symbol->name, "_einittext") == 0)
+ kernel_einittext = symbol->address;
+ }
+
+ fclose(f);
+}
#ifdef __i386__
void print_ctx(vcpu_guest_context_t *ctx1)
{
struct cpu_user_regs *regs = &ctx1->user_regs;
- printf("eip: %08x\t", regs->eip);
+ printf("eip: %08x ", regs->eip);
+ print_symbol(regs->eip);
+ printf("\n");
+
printf("esp: %08x\n", regs->esp);
printf("eax: %08x\t", regs->eax);
@@ -51,7 +220,9 @@
{
struct cpu_user_regs *regs = &ctx1->user_regs;
- printf("rip: %08lx\t", regs->rip);
+ printf("rip: %08lx ", regs->rip);
+ print_symbol(regs->rip);
+ printf("\n");
printf("rsp: %08lx\n", regs->rsp);
printf("rax: %08lx\t", regs->rax);
@@ -63,8 +234,8 @@
printf("rdi: %08lx\t", regs->rdi);
printf("rbp: %08lx\n", regs->rbp);
- printf("r8: %08lx\t", regs->r8);
- printf("r9: %08lx\t", regs->r9);
+ printf(" r8: %08lx\t", regs->r8);
+ printf(" r9: %08lx\t", regs->r9);
printf("r10: %08lx\t", regs->r10);
printf("r11: %08lx\n", regs->r11);
@@ -81,35 +252,238 @@
}
#endif
-void dump_ctx(uint32_t domid, uint32_t vcpu)
+void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
+{
+ static unsigned long previous_mfn = 0;
+ static void *mapped = NULL;
+
+ unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu,
virt);
+ unsigned long offset = virt & ~XC_PAGE_MASK;
+
+ if (mapped && mfn == previous_mfn)
+ goto out;
+
+ if (mapped)
+ munmap(mapped, XC_PAGE_SIZE);
+
+ previous_mfn = mfn;
+
+ mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ,
mfn);
+
+ if (mapped == NULL) {
+ fprintf(stderr, "failed to map page.\n");
+ exit(-1);
+ }
+
+ out:
+ return (void *)(mapped + offset);
+}
+
+void print_stack(vcpu_guest_context_t *ctx, int vcpu)
+{
+ struct cpu_user_regs *regs = &ctx->user_regs;
+ size_t stack = STACK_POINTER(regs);
+ size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE;
+ size_t frame;
+ size_t instr;
+ size_t *p;
+ int i;
+
+ printf("\n");
+ printf("Stack:\n");
+ for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) {
+ while(stack < stack_limit && stack < STACK_POINTER(regs) +
i*STACK_COLS*sizeof(stack)) {
+ p = map_page(ctx, vcpu, stack);
+ printf(" " FMT_SIZE_T, *p);
+ stack += sizeof(stack);
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ printf("Code:\n");
+ instr = INSTR_POINTER(regs) - 21;
+ for(i=0; i<32; i++) {
+ unsigned char *c = map_page(ctx, vcpu, instr+i);
+ if (instr+i == INSTR_POINTER(regs))
+ printf("<%02x> ", *c);
+ else
+ printf("%02x ", *c);
+ }
+ printf("\n");
+
+ printf("\n");
+
+ if(stack_trace)
+ printf("Stack Trace:\n");
+ else
+ printf("Call Trace:\n");
+ printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ',
INSTR_POINTER(regs));
+
+ print_symbol(INSTR_POINTER(regs));
+ printf(" <--\n");
+ if (frame_ptrs) {
+ stack = STACK_POINTER(regs);
+ frame = FRAME_POINTER(regs);
+ while(frame && stack < stack_limit) {
+ if (stack_trace) {
+ while (stack < frame) {
+ p = map_page(ctx, vcpu, stack);
+ printf("| " FMT_SIZE_T " ", *p);
+ printf("\n");
+ stack += sizeof(*p);
+ }
+ } else {
+ stack = frame;
+ }
+
+ p = map_page(ctx, vcpu, stack);
+ frame = *p;
+ if (stack_trace)
+ printf("|-- " FMT_SIZE_T "\n", *p);
+ stack += sizeof(*p);
+
+ if (frame) {
+ p = map_page(ctx, vcpu, stack);
+ printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p);
+ print_symbol(*p);
+ printf("\n");
+ stack += sizeof(*p);
+ }
+ }
+ } else {
+ stack = STACK_POINTER(regs);
+ while(stack < stack_limit) {
+ p = map_page(ctx, vcpu, stack);
+ if (is_kernel_text(*p)) {
+ printf(" [<" FMT_SIZE_T ">] ", *p);
+ print_symbol(*p);
+ printf("\n");
+ } else if (stack_trace) {
+ printf(" " FMT_SIZE_T "\n", *p);
+ }
+ stack += sizeof(*p);
+ }
+ }
+}
+
+void dump_ctx(int vcpu)
{
int ret;
vcpu_guest_context_t ctx;
- int xc_handle = xc_interface_open(); /* for accessing control interface */
+ xc_handle = xc_interface_open(); /* for accessing control interface */
+
+ ret = xc_domain_pause(xc_handle, domid);
+ if (ret < 0) {
+ perror("xc_domain_pause");
+ exit(-1);
+ }
ret = xc_domain_get_vcpu_context(xc_handle, domid, vcpu, &ctx);
- if (ret != 0) {
+ if (ret < 0) {
+ xc_domain_unpause(xc_handle, domid);
perror("xc_domain_get_vcpu_context");
exit(-1);
}
+
print_ctx(&ctx);
+ if (is_kernel_text(ctx.user_regs.eip))
+ print_stack(&ctx, vcpu);
+
+ ret = xc_domain_unpause(xc_handle, domid);
+ if (ret < 0) {
+ perror("xc_domain_unpause");
+ exit(-1);
+ }
+
xc_interface_close(xc_handle);
+ if (ret < 0) {
+ perror("xc_interface_close");
+ exit(-1);
+ }
+}
+
+void usage(void)
+{
+ printf("usage:\n\n");
+
+ printf(" xenctx [options] <DOMAIN> [VCPU]\n\n");
+
+ printf("options:\n");
+ printf(" -f, --frame-pointers\n");
+ printf(" assume the kernel was compiled with\n");
+ printf(" frame pointers.\n");
+ printf(" -s SYMTAB, --symbol-table=SYMTAB\n");
+ printf(" read symbol table from SYMTAB.\n");
+ printf(" --stack-trace print a complete stack trace.\n");
}
int main(int argc, char **argv)
{
+ int ch;
+ const char *sopts = "fs:h";
+ const struct option lopts[] = {
+ {"stack-trace", 0, NULL, 'S'},
+ {"symbol-table", 1, NULL, 's'},
+ {"frame-pointers", 0, NULL, 'f'},
+ {"help", 0, NULL, 'h'},
+ {0, 0, 0, 0}
+ };
+ const char *symbol_table = NULL;
+
int vcpu = 0;
- if (argc < 2) {
- printf("usage: xenctx <domid> <optional vcpu>\n");
- exit(-1);
- }
-
- if (argc == 3)
- vcpu = atoi(argv[2]);
-
- dump_ctx(atoi(argv[1]), vcpu);
+ while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
+ switch(ch) {
+ case 'f':
+ frame_ptrs = 1;
+ break;
+ case 's':
+ symbol_table = optarg;
+ break;
+ case 'S':
+ stack_trace = 1;
+ break;
+ case 'h':
+ usage();
+ exit(-1);
+ case '?':
+ fprintf(stderr, "%s --help for more options\n", argv[0]);
+ exit(-1);
+ }
+ }
+
+ argv += optind; argc -= optind;
+
+ if (argc < 1 || argc > 2) {
+ printf("usage: xenctx [options] <domid> <optional vcpu>\n");
+ exit(-1);
+ }
+
+ domid = atoi(argv[0]);
+ if (domid==0) {
+ fprintf(stderr, "cannot trace dom0\n");
+ exit(-1);
+ }
+
+ if (argc == 2)
+ vcpu = atoi(argv[1]);
+
+ if (symbol_table)
+ read_symbol_table(symbol_table);
+
+ dump_ctx(vcpu);
return 0;
}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 2f4dff8ec864 -r 0bb5205fa6ad tools/libxc/xc_pagetab.c
--- /dev/null Fri Dec 30 10:55:19 2005
+++ b/tools/libxc/xc_pagetab.c Thu Dec 22 06:33:19 2005
@@ -0,0 +1,192 @@
+/******************************************************************************
+ * xc_pagetab.c
+ *
+ * Function to translate virtual to physical addresses.
+ */
+#include "xc_private.h"
+
+#if defined(__i386__)
+
+#define L1_PAGETABLE_SHIFT_PAE 12
+#define L2_PAGETABLE_SHIFT_PAE 21
+#define L3_PAGETABLE_SHIFT_PAE 30
+
+#define L1_PAGETABLE_SHIFT 12
+#define L2_PAGETABLE_SHIFT 22
+
+#define L0_PAGETABLE_MASK_PAE 0x0000000ffffff000ULL
+#define L1_PAGETABLE_MASK_PAE 0x1ffULL
+#define L2_PAGETABLE_MASK_PAE 0x1ffULL
+#define L3_PAGETABLE_MASK_PAE 0x3ULL
+
+#define L0_PAGETABLE_MASK 0xfffff000ULL
+#define L1_PAGETABLE_MASK 0x3ffULL
+#define L2_PAGETABLE_MASK 0x3ffULL
+
+#elif defined(__x86_64__)
+
+#define L1_PAGETABLE_SHIFT_PAE 12
+#define L2_PAGETABLE_SHIFT_PAE 21
+#define L3_PAGETABLE_SHIFT_PAE 30
+#define L4_PAGETABLE_SHIFT_PAE 39
+
+#define L1_PAGETABLE_SHIFT L1_PAGETABLE_SHIFT_PAE
+#define L2_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT_PAE
+
+#define L0_PAGETABLE_MASK_PAE 0x000000fffffff000ULL
+#define L1_PAGETABLE_MASK_PAE 0x1ffULL
+#define L2_PAGETABLE_MASK_PAE 0x1ffULL
+#define L3_PAGETABLE_MASK_PAE 0x1ffULL
+#define L4_PAGETABLE_MASK_PAE 0x1ffULL
+
+#define L0_PAGETABLE_MASK L0_PAGETABLE_MASK_PAE
+#define L1_PAGETABLE_MASK L1_PAGETABLE_MASK_PAE
+#define L2_PAGETABLE_MASK L2_PAGETABLE_MASK_PAE
+
+#endif
+
+unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
+ int vcpu, unsigned long long virt )
+{
+ vcpu_guest_context_t ctx;
+ unsigned long long cr3;
+ void *pd, *pt, *pdppage = NULL, *pdp, *pml = NULL;
+ unsigned long long pde, pte, pdpe, pmle;
+ unsigned long mfn = 0;
+#if defined (__i386__)
+ static int pt_levels = 0;
+
+ if (pt_levels == 0) {
+ xen_capabilities_info_t xen_caps = "";
+
+ if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
+ goto out;
+ if (strstr(xen_caps, "xen-3.0-x86_64"))
+ pt_levels = 4;
+ else if (strstr(xen_caps, "xen-3.0-x86_32p"))
+ pt_levels = 3;
+ else if (strstr(xen_caps, "xen-3.0-x86_32"))
+ pt_levels = 2;
+ else
+ goto out;
+ }
+#elif defined (__x86_64__)
+#define pt_levels 4
+#endif
+
+ if (xc_domain_get_vcpu_context(xc_handle, dom, vcpu, &ctx) != 0) {
+ fprintf(stderr, "failed to retreive vcpu context\n");
+ goto out;
+ }
+ cr3 = ctx.ctrlreg[3];
+
+ /* Page Map Level 4 */
+
+#if defined(__i386__)
+ pmle = cr3;
+#elif defined(__x86_64__)
+ pml = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, cr3 >>
PAGE_SHIFT);
+ if (pml == NULL) {
+ fprintf(stderr, "failed to map PML4\n");
+ goto out;
+ }
+ pmle = *(unsigned long long *)(pml + 8 * ((virt >> L4_PAGETABLE_SHIFT_PAE)
& L4_PAGETABLE_MASK_PAE));
+ if((pmle & 1) == 0) {
+ fprintf(stderr, "page entry not present in PML4\n");
+ goto out_unmap_pml;
+ }
+#endif
+
+ /* Page Directory Pointer Table */
+
+ if (pt_levels >= 3) {
+ pdppage = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ,
pmle >> PAGE_SHIFT);
+ if (pdppage == NULL) {
+ fprintf(stderr, "failed to map PDP\n");
+ goto out_unmap_pml;
+ }
+ if (pt_levels >= 4)
+ pdp = pdppage;
+ else
+ /* PDP is only 32 bit aligned with 3 level pts */
+ pdp = pdppage + (pmle & ~(XC_PAGE_MASK | 0x1f));
+
+ pdpe = *(unsigned long long *)(pdp + 8 * ((virt >>
L3_PAGETABLE_SHIFT_PAE) & L3_PAGETABLE_MASK_PAE));
+
+ if((pdpe & 1) == 0) {
+ fprintf(stderr, "page entry not present in PDP\n");
+ goto out_unmap_pdp;
+ }
+ } else {
+ pdpe = pmle;
+ }
+
+ /* Page Directory */
+
+ pd = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, pdpe >>
PAGE_SHIFT);
+ if (pd == NULL) {
+ fprintf(stderr, "failed to map PD\n");
+ goto out_unmap_pdp;
+ }
+
+ if (pt_levels >= 3)
+ pde = *(unsigned long long *)(pd + 8 * ((virt >>
L2_PAGETABLE_SHIFT_PAE) & L2_PAGETABLE_MASK_PAE));
+ else
+ pde = *(unsigned long long *)(pd + 4 * ((virt >> L2_PAGETABLE_SHIFT) &
L2_PAGETABLE_MASK));
+
+ if ((pde & 1) == 0) {
+ fprintf(stderr, "page entry not present in PD\n");
+ goto out_unmap_pd;
+ }
+
+ /* Page Table */
+
+ if (pde & 0x00000008) { /* 4M page (or 2M in PAE mode) */
+ fprintf(stderr, "Cannot currently cope with 2/4M pages\n");
+ exit(-1);
+ } else { /* 4k page */
+ pt = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ,
+ pde >> PAGE_SHIFT);
+
+ if (pt == NULL) {
+ fprintf(stderr, "failed to map PT\n");
+ goto out_unmap_pd;
+ }
+
+ if (pt_levels >= 3)
+ pte = *(unsigned long long *)(pt + 8 * ((virt >>
L1_PAGETABLE_SHIFT_PAE) & L1_PAGETABLE_MASK_PAE));
+ else
+ pte = *(unsigned long long *)(pt + 4 * ((virt >>
L1_PAGETABLE_SHIFT) & L1_PAGETABLE_MASK));
+
+ if ((pte & 0x00000001) == 0) {
+ fprintf(stderr, "page entry not present in PT\n");
+ goto out_unmap_pt;
+ }
+
+ if (pt_levels >= 3)
+ mfn = (pte & L0_PAGETABLE_MASK_PAE) >> PAGE_SHIFT;
+ else
+ mfn = (pte & L0_PAGETABLE_MASK) >> PAGE_SHIFT;
+ }
+
+ out_unmap_pt:
+ munmap(pt, PAGE_SIZE);
+ out_unmap_pd:
+ munmap(pd, PAGE_SIZE);
+ out_unmap_pdp:
+ munmap(pdppage, PAGE_SIZE);
+ out_unmap_pml:
+ munmap(pml, PAGE_SIZE);
+ out:
+ return mfn;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|