@@ -29,10 +29,10 @@ use crate::{AddrTranslationError, Gpa, Gva, KdmpParserError, Pfn, Pxe};
2929/// marked as not present. In other words, if the translation succeeds, the page
3030/// is at least readable.
3131#[ derive( Debug ) ]
32- pub struct TranslationDetails {
32+ pub struct VirtTranslationDetails {
3333 /// The physical address backing the virtual address that was requested.
3434 pub pfn : Pfn ,
35- /// The base physical address of the page.
35+ /// The byte offset in that physical page.
3636 pub offset : u64 ,
3737 /// The kind of physical page.
3838 pub page_kind : PageKind ,
@@ -44,11 +44,19 @@ pub struct TranslationDetails {
4444 pub user_accessible : bool ,
4545}
4646
47- impl TranslationDetails {
48- pub fn new ( pfn : Pfn , offset : u64 , page_kind : PageKind , pxes : & [ Pxe ] ) -> Self {
47+ impl VirtTranslationDetails {
48+ pub fn new ( pxes : & [ Pxe ] , gva : Gva ) -> Self {
4949 let writable = pxes. iter ( ) . all ( Pxe :: writable) ;
5050 let executable = pxes. iter ( ) . all ( Pxe :: executable) ;
5151 let user_accessible = pxes. iter ( ) . all ( Pxe :: user_accessible) ;
52+ let pfn = pxes. last ( ) . map ( |p| p. pfn ) . expect ( "at least one pxe" ) ;
53+ let page_kind = match pxes. len ( ) {
54+ 4 => PageKind :: Normal ,
55+ 3 => PageKind :: Large ,
56+ 2 => PageKind :: Huge ,
57+ _ => unreachable ! ( "pxes len should be between 2 and 4" ) ,
58+ } ;
59+ let offset = page_kind. page_offset ( gva. u64 ( ) ) ;
5260
5361 Self {
5462 pfn,
@@ -598,13 +606,13 @@ impl KernelDumpParser {
598606 }
599607
600608 /// Translate a [`Gva`] into a [`Gpa`].
601- pub fn virt_translate ( & self , gva : Gva ) -> Result < TranslationDetails > {
609+ pub fn virt_translate ( & self , gva : Gva ) -> Result < VirtTranslationDetails > {
602610 self . virt_translate_with_dtb ( gva, Gpa :: new ( self . headers . directory_table_base ) )
603611 }
604612
605613 /// Translate a [`Gva`] into a [`Gpa`] using a specific directory table base
606614 /// / set of page tables.
607- pub fn virt_translate_with_dtb ( & self , gva : Gva , dtb : Gpa ) -> Result < TranslationDetails > {
615+ pub fn virt_translate_with_dtb ( & self , gva : Gva , dtb : Gpa ) -> Result < VirtTranslationDetails > {
608616 // Aligning in case PCID bits are set (bits 11:0)
609617 let pml4_base = dtb. page_align ( ) ;
610618 let pml4e_gpa = Gpa :: new ( pml4_base. u64 ( ) + ( gva. pml4e_idx ( ) * 8 ) ) ;
@@ -625,11 +633,7 @@ impl KernelDumpParser {
625633 // directory; see Table 4-1
626634 let pd_base = pdpte. pfn . gpa ( ) ;
627635 if pdpte. large_page ( ) {
628- let page_kind = PageKind :: Huge ;
629- let offset = page_kind. page_offset ( gva. u64 ( ) ) ;
630- return Ok ( TranslationDetails :: new ( pdpte. pfn , offset, page_kind, & [
631- pml4e, pdpte,
632- ] ) ) ;
636+ return Ok ( VirtTranslationDetails :: new ( & [ pml4e, pdpte] , gva) ) ;
633637 }
634638
635639 let pde_gpa = Gpa :: new ( pd_base. u64 ( ) + ( gva. pde_idx ( ) * 8 ) ) ;
@@ -643,14 +647,7 @@ impl KernelDumpParser {
643647 // table; see Table 4-18
644648 let pt_base = pde. pfn . gpa ( ) ;
645649 if pde. large_page ( ) {
646- let page_kind = PageKind :: Large ;
647- let offset = page_kind. page_offset ( gva. u64 ( ) ) ;
648- return Ok ( TranslationDetails :: new (
649- pde. pfn ,
650- offset,
651- PageKind :: Large ,
652- & [ pml4e, pdpte, pde] ,
653- ) ) ;
650+ return Ok ( VirtTranslationDetails :: new ( & [ pml4e, pdpte, pde] , gva) ) ;
654651 }
655652
656653 let pte_gpa = Gpa :: new ( pt_base. u64 ( ) + ( gva. pte_idx ( ) * 8 ) ) ;
@@ -663,12 +660,7 @@ impl KernelDumpParser {
663660 }
664661 }
665662
666- let page_kind = PageKind :: Normal ;
667- let offset = page_kind. page_offset ( gva. u64 ( ) ) ;
668-
669- Ok ( TranslationDetails :: new ( pte. pfn , offset, page_kind, & [
670- pml4e, pdpte, pde, pte,
671- ] ) )
663+ Ok ( VirtTranslationDetails :: new ( & [ pml4e, pdpte, pde, pte] , gva) )
672664 }
673665
674666 /// Read virtual memory starting at `gva` into a `buffer`.
0 commit comments