Horms wrote:
Hi,

I did some poking around with regards to accessing guest domain's cr3
from within the hypervisor (and thus a crash dump). I'm pretty sure that
the following loop finds them all:

void find_cr3(void)
{
        struct domain *d;
        struct vcpu   *v;

        /* Don't need to grab domlist_lock as we are the only thing running */
        for_each_domain ( d )
                for_each_vcpu ( d, v )
                        if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
                                printk("domain:%i vcpu:%u cr3:%08x\n",
                                        d->domain_id, v->vcpu_id,
                                        pagetable_get_pfn(v->arch.guest_table));
}

I currently call that function in machine_crash_shutdown() just before
calling crash_save_self(). That is after all but the crashing CPU have
been shutdown, and just before the crashing CPU is saved and the crash
kernel is run.

It produces the following output on a 2 CPU system with 2 guest (and one
privileged) domains. All domains have all CPUs, though its fairly easy to
imagine what the output would look like if they didn't.

(XEN) domain:0 vcpu:0 cr3:00027243
(XEN) domain:0 vcpu:1 cr3:0003e8a9
(XEN) domain:1 vcpu:0 cr3:00026e0b
(XEN) domain:1 vcpu:1 cr3:0002080c
(XEN) domain:2 vcpu:0 cr3:000297d4
(XEN) domain:2 vcpu:1 cr3:000297d0

The nice thing is that this code is really just a trivial walk of
domain_list, a global symbol. Is it possible for you to just access that,
or perhaps for me to just save it in a crash note somewhere? It would
be nice not to have to save all of the cr3 values in crash notes as
the number of them depends on the number of active domains (and online
CPUs), which cannot be predicted at boot time.

That would be ideal, but I now realize that your kdump kernel
is a hypervisor kernel and not a vmlinux kernel -- I didn't realize
that prior to this.

Anyway, there is no "domain_list" in the dom0 vmlinux file,
So we're still stuck not being able to gain access to the key data
pieces with vmlinux symbols alone.

Again, the best thing to have would be the access to this
shared data structure:

struct arch_shared_info {
    unsigned long max_pfn;                  /* max pfn that appears in table */
    /* Frame containing list of mfns containing list of mfns containing p2m. */
    unsigned long pfn_to_mfn_frame_list_list;
    unsigned long nmi_reason;
};

which seems to be common to both the hypervisor and the
vmlinux kernels.  With the pfn_to_mfn_frame_list_list mfn value,
the phys_to_machine_mapping[] array can be reconstructed.

Alternatively, having a legitimate cr3 value -- in a writable page table
xen kernel -- currently allows the pagetable walkthough to find the
location of the phys_to_machine_mapping array.

However...

Kazuo Moriwaka <moriwaka@valinux.co.jp> wrote:

Hi, 

I'm not clear about shadow mode; are vcpu->arch.shadow_table need for
shadow-mode domains?


That's an excellent point -- in which case the cr3 values would seemingly
be useless if they point to pseudo-physical addresses in a shadow-pagetable
xen kernel.  Note that I've only worked with writeable pagetable kernels
up to this point; I haven't even looked into how to reconstruct the p2m table
with a shadow-pagetable xendump.

In any case, it would appear that it will require knowing where the
pfn_to_mfn_frame_list_list mfn is in order to cover both writable and
shadow pagetable kernels.

Dave
 

 

If you do need stuff saved in crash notes, I guess I could just chain it
off the crash note for CPU0. Or if its just one pointer I could probably
find free space in the existing crash note for CPU0 as I seem to recall
that some fields (like say for instance the pid as the hypervisor doesn't
have them) aren't used.