All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
@ 2012-12-17 11:38 Razvan Cojocaru
  2012-12-18 17:04 ` Ian Campbell
  0 siblings, 1 reply; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-17 11:38 UTC (permalink / raw)
  To: xen-devel

Add a xc_domain_hvm_get_mtrr_type() call to the libxc API,
to support functionality similar to get_mtrr_type() (which
is only available at the hypervisor level).

Signed-off-by: Razvan Cojocaru <rzvncj@gmail.com>

diff -r f50aab21f9f2 -r a23515aabc91 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c	Thu Dec 13 14:39:31 2012 +0000
+++ b/tools/libxc/xc_domain.c	Mon Dec 17 12:53:11 2012 +0200
@@ -379,6 +379,45 @@ int xc_domain_hvm_setcontext(xc_interfac
     return ret;
 }
 
+#define MTRR_PHYSMASK_VALID_BIT  11
+#define MTRR_PHYSMASK_SHIFT      12
+#define MTRR_PHYSBASE_TYPE_MASK  0xff   /* lowest 8 bits */
+
+int xc_domain_hvm_get_mtrr_type(xc_interface *xch, 
+                                uint32_t domid,
+                                unsigned long paddress,
+                                uint8_t *type)
+{
+    struct      hvm_hw_mtrr hw_mtrr;
+    int32_t     seg;
+    uint8_t     num_var_ranges;
+    uint64_t    phys_base;
+    uint64_t    phys_mask;
+
+    if ( xc_domain_hvm_getcontext_partial(xch, domid, HVM_SAVE_CODE(MTRR), 0, &hw_mtrr, sizeof hw_mtrr) )
+        return -1;
+
+    num_var_ranges = hw_mtrr.msr_mtrr_cap & 0xff;
+
+    for ( seg = 0; seg < num_var_ranges; seg++ )
+    {
+        phys_base = hw_mtrr.msr_mtrr_var[seg*2];
+        phys_mask = hw_mtrr.msr_mtrr_var[seg*2 + 1];
+
+        if ( phys_mask & (1 << MTRR_PHYSMASK_VALID_BIT) )
+        {
+            if ( ((uint64_t) paddress & phys_mask) >> MTRR_PHYSMASK_SHIFT ==
+                 (phys_base & phys_mask) >> MTRR_PHYSMASK_SHIFT )
+            {
+                *type = phys_base & MTRR_PHYSBASE_TYPE_MASK;
+                return 0;
+            }
+        }
+    }
+
+    return -1;
+}
+
 int xc_vcpu_getcontext(xc_interface *xch,
                        uint32_t domid,
                        uint32_t vcpu,
diff -r f50aab21f9f2 -r a23515aabc91 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h	Thu Dec 13 14:39:31 2012 +0000
+++ b/tools/libxc/xenctrl.h	Mon Dec 17 12:53:11 2012 +0200
@@ -633,6 +633,15 @@ int xc_domain_hvm_setcontext(xc_interfac
                              uint32_t size);
 
 /**
+ * This function returns information about the MTRR type of
+ * a given guest physical address/
+ */
+int xc_domain_hvm_get_mtrr_type(xc_interface *xch, 
+                                uint32_t domid,
+                                unsigned long paddress,
+                                uint8_t *type);
+
+/**
  * This function returns information about the execution context of a
  * particular vcpu of a domain.
  *

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-17 11:38 [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call Razvan Cojocaru
@ 2012-12-18 17:04 ` Ian Campbell
  2012-12-18 17:24   ` Razvan Cojocaru
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Campbell @ 2012-12-18 17:04 UTC (permalink / raw)
  To: Razvan Cojocaru; +Cc: xen-devel

On Mon, 2012-12-17 at 11:38 +0000, Razvan Cojocaru wrote:
> Add a xc_domain_hvm_get_mtrr_type() call to the libxc API,
> to support functionality similar to get_mtrr_type() (which
> is only available at the hypervisor level).

Do you have a user in mind for this new functionality?

> Signed-off-by: Razvan Cojocaru <rzvncj@gmail.com>
> 
> diff -r f50aab21f9f2 -r a23515aabc91 tools/libxc/xc_domain.c
> --- a/tools/libxc/xc_domain.c	Thu Dec 13 14:39:31 2012 +0000
> +++ b/tools/libxc/xc_domain.c	Mon Dec 17 12:53:11 2012 +0200
> @@ -379,6 +379,45 @@ int xc_domain_hvm_setcontext(xc_interfac
>      return ret;
>  }
>  
> +#define MTRR_PHYSMASK_VALID_BIT  11
> +#define MTRR_PHYSMASK_SHIFT      12
> +#define MTRR_PHYSBASE_TYPE_MASK  0xff   /* lowest 8 bits */
> +
> +int xc_domain_hvm_get_mtrr_type(xc_interface *xch, 
> +                                uint32_t domid,
> +                                unsigned long paddress,
> +                                uint8_t *type)
> +{

This version seems to do a lot less than get_mtrr_type() in the
hypervisor. Is that deliberate? Why isn't the fixed mtrr slot and
overlap handling required here?

> [...]

> diff -r f50aab21f9f2 -r a23515aabc91 tools/libxc/xenctrl.h
> --- a/tools/libxc/xenctrl.h	Thu Dec 13 14:39:31 2012 +0000
> +++ b/tools/libxc/xenctrl.h	Mon Dec 17 12:53:11 2012 +0200
> @@ -633,6 +633,15 @@ int xc_domain_hvm_setcontext(xc_interfac
>                               uint32_t size);
>  
>  /**
> + * This function returns information about the MTRR type of
> + * a given guest physical address/

                                   ^ you mean . not / I think.

Ian.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-18 17:04 ` Ian Campbell
@ 2012-12-18 17:24   ` Razvan Cojocaru
  2012-12-19 10:14     ` Ian Campbell
  0 siblings, 1 reply; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-18 17:24 UTC (permalink / raw)
  To: xen-devel

Thanks for the reply!

> Do you have a user in mind for this new functionality?

Yes. An (userspace) application that needs to look at this information 
to decide if a set of pages are interesting for monitoring.

> This version seems to do a lot less than get_mtrr_type() in the
> hypervisor. Is that deliberate? Why isn't the fixed mtrr slot and
> overlap handling required here?

It does do less. It's somewhat deliberate :), ideally it should have 
done everything that get_mtrr_type() does. It did work with my initial 
test addresses, but clearly more is required if it is to provide the 
full functionality of get_mtrr_type(). The code currently only iterates 
through the var_ranges, not the fixed array, etc.

The overlap handling isn't there because there doesn't seem to be a 
clear correspondence between struct mtrr_state and  struct hvm_hw_mtrr. 
I implemented as much of the get_mtrr_type() logic as was obvious using 
what mapping was clear bewtween them.

Is having the full functionality in libxc feasible?

>>   /**
>> + * This function returns information about the MTRR type of
>> + * a given guest physical address/
>
>                                     ^ you mean . not / I think.

You're right, sorry for the typo.

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-18 17:24   ` Razvan Cojocaru
@ 2012-12-19 10:14     ` Ian Campbell
  2012-12-19 10:42       ` Razvan Cojocaru
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Campbell @ 2012-12-19 10:14 UTC (permalink / raw)
  To: Razvan Cojocaru; +Cc: Tim Deegan, xen-devel

On Tue, 2012-12-18 at 17:24 +0000, Razvan Cojocaru wrote:
> Thanks for the reply!
> 
> > Do you have a user in mind for this new functionality?
> 
> Yes. An (userspace) application that needs to look at this information 
> to decide if a set of pages are interesting for monitoring.
> 
> > This version seems to do a lot less than get_mtrr_type() in the
> > hypervisor. Is that deliberate? Why isn't the fixed mtrr slot and
> > overlap handling required here?
> 
> It does do less. It's somewhat deliberate :), ideally it should have 
> done everything that get_mtrr_type() does. It did work with my initial 
> test addresses, but clearly more is required if it is to provide the 
> full functionality of get_mtrr_type(). The code currently only iterates 
> through the var_ranges, not the fixed array, etc.
> 
> The overlap handling isn't there because there doesn't seem to be a 
> clear correspondence between struct mtrr_state and  struct hvm_hw_mtrr. 
> I implemented as much of the get_mtrr_type() logic as was obvious using 
> what mapping was clear bewtween them.
> 
> Is having the full functionality in libxc feasible?

It would certainly be preferable to have libxc do it now rather than
every application it or having to introduce cleverer versions of the API
in the future.

I don't know enough about MTRRs or how Xen represents them either
internally or at the hypercall interface to have a sensible opinion
about the feasibility but my gut feeling is that there's no reason it
shouldn't be.

>From a brief look it seems like hvm_hw_mtrr is a subset of mtrr_state,
which makes sense since you would expect the internal state (struct
mtrr_state) to cache or precompute some stuff for efficiency while
emulating but you don't want to expose that in the architectural state
(struct hvm_hw_mtrr). libxc can (and should) probably recompute anything
it needs above what is in hvm_hw_mtrr on the fly (e.g. check for
overlaps).


Ian.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 10:14     ` Ian Campbell
@ 2012-12-19 10:42       ` Razvan Cojocaru
  2012-12-19 11:28         ` Ian Campbell
  0 siblings, 1 reply; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 10:42 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim Deegan, xen-devel

> It would certainly be preferable to have libxc do it now rather than
> every application it or having to introduce cleverer versions of the API
> in the future.

I agree.

> I don't know enough about MTRRs or how Xen represents them either
> internally or at the hypercall interface to have a sensible opinion
> about the feasibility but my gut feeling is that there's no reason it
> shouldn't be.

Unfortunately I'm far from being an expert on MTRRs too, so maybe 
someone can tell us what the equivalent of this:

uint8_t get_mtrr_type(struct mtrr_state *m, paddr_t pa)
{
     [...]
     if ( unlikely(!(m->enabled & 0x2)) )
         return MTRR_TYPE_UNCACHABLE;
     [...]
}

whould be with libxc code using struct hvm_hw_mtrr? Or, more to the 
point, what the equivalent of m->enabled is in this:

struct hvm_hw_mtrr {
#define MTRR_VCNT 8
#define NUM_FIXED_MSR 11
     uint64_t msr_pat_cr;
     /* mtrr physbase & physmask msr pair*/
     uint64_t msr_mtrr_var[MTRR_VCNT*2];
     uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
     uint64_t msr_mtrr_cap;
     uint64_t msr_mtrr_def_type;
};

I'm also having a hard time figuring out how to map m->overlapped on the 
hvm_hw_mtrr members. It's also quite possible (to me, at least, at this 
stage) that they're not needed because at libxc level they're assumed to 
be set to some value (i.e. 'overlapped' is assumed to be 0, 'enabled' to 
be 1).

Any help is appreciated, if we clear this up I'll modify and re-submit 
the patch.

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 10:42       ` Razvan Cojocaru
@ 2012-12-19 11:28         ` Ian Campbell
  2012-12-19 11:49           ` Razvan Cojocaru
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Campbell @ 2012-12-19 11:28 UTC (permalink / raw)
  To: Razvan Cojocaru; +Cc: Tim (Xen.org), xen-devel

On Wed, 2012-12-19 at 10:42 +0000, Razvan Cojocaru wrote:
> > It would certainly be preferable to have libxc do it now rather than
> > every application it or having to introduce cleverer versions of the API
> > in the future.
> 
> I agree.
> 
> > I don't know enough about MTRRs or how Xen represents them either
> > internally or at the hypercall interface to have a sensible opinion
> > about the feasibility but my gut feeling is that there's no reason it
> > shouldn't be.
> 
> Unfortunately I'm far from being an expert on MTRRs too,

There is a section in the Intel SDM (chapter 10.4 in my copy) which
explains the meanings etc of the registers, which are what is exposed in
hvm_hw_mtrr I think.

>  so maybe 
> someone can tell us what the equivalent of this:
> 
> uint8_t get_mtrr_type(struct mtrr_state *m, paddr_t pa)
> {
>      [...]
>      if ( unlikely(!(m->enabled & 0x2)) )
>          return MTRR_TYPE_UNCACHABLE;
>      [...]
> }
> 
> whould be with libxc code using struct hvm_hw_mtrr? Or, more to the 
> point, what the equivalent of m->enabled is in this:

xen/arch/x86/hvm/mtrr.c:mtrr_def_type_msr_set() seems to be where it is
written, and it is called with hw_mtrr.msr_mtrr_def_type so it looks
like it can be derived from that value in hvm_hw_mtrr.

> 
> struct hvm_hw_mtrr {
> #define MTRR_VCNT 8
> #define NUM_FIXED_MSR 11
>      uint64_t msr_pat_cr;
>      /* mtrr physbase & physmask msr pair*/
>      uint64_t msr_mtrr_var[MTRR_VCNT*2];
>      uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
>      uint64_t msr_mtrr_cap;
>      uint64_t msr_mtrr_def_type;
> };
> 
> I'm also having a hard time figuring out how to map m->overlapped on the 
> hvm_hw_mtrr members.

    m->overlapped = is_var_mtrr_overlapped(m);

Looks like that function contains the necessary logic.

>  It's also quite possible (to me, at least, at this 
> stage) that they're not needed because at libxc level they're assumed to 
> be set to some value (i.e. 'overlapped' is assumed to be 0, 'enabled' to 
> be 1).
> 
> Any help is appreciated, if we clear this up I'll modify and re-submit 
> the patch.
> 
> Thanks,
> Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 11:28         ` Ian Campbell
@ 2012-12-19 11:49           ` Razvan Cojocaru
  2012-12-19 12:00             ` Razvan Cojocaru
  2012-12-19 14:57             ` Razvan Cojocaru
  0 siblings, 2 replies; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 11:49 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim (Xen.org), xen-devel

> There is a section in the Intel SDM (chapter 10.4 in my copy) which
> explains the meanings etc of the registers, which are what is exposed in
> hvm_hw_mtrr I think.

Thanks, I'll look that up.

> xen/arch/x86/hvm/mtrr.c:mtrr_def_type_msr_set() seems to be where it is
> written, and it is called with hw_mtrr.msr_mtrr_def_type so it looks
> like it can be derived from that value in hvm_hw_mtrr.

Indeed it is, but this happens there:

uint8_t def_type = msr_content & 0xff;
uint8_t enabled = (msr_content >> 10) & 0x3;

So what ends up being put in def_type is only one byte of msr_content, 
whereas enabled is some bits from another byte of msr_content. To make 
matters worse, hw_mtrr.msr_mtrr_def_type is an uint64_t, so would that 
mean that hw_mtrr.msr_mtrr_def_type is actually the whole of msr_content?

>> I'm also having a hard time figuring out how to map m->overlapped on the
>> hvm_hw_mtrr members.
>
>      m->overlapped = is_var_mtrr_overlapped(m);
>
> Looks like that function contains the necessary logic.

You're right, but what happens there is that that function depends on 
the get_mtrr_range() function, which in turn depends on the size_or_mask 
global variable, which is initialized in hvm_mtrr_pat_init(), which then 
depends on a global table, and so on. Putting that into libxc is pretty 
much putting the whole mtrr.c file there.

Is this amount of copy/paste code a good thing, and wouldn't it be less 
tedious and bug-prone to have that code in a single place, and just add 
overlapped and enabled to hw_mtrr before sending it out into userspace?

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 11:49           ` Razvan Cojocaru
@ 2012-12-19 12:00             ` Razvan Cojocaru
  2012-12-19 14:57             ` Razvan Cojocaru
  1 sibling, 0 replies; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 12:00 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim (Xen.org), xen-devel

>> xen/arch/x86/hvm/mtrr.c:mtrr_def_type_msr_set() seems to be where it is
>> written, and it is called with hw_mtrr.msr_mtrr_def_type so it looks
>> like it can be derived from that value in hvm_hw_mtrr.
>
> Indeed it is, but this happens there:
>
> uint8_t def_type = msr_content & 0xff;
> uint8_t enabled = (msr_content >> 10) & 0x3;

Nevermind, found it :)

mtrr.c / static int hvm_save_mtrr_msr(struct domain *d, 
hvm_domain_context_t *h):

hw_mtrr.msr_mtrr_def_type = mtrr_state->def_type
     | (mtrr_state->enabled << 10);

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 11:49           ` Razvan Cojocaru
  2012-12-19 12:00             ` Razvan Cojocaru
@ 2012-12-19 14:57             ` Razvan Cojocaru
  2012-12-19 15:00               ` Ian Campbell
  2012-12-20 11:54               ` Tim Deegan
  1 sibling, 2 replies; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 14:57 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim (Xen.org), xen-devel

>>      m->overlapped = is_var_mtrr_overlapped(m);
>>
>> Looks like that function contains the necessary logic.
>
> You're right, but what happens there is that that function depends on
> the get_mtrr_range() function, which in turn depends on the size_or_mask
> global variable, which is initialized in hvm_mtrr_pat_init(), which then
> depends on a global table, and so on. Putting that into libxc is pretty
> much putting the whole mtrr.c file there.

This is where it gets tricky:

static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
                            uint64_t *base, uint64_t *end)
{
     [...]
     phys_addr = 36;

     if ( cpuid_eax(0x80000000) >= 0x80000008 )
         phys_addr = (uint8_t)cpuid_eax(0x80000008);

     size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
     [...]
}

specifically, in the cpuid_eax() call, which doesn't make much sense in 
dom0 userspace.

I did manage to take 'enabled' into account with what appears to be 
success, but if I've read the situation correctly, there's not much to 
do about 'overlap', unless we save it in hvm_save_mtrr_msr() like it's 
done with 'enabled'. What do you think?

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 14:57             ` Razvan Cojocaru
@ 2012-12-19 15:00               ` Ian Campbell
  2012-12-19 15:10                 ` Razvan Cojocaru
                                   ` (2 more replies)
  2012-12-20 11:54               ` Tim Deegan
  1 sibling, 3 replies; 22+ messages in thread
From: Ian Campbell @ 2012-12-19 15:00 UTC (permalink / raw)
  To: Razvan Cojocaru; +Cc: Tim (Xen.org), xen-devel

On Wed, 2012-12-19 at 14:57 +0000, Razvan Cojocaru wrote:
> >>      m->overlapped = is_var_mtrr_overlapped(m);
> >>
> >> Looks like that function contains the necessary logic.
> >
> > You're right, but what happens there is that that function depends on
> > the get_mtrr_range() function, which in turn depends on the size_or_mask
> > global variable, which is initialized in hvm_mtrr_pat_init(), which then
> > depends on a global table, and so on. Putting that into libxc is pretty
> > much putting the whole mtrr.c file there.
> 
> This is where it gets tricky:
> 
> static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
>                             uint64_t *base, uint64_t *end)
> {
>      [...]
>      phys_addr = 36;
> 
>      if ( cpuid_eax(0x80000000) >= 0x80000008 )
>          phys_addr = (uint8_t)cpuid_eax(0x80000008);
> 
>      size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
>      [...]
> }
> 
> specifically, in the cpuid_eax() call, which doesn't make much sense in 
> dom0 userspace.

The fact that get_mtrr_range is querying the underlying physical CPUID
suggests it has something to do with the translation from virtual to
physical MTRR and is therefore not something userspace needs to worry
about, but I'm only speculating.

> I did manage to take 'enabled' into account with what appears to be 
> success, but if I've read the situation correctly, there's not much to 
> do about 'overlap', unless we save it in hvm_save_mtrr_msr() like it's 
> done with 'enabled'. What do you think?

It's not an architectural thing so I don't think it belongs in there.

TBH until someone figures out or explains what overlap actually is I
don't know if it even needs exporting or taking into account in
userspace.

Ian.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 15:00               ` Ian Campbell
@ 2012-12-19 15:10                 ` Razvan Cojocaru
  2012-12-19 15:27                 ` Andrew Cooper
  2012-12-19 15:43                 ` Razvan Cojocaru
  2 siblings, 0 replies; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 15:10 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim (Xen.org), xen-devel

>> I did manage to take 'enabled' into account with what appears to be
>> success, but if I've read the situation correctly, there's not much to
>> do about 'overlap', unless we save it in hvm_save_mtrr_msr() like it's
>> done with 'enabled'. What do you think?
>
> It's not an architectural thing so I don't think it belongs in there.
>
> TBH until someone figures out or explains what overlap actually is I
> don't know if it even needs exporting or taking into account in
> userspace.

Well, get_mtrr_range() is being called by is_var_mtrr_overlapped(), 
which is the function that sets m->overlapped, which is then used quite 
a lot in the logic of the get_mtrr_type(), which this patch attempts to 
bring into userspace via libxc.

I would quite happily discount all checks against the overlap boolean 
argument (and my code seems to work like that), but I suspect whoever 
wrote get_mtrr_type() had good reason to check for that.

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 15:00               ` Ian Campbell
  2012-12-19 15:10                 ` Razvan Cojocaru
@ 2012-12-19 15:27                 ` Andrew Cooper
  2012-12-19 15:54                   ` Ian Campbell
  2012-12-19 15:43                 ` Razvan Cojocaru
  2 siblings, 1 reply; 22+ messages in thread
From: Andrew Cooper @ 2012-12-19 15:27 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim (Xen.org), Razvan Cojocaru, xen-devel

On 19/12/2012 15:00, Ian Campbell wrote:
> On Wed, 2012-12-19 at 14:57 +0000, Razvan Cojocaru wrote:
>>>>      m->overlapped = is_var_mtrr_overlapped(m);
>>>>
>>>> Looks like that function contains the necessary logic.
>>> You're right, but what happens there is that that function depends on
>>> the get_mtrr_range() function, which in turn depends on the size_or_mask
>>> global variable, which is initialized in hvm_mtrr_pat_init(), which then
>>> depends on a global table, and so on. Putting that into libxc is pretty
>>> much putting the whole mtrr.c file there.
>> This is where it gets tricky:
>>
>> static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
>>                             uint64_t *base, uint64_t *end)
>> {
>>      [...]
>>      phys_addr = 36;
>>
>>      if ( cpuid_eax(0x80000000) >= 0x80000008 )
>>          phys_addr = (uint8_t)cpuid_eax(0x80000008);
>>
>>      size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
>>      [...]
>> }
>>
>> specifically, in the cpuid_eax() call, which doesn't make much sense in 
>> dom0 userspace.
> The fact that get_mtrr_range is querying the underlying physical CPUID
> suggests it has something to do with the translation from virtual to
> physical MTRR and is therefore not something userspace needs to worry
> about, but I'm only speculating.

CPUID 0x80000008.EAX is the physical address size supported by the
processor (in bits).  Typical values on modern hardware are 40 or 48.

You need to know this information to work out which bits in the MTRR are
valid.  It is a variable scale of which bits are reserved.

Having said the above, this information is never going to change on the
same CPU, so should be cached once to save repeated emulates of cpuid.

~Andrew

>
>> I did manage to take 'enabled' into account with what appears to be 
>> success, but if I've read the situation correctly, there's not much to 
>> do about 'overlap', unless we save it in hvm_save_mtrr_msr() like it's 
>> done with 'enabled'. What do you think?
> It's not an architectural thing so I don't think it belongs in there.
>
> TBH until someone figures out or explains what overlap actually is I
> don't know if it even needs exporting or taking into account in
> userspace.
>
> Ian.
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 15:00               ` Ian Campbell
  2012-12-19 15:10                 ` Razvan Cojocaru
  2012-12-19 15:27                 ` Andrew Cooper
@ 2012-12-19 15:43                 ` Razvan Cojocaru
  2 siblings, 0 replies; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 15:43 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim (Xen.org), xen-devel

> TBH until someone figures out or explains what overlap actually is I
> don't know if it even needs exporting or taking into account in
> userspace.

http://www.mjmwired.net/kernel/Documentation/mtrr.txt

"Creating overlapping MTRRs:

%echo "base=0xfb000000 size=0x1000000 type=write-combining" >/proc/mtrr
%echo "base=0xfb000000 size=0x1000 type=uncachable" >/proc/mtrr

And the results: cat /proc/mtrr
reg00: base=0x00000000 (   0MB), size=  64MB: write-back, count=1
reg01: base=0xfb000000 (4016MB), size=  16MB: write-combining, count=1
reg02: base=0xfb000000 (4016MB), size=   4kB: uncachable, count=1"

Overlapped MTRRs are MTRRs with the same base, but different types of 
addresses at different offsets.

At least to my understanding.

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 15:27                 ` Andrew Cooper
@ 2012-12-19 15:54                   ` Ian Campbell
  2012-12-19 16:11                     ` Andrew Cooper
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Campbell @ 2012-12-19 15:54 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Tim (Xen.org), Razvan Cojocaru, xen-devel

On Wed, 2012-12-19 at 15:27 +0000, Andrew Cooper wrote:
> On 19/12/2012 15:00, Ian Campbell wrote:
> > On Wed, 2012-12-19 at 14:57 +0000, Razvan Cojocaru wrote:
> >>>>      m->overlapped = is_var_mtrr_overlapped(m);
> >>>>
> >>>> Looks like that function contains the necessary logic.
> >>> You're right, but what happens there is that that function depends on
> >>> the get_mtrr_range() function, which in turn depends on the size_or_mask
> >>> global variable, which is initialized in hvm_mtrr_pat_init(), which then
> >>> depends on a global table, and so on. Putting that into libxc is pretty
> >>> much putting the whole mtrr.c file there.
> >> This is where it gets tricky:
> >>
> >> static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
> >>                             uint64_t *base, uint64_t *end)
> >> {
> >>      [...]
> >>      phys_addr = 36;
> >>
> >>      if ( cpuid_eax(0x80000000) >= 0x80000008 )
> >>          phys_addr = (uint8_t)cpuid_eax(0x80000008);
> >>
> >>      size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
> >>      [...]
> >> }
> >>
> >> specifically, in the cpuid_eax() call, which doesn't make much sense in 
> >> dom0 userspace.
> > The fact that get_mtrr_range is querying the underlying physical CPUID
> > suggests it has something to do with the translation from virtual to
> > physical MTRR and is therefore not something userspace needs to worry
> > about, but I'm only speculating.
> 
> CPUID 0x80000008.EAX is the physical address size supported by the
> processor (in bits).  Typical values on modern hardware are 40 or 48.

I know what the bit is. This code seems to be leaking physical CPU
parameters into the virtual CPU state and the question is if userspace
needs to care about that. I suspect the answer is no.

What should matter for the guest state is the virtualised CPUID
0x80000008.EAX which, at least in theory, could be different (e.g. a
migrated guest?). 

Ian.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 15:54                   ` Ian Campbell
@ 2012-12-19 16:11                     ` Andrew Cooper
  2012-12-19 16:15                       ` Ian Campbell
  0 siblings, 1 reply; 22+ messages in thread
From: Andrew Cooper @ 2012-12-19 16:11 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Tim (Xen.org), Razvan Cojocaru, xen-devel

On 19/12/2012 15:54, Ian Campbell wrote:
> On Wed, 2012-12-19 at 15:27 +0000, Andrew Cooper wrote:
>> On 19/12/2012 15:00, Ian Campbell wrote:
>>> On Wed, 2012-12-19 at 14:57 +0000, Razvan Cojocaru wrote:
>>>>>>      m->overlapped = is_var_mtrr_overlapped(m);
>>>>>>
>>>>>> Looks like that function contains the necessary logic.
>>>>> You're right, but what happens there is that that function depends on
>>>>> the get_mtrr_range() function, which in turn depends on the size_or_mask
>>>>> global variable, which is initialized in hvm_mtrr_pat_init(), which then
>>>>> depends on a global table, and so on. Putting that into libxc is pretty
>>>>> much putting the whole mtrr.c file there.
>>>> This is where it gets tricky:
>>>>
>>>> static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
>>>>                             uint64_t *base, uint64_t *end)
>>>> {
>>>>      [...]
>>>>      phys_addr = 36;
>>>>
>>>>      if ( cpuid_eax(0x80000000) >= 0x80000008 )
>>>>          phys_addr = (uint8_t)cpuid_eax(0x80000008);
>>>>
>>>>      size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
>>>>      [...]
>>>> }
>>>>
>>>> specifically, in the cpuid_eax() call, which doesn't make much sense in 
>>>> dom0 userspace.
>>> The fact that get_mtrr_range is querying the underlying physical CPUID
>>> suggests it has something to do with the translation from virtual to
>>> physical MTRR and is therefore not something userspace needs to worry
>>> about, but I'm only speculating.
>> CPUID 0x80000008.EAX is the physical address size supported by the
>> processor (in bits).  Typical values on modern hardware are 40 or 48.
> I know what the bit is. This code seems to be leaking physical CPU
> parameters into the virtual CPU state and the question is if userspace
> needs to care about that. I suspect the answer is no.
>
> What should matter for the guest state is the virtualised CPUID
> 0x80000008.EAX which, at least in theory, could be different (e.g. a
> migrated guest?). 
>
> Ian.
>

Ah - I see your concern.  Yes - it might well be different.  Is this
information passed in an HVM save record?  It does not appear to be
associated with the MTRR HVM save record.

An HVM domain, booted on processor with 48bit physical addressing, which
makes use of the upper 8 bits when setting up the variable MTRRs, which
is subsequently migrated to a different server with only 40bit physical
addressing is going to have problems.  Whether a protection fault occurs
or the top bits are simply ignored, stuff will break.

As a result, I think the virtualised CPUID value needs feature levelling
across hosts, or restrictions applied to where you can migrate a started
VM to.

~Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 16:11                     ` Andrew Cooper
@ 2012-12-19 16:15                       ` Ian Campbell
  2012-12-19 16:29                         ` Razvan Cojocaru
  0 siblings, 1 reply; 22+ messages in thread
From: Ian Campbell @ 2012-12-19 16:15 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Tim (Xen.org), Razvan Cojocaru, xen-devel

On Wed, 2012-12-19 at 16:11 +0000, Andrew Cooper wrote:
> On 19/12/2012 15:54, Ian Campbell wrote:
> > On Wed, 2012-12-19 at 15:27 +0000, Andrew Cooper wrote:
> >> On 19/12/2012 15:00, Ian Campbell wrote:
> >>> On Wed, 2012-12-19 at 14:57 +0000, Razvan Cojocaru wrote:
> >>>>>>      m->overlapped = is_var_mtrr_overlapped(m);
> >>>>>>
> >>>>>> Looks like that function contains the necessary logic.
> >>>>> You're right, but what happens there is that that function depends on
> >>>>> the get_mtrr_range() function, which in turn depends on the size_or_mask
> >>>>> global variable, which is initialized in hvm_mtrr_pat_init(), which then
> >>>>> depends on a global table, and so on. Putting that into libxc is pretty
> >>>>> much putting the whole mtrr.c file there.
> >>>> This is where it gets tricky:
> >>>>
> >>>> static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
> >>>>                             uint64_t *base, uint64_t *end)
> >>>> {
> >>>>      [...]
> >>>>      phys_addr = 36;
> >>>>
> >>>>      if ( cpuid_eax(0x80000000) >= 0x80000008 )
> >>>>          phys_addr = (uint8_t)cpuid_eax(0x80000008);
> >>>>
> >>>>      size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
> >>>>      [...]
> >>>> }
> >>>>
> >>>> specifically, in the cpuid_eax() call, which doesn't make much sense in 
> >>>> dom0 userspace.
> >>> The fact that get_mtrr_range is querying the underlying physical CPUID
> >>> suggests it has something to do with the translation from virtual to
> >>> physical MTRR and is therefore not something userspace needs to worry
> >>> about, but I'm only speculating.
> >> CPUID 0x80000008.EAX is the physical address size supported by the
> >> processor (in bits).  Typical values on modern hardware are 40 or 48.
> > I know what the bit is. This code seems to be leaking physical CPU
> > parameters into the virtual CPU state and the question is if userspace
> > needs to care about that. I suspect the answer is no.
> >
> > What should matter for the guest state is the virtualised CPUID
> > 0x80000008.EAX which, at least in theory, could be different (e.g. a
> > migrated guest?). 
> >
> > Ian.
> >
> 
> Ah - I see your concern.  Yes - it might well be different.  Is this
> information passed in an HVM save record?  It does not appear to be
> associated with the MTRR HVM save record.

No , this is the internal state not the save record but Razvan is
implementing the same logic in libxc which must necessarily be based on
the hvm saved state only and not the internal emulation state.

> An HVM domain, booted on processor with 48bit physical addressing, which
> makes use of the upper 8 bits when setting up the variable MTRRs, which
> is subsequently migrated to a different server with only 40bit physical
> addressing is going to have problems.  Whether a protection fault occurs
> or the top bits are simply ignored, stuff will break.

This is HVM, so I would hope the hypervisor would catch it and do
something sensible before it hits the real (or VMCS) registers.

> As a result, I think the virtualised CPUID value needs feature levelling
> across hosts, or restrictions applied to where you can migrate a started
> VM to.

This seems likely. 

Ian.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 16:15                       ` Ian Campbell
@ 2012-12-19 16:29                         ` Razvan Cojocaru
  2012-12-19 17:46                           ` Tim Deegan
  0 siblings, 1 reply; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 16:29 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Andrew Cooper, Tim (Xen.org), xen-devel

>> Ah - I see your concern.  Yes - it might well be different.  Is this
>> information passed in an HVM save record?  It does not appear to be
>> associated with the MTRR HVM save record.
>
> No , this is the internal state not the save record but Razvan is
> implementing the same logic in libxc which must necessarily be based on
> the hvm saved state only and not the internal emulation state.

Exactly, and all I need extra an extra variable in the save record (or 
simply a single bit in a safe place in one of the existing ones), 
telling me if the MTRRs are overlapped or not. The CPUID code is just a 
part of the logic that finds this out in the hypervisor; and 
specifically it is a part that's better _left_in_ the hypervisor. That 
is in fact what I was trying to say a few messages ago, when I called 
the cpuid_eax() function the tricky part. :)

Do we agree that a bool_t overlapped should be added to struct 
hvm_hw_mtrr for this case?

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 16:29                         ` Razvan Cojocaru
@ 2012-12-19 17:46                           ` Tim Deegan
  2012-12-19 19:35                             ` Razvan Cojocaru
  0 siblings, 1 reply; 22+ messages in thread
From: Tim Deegan @ 2012-12-19 17:46 UTC (permalink / raw)
  To: Razvan Cojocaru; +Cc: Andrew Cooper, Ian Campbell, xen-devel

At 18:29 +0200 on 19 Dec (1355941750), Razvan Cojocaru wrote:
> >>Ah - I see your concern.  Yes - it might well be different.  Is this
> >>information passed in an HVM save record?  It does not appear to be
> >>associated with the MTRR HVM save record.
> >
> >No , this is the internal state not the save record but Razvan is
> >implementing the same logic in libxc which must necessarily be based on
> >the hvm saved state only and not the internal emulation state.
> 
> Exactly, and all I need extra an extra variable in the save record (or 
> simply a single bit in a safe place in one of the existing ones), 
> telling me if the MTRRs are overlapped or not. The CPUID code is just a 
> part of the logic that finds this out in the hypervisor; and 
> specifically it is a part that's better _left_in_ the hypervisor. That 
> is in fact what I was trying to say a few messages ago, when I called 
> the cpuid_eax() function the tricky part. :)
> 
> Do we agree that a bool_t overlapped should be added to struct 
> hvm_hw_mtrr for this case?

Sorry, no.  The 'overlapped' bit is a piece of xen implementation, and
not an architectural state of the VM, so it doesn't belong in the save
record.  It's trivial to recalculate in a user-space tool, and the
result can be cached (since you can also get a mem-event on MSR writes,
you don't have to pull all this MTRR state out of the giuest except when
the MTRRs have been changed).

I'll take a proper look at this thread tomorrow and see if I can suggest
anything more helpful. 

Tim.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 17:46                           ` Tim Deegan
@ 2012-12-19 19:35                             ` Razvan Cojocaru
  2012-12-20 11:57                               ` Tim Deegan
  0 siblings, 1 reply; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-19 19:35 UTC (permalink / raw)
  To: Tim Deegan; +Cc: Andrew Cooper, Ian Campbell, xen-devel

> Sorry, no.  The 'overlapped' bit is a piece of xen implementation, and
> not an architectural state of the VM, so it doesn't belong in the save
> record.  It's trivial to recalculate in a user-space tool, and the

Is it trivial to recalculate that in a userspace tool? I thought the
only way to properly calculate that in the first place was to use
cpuid_eax() in the calculation, which is only available at hypervisor
level (hence much of this thread). Am I missing something?

> result can be cached (since you can also get a mem-event on MSR writes,
> you don't have to pull all this MTRR state out of the giuest except when
> the MTRRs have been changed).

Unfortunately, due to the design of components I don't control, my
application does not have the luxury of waiting for an MSR write event.
(Has my MSR mem_event patch been acknowledged? Or was this already work
in progress? I had to patch my Xen source code to be able to get MSR
events...)

> I'll take a proper look at this thread tomorrow and see if I can suggest
> anything more helpful. 

Thank you, I appreciate the reply, and your time.

All the best,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 14:57             ` Razvan Cojocaru
  2012-12-19 15:00               ` Ian Campbell
@ 2012-12-20 11:54               ` Tim Deegan
  1 sibling, 0 replies; 22+ messages in thread
From: Tim Deegan @ 2012-12-20 11:54 UTC (permalink / raw)
  To: Razvan Cojocaru; +Cc: Ian Campbell, xen-devel

At 16:57 +0200 on 19 Dec (1355936221), Razvan Cojocaru wrote:
> >>     m->overlapped = is_var_mtrr_overlapped(m);
> >>
> >>Looks like that function contains the necessary logic.
> >
> >You're right, but what happens there is that that function depends on
> >the get_mtrr_range() function, which in turn depends on the size_or_mask
> >global variable, which is initialized in hvm_mtrr_pat_init(), which then
> >depends on a global table, and so on. Putting that into libxc is pretty
> >much putting the whole mtrr.c file there.
> 
> This is where it gets tricky:
> 
> static void get_mtrr_range(uint64_t base_msr, uint64_t mask_msr,
>                            uint64_t *base, uint64_t *end)
> {
>     [...]
>     phys_addr = 36;
> 
>     if ( cpuid_eax(0x80000000) >= 0x80000008 )
>         phys_addr = (uint8_t)cpuid_eax(0x80000008);
> 
>     size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
>     [...]
> }
> 
> specifically, in the cpuid_eax() call, which doesn't make much sense in 
> dom0 userspace.

You can execute the CPUID instruction from dom0 userspace, and get
exactly the same result as Xen does.

(It may, separately, be a bug that Xen uses the host CPUID here and not
a well-defined guest width.  If that gets fixed, the guest address width
will be made available in the save record and you can extract it from
there.)

But also, you don't necessarily need to calculate 'overlapped' for each
MTRR in advance.  It may make sense to do so for speed, as Xen does, but
you could also just handle overlapping MTRRS in your lookup function, by
comparing the address to all MTRRs and handling the case where it
matches more than one.

Tim.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-19 19:35                             ` Razvan Cojocaru
@ 2012-12-20 11:57                               ` Tim Deegan
  2012-12-20 13:40                                 ` Razvan Cojocaru
  0 siblings, 1 reply; 22+ messages in thread
From: Tim Deegan @ 2012-12-20 11:57 UTC (permalink / raw)
  To: Razvan Cojocaru; +Cc: Andrew Cooper, Ian Campbell, xen-devel

At 21:35 +0200 on 19 Dec (1355952919), Razvan Cojocaru wrote:
> > result can be cached (since you can also get a mem-event on MSR writes,
> > you don't have to pull all this MTRR state out of the giuest except when
> > the MTRRs have been changed).
> 
> Unfortunately, due to the design of components I don't control, my
> application does not have the luxury of waiting for an MSR write event.

Hmm.  In that case I guess you can't cache the MTRR state between
lookups, which may be a performance problem for you.

> (Has my MSR mem_event patch been acknowledged? Or was this already work
> in progress? I had to patch my Xen source code to be able to get MSR
> events...)

I've replied to that separately. 

Cheers,

Tim.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call
  2012-12-20 11:57                               ` Tim Deegan
@ 2012-12-20 13:40                                 ` Razvan Cojocaru
  0 siblings, 0 replies; 22+ messages in thread
From: Razvan Cojocaru @ 2012-12-20 13:40 UTC (permalink / raw)
  To: Tim Deegan; +Cc: Andrew Cooper, Ian Campbell, xen-devel

 >> Unfortunately, due to the design of components I don't control, my
 >> application does not have the luxury of waiting for an MSR write event.
 >
 > Hmm.  In that case I guess you can't cache the MTRR state between
 > lookups, which may be a performance problem for you.

Indeed, however I do need the ability to pull the MTRR type for a given 
address, via a userspace application, from the hypervisor.

I'll play around with the libxc implementation and see what I can come 
up with, then if it'll all seem to work out I'll send the patch to 
xen-devel.

Thanks,
Razvan Cojocaru

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2012-12-20 13:40 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-17 11:38 [PATCH] libxc: Add xc_domain_hvm_get_mtrr_type() call Razvan Cojocaru
2012-12-18 17:04 ` Ian Campbell
2012-12-18 17:24   ` Razvan Cojocaru
2012-12-19 10:14     ` Ian Campbell
2012-12-19 10:42       ` Razvan Cojocaru
2012-12-19 11:28         ` Ian Campbell
2012-12-19 11:49           ` Razvan Cojocaru
2012-12-19 12:00             ` Razvan Cojocaru
2012-12-19 14:57             ` Razvan Cojocaru
2012-12-19 15:00               ` Ian Campbell
2012-12-19 15:10                 ` Razvan Cojocaru
2012-12-19 15:27                 ` Andrew Cooper
2012-12-19 15:54                   ` Ian Campbell
2012-12-19 16:11                     ` Andrew Cooper
2012-12-19 16:15                       ` Ian Campbell
2012-12-19 16:29                         ` Razvan Cojocaru
2012-12-19 17:46                           ` Tim Deegan
2012-12-19 19:35                             ` Razvan Cojocaru
2012-12-20 11:57                               ` Tim Deegan
2012-12-20 13:40                                 ` Razvan Cojocaru
2012-12-19 15:43                 ` Razvan Cojocaru
2012-12-20 11:54               ` Tim Deegan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.