Skip to contentSkip to conversation

remove BAT mappings

PATCH In review Hollis Blanchard 3 participants 4 messages Oct 15, 2004 – Oct 20, 2004

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 remove BAT mappings

This patch removes the use of BAT registers to perform virtual memory translations. BATs are a convenient way to avoid dealing with page tables, however, there are two problems:
- Old World Macs apparently do not consider the BAT registers when performing /chosen/mmu "translate" calls. The Linux kernel requires that the "translate" result be accurate.
(Given that New World Macs seem to have been booting ok without this, I can only assume that New World firmware was fixed.)
- BATs have been removed from POWER4 and POWER5 processors, used in pSeries servers.

Instead of performing large one-time mappings, we map what we need. We do this by calling the "map" method of /chosen/mmu (after claiming the space first).

I have tested this patch on Old World and New World Macintosh. With this patch applied, Old World can successfully boot into Linux. :)

-Hollis

2004-10-15 Hollis Blanchard <[email protected]>

* boot/powerpc/ieee1275/cmain.c (cmain): Remove asm statements which initialized BAT registers.
* boot/powerpc/ieee1275/ieee1275.c (IEEE1275_CALL_ENTRY_FN): Move to include/grub/powerpc/ieee1275/ieee1275.h. (grub_ieee1275_common_hdr): Likewise. (INIT_IEEE1275_COMMON): Likewise.
* include/grub/powerpc/ieee1275/ieee1275.h (IEEE1275_CALL_ENTRY_FN):
Move from boot/powerpc/ieee1275/ieee1275.c. (grub_ieee1275_common_hdr): Likewise. (INIT_IEEE1275_COMMON): Likewise.
* kern/powerpc/ieee1275/openfw.c (grub_map): New function. (grub_mapclaim): Likewise.
* loader/powerpc/ieee1275/linux.c (grub_load_linux): Use grub_mapclaim instead of grub_ieee1275_claim. Assign linux_addr by hand.

Index: boot/powerpc/ieee1275/cmain.c
===================================================================
RCS file: /cvsroot/grub/grub2/boot/powerpc/ieee1275/cmain.c,v retrieving revision 1.3

powerpc/ieee1275/cmain.c +0 -22
diff -u -p -r1.3 cmain.c
@@ -55,7 +55,6 @@ cmain (uint32_t r3, uint32_t r4 __attrib
   char **argv, args[256];
   grub_ieee1275_phandle_t chosen;
   int argc = 0, actual;
-  long batl, batu;
 
   if (r5 == 0xdeadbeef)
     {
@@ -81,27 +80,6 @@ cmain (uint32_t r3, uint32_t r4 __attrib
       grub_ieee1275_entry_fn = (intptr_t (*)(void *)) r5;
     }
 
-  /* Initialize BAT registers to unmapped to not generate overlapping
-     mappings below.  */
-  asm volatile ("mtibatu 0,%0" :: "r"(0));
-  asm volatile ("mtibatu 1,%0" :: "r"(0));
-  asm volatile ("mtibatu 2,%0" :: "r"(0));
-  asm volatile ("mtibatu 3,%0" :: "r"(0));
-  asm volatile ("mtdbatu 0,%0" :: "r"(0));
-  asm volatile ("mtdbatu 1,%0" :: "r"(0));
-  asm volatile ("mtdbatu 2,%0" :: "r"(0));
-  asm volatile ("mtdbatu 3,%0" :: "r"(0));
-
-  /* Set up initial BAT table to only map the lowest 256 MB area.  */
-  batl = 0x00000000 | 0x10   | 0x02;
-  batu = 0x00000000 | 0x1ffc | 0x02;
-
-  /* IBAT0 used for initial 256 MB segment */
-  asm volatile ("mtibatl 3,%0; mtibatu 3,%1" :: "r" (batl), "r" (batu));
-  /* DBAT0 used similar */
-  asm volatile ("mtdbatl 3,%0; mtdbatu 3,%1" :: "r" (batl), "r" (batu));
-  asm ("isync");
-
   /* If any argument was passed to the kernel (us), they are
      put in the bootargs property of /chosen.  The string can
      be null (just the nul-character), so check that the size

Index: boot/powerpc/ieee1275/ieee1275.c
===================================================================
RCS file: /cvsroot/grub/grub2/boot/powerpc/ieee1275/ieee1275.c,v retrieving revision 1.7

powerpc/ieee1275/ieee1275.c +0 -19
diff -u -p -r1.7 ieee1275.c
@@ -26,25 +26,6 @@
 
 intptr_t (*grub_ieee1275_entry_fn) (void *);
 
-#ifndef IEEE1275_CALL_ENTRY_FN
-#define IEEE1275_CALL_ENTRY_FN(args) (*grub_ieee1275_entry_fn) (args)
-#endif
-
-/* All backcalls to the firmware is done by calling an entry function 
-   which was passed to us from the bootloader.  When doing the backcall, 
-   a structure is passed which specifies what the firmware should do.  
-   NAME is the requested service.  NR_INS and NR_OUTS is the number of
-   passed arguments and the expected number of return values, resp. */
-struct grub_ieee1275_common_hdr
-{
-  char *name;
-  int nr_ins;
-  int nr_outs;
-};
-
-#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \
-  (p)->name = xname; (p)->nr_ins = xins; (p)->nr_outs = xouts
-
 /* FIXME is this function needed? */
 grub_uint32_t
 grub_ieee1275_decode_int_4 (unsigned char *p)

Index: include/grub/powerpc/ieee1275/ieee1275.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/ieee1275.h,v retrieving revision 1.8

grub/powerpc/ieee1275/ieee1275.h +22 -0
diff -u -p -r1.8 ieee1275.h
@@ -39,6 +39,27 @@ struct grub_ieee1275_mem_region 
   unsigned int size;
 };
 
+extern intptr_t (*grub_ieee1275_entry_fn) (void *);
+
+#ifndef IEEE1275_CALL_ENTRY_FN
+#define IEEE1275_CALL_ENTRY_FN(args) (*grub_ieee1275_entry_fn) (args)
+#endif
+
+/* All backcalls to the firmware is done by calling an entry function 
+   which was passed to us from the bootloader.  When doing the backcall, 
+   a structure is passed which specifies what the firmware should do.  
+   NAME is the requested service.  NR_INS and NR_OUTS is the number of
+   passed arguments and the expected number of return values, resp. */
+struct grub_ieee1275_common_hdr
+{
+  char *name;
+  int nr_ins;
+  int nr_outs;
+};
+
+#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \
+  (p)->name = xname; (p)->nr_ins = xins; (p)->nr_outs = xouts
+
 /* FIXME jrydberg: is this correct cell types? */
 typedef intptr_t grub_ieee1275_ihandle_t;
 typedef intptr_t grub_ieee1275_phandle_t;
@@ -103,6 +124,7 @@ grub_err_t EXPORT_FUNC(grub_devalias_ite
      (int (*hook) (struct grub_ieee1275_devalias *alias));
 grub_err_t EXPORT_FUNC(grub_children_iterate) (char *devpath,
      int (*hook) (struct grub_ieee1275_devalias *alias));
+int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
 
 void EXPORT_FUNC(abort) (void);
 

Index: kern/powerpc/ieee1275/openfw.c
===================================================================
RCS file: /cvsroot/grub/grub2/kern/powerpc/ieee1275/openfw.c,v retrieving revision 1.3

powerpc/ieee1275/openfw.c +54 -0

57 lines not on this page · raw message

Index: loader/powerpc/ieee1275/linux.c
===================================================================
RCS file: /cvsroot/grub/grub2/loader/powerpc/ieee1275/linux.c,v retrieving revision 1.3

powerpc/ieee1275/linux.c +3 -2
diff -u -p -r1.3 linux.c
@@ -188,12 +188,13 @@ grub_load_linux (int argc, char *argv[])
   /* Reserve memory for the kernel.  */
   linux_size += 0x100000;
   
-  if (grub_ieee1275_claim (entry, linux_size, 0, &linux_addr) == -1)
+  if (grub_claimmap (entry, linux_size) == -1)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not claim memory");
       goto fail;
     }
-  
+  linux_addr = entry;
+
   /* Load every loadable segment in memory.  */
   for (i = 0; i < ehdr.e_phnum; i++)
     {
#1 lore raw

Any comments on this patch?

Quoted 258 lines · Hollis Blanchard

This patch removes the use of BAT registers to perform virtual memory translations. BATs are a convenient way to avoid dealing with page tables, however, there are two problems:
- Old World Macs apparently do not consider the BAT registers when performing /chosen/mmu "translate" calls. The Linux kernel requires that the "translate" result be accurate.
(Given that New World Macs seem to have been booting ok without
this, I
can only assume that New World firmware was fixed.)
- BATs have been removed from POWER4 and POWER5 processors, used in pSeries servers.

Instead of performing large one-time mappings, we map what we need. We do this by calling the "map" method of /chosen/mmu (after claiming the space first).

I have tested this patch on Old World and New World Macintosh. With this patch applied, Old World can successfully boot into Linux. :)

-Hollis

2004-10-15 Hollis Blanchard <[email protected]>

* boot/powerpc/ieee1275/cmain.c (cmain): Remove asm statements which initialized BAT registers.
* boot/powerpc/ieee1275/ieee1275.c (IEEE1275_CALL_ENTRY_FN): Move to include/grub/powerpc/ieee1275/ieee1275.h. (grub_ieee1275_common_hdr): Likewise. (INIT_IEEE1275_COMMON): Likewise.
* include/grub/powerpc/ieee1275/ieee1275.h (IEEE1275_CALL_ENTRY_FN):
Move from boot/powerpc/ieee1275/ieee1275.c. (grub_ieee1275_common_hdr): Likewise. (INIT_IEEE1275_COMMON): Likewise.
* kern/powerpc/ieee1275/openfw.c (grub_map): New function. (grub_mapclaim): Likewise.
* loader/powerpc/ieee1275/linux.c (grub_load_linux): Use grub_mapclaim instead of grub_ieee1275_claim. Assign linux_addr by hand.

Index: boot/powerpc/ieee1275/cmain.c
===================================================================
RCS file: /cvsroot/grub/grub2/boot/powerpc/ieee1275/cmain.c,v retrieving revision 1.3
diff -u -p -r1.3 cmain.c

powerpc/ieee1275/cmain.c +0 -22
@@ -55,7 +55,6 @@ cmain (uint32_t r3, uint32_t r4 __attrib
   char **argv, args[256];
   grub_ieee1275_phandle_t chosen;
   int argc = 0, actual;
-  long batl, batu;
 
   if (r5 == 0xdeadbeef)
     {
@@ -81,27 +80,6 @@ cmain (uint32_t r3, uint32_t r4 __attrib
       grub_ieee1275_entry_fn = (intptr_t (*)(void *)) r5;
     }
 
-  /* Initialize BAT registers to unmapped to not generate overlapping
-     mappings below.  */
-  asm volatile ("mtibatu 0,%0" :: "r"(0));
-  asm volatile ("mtibatu 1,%0" :: "r"(0));
-  asm volatile ("mtibatu 2,%0" :: "r"(0));
-  asm volatile ("mtibatu 3,%0" :: "r"(0));
-  asm volatile ("mtdbatu 0,%0" :: "r"(0));
-  asm volatile ("mtdbatu 1,%0" :: "r"(0));
-  asm volatile ("mtdbatu 2,%0" :: "r"(0));
-  asm volatile ("mtdbatu 3,%0" :: "r"(0));
-
-  /* Set up initial BAT table to only map the lowest 256 MB area.  */
-  batl = 0x00000000 | 0x10   | 0x02;
-  batu = 0x00000000 | 0x1ffc | 0x02;
-
-  /* IBAT0 used for initial 256 MB segment */
-  asm volatile ("mtibatl 3,%0; mtibatu 3,%1" :: "r" (batl), "r" 
 (batu));
-  /* DBAT0 used similar */
-  asm volatile ("mtdbatl 3,%0; mtdbatu 3,%1" :: "r" (batl), "r" 
 (batu));
-  asm ("isync");
-
   /* If any argument was passed to the kernel (us), they are

put in the bootargs property of /chosen. The string can be null (just the nul-character), so check that the size
Index: boot/powerpc/ieee1275/ieee1275.c
===================================================================
RCS file: /cvsroot/grub/grub2/boot/powerpc/ieee1275/ieee1275.c,v retrieving revision 1.7
diff -u -p -r1.7 ieee1275.c

powerpc/ieee1275/ieee1275.c +0 -19
@@ -26,25 +26,6 @@
 
 intptr_t (*grub_ieee1275_entry_fn) (void *);
 
-#ifndef IEEE1275_CALL_ENTRY_FN
-#define IEEE1275_CALL_ENTRY_FN(args) (*grub_ieee1275_entry_fn) (args)
-#endif
-
-/* All backcalls to the firmware is done by calling an entry function
-   which was passed to us from the bootloader.  When doing the 
 backcall,
-   a structure is passed which specifies what the firmware should do.
-   NAME is the requested service.  NR_INS and NR_OUTS is the number of
-   passed arguments and the expected number of return values, resp. */
-struct grub_ieee1275_common_hdr
-{
-  char *name;
-  int nr_ins;
-  int nr_outs;
-};
-
-#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \
-  (p)->name = xname; (p)->nr_ins = xins; (p)->nr_outs = xouts
-
 /* FIXME is this function needed? */
 grub_uint32_t

grub_ieee1275_decode_int_4 (unsigned char *p)
Index: include/grub/powerpc/ieee1275/ieee1275.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/powerpc/ieee1275/ieee1275.h,v retrieving revision 1.8
diff -u -p -r1.8 ieee1275.h
--- include/grub/powerpc/ieee1275/ieee1275.h 15 Oct 2004 02:29:11
-0000 1.8
+++ include/grub/powerpc/ieee1275/ieee1275.h 15 Oct 2004 22:19:54 -0000

powerpc/ieee1275/ieee1275.c +21 -0
@@ -39,6 +39,27 @@ struct grub_ieee1275_mem_region
   unsigned int size;
 };
 
+extern intptr_t (*grub_ieee1275_entry_fn) (void *);
+
+#ifndef IEEE1275_CALL_ENTRY_FN
+#define IEEE1275_CALL_ENTRY_FN(args) (*grub_ieee1275_entry_fn) (args)
+#endif
+
+/* All backcalls to the firmware is done by calling an entry function
+   which was passed to us from the bootloader.  When doing the 
 backcall,
+   a structure is passed which specifies what the firmware should do.
+   NAME is the requested service.  NR_INS and NR_OUTS is the number of
+   passed arguments and the expected number of return values, resp. */
+struct grub_ieee1275_common_hdr
+{
+  char *name;
+  int nr_ins;
+  int nr_outs;
+};
+
+#define INIT_IEEE1275_COMMON(p, xname, xins, xouts) \
+  (p)->name = xname; (p)->nr_ins = xins; (p)->nr_outs = xouts
+
 /* FIXME jrydberg: is this correct cell types? */
 typedef intptr_t grub_ieee1275_ihandle_t;

typedef intptr_t grub_ieee1275_phandle_t;

powerpc/ieee1275/ieee1275.c +1 -0
@@ -103,6 +124,7 @@ grub_err_t EXPORT_FUNC(grub_devalias_ite
      (int (*hook) (struct grub_ieee1275_devalias *alias));
 grub_err_t EXPORT_FUNC(grub_children_iterate) (char *devpath,
      int (*hook) (struct grub_ieee1275_devalias *alias));
+int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
 
 void EXPORT_FUNC(abort) (void);
 

Index: kern/powerpc/ieee1275/openfw.c
===================================================================
RCS file: /cvsroot/grub/grub2/kern/powerpc/ieee1275/openfw.c,v retrieving revision 1.3
diff -u -p -r1.3 openfw.c

powerpc/ieee1275/openfw.c +54 -0
@@ -137,3 +137,57 @@ grub_devalias_iterate (int (*hook) (stru
 
   return 0;
 }
+
+/* Call the "map" method of /chosen/mmu.  */
+int
+grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size,
+		   grub_uint8_t mode)
+{
+  struct map_args {
+    struct grub_ieee1275_common_hdr common;
+    char *method;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_uint32_t mode;
+    grub_uint32_t size;
+    grub_uint32_t virt;
+    grub_uint32_t phys;
+    int catch_result;
+  } args;
+  grub_ieee1275_ihandle_t mmu;
+  grub_ieee1275_ihandle_t chosen;
+  int len;
+
+  grub_ieee1275_finddevice ("/chosen", &chosen);
+  if (chosen == 0)
+    return -1;
+
+  grub_ieee1275_get_property (chosen, "mmu", &mmu, sizeof mmu, &len);
+  if (len != sizeof mmu)
+    return -1;
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1);
+  args.method = "map";
+  args.ihandle = mmu;
+  args.phys = phys;
+  args.virt = virt;
+  args.size = size;
+  args.mode = mode; /* Format is WIMG0PP.  */
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+    return -1;
+
+  return args.catch_result;
+}
+
+int
+grub_claimmap (grub_addr_t addr, grub_size_t size)
+{
+  if (grub_ieee1275_claim (addr, size, 0, 0))
+    return -1;
+  if (grub_map (addr, addr, size, 0x00))
+    {
+      grub_ieee1275_release (addr, size);
+      return -1;
+    }
+  return 0;
+}

Index: loader/powerpc/ieee1275/linux.c
===================================================================
RCS file: /cvsroot/grub/grub2/loader/powerpc/ieee1275/linux.c,v retrieving revision 1.3
diff -u -p -r1.3 linux.c

powerpc/ieee1275/linux.c +3 -2
@@ -188,12 +188,13 @@ grub_load_linux (int argc, char *argv[])
   /* Reserve memory for the kernel.  */
   linux_size += 0x100000;
 
-  if (grub_ieee1275_claim (entry, linux_size, 0, &linux_addr) == -1)
+  if (grub_claimmap (entry, linux_size) == -1)
     {
       grub_error (GRUB_ERR_OUT_OF_MEMORY, "Can not claim memory");
       goto fail;
     }
-
+  linux_addr = entry;
+
   /* Load every loadable segment in memory.  */
   for (i = 0; i < ehdr.e_phnum; i++)
     {

_______________________________________________
Grub-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel

#2 lore raw
Quoted 1 line · Hollis Blanchard

Any comments on this patch?

I hope Johan can tell us more about this, he wrote this code.

--
Marco

#3 lore raw
Quoted 5 lines · Marco Gerards
Quoted 1 line · Hollis Blanchard

Any comments on this patch?

I hope Johan can tell us more about this, he wrote this code.

No, I do not have any comments. I just added the mappings to have a known state when entering my OS (where the code originally came from.)

If removing them enables us to boot Linux? Good. Make them go away.

~j