* [U-Boot] [PATCH v2 0/5] x86: Move x86 to use board_init_f_mem() instead of assembler
@ 2015-08-11 2:44 Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 1/5] x86: Remove init_gd() function Simon Glass
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: Simon Glass @ 2015-08-11 2:44 UTC (permalink / raw
To: u-boot
Much of the early-init assembler on x86 can be removed if we use the new
board_init_f_mem() function. At present only PowerPC uses it, but we should
try to move more archs over.
This has been contemplated for a while but it is time to take the plunge.
Changes in v2:
- Correct logic to round down instead of up
- Drop unused 'reserve_size' argument
- Rename arch_setup_gdt() to arch_setup_gd()
- Expand the comment about the 64-byte stack space
- Fix a comma which should be a period
- Add a comment as to why we can't compile the weak arch_setup_gd() on x86
- Don't rely on value of %edx from board_init_f_mem()
Simon Glass (5):
x86: Remove init_gd() function
Align global_data to a 16-byte boundary
Allow arch-specific setting of global_data in board_init_f_mem()
x86: Move the GDT into global_data
x86: Switch to using generic global_data setup
arch/x86/cpu/cpu.c | 11 +++--
arch/x86/cpu/start.S | 95 ++++++--------------------------------
arch/x86/include/asm/global_data.h | 4 +-
arch/x86/include/asm/u-boot-x86.h | 1 -
common/board_f.c | 17 +++++--
include/asm-generic/global_data.h | 2 +-
include/common.h | 43 +++++++++++++++++
7 files changed, 81 insertions(+), 92 deletions(-)
--
2.5.0.rc2.392.g76e840b
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 1/5] x86: Remove init_gd() function
2015-08-11 2:44 [U-Boot] [PATCH v2 0/5] x86: Move x86 to use board_init_f_mem() instead of assembler Simon Glass
@ 2015-08-11 2:44 ` Simon Glass
2015-08-12 3:55 ` Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 2/5] Align global_data to a 16-byte boundary Simon Glass
` (3 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Simon Glass @ 2015-08-11 2:44 UTC (permalink / raw
To: u-boot
This is declared but no-longer exists. Drop it.
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
Changes in v2: None
arch/x86/include/asm/u-boot-x86.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 4dae365..1c459d5 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -14,7 +14,6 @@ extern char gdt_rom[];
int arch_cpu_init(void);
int x86_cpu_init_f(void);
int cpu_init_f(void);
-void init_gd(gd_t *id, u64 *gdt_addr);
void setup_gdt(gd_t *id, u64 *gdt_addr);
/*
* Setup FSP execution environment GDT to use the one we used in
--
2.5.0.rc2.392.g76e840b
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 2/5] Align global_data to a 16-byte boundary
2015-08-11 2:44 [U-Boot] [PATCH v2 0/5] x86: Move x86 to use board_init_f_mem() instead of assembler Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 1/5] x86: Remove init_gd() function Simon Glass
@ 2015-08-11 2:44 ` Simon Glass
2015-08-11 6:28 ` Bin Meng
2015-08-11 2:44 ` [U-Boot] [PATCH v2 3/5] Allow arch-specific setting of global_data in board_init_f_mem() Simon Glass
` (2 subsequent siblings)
4 siblings, 1 reply; 14+ messages in thread
From: Simon Glass @ 2015-08-11 2:44 UTC (permalink / raw
To: u-boot
Some archs like to have larger alignment for their global data. Use 16 bytes
which suits all current archs.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Correct logic to round down instead of up
common/board_f.c | 1 +
include/asm-generic/global_data.h | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/common/board_f.c b/common/board_f.c
index 8cca4de..74f77f1 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -499,6 +499,7 @@ static int setup_machine(void)
static int reserve_global_data(void)
{
gd->start_addr_sp -= sizeof(gd_t);
+ gd->start_addr_sp &= ~0xf;
gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
debug("Reserving %zu Bytes for Global Data at: %08lx\n",
sizeof(gd_t), gd->start_addr_sp);
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 2155265..147f646 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -99,7 +99,7 @@ typedef struct global_data {
int pcidelay_done;
#endif
struct udevice *cur_serial_dev; /* current serial device */
- struct arch_global_data arch; /* architecture-specific data */
+ struct arch_global_data arch __aligned(16); /* arch-specific data */
} gd_t;
#endif
--
2.5.0.rc2.392.g76e840b
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 3/5] Allow arch-specific setting of global_data in board_init_f_mem()
2015-08-11 2:44 [U-Boot] [PATCH v2 0/5] x86: Move x86 to use board_init_f_mem() instead of assembler Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 1/5] x86: Remove init_gd() function Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 2/5] Align global_data to a 16-byte boundary Simon Glass
@ 2015-08-11 2:44 ` Simon Glass
2015-08-11 6:28 ` Bin Meng
2015-08-11 2:44 ` [U-Boot] [PATCH v2 4/5] x86: Move the GDT into global_data Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 5/5] x86: Switch to using generic global_data setup Simon Glass
4 siblings, 1 reply; 14+ messages in thread
From: Simon Glass @ 2015-08-11 2:44 UTC (permalink / raw
To: u-boot
At present we have a simple assignment to gd. With some archs this is
implemented as a register or through some other means; a simple assignment
does not suit in all cases.
Change this to a function and add documentation to describe how this all
works.
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: York Sun <yorksun@freescale.com>
---
Changes in v2:
- Drop unused 'reserve_size' argument
- Rename arch_setup_gdt() to arch_setup_gd()
- Expand the comment about the 64-byte stack space
- Fix a comma which should be a period
- Add a comment as to why we can't compile the weak arch_setup_gd() on x86
common/board_f.c | 13 +++++++++++--
include/common.h | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/common/board_f.c b/common/board_f.c
index 74f77f1..37b7bf5 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -1027,16 +1027,25 @@ void board_init_f_r(void)
}
#endif /* CONFIG_X86 */
+/* Unfortunately x86 can't compile this code as gd cannot be assigned */
#ifndef CONFIG_X86
+__weak void arch_setup_gd(struct global_data *gd_ptr)
+{
+ gd = gd_ptr;
+}
+
ulong board_init_f_mem(ulong top)
{
+ struct global_data *gd_ptr;
+
/* Leave space for the stack we are running with now */
top -= 0x40;
top -= sizeof(struct global_data);
top = ALIGN(top, 16);
- gd = (struct global_data *)top;
- memset((void *)gd, '\0', sizeof(*gd));
+ gd_ptr = (struct global_data *)top;
+ memset(gd_ptr, '\0', sizeof(*gd));
+ arch_setup_gd(gd_ptr);
#ifdef CONFIG_SYS_MALLOC_F_LEN
top -= CONFIG_SYS_MALLOC_F_LEN;
diff --git a/include/common.h b/include/common.h
index fcc9ae7..48e5006 100644
--- a/include/common.h
+++ b/include/common.h
@@ -217,6 +217,49 @@ extern char console_buffer[];
/* arch/$(ARCH)/lib/board.c */
void board_init_f(ulong);
void board_init_r(gd_t *, ulong) __attribute__ ((noreturn));
+
+/**
+ * board_init_f_mem() - Allocate global data and set stack position
+ *
+ * This function is called by each architecture very early in the start-up
+ * code to set up the environment for board_init_f(). It allocates space for
+ * global_data (see include/asm-generic/global_data.h) and places the stack
+ * below this.
+ *
+ * This function requires a stack[1] Normally this is at @top. The function
+ * starts allocating space from 64 bytes below @top. First it creates space
+ * for global_data. Then it calls arch_setup_gd() which sets gd to point to
+ * the global_data space and can reserve additional bytes of space if
+ * required). Finally it allocates early malloc() memory
+ * (CONFIG_SYS_MALLOC_F_LEN). The new top of the stack is just below this,
+ * and it returned by this function.
+ *
+ * [1] Strictly speaking it would be possible to implement this function
+ * in C on many archs such that it does not require a stack. However this
+ * does not seem hugely important as only 64 byte are wasted. The 64 bytes
+ * are used to handle the calling standard which generally requires pushing
+ * addresses or registers onto the stack. We should be able to get away with
+ * less if this becomes important.
+ *
+ * @top: Top of available memory, also normally the top of the stack
+ * @return: New stack location
+ */
+ulong board_init_f_mem(ulong top);
+
+/**
+ * arch_setup_gd() - Set up the global_data pointer
+ *
+ * This pointer is special in some architectures and cannot easily be assigned
+ * to. For example on x86 it is implemented by adding a specific record to its
+ * Global Descriptor Table! So we we provide a function to carry out this task.
+ * For most architectures this can simply be:
+ *
+ * gd = gd_ptr;
+ *
+ * @gd_ptr: Pointer to global data
+ */
+void arch_setup_gd(gd_t *gd_ptr);
+
int checkboard(void);
int show_board_info(void);
int checkflash(void);
--
2.5.0.rc2.392.g76e840b
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 4/5] x86: Move the GDT into global_data
2015-08-11 2:44 [U-Boot] [PATCH v2 0/5] x86: Move x86 to use board_init_f_mem() instead of assembler Simon Glass
` (2 preceding siblings ...)
2015-08-11 2:44 ` [U-Boot] [PATCH v2 3/5] Allow arch-specific setting of global_data in board_init_f_mem() Simon Glass
@ 2015-08-11 2:44 ` Simon Glass
2015-08-12 3:55 ` Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 5/5] x86: Switch to using generic global_data setup Simon Glass
4 siblings, 1 reply; 14+ messages in thread
From: Simon Glass @ 2015-08-11 2:44 UTC (permalink / raw
To: u-boot
Rather than keeping track of the Global Descriptor Table in its own memory
we may as well put it in global_data with everything else. As a first step,
stop using the separately allocated GDT.
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
Changes in v2: None
arch/x86/cpu/cpu.c | 9 +++++----
arch/x86/include/asm/global_data.h | 4 +++-
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 129777c..4f57145 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -136,9 +136,10 @@ static void load_gdt(const u64 *boot_gdt, u16 num_entries)
asm volatile("lgdtl %0\n" : : "m" (gdt));
}
-void setup_gdt(gd_t *id, u64 *gdt_addr)
+void setup_gdt(gd_t *new_gd, u64 *gdt_addr)
{
- id->arch.gdt = gdt_addr;
+ gdt_addr = new_gd->arch.gdt;
+
/* CS: code, read/execute, 4 GB, base 0 */
gdt_addr[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff);
@@ -146,9 +147,9 @@ void setup_gdt(gd_t *id, u64 *gdt_addr)
gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff);
/* FS: data, read/write, 4 GB, base (Global Data Pointer) */
- id->arch.gd_addr = id;
+ new_gd->arch.gd_addr = new_gd;
gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0xc093,
- (ulong)&id->arch.gd_addr, 0xfffff);
+ (ulong)&new_gd->arch.gd_addr, 0xfffff);
/* 16-bit CS: code, read/execute, 64 kB, base 0 */
gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff);
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index f7e3889..35148ab 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -10,6 +10,8 @@
#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+
enum pei_boot_mode_t {
PEI_BOOT_NONE = 0,
PEI_BOOT_SOFT_RESET,
@@ -44,6 +46,7 @@ struct mtrr_request {
/* Architecture-specific global data */
struct arch_global_data {
+ u64 gdt[X86_GDT_NUM_ENTRIES] __aligned(16);
struct global_data *gd_addr; /* Location of Global Data */
uint8_t x86; /* CPU family */
uint8_t x86_vendor; /* CPU vendor */
@@ -68,7 +71,6 @@ struct arch_global_data {
/* MRC training data to save for the next boot */
char *mrc_output;
unsigned int mrc_output_len;
- void *gdt; /* Global descriptor table */
ulong table; /* Table pointer from previous loader */
};
--
2.5.0.rc2.392.g76e840b
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 5/5] x86: Switch to using generic global_data setup
2015-08-11 2:44 [U-Boot] [PATCH v2 0/5] x86: Move x86 to use board_init_f_mem() instead of assembler Simon Glass
` (3 preceding siblings ...)
2015-08-11 2:44 ` [U-Boot] [PATCH v2 4/5] x86: Move the GDT into global_data Simon Glass
@ 2015-08-11 2:44 ` Simon Glass
2015-08-11 6:28 ` Bin Meng
4 siblings, 1 reply; 14+ messages in thread
From: Simon Glass @ 2015-08-11 2:44 UTC (permalink / raw
To: u-boot
There is quite a bit of assembler code that can be removed if we use the
generic global_data setup. Less arch-specific code makes it easier to add
new features and maintain the start-up code.
Drop the unneeded code and adjust the hooks in board_f.c to cope.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Don't rely on value of %edx from board_init_f_mem()
arch/x86/cpu/cpu.c | 4 ++-
arch/x86/cpu/start.S | 95 +++++++---------------------------------------------
common/board_f.c | 3 +-
3 files changed, 18 insertions(+), 84 deletions(-)
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 4f57145..1b76ca1 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -136,8 +136,10 @@ static void load_gdt(const u64 *boot_gdt, u16 num_entries)
asm volatile("lgdtl %0\n" : : "m" (gdt));
}
-void setup_gdt(gd_t *new_gd, u64 *gdt_addr)
+void arch_setup_gd(gd_t *new_gd)
{
+ u64 *gdt_addr;
+
gdt_addr = new_gd->arch.gdt;
/* CS: code, read/execute, 4 GB, base 0 */
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 313fa3f..e94ddc4 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -104,8 +104,7 @@ car_init_ret:
*
* top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE
* MRC area
- * global_data
- * x86 global descriptor table
+ * global_data with x86 global descriptor table
* early malloc area
* stack
* bottom-> CONFIG_SYS_CAR_ADDR
@@ -120,13 +119,10 @@ car_init_ret:
* and esi holds the HOB list address returned by the FSP.
*/
#endif
-
- /* Reserve space on stack for global data */
- subl $GENERATED_GBL_DATA_SIZE, %esp
-
- /* Align global data to 16-byte boundary */
- andl $0xfffffff0, %esp
- post_code(POST_START_STACK)
+ /* Set up global data */
+ mov %esp, %eax
+ call board_init_f_mem
+ mov %eax, %esp
/*
* Debug UART is available here although it may not be plumbed out
@@ -137,56 +133,21 @@ car_init_ret:
* call printch
*/
- /* Zero the global data since it won't happen later */
- xorl %eax, %eax
- movl $GENERATED_GBL_DATA_SIZE, %ecx
- movl %esp, %edi
- rep stosb
-
+ /* Get address of global_data */
+ mov %fs:0, %edx
#ifdef CONFIG_HAVE_FSP
+ /* Store the HOB list if we have one */
test %esi, %esi
jz skip_hob
-
- /* Store HOB list */
- movl %esp, %edx
- addl $GD_HOB_LIST, %edx
- movl %esi, (%edx)
+ movl %esi, GD_HOB_LIST(%edx)
skip_hob:
#else
/* Store table pointer */
- movl %esp, %edx
- addl $GD_TABLE, %edx
- movl %esi, (%edx)
+ movl %esi, GD_TABLE(%edx)
#endif
-
- /* Setup first parameter to setup_gdt, pointer to global_data */
- movl %esp, %eax
-
- /* Reserve space for global descriptor table */
- subl $X86_GDT_SIZE, %esp
-
- /* Align temporary global descriptor table to 16-byte boundary */
- andl $0xfffffff0, %esp
- movl %esp, %ecx
-
-#if defined(CONFIG_SYS_MALLOC_F_LEN)
- /* Set up the pre-relocation malloc pool */
- subl $CONFIG_SYS_MALLOC_F_LEN, %esp
- movl %eax, %edx
- addl $GD_MALLOC_BASE, %edx
- movl %esp, (%edx)
-#endif
- /* Store BIST into global_data */
- movl %eax, %edx
- addl $GD_BIST, %edx
- movl %ebp, (%edx)
-
- /* Set second parameter to setup_gdt() */
- movl %ecx, %edx
-
- /* Setup global descriptor table so gd->xyz works */
- call setup_gdt
+ /* Store BIST */
+ movl %ebp, GD_BIST(%edx)
/* Set parameter to board_init_f() to boot flags */
post_code(POST_START_DONE)
@@ -213,37 +174,7 @@ board_init_f_r_trampoline:
/* Stack grows down from top of SDRAM */
movl %eax, %esp
- /* Reserve space on stack for global data */
- subl $GENERATED_GBL_DATA_SIZE, %esp
-
- /* Align global data to 16-byte boundary */
- andl $0xfffffff0, %esp
-
- /* Setup first parameter to memcpy() and setup_gdt() */
- movl %esp, %eax
-
- /* Setup second parameter to memcpy() */
- fs movl 0, %edx
-
- /* Set third parameter to memcpy() */
- movl $GENERATED_GBL_DATA_SIZE, %ecx
-
- /* Copy global data from CAR to SDRAM stack */
- call memcpy
-
- /* Reserve space for global descriptor table */
- subl $X86_GDT_SIZE, %esp
-
- /* Align global descriptor table to 16-byte boundary */
- andl $0xfffffff0, %esp
-
- /* Set second parameter to setup_gdt() */
- movl %esp, %edx
-
- /* Setup global descriptor table so gd->xyz works */
- call setup_gdt
-
- /* Set if we need to disable CAR */
+ /* See if we need to disable CAR */
.weak car_uninit
movl $car_uninit, %eax
cmpl $0, %eax
diff --git a/common/board_f.c b/common/board_f.c
index 37b7bf5..c959774 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -715,6 +715,7 @@ static int jump_to_copy(void)
* with the stack in SDRAM and Global Data in temporary memory
* (CPU cache)
*/
+ arch_setup_gd(gd->new_gd);
board_init_f_r_trampoline(gd->start_addr_sp);
#else
relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
@@ -1033,6 +1034,7 @@ __weak void arch_setup_gd(struct global_data *gd_ptr)
{
gd = gd_ptr;
}
+#endif /* !CONFIG_X86 */
ulong board_init_f_mem(ulong top)
{
@@ -1054,4 +1056,3 @@ ulong board_init_f_mem(ulong top)
return top;
}
-#endif /* !CONFIG_X86 */
--
2.5.0.rc2.392.g76e840b
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 2/5] Align global_data to a 16-byte boundary
2015-08-11 2:44 ` [U-Boot] [PATCH v2 2/5] Align global_data to a 16-byte boundary Simon Glass
@ 2015-08-11 6:28 ` Bin Meng
2015-08-12 3:55 ` Simon Glass
0 siblings, 1 reply; 14+ messages in thread
From: Bin Meng @ 2015-08-11 6:28 UTC (permalink / raw
To: u-boot
On Tue, Aug 11, 2015 at 10:44 AM, Simon Glass <sjg@chromium.org> wrote:
> Some archs like to have larger alignment for their global data. Use 16 bytes
> which suits all current archs.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v2:
> - Correct logic to round down instead of up
>
> common/board_f.c | 1 +
> include/asm-generic/global_data.h | 2 +-
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/common/board_f.c b/common/board_f.c
> index 8cca4de..74f77f1 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -499,6 +499,7 @@ static int setup_machine(void)
> static int reserve_global_data(void)
> {
> gd->start_addr_sp -= sizeof(gd_t);
> + gd->start_addr_sp &= ~0xf;
> gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
> debug("Reserving %zu Bytes for Global Data at: %08lx\n",
> sizeof(gd_t), gd->start_addr_sp);
> diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
> index 2155265..147f646 100644
> --- a/include/asm-generic/global_data.h
> +++ b/include/asm-generic/global_data.h
> @@ -99,7 +99,7 @@ typedef struct global_data {
> int pcidelay_done;
> #endif
> struct udevice *cur_serial_dev; /* current serial device */
> - struct arch_global_data arch; /* architecture-specific data */
> + struct arch_global_data arch __aligned(16); /* arch-specific data */
> } gd_t;
> #endif
>
> --
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 3/5] Allow arch-specific setting of global_data in board_init_f_mem()
2015-08-11 2:44 ` [U-Boot] [PATCH v2 3/5] Allow arch-specific setting of global_data in board_init_f_mem() Simon Glass
@ 2015-08-11 6:28 ` Bin Meng
2015-08-12 3:55 ` Simon Glass
0 siblings, 1 reply; 14+ messages in thread
From: Bin Meng @ 2015-08-11 6:28 UTC (permalink / raw
To: u-boot
On Tue, Aug 11, 2015 at 10:44 AM, Simon Glass <sjg@chromium.org> wrote:
> At present we have a simple assignment to gd. With some archs this is
> implemented as a register or through some other means; a simple assignment
> does not suit in all cases.
>
> Change this to a function and add documentation to describe how this all
> works.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: York Sun <yorksun@freescale.com>
> ---
>
> Changes in v2:
> - Drop unused 'reserve_size' argument
> - Rename arch_setup_gdt() to arch_setup_gd()
> - Expand the comment about the 64-byte stack space
> - Fix a comma which should be a period
> - Add a comment as to why we can't compile the weak arch_setup_gd() on x86
>
> common/board_f.c | 13 +++++++++++--
> include/common.h | 43 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 54 insertions(+), 2 deletions(-)
>
> diff --git a/common/board_f.c b/common/board_f.c
> index 74f77f1..37b7bf5 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -1027,16 +1027,25 @@ void board_init_f_r(void)
> }
> #endif /* CONFIG_X86 */
>
> +/* Unfortunately x86 can't compile this code as gd cannot be assigned */
> #ifndef CONFIG_X86
> +__weak void arch_setup_gd(struct global_data *gd_ptr)
> +{
> + gd = gd_ptr;
> +}
> +
> ulong board_init_f_mem(ulong top)
> {
> + struct global_data *gd_ptr;
> +
> /* Leave space for the stack we are running with now */
> top -= 0x40;
>
> top -= sizeof(struct global_data);
> top = ALIGN(top, 16);
> - gd = (struct global_data *)top;
> - memset((void *)gd, '\0', sizeof(*gd));
> + gd_ptr = (struct global_data *)top;
> + memset(gd_ptr, '\0', sizeof(*gd));
> + arch_setup_gd(gd_ptr);
>
> #ifdef CONFIG_SYS_MALLOC_F_LEN
> top -= CONFIG_SYS_MALLOC_F_LEN;
> diff --git a/include/common.h b/include/common.h
> index fcc9ae7..48e5006 100644
> --- a/include/common.h
> +++ b/include/common.h
> @@ -217,6 +217,49 @@ extern char console_buffer[];
> /* arch/$(ARCH)/lib/board.c */
> void board_init_f(ulong);
> void board_init_r(gd_t *, ulong) __attribute__ ((noreturn));
> +
> +/**
> + * board_init_f_mem() - Allocate global data and set stack position
> + *
> + * This function is called by each architecture very early in the start-up
> + * code to set up the environment for board_init_f(). It allocates space for
> + * global_data (see include/asm-generic/global_data.h) and places the stack
> + * below this.
> + *
> + * This function requires a stack[1] Normally this is at @top. The function
> + * starts allocating space from 64 bytes below @top. First it creates space
> + * for global_data. Then it calls arch_setup_gd() which sets gd to point to
> + * the global_data space and can reserve additional bytes of space if
> + * required). Finally it allocates early malloc() memory
> + * (CONFIG_SYS_MALLOC_F_LEN). The new top of the stack is just below this,
> + * and it returned by this function.
> + *
> + * [1] Strictly speaking it would be possible to implement this function
> + * in C on many archs such that it does not require a stack. However this
> + * does not seem hugely important as only 64 byte are wasted. The 64 bytes
> + * are used to handle the calling standard which generally requires pushing
> + * addresses or registers onto the stack. We should be able to get away with
> + * less if this becomes important.
> + *
> + * @top: Top of available memory, also normally the top of the stack
> + * @return: New stack location
> + */
> +ulong board_init_f_mem(ulong top);
> +
> +/**
> + * arch_setup_gd() - Set up the global_data pointer
> + *
> + * This pointer is special in some architectures and cannot easily be assigned
> + * to. For example on x86 it is implemented by adding a specific record to its
> + * Global Descriptor Table! So we we provide a function to carry out this task.
> + * For most architectures this can simply be:
> + *
> + * gd = gd_ptr;
> + *
> + * @gd_ptr: Pointer to global data
> + */
> +void arch_setup_gd(gd_t *gd_ptr);
> +
> int checkboard(void);
> int show_board_info(void);
> int checkflash(void);
> --
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 5/5] x86: Switch to using generic global_data setup
2015-08-11 2:44 ` [U-Boot] [PATCH v2 5/5] x86: Switch to using generic global_data setup Simon Glass
@ 2015-08-11 6:28 ` Bin Meng
2015-08-12 3:55 ` Simon Glass
0 siblings, 1 reply; 14+ messages in thread
From: Bin Meng @ 2015-08-11 6:28 UTC (permalink / raw
To: u-boot
On Tue, Aug 11, 2015 at 10:44 AM, Simon Glass <sjg@chromium.org> wrote:
> There is quite a bit of assembler code that can be removed if we use the
> generic global_data setup. Less arch-specific code makes it easier to add
> new features and maintain the start-up code.
>
> Drop the unneeded code and adjust the hooks in board_f.c to cope.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v2:
> - Don't rely on value of %edx from board_init_f_mem()
>
> arch/x86/cpu/cpu.c | 4 ++-
> arch/x86/cpu/start.S | 95 +++++++---------------------------------------------
> common/board_f.c | 3 +-
> 3 files changed, 18 insertions(+), 84 deletions(-)
>
> diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
> index 4f57145..1b76ca1 100644
> --- a/arch/x86/cpu/cpu.c
> +++ b/arch/x86/cpu/cpu.c
> @@ -136,8 +136,10 @@ static void load_gdt(const u64 *boot_gdt, u16 num_entries)
> asm volatile("lgdtl %0\n" : : "m" (gdt));
> }
>
> -void setup_gdt(gd_t *new_gd, u64 *gdt_addr)
> +void arch_setup_gd(gd_t *new_gd)
> {
> + u64 *gdt_addr;
> +
> gdt_addr = new_gd->arch.gdt;
>
> /* CS: code, read/execute, 4 GB, base 0 */
> diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
> index 313fa3f..e94ddc4 100644
> --- a/arch/x86/cpu/start.S
> +++ b/arch/x86/cpu/start.S
> @@ -104,8 +104,7 @@ car_init_ret:
> *
> * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE
> * MRC area
> - * global_data
> - * x86 global descriptor table
> + * global_data with x86 global descriptor table
> * early malloc area
> * stack
> * bottom-> CONFIG_SYS_CAR_ADDR
> @@ -120,13 +119,10 @@ car_init_ret:
> * and esi holds the HOB list address returned by the FSP.
> */
> #endif
> -
> - /* Reserve space on stack for global data */
> - subl $GENERATED_GBL_DATA_SIZE, %esp
> -
> - /* Align global data to 16-byte boundary */
> - andl $0xfffffff0, %esp
> - post_code(POST_START_STACK)
> + /* Set up global data */
> + mov %esp, %eax
> + call board_init_f_mem
> + mov %eax, %esp
>
> /*
> * Debug UART is available here although it may not be plumbed out
> @@ -137,56 +133,21 @@ car_init_ret:
> * call printch
> */
>
> - /* Zero the global data since it won't happen later */
> - xorl %eax, %eax
> - movl $GENERATED_GBL_DATA_SIZE, %ecx
> - movl %esp, %edi
> - rep stosb
> -
> + /* Get address of global_data */
> + mov %fs:0, %edx
> #ifdef CONFIG_HAVE_FSP
> + /* Store the HOB list if we have one */
> test %esi, %esi
> jz skip_hob
> -
> - /* Store HOB list */
> - movl %esp, %edx
> - addl $GD_HOB_LIST, %edx
> - movl %esi, (%edx)
> + movl %esi, GD_HOB_LIST(%edx)
>
> skip_hob:
> #else
> /* Store table pointer */
> - movl %esp, %edx
> - addl $GD_TABLE, %edx
> - movl %esi, (%edx)
> + movl %esi, GD_TABLE(%edx)
> #endif
> -
> - /* Setup first parameter to setup_gdt, pointer to global_data */
> - movl %esp, %eax
> -
> - /* Reserve space for global descriptor table */
> - subl $X86_GDT_SIZE, %esp
> -
> - /* Align temporary global descriptor table to 16-byte boundary */
> - andl $0xfffffff0, %esp
> - movl %esp, %ecx
> -
> -#if defined(CONFIG_SYS_MALLOC_F_LEN)
> - /* Set up the pre-relocation malloc pool */
> - subl $CONFIG_SYS_MALLOC_F_LEN, %esp
> - movl %eax, %edx
> - addl $GD_MALLOC_BASE, %edx
> - movl %esp, (%edx)
> -#endif
> - /* Store BIST into global_data */
> - movl %eax, %edx
> - addl $GD_BIST, %edx
> - movl %ebp, (%edx)
> -
> - /* Set second parameter to setup_gdt() */
> - movl %ecx, %edx
> -
> - /* Setup global descriptor table so gd->xyz works */
> - call setup_gdt
> + /* Store BIST */
> + movl %ebp, GD_BIST(%edx)
>
> /* Set parameter to board_init_f() to boot flags */
> post_code(POST_START_DONE)
> @@ -213,37 +174,7 @@ board_init_f_r_trampoline:
> /* Stack grows down from top of SDRAM */
> movl %eax, %esp
>
> - /* Reserve space on stack for global data */
> - subl $GENERATED_GBL_DATA_SIZE, %esp
> -
> - /* Align global data to 16-byte boundary */
> - andl $0xfffffff0, %esp
> -
> - /* Setup first parameter to memcpy() and setup_gdt() */
> - movl %esp, %eax
> -
> - /* Setup second parameter to memcpy() */
> - fs movl 0, %edx
> -
> - /* Set third parameter to memcpy() */
> - movl $GENERATED_GBL_DATA_SIZE, %ecx
> -
> - /* Copy global data from CAR to SDRAM stack */
> - call memcpy
> -
> - /* Reserve space for global descriptor table */
> - subl $X86_GDT_SIZE, %esp
> -
> - /* Align global descriptor table to 16-byte boundary */
> - andl $0xfffffff0, %esp
> -
> - /* Set second parameter to setup_gdt() */
> - movl %esp, %edx
> -
> - /* Setup global descriptor table so gd->xyz works */
> - call setup_gdt
> -
> - /* Set if we need to disable CAR */
> + /* See if we need to disable CAR */
> .weak car_uninit
> movl $car_uninit, %eax
> cmpl $0, %eax
> diff --git a/common/board_f.c b/common/board_f.c
> index 37b7bf5..c959774 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -715,6 +715,7 @@ static int jump_to_copy(void)
> * with the stack in SDRAM and Global Data in temporary memory
> * (CPU cache)
> */
> + arch_setup_gd(gd->new_gd);
> board_init_f_r_trampoline(gd->start_addr_sp);
> #else
> relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
> @@ -1033,6 +1034,7 @@ __weak void arch_setup_gd(struct global_data *gd_ptr)
> {
> gd = gd_ptr;
> }
> +#endif /* !CONFIG_X86 */
>
> ulong board_init_f_mem(ulong top)
> {
> @@ -1054,4 +1056,3 @@ ulong board_init_f_mem(ulong top)
>
> return top;
> }
> -#endif /* !CONFIG_X86 */
> --
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 1/5] x86: Remove init_gd() function
2015-08-11 2:44 ` [U-Boot] [PATCH v2 1/5] x86: Remove init_gd() function Simon Glass
@ 2015-08-12 3:55 ` Simon Glass
0 siblings, 0 replies; 14+ messages in thread
From: Simon Glass @ 2015-08-12 3:55 UTC (permalink / raw
To: u-boot
On 10 August 2015 at 20:44, Simon Glass <sjg@chromium.org> wrote:
> This is declared but no-longer exists. Drop it.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> ---
>
> Changes in v2: None
>
> arch/x86/include/asm/u-boot-x86.h | 1 -
> 1 file changed, 1 deletion(-)
Applied to u-boot-x86
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 2/5] Align global_data to a 16-byte boundary
2015-08-11 6:28 ` Bin Meng
@ 2015-08-12 3:55 ` Simon Glass
0 siblings, 0 replies; 14+ messages in thread
From: Simon Glass @ 2015-08-12 3:55 UTC (permalink / raw
To: u-boot
On 11 August 2015 at 00:28, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Tue, Aug 11, 2015 at 10:44 AM, Simon Glass <sjg@chromium.org> wrote:
>> Some archs like to have larger alignment for their global data. Use 16 bytes
>> which suits all current archs.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes in v2:
>> - Correct logic to round down instead of up
>>
>> common/board_f.c | 1 +
>> include/asm-generic/global_data.h | 2 +-
>> 2 files changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/common/board_f.c b/common/board_f.c
>> index 8cca4de..74f77f1 100644
>> --- a/common/board_f.c
>> +++ b/common/board_f.c
>> @@ -499,6 +499,7 @@ static int setup_machine(void)
>> static int reserve_global_data(void)
>> {
>> gd->start_addr_sp -= sizeof(gd_t);
>> + gd->start_addr_sp &= ~0xf;
>> gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
>> debug("Reserving %zu Bytes for Global Data at: %08lx\n",
>> sizeof(gd_t), gd->start_addr_sp);
>> diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
>> index 2155265..147f646 100644
>> --- a/include/asm-generic/global_data.h
>> +++ b/include/asm-generic/global_data.h
>> @@ -99,7 +99,7 @@ typedef struct global_data {
>> int pcidelay_done;
>> #endif
>> struct udevice *cur_serial_dev; /* current serial device */
>> - struct arch_global_data arch; /* architecture-specific data */
>> + struct arch_global_data arch __aligned(16); /* arch-specific data */
>> } gd_t;
>> #endif
>>
>> --
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Applied to u-boot-x86
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 3/5] Allow arch-specific setting of global_data in board_init_f_mem()
2015-08-11 6:28 ` Bin Meng
@ 2015-08-12 3:55 ` Simon Glass
0 siblings, 0 replies; 14+ messages in thread
From: Simon Glass @ 2015-08-12 3:55 UTC (permalink / raw
To: u-boot
On 11 August 2015 at 00:28, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Tue, Aug 11, 2015 at 10:44 AM, Simon Glass <sjg@chromium.org> wrote:
>> At present we have a simple assignment to gd. With some archs this is
>> implemented as a register or through some other means; a simple assignment
>> does not suit in all cases.
>>
>> Change this to a function and add documentation to describe how this all
>> works.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> Reviewed-by: York Sun <yorksun@freescale.com>
>> ---
>>
>> Changes in v2:
>> - Drop unused 'reserve_size' argument
>> - Rename arch_setup_gdt() to arch_setup_gd()
>> - Expand the comment about the 64-byte stack space
>> - Fix a comma which should be a period
>> - Add a comment as to why we can't compile the weak arch_setup_gd() on x86
>>
>> common/board_f.c | 13 +++++++++++--
>> include/common.h | 43 +++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 54 insertions(+), 2 deletions(-)
>>
>> diff --git a/common/board_f.c b/common/board_f.c
>> index 74f77f1..37b7bf5 100644
>> --- a/common/board_f.c
>> +++ b/common/board_f.c
>> @@ -1027,16 +1027,25 @@ void board_init_f_r(void)
>> }
>> #endif /* CONFIG_X86 */
>>
>> +/* Unfortunately x86 can't compile this code as gd cannot be assigned */
>> #ifndef CONFIG_X86
>> +__weak void arch_setup_gd(struct global_data *gd_ptr)
>> +{
>> + gd = gd_ptr;
>> +}
>> +
>> ulong board_init_f_mem(ulong top)
>> {
>> + struct global_data *gd_ptr;
>> +
>> /* Leave space for the stack we are running with now */
>> top -= 0x40;
>>
>> top -= sizeof(struct global_data);
>> top = ALIGN(top, 16);
>> - gd = (struct global_data *)top;
>> - memset((void *)gd, '\0', sizeof(*gd));
>> + gd_ptr = (struct global_data *)top;
>> + memset(gd_ptr, '\0', sizeof(*gd));
>> + arch_setup_gd(gd_ptr);
>>
>> #ifdef CONFIG_SYS_MALLOC_F_LEN
>> top -= CONFIG_SYS_MALLOC_F_LEN;
>> diff --git a/include/common.h b/include/common.h
>> index fcc9ae7..48e5006 100644
>> --- a/include/common.h
>> +++ b/include/common.h
>> @@ -217,6 +217,49 @@ extern char console_buffer[];
>> /* arch/$(ARCH)/lib/board.c */
>> void board_init_f(ulong);
>> void board_init_r(gd_t *, ulong) __attribute__ ((noreturn));
>> +
>> +/**
>> + * board_init_f_mem() - Allocate global data and set stack position
>> + *
>> + * This function is called by each architecture very early in the start-up
>> + * code to set up the environment for board_init_f(). It allocates space for
>> + * global_data (see include/asm-generic/global_data.h) and places the stack
>> + * below this.
>> + *
>> + * This function requires a stack[1] Normally this is at @top. The function
>> + * starts allocating space from 64 bytes below @top. First it creates space
>> + * for global_data. Then it calls arch_setup_gd() which sets gd to point to
>> + * the global_data space and can reserve additional bytes of space if
>> + * required). Finally it allocates early malloc() memory
>> + * (CONFIG_SYS_MALLOC_F_LEN). The new top of the stack is just below this,
>> + * and it returned by this function.
>> + *
>> + * [1] Strictly speaking it would be possible to implement this function
>> + * in C on many archs such that it does not require a stack. However this
>> + * does not seem hugely important as only 64 byte are wasted. The 64 bytes
>> + * are used to handle the calling standard which generally requires pushing
>> + * addresses or registers onto the stack. We should be able to get away with
>> + * less if this becomes important.
>> + *
>> + * @top: Top of available memory, also normally the top of the stack
>> + * @return: New stack location
>> + */
>> +ulong board_init_f_mem(ulong top);
>> +
>> +/**
>> + * arch_setup_gd() - Set up the global_data pointer
>> + *
>> + * This pointer is special in some architectures and cannot easily be assigned
>> + * to. For example on x86 it is implemented by adding a specific record to its
>> + * Global Descriptor Table! So we we provide a function to carry out this task.
>> + * For most architectures this can simply be:
>> + *
>> + * gd = gd_ptr;
>> + *
>> + * @gd_ptr: Pointer to global data
>> + */
>> +void arch_setup_gd(gd_t *gd_ptr);
>> +
>> int checkboard(void);
>> int show_board_info(void);
>> int checkflash(void);
>> --
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Applied to u-boot-x86
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 4/5] x86: Move the GDT into global_data
2015-08-11 2:44 ` [U-Boot] [PATCH v2 4/5] x86: Move the GDT into global_data Simon Glass
@ 2015-08-12 3:55 ` Simon Glass
0 siblings, 0 replies; 14+ messages in thread
From: Simon Glass @ 2015-08-12 3:55 UTC (permalink / raw
To: u-boot
On 10 August 2015 at 20:44, Simon Glass <sjg@chromium.org> wrote:
> Rather than keeping track of the Global Descriptor Table in its own memory
> we may as well put it in global_data with everything else. As a first step,
> stop using the separately allocated GDT.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
> ---
>
> Changes in v2: None
>
> arch/x86/cpu/cpu.c | 9 +++++----
> arch/x86/include/asm/global_data.h | 4 +++-
> 2 files changed, 8 insertions(+), 5 deletions(-)
Applied to u-boot-x86
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v2 5/5] x86: Switch to using generic global_data setup
2015-08-11 6:28 ` Bin Meng
@ 2015-08-12 3:55 ` Simon Glass
0 siblings, 0 replies; 14+ messages in thread
From: Simon Glass @ 2015-08-12 3:55 UTC (permalink / raw
To: u-boot
On 11 August 2015 at 00:28, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Tue, Aug 11, 2015 at 10:44 AM, Simon Glass <sjg@chromium.org> wrote:
>> There is quite a bit of assembler code that can be removed if we use the
>> generic global_data setup. Less arch-specific code makes it easier to add
>> new features and maintain the start-up code.
>>
>> Drop the unneeded code and adjust the hooks in board_f.c to cope.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes in v2:
>> - Don't rely on value of %edx from board_init_f_mem()
>>
>> arch/x86/cpu/cpu.c | 4 ++-
>> arch/x86/cpu/start.S | 95 +++++++---------------------------------------------
>> common/board_f.c | 3 +-
>> 3 files changed, 18 insertions(+), 84 deletions(-)
>>
[snip]
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Applied to u-boot-x86
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-08-12 3:55 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-11 2:44 [U-Boot] [PATCH v2 0/5] x86: Move x86 to use board_init_f_mem() instead of assembler Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 1/5] x86: Remove init_gd() function Simon Glass
2015-08-12 3:55 ` Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 2/5] Align global_data to a 16-byte boundary Simon Glass
2015-08-11 6:28 ` Bin Meng
2015-08-12 3:55 ` Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 3/5] Allow arch-specific setting of global_data in board_init_f_mem() Simon Glass
2015-08-11 6:28 ` Bin Meng
2015-08-12 3:55 ` Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 4/5] x86: Move the GDT into global_data Simon Glass
2015-08-12 3:55 ` Simon Glass
2015-08-11 2:44 ` [U-Boot] [PATCH v2 5/5] x86: Switch to using generic global_data setup Simon Glass
2015-08-11 6:28 ` Bin Meng
2015-08-12 3:55 ` Simon Glass
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.