All of lore.kernel.org
 help / color / mirror / Atom feed
From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
To: qemu-devel@nongnu.org
Cc: dgilbert@redhat.com, armbru@redhat.com,
	david@gibson.dropbear.id.au, qemu-ppc@nongnu.org,
	Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Subject: [Qemu-devel] [PATCH 2/2] ppc: Add dump-stack implementation
Date: Wed,  1 May 2019 15:35:22 +1000	[thread overview]
Message-ID: <20190501053522.10967-2-sjitindarsingh@gmail.com> (raw)
In-Reply-To: <20190501053522.10967-1-sjitindarsingh@gmail.com>

The monitor function dump-stack is used to dump the stack for a cpu.
This can be useful for debugging purposes when the stack cannot be
dumped by another means.

Add a ppc implementation ppc_cpu_dump_stack().
The stack pointer is stored in R1 with the back pointer at offset 0 and
the link register at offset 2.
Also dump the registers from the stack frame if the marker "regshere" is
found.
This only dumps the kernel stack, stopping if a non-kernel address is
found in the stack.

Sample output:
(qemu) dump-stack
sp: 0xc00000007bfc5690 lr: 0xc0000000000974b8
sp: 0xc00000007bfc56f0 lr: 0xc00000000065aab4
sp: 0xc00000007bfc5720 lr: 0xc00000000065ab04
sp: 0xc00000007bfc5740 lr: 0xc0000000000c29b8
sp: 0xc00000007bfc57b0 lr: 0xc0000000000bc9e8
sp: 0xc00000007bfc57e0 lr: 0xc0000000000bd584
sp: 0xc00000007bfc5800 lr: 0xc0000000000bee14
sp: 0xc00000007bfc5ac0 lr: 0xc0000000000c2100
sp: 0xc00000007bfc5c60 lr: 0xc000000000029460
sp: 0xc00000007bfc5ca0 lr: 0xc00000000010b5e8
sp: 0xc00000007bfc5d00 lr: 0xc000000000105f34
	trap : 0x0000000000000700
	pc   : 0xc000000000104490
	msr  : 0x9000000002843003
	lr   : 0xc000000000103ffc
	gpr 0: 0x0000000000000001
	gpr 1: 0xc00000005051f530
	gpr 2: 0xc000000001088200
	gpr 3: 0x0000000000000001
	gpr 4: 0xc000000032d60000
	gpr 5: 0xc0000000014b8f00
	gpr 6: 0x0000000000c835e0
	gpr 7: 0x0000000000000000
	gpr 8: 0x0000000000000000
	gpr 9: 0xc000000032f00000
	gpr10: 0x9000000002803033
	gpr11: 0xc000000000b60f00
	gpr12: 0x0000000000002000
	gpr13: 0xc000000001250000
	gpr14: 0x0000000000000000
	gpr15: 0x0000000000000008
	gpr16: 0x0000000000000000
	gpr17: 0xc00000000114f790
	gpr18: 0x00000000ffffffff
	gpr19: 0xc00000005051f8e8
	gpr20: 0x0000000000000001
	gpr21: 0x0000000000000000
	gpr22: 0x0000000000000001
	gpr23: 0x0000000000000001
	gpr24: 0x0000000000000001
	gpr25: 0xc0000000014b8f70
	gpr26: 0x0000000000000000
	gpr27: 0x0000000000000001
	gpr28: 0x0000000000000001
	gpr29: 0x0000000000000000
	gpr30: 0xc0000000014b8f00
	gpr31: 0xc0000000014b8f00
sp: 0xc00000005051f530 lr: 0x0000000000000000
sp: 0xc00000005051f600 lr: 0xc000000000103ffc
sp: 0xc00000005051f670 lr: 0xc0000000000f60a8
sp: 0xc00000005051f850 lr: 0xc0000000000f18c0
sp: 0xc00000005051fa10 lr: 0xc0000000000f5184
sp: 0xc00000005051fae0 lr: 0xc0000000000ddf54
sp: 0xc00000005051fb00 lr: 0xc0000000000dab9c
sp: 0xc00000005051fb90 lr: 0xc0000000000cbf88
sp: 0xc00000005051fd00 lr: 0xc0000000003e7480
sp: 0xc00000005051fdb0 lr: 0xc0000000003e7ce4
sp: 0xc00000005051fe00 lr: 0xc0000000003e7d88
sp: 0xc00000005051fe20 lr: 0xc00000000000b3a4
	trap : 0x0000000000000c01
	pc   : 0x00007fffa6c9d8d0
	msr  : 0x900000000280f033
	lr   : 0x0000000010090f40
	gpr 0: 0x0000000000000036
	gpr 1: 0x00007fffa62fdd70
	gpr 2: 0x00007fffa6d57300
	gpr 3: 0x000000000000000d
	gpr 4: 0x000000002000ae80
	gpr 5: 0x0000000000000000
	gpr 6: 0x0000000000000537
	gpr 7: 0x0000000000000000
	gpr 8: 0x000000000000000d
	gpr 9: 0x0000000000000000
	gpr10: 0x0000000000000000
	gpr11: 0x0000000000000000
	gpr12: 0x0000000000000000
	gpr13: 0x00007fffa6306380
	gpr14: 0x0000000000000000
	gpr15: 0x0000000000000001
	gpr16: 0x0000000039ba6928
	gpr17: 0x0000000000000000
	gpr18: 0x0000000000000000
	gpr19: 0x00007fffa6d702f0
	gpr20: 0x00007fffa62fddf0
	gpr21: 0x0000000000000080
	gpr22: 0x0000000000000004
	gpr23: 0x0000000000000000
	gpr24: 0x0000000010ac85c0
	gpr25: 0x0000000000000008
	gpr26: 0x00007fffa62fde10
	gpr27: 0x0000000000000000
	gpr28: 0x0000000000000002
	gpr29: 0x0000000000000000
	gpr30: 0x0000000039ba6900
	gpr31: 0x0000000010ac85c0
sp: 0x00007fffa62fdd70

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
---
 target/ppc/cpu.h                |  1 +
 target/ppc/translate.c          | 60 +++++++++++++++++++++++++++++++++++++++++
 target/ppc/translate_init.inc.c |  1 +
 3 files changed, 62 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 5e7cf54b2f..28c4dffca1 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1284,6 +1284,7 @@ struct PPCVirtualHypervisorClass {
 void ppc_cpu_do_interrupt(CPUState *cpu);
 bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
 void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
+void ppc_cpu_dump_stack(CPUState *cpu, FILE *f);
 void ppc_cpu_dump_statistics(CPUState *cpu, int flags);
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 8d08625c33..b162998ce7 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7705,6 +7705,66 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 #undef RFPL
 }
 
+struct ppc_pt_regs {
+        unsigned long gpr[32];
+        unsigned long nip;
+        unsigned long msr;
+        unsigned long orig_gpr3;
+        unsigned long ctr;
+        unsigned long link;
+        unsigned long xer;
+        unsigned long ccr;
+        unsigned long softe;
+        unsigned long trap;
+        unsigned long dar;
+        unsigned long dsisr;
+        unsigned long result;
+};
+
+void ppc_cpu_dump_stack(CPUState *cs, FILE *f)
+{
+#if defined(TARGET_PPC64)
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    uint64_t sp, next_sp, lr, buf[4];
+
+    /* stack pointer stored in r1 */
+    sp = env->gpr[1];
+
+    while (sp && (sp & (0xCUL << 60))) {
+        uint64_t marker = 0UL;
+
+        /* read and print LR */
+        cpu_physical_memory_read(sp & ~(0xCUL << 60), buf, sizeof(*buf) * 4);
+        next_sp = buf[0];
+        lr = buf[2];
+        qemu_fprintf(f, "sp: 0x%.16lx lr: 0x%.16lx\n", sp, lr);
+        sp &= ~(0xCUL << 60);
+
+        /* Does the stackframe contain regs? */
+        cpu_physical_memory_read(sp + 96, &marker, sizeof(marker));
+        if (marker == 0x7265677368657265) { /* regshere */
+            struct ppc_pt_regs regs;
+            int i;
+
+            cpu_physical_memory_read(sp + 112, &regs, sizeof(regs));
+
+            qemu_fprintf(f, "\ttrap : 0x%.16lx\n", regs.trap);
+            qemu_fprintf(f, "\tpc   : 0x%.16lx\n", regs.nip);
+            qemu_fprintf(f, "\tmsr  : 0x%.16lx\n", regs.msr);
+            qemu_fprintf(f, "\tlr   : 0x%.16lx\n", regs.link);
+            for (i = 0; i < 32; i++)
+                qemu_fprintf(f, "\tgpr%2d: 0x%.16lx\n", i,
+                            regs.gpr[i]);
+        }
+
+        sp = next_sp;
+    }
+
+    qemu_fprintf(f, "sp: 0x%.16lx\n", sp);
+#endif
+}
+
 void ppc_cpu_dump_statistics(CPUState *cs, int flags)
 {
 #if defined(DO_PPC_STATISTICS)
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 0394a9ddad..3fd24f85cc 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -10587,6 +10587,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = ppc_cpu_do_interrupt;
     cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;
     cc->dump_state = ppc_cpu_dump_state;
+    cc->dump_stack = ppc_cpu_dump_stack;
     cc->dump_statistics = ppc_cpu_dump_statistics;
     cc->set_pc = ppc_cpu_set_pc;
     cc->gdb_read_register = ppc_cpu_gdb_read_register;
-- 
2.13.6

WARNING: multiple messages have this Message-ID (diff)
From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
To: qemu-devel@nongnu.org
Cc: david@gibson.dropbear.id.au, qemu-ppc@nongnu.org,
	dgilbert@redhat.com,
	Suraj Jitindar Singh <sjitindarsingh@gmail.com>,
	armbru@redhat.com
Subject: [Qemu-devel] [PATCH 2/2] ppc: Add dump-stack implementation
Date: Wed,  1 May 2019 15:35:22 +1000	[thread overview]
Message-ID: <20190501053522.10967-2-sjitindarsingh@gmail.com> (raw)
Message-ID: <20190501053522.xnZNOporOEesprEXMjISemnHI-wdIL1cbMODxlThu38@z> (raw)
In-Reply-To: <20190501053522.10967-1-sjitindarsingh@gmail.com>

The monitor function dump-stack is used to dump the stack for a cpu.
This can be useful for debugging purposes when the stack cannot be
dumped by another means.

Add a ppc implementation ppc_cpu_dump_stack().
The stack pointer is stored in R1 with the back pointer at offset 0 and
the link register at offset 2.
Also dump the registers from the stack frame if the marker "regshere" is
found.
This only dumps the kernel stack, stopping if a non-kernel address is
found in the stack.

Sample output:
(qemu) dump-stack
sp: 0xc00000007bfc5690 lr: 0xc0000000000974b8
sp: 0xc00000007bfc56f0 lr: 0xc00000000065aab4
sp: 0xc00000007bfc5720 lr: 0xc00000000065ab04
sp: 0xc00000007bfc5740 lr: 0xc0000000000c29b8
sp: 0xc00000007bfc57b0 lr: 0xc0000000000bc9e8
sp: 0xc00000007bfc57e0 lr: 0xc0000000000bd584
sp: 0xc00000007bfc5800 lr: 0xc0000000000bee14
sp: 0xc00000007bfc5ac0 lr: 0xc0000000000c2100
sp: 0xc00000007bfc5c60 lr: 0xc000000000029460
sp: 0xc00000007bfc5ca0 lr: 0xc00000000010b5e8
sp: 0xc00000007bfc5d00 lr: 0xc000000000105f34
	trap : 0x0000000000000700
	pc   : 0xc000000000104490
	msr  : 0x9000000002843003
	lr   : 0xc000000000103ffc
	gpr 0: 0x0000000000000001
	gpr 1: 0xc00000005051f530
	gpr 2: 0xc000000001088200
	gpr 3: 0x0000000000000001
	gpr 4: 0xc000000032d60000
	gpr 5: 0xc0000000014b8f00
	gpr 6: 0x0000000000c835e0
	gpr 7: 0x0000000000000000
	gpr 8: 0x0000000000000000
	gpr 9: 0xc000000032f00000
	gpr10: 0x9000000002803033
	gpr11: 0xc000000000b60f00
	gpr12: 0x0000000000002000
	gpr13: 0xc000000001250000
	gpr14: 0x0000000000000000
	gpr15: 0x0000000000000008
	gpr16: 0x0000000000000000
	gpr17: 0xc00000000114f790
	gpr18: 0x00000000ffffffff
	gpr19: 0xc00000005051f8e8
	gpr20: 0x0000000000000001
	gpr21: 0x0000000000000000
	gpr22: 0x0000000000000001
	gpr23: 0x0000000000000001
	gpr24: 0x0000000000000001
	gpr25: 0xc0000000014b8f70
	gpr26: 0x0000000000000000
	gpr27: 0x0000000000000001
	gpr28: 0x0000000000000001
	gpr29: 0x0000000000000000
	gpr30: 0xc0000000014b8f00
	gpr31: 0xc0000000014b8f00
sp: 0xc00000005051f530 lr: 0x0000000000000000
sp: 0xc00000005051f600 lr: 0xc000000000103ffc
sp: 0xc00000005051f670 lr: 0xc0000000000f60a8
sp: 0xc00000005051f850 lr: 0xc0000000000f18c0
sp: 0xc00000005051fa10 lr: 0xc0000000000f5184
sp: 0xc00000005051fae0 lr: 0xc0000000000ddf54
sp: 0xc00000005051fb00 lr: 0xc0000000000dab9c
sp: 0xc00000005051fb90 lr: 0xc0000000000cbf88
sp: 0xc00000005051fd00 lr: 0xc0000000003e7480
sp: 0xc00000005051fdb0 lr: 0xc0000000003e7ce4
sp: 0xc00000005051fe00 lr: 0xc0000000003e7d88
sp: 0xc00000005051fe20 lr: 0xc00000000000b3a4
	trap : 0x0000000000000c01
	pc   : 0x00007fffa6c9d8d0
	msr  : 0x900000000280f033
	lr   : 0x0000000010090f40
	gpr 0: 0x0000000000000036
	gpr 1: 0x00007fffa62fdd70
	gpr 2: 0x00007fffa6d57300
	gpr 3: 0x000000000000000d
	gpr 4: 0x000000002000ae80
	gpr 5: 0x0000000000000000
	gpr 6: 0x0000000000000537
	gpr 7: 0x0000000000000000
	gpr 8: 0x000000000000000d
	gpr 9: 0x0000000000000000
	gpr10: 0x0000000000000000
	gpr11: 0x0000000000000000
	gpr12: 0x0000000000000000
	gpr13: 0x00007fffa6306380
	gpr14: 0x0000000000000000
	gpr15: 0x0000000000000001
	gpr16: 0x0000000039ba6928
	gpr17: 0x0000000000000000
	gpr18: 0x0000000000000000
	gpr19: 0x00007fffa6d702f0
	gpr20: 0x00007fffa62fddf0
	gpr21: 0x0000000000000080
	gpr22: 0x0000000000000004
	gpr23: 0x0000000000000000
	gpr24: 0x0000000010ac85c0
	gpr25: 0x0000000000000008
	gpr26: 0x00007fffa62fde10
	gpr27: 0x0000000000000000
	gpr28: 0x0000000000000002
	gpr29: 0x0000000000000000
	gpr30: 0x0000000039ba6900
	gpr31: 0x0000000010ac85c0
sp: 0x00007fffa62fdd70

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
---
 target/ppc/cpu.h                |  1 +
 target/ppc/translate.c          | 60 +++++++++++++++++++++++++++++++++++++++++
 target/ppc/translate_init.inc.c |  1 +
 3 files changed, 62 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 5e7cf54b2f..28c4dffca1 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1284,6 +1284,7 @@ struct PPCVirtualHypervisorClass {
 void ppc_cpu_do_interrupt(CPUState *cpu);
 bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req);
 void ppc_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
+void ppc_cpu_dump_stack(CPUState *cpu, FILE *f);
 void ppc_cpu_dump_statistics(CPUState *cpu, int flags);
 hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 8d08625c33..b162998ce7 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7705,6 +7705,66 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 #undef RFPL
 }
 
+struct ppc_pt_regs {
+        unsigned long gpr[32];
+        unsigned long nip;
+        unsigned long msr;
+        unsigned long orig_gpr3;
+        unsigned long ctr;
+        unsigned long link;
+        unsigned long xer;
+        unsigned long ccr;
+        unsigned long softe;
+        unsigned long trap;
+        unsigned long dar;
+        unsigned long dsisr;
+        unsigned long result;
+};
+
+void ppc_cpu_dump_stack(CPUState *cs, FILE *f)
+{
+#if defined(TARGET_PPC64)
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    uint64_t sp, next_sp, lr, buf[4];
+
+    /* stack pointer stored in r1 */
+    sp = env->gpr[1];
+
+    while (sp && (sp & (0xCUL << 60))) {
+        uint64_t marker = 0UL;
+
+        /* read and print LR */
+        cpu_physical_memory_read(sp & ~(0xCUL << 60), buf, sizeof(*buf) * 4);
+        next_sp = buf[0];
+        lr = buf[2];
+        qemu_fprintf(f, "sp: 0x%.16lx lr: 0x%.16lx\n", sp, lr);
+        sp &= ~(0xCUL << 60);
+
+        /* Does the stackframe contain regs? */
+        cpu_physical_memory_read(sp + 96, &marker, sizeof(marker));
+        if (marker == 0x7265677368657265) { /* regshere */
+            struct ppc_pt_regs regs;
+            int i;
+
+            cpu_physical_memory_read(sp + 112, &regs, sizeof(regs));
+
+            qemu_fprintf(f, "\ttrap : 0x%.16lx\n", regs.trap);
+            qemu_fprintf(f, "\tpc   : 0x%.16lx\n", regs.nip);
+            qemu_fprintf(f, "\tmsr  : 0x%.16lx\n", regs.msr);
+            qemu_fprintf(f, "\tlr   : 0x%.16lx\n", regs.link);
+            for (i = 0; i < 32; i++)
+                qemu_fprintf(f, "\tgpr%2d: 0x%.16lx\n", i,
+                            regs.gpr[i]);
+        }
+
+        sp = next_sp;
+    }
+
+    qemu_fprintf(f, "sp: 0x%.16lx\n", sp);
+#endif
+}
+
 void ppc_cpu_dump_statistics(CPUState *cs, int flags)
 {
 #if defined(DO_PPC_STATISTICS)
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 0394a9ddad..3fd24f85cc 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -10587,6 +10587,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
     cc->do_interrupt = ppc_cpu_do_interrupt;
     cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;
     cc->dump_state = ppc_cpu_dump_state;
+    cc->dump_stack = ppc_cpu_dump_stack;
     cc->dump_statistics = ppc_cpu_dump_statistics;
     cc->set_pc = ppc_cpu_set_pc;
     cc->gdb_read_register = ppc_cpu_gdb_read_register;
-- 
2.13.6



  reply	other threads:[~2019-05-01  5:35 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-01  5:35 [Qemu-devel] [PATCH 1/2] monitor: Add dump-stack command Suraj Jitindar Singh
2019-05-01  5:35 ` Suraj Jitindar Singh
2019-05-01  5:35 ` Suraj Jitindar Singh [this message]
2019-05-01  5:35   ` [Qemu-devel] [PATCH 2/2] ppc: Add dump-stack implementation Suraj Jitindar Singh
2019-05-01  9:48   ` Alexey Kardashevskiy
2019-05-01  9:48     ` Alexey Kardashevskiy
2019-05-02  0:43     ` David Gibson
2019-05-02  0:43       ` David Gibson
2019-05-02  3:47       ` Alexey Kardashevskiy
2019-05-02  3:47         ` Alexey Kardashevskiy
2019-05-06  3:39         ` David Gibson
2019-05-02 13:59   ` [Qemu-devel] [Qemu-ppc] " Greg Kurz
2019-05-02 13:59     ` Greg Kurz
2019-05-07 11:24   ` [Qemu-devel] " Markus Armbruster
2019-05-01 10:44 ` [Qemu-devel] [PATCH 1/2] monitor: Add dump-stack command Dr. David Alan Gilbert
2019-05-01 10:44   ` Dr. David Alan Gilbert
2019-05-02  0:44 ` David Gibson
2019-05-02  0:44   ` David Gibson
2019-05-02  2:15   ` [Qemu-devel] [Qemu-ppc] " Alexey Kardashevskiy
2019-05-02  2:15     ` Alexey Kardashevskiy
2019-05-07 11:21     ` Markus Armbruster
2019-05-07 11:09 ` [Qemu-devel] " Markus Armbruster
2019-05-08 10:26   ` Dr. David Alan Gilbert
2019-05-08 13:10     ` Markus Armbruster
2019-05-08 13:15       ` Dr. David Alan Gilbert
2019-06-21  0:51 ` Suraj Jitindar Singh
2019-06-24  8:57   ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190501053522.10967-2-sjitindarsingh@gmail.com \
    --to=sjitindarsingh@gmail.com \
    --cc=armbru@redhat.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=dgilbert@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.