Patchwork [U-Boot,v2,04/17] x86: Rework Global Descriptor Table loading

login
register
mail settings
Submitter Graeme Russ
Date Jan. 4, 2012, 7:59 p.m.
Message ID <1325707195-3218-4-git-send-email-graeme.russ@gmail.com>
Download mbox | patch
Permalink /patch/134340/
State Awaiting Upstream
Delegated to: Graeme Russ
Headers show

Comments

Graeme Russ - Jan. 4, 2012, 7:59 p.m.
The inline assembler is ugly and uses hard coded magic numbers. Make it more
elegant to allow cleaner implementation of future GDT related patches. The
compiler seems smart enough to generate the same code anyway

Signed-off-by: Graeme Russ <graeme.russ@gmail.com>
---
Changes for v2:
 - Rebased against revised patch #3
 - Use GDT size define instead of magic number
 - Added commit message

 arch/x86/cpu/cpu.c |   82 +++++++++++++++++++++++++++++++++------------------
 1 files changed, 53 insertions(+), 29 deletions(-)

--
1.7.5.2.317.g391b14
Simon Glass - Jan. 12, 2012, 4:47 a.m.
On Wed, Jan 4, 2012 at 11:59 AM, Graeme Russ <graeme.russ@gmail.com> wrote:
> The inline assembler is ugly and uses hard coded magic numbers. Make it more
> elegant to allow cleaner implementation of future GDT related patches. The
> compiler seems smart enough to generate the same code anyway
>
> Signed-off-by: Graeme Russ <graeme.russ@gmail.com>

Acked-by: Simon Glass <sjg@chromium.org>

> ---
> Changes for v2:
>  - Rebased against revised patch #3
>  - Use GDT size define instead of magic number
>  - Added commit message
>
>  arch/x86/cpu/cpu.c |   82 +++++++++++++++++++++++++++++++++------------------
>  1 files changed, 53 insertions(+), 29 deletions(-)
>
> diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
> index 209ff29..8102fb9 100644
> --- a/arch/x86/cpu/cpu.c
> +++ b/arch/x86/cpu/cpu.c
> @@ -55,35 +55,39 @@ struct gdt_ptr {
>        u32 ptr;
>  } __packed;
>
> -static void reload_gdt(void)
> +static void load_ds(u32 segment)
>  {
> -       /*
> -        * There are machines which are known to not boot with the GDT
> -        * being 8-byte unaligned.  Intel recommends 16 byte alignment
> -        */
> -       static const u64 boot_gdt[] __attribute__((aligned(16))) = {
> -               /* CS: code, read/execute, 4 GB, base 0 */
> -               [X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
> -               /* DS: data, read/write, 4 GB, base 0 */
> -               [X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
> -               /* 16-bit CS: code, read/execute, 64 kB, base 0 */
> -               [X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff),
> -               /* 16-bit DS: data, read/write, 64 kB, base 0 */
> -               [X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff),
> -       };
> -       static struct gdt_ptr gdt;
> -
> -       gdt.len = sizeof(boot_gdt)-1;
> -       gdt.ptr = (u32)&boot_gdt;
> -
> -       asm volatile("lgdtl %0\n" \
> -                    "movl $((2+1)*8), %%ecx\n" \
> -                    "movl %%ecx, %%ds\n" \
> -                    "movl %%ecx, %%es\n" \
> -                    "movl %%ecx, %%fs\n" \
> -                    "movl %%ecx, %%gs\n" \
> -                    "movl %%ecx, %%ss" \
> -                    : : "m" (gdt) : "ecx");
> +       asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE));
> +}
> +
> +static void load_es(u32 segment)
> +{
> +       asm volatile("movl %0, %%es" : : "r" (segment * X86_GDT_ENTRY_SIZE));
> +}
> +
> +static void load_fs(u32 segment)
> +{
> +       asm volatile("movl %0, %%fs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
> +}
> +
> +static void load_gs(u32 segment)
> +{
> +       asm volatile("movl %0, %%gs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
> +}
> +
> +static void load_ss(u32 segment)
> +{
> +       asm volatile("movl %0, %%ss" : : "r" (segment * X86_GDT_ENTRY_SIZE));
> +}
> +
> +static void load_gdt(const u64 *boot_gdt, u16 num_entries)
> +{
> +       struct gdt_ptr gdt;
> +
> +       gdt.len = (num_entries * 8) - 1;
> +       gdt.ptr = (u32)boot_gdt;
> +
> +       asm volatile("lgdtl %0\n" : : "m" (gdt));
>  }
>
>  int x86_cpu_init_f(void)
> @@ -113,7 +117,27 @@ int x86_cpu_init_r(void)
>            "movl       %%eax, %%cr0\n"
>            "wbinvd\n" : : "i" (nw_cd_rst) : "eax");
>
> -       reload_gdt();
> +       /*
> +        * There are machines which are known to not boot with the GDT
> +        * being 8-byte unaligned. Intel recommends 16 byte alignment
> +        */
> +       static const u64 boot_gdt[] __aligned(16) = {
> +               /* CS: code, read/execute, 4 GB, base 0 */
> +               [X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
> +               /* DS: data, read/write, 4 GB, base 0 */
> +               [X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
> +               /* 16-bit CS: code, read/execute, 64 kB, base 0 */
> +               [X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff),
> +               /* 16-bit DS: data, read/write, 64 kB, base 0 */
> +               [X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff),
> +       };
> +
> +       load_gdt(boot_gdt, X86_GDT_NUM_ENTRIES);
> +       load_ds(X86_GDT_ENTRY_32BIT_DS);
> +       load_es(X86_GDT_ENTRY_32BIT_DS);
> +       load_fs(X86_GDT_ENTRY_32BIT_DS);
> +       load_gs(X86_GDT_ENTRY_32BIT_DS);
> +       load_ss(X86_GDT_ENTRY_32BIT_DS);
>
>        /* Initialize core interrupt and exception functionality of CPU */
>        cpu_init_interrupts();
> --
> 1.7.5.2.317.g391b14
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

Patch

diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 209ff29..8102fb9 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -55,35 +55,39 @@  struct gdt_ptr {
 	u32 ptr;
 } __packed;

-static void reload_gdt(void)
+static void load_ds(u32 segment)
 {
-	/*
-	 * There are machines which are known to not boot with the GDT
-	 * being 8-byte unaligned.  Intel recommends 16 byte alignment
-	 */
-	static const u64 boot_gdt[] __attribute__((aligned(16))) = {
-		/* CS: code, read/execute, 4 GB, base 0 */
-		[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
-		/* DS: data, read/write, 4 GB, base 0 */
-		[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
-		/* 16-bit CS: code, read/execute, 64 kB, base 0 */
-		[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff),
-		/* 16-bit DS: data, read/write, 64 kB, base 0 */
-		[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff),
-	};
-	static struct gdt_ptr gdt;
-
-	gdt.len = sizeof(boot_gdt)-1;
-	gdt.ptr = (u32)&boot_gdt;
-
-	asm volatile("lgdtl %0\n" \
-		     "movl $((2+1)*8), %%ecx\n" \
-		     "movl %%ecx, %%ds\n" \
-		     "movl %%ecx, %%es\n" \
-		     "movl %%ecx, %%fs\n" \
-		     "movl %%ecx, %%gs\n" \
-		     "movl %%ecx, %%ss" \
-		     : : "m" (gdt) : "ecx");
+	asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_es(u32 segment)
+{
+	asm volatile("movl %0, %%es" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_fs(u32 segment)
+{
+	asm volatile("movl %0, %%fs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_gs(u32 segment)
+{
+	asm volatile("movl %0, %%gs" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_ss(u32 segment)
+{
+	asm volatile("movl %0, %%ss" : : "r" (segment * X86_GDT_ENTRY_SIZE));
+}
+
+static void load_gdt(const u64 *boot_gdt, u16 num_entries)
+{
+	struct gdt_ptr gdt;
+
+	gdt.len = (num_entries * 8) - 1;
+	gdt.ptr = (u32)boot_gdt;
+
+	asm volatile("lgdtl %0\n" : : "m" (gdt));
 }

 int x86_cpu_init_f(void)
@@ -113,7 +117,27 @@  int x86_cpu_init_r(void)
 	    "movl	%%eax, %%cr0\n"
 	    "wbinvd\n" : : "i" (nw_cd_rst) : "eax");

-	reload_gdt();
+	/*
+	 * There are machines which are known to not boot with the GDT
+	 * being 8-byte unaligned. Intel recommends 16 byte alignment
+	 */
+	static const u64 boot_gdt[] __aligned(16) = {
+		/* CS: code, read/execute, 4 GB, base 0 */
+		[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+		/* DS: data, read/write, 4 GB, base 0 */
+		[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+		/* 16-bit CS: code, read/execute, 64 kB, base 0 */
+		[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff),
+		/* 16-bit DS: data, read/write, 64 kB, base 0 */
+		[X86_GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff),
+	};
+
+	load_gdt(boot_gdt, X86_GDT_NUM_ENTRIES);
+	load_ds(X86_GDT_ENTRY_32BIT_DS);
+	load_es(X86_GDT_ENTRY_32BIT_DS);
+	load_fs(X86_GDT_ENTRY_32BIT_DS);
+	load_gs(X86_GDT_ENTRY_32BIT_DS);
+	load_ss(X86_GDT_ENTRY_32BIT_DS);

 	/* Initialize core interrupt and exception functionality of CPU */
 	cpu_init_interrupts();