This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfc] [8/9] Cell multi-arch: Support PPU address space access


Hello,

this adds support for the __ea address space qualifier (the GCC patches
to add this feature are currently being contributed to mainline).

This feature adds support for pointers in SPU code that hold PowerPC
addresses.  These are marked using an address class of 1 in DWARF-2
debug info.  The patch below uses GDB's existing support for address
classes to recognize such pointers, and handle proper conversion in
the pointer/integer to address routines.

In addition, the __ea pointers are implemented in SPU code with the help
of a software-managed cache.  This causes some challenges for debugging,
because if you access a PowerPC variable via an __ea pointer from SPU code,
changes to that variable are not actually visible in PowerPC memory until
the SPU software-managed cache has written back the cache line.

This patch has GDB perform an inferior call to __cache_flush every time the
inferior stops in SPU code that uses the software-managed cache.  Thus,
the user is able to inspect PowerPC variables and see current values.

However, there are situations where this is counter-productive, e.g. when
you are actually trying to debug the cache manager itself.  Therefore,
the patch also adds a command to disable that feature.

Bye,
Ulrich


ChangeLog:

        * spu-tdep.c: Include "infcall.h".
	(spu_address_class_type_flags): New function.
	(spu_address_class_type_flags_to_name): Likewise.
	(spu_address_class_name_to_type_flags): Likewise.
	(spu_pointer_to_address): Handle __ea pointers.
        (spu_auto_flush_cache_p): New static variable.
        (spu_objfile_from_frame): New function.
        (flush_ea_cache, spu_attach_normal_stop): Likewise.
        (show_spu_auto_flush_cache): Likewise.
	(spu_gdbarch_init): Install address class handlers.
        (_initialize_spu_tdep): Attach to normal_stop observer.
        Install "set spu auto-flush-cache" / "show spu auto-flush-cache"
        commands.

	* NEWS: Mention "set/show spu auto-flush-cache" commands.

doc/ChangeLog:

        * gdb.texinfo (Cell Broadband Engine SPU architecture): Document the
        "set spu auto-flush-cache" and "show spu auto-flush-cache" commands.


Bye,
Ulrich


Index: src/gdb/spu-tdep.c
===================================================================
--- src.orig/gdb/spu-tdep.c
+++ src/gdb/spu-tdep.c
@@ -42,6 +42,7 @@
 #include "floatformat.h"
 #include "block.h"
 #include "observer.h"
+#include "infcall.h"
 
 #include "spu-tdep.h"
 
@@ -52,6 +53,8 @@ static struct cmd_list_element *showspuc
 
 /* Whether to stop for new SPE contexts.  */
 static int spu_stop_on_load_p = 0;
+/* Whether to automatically flush the SW-managed cache.  */
+static int spu_auto_flush_cache_p = 1;
 
 
 /* The tdep structure.  */
@@ -340,7 +343,8 @@ spu_register_reggroup_p (struct gdbarch 
   return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
-/* Address conversion.  */
+
+/* Address handling.  */
 
 static int
 spu_gdbarch_id (struct gdbarch *gdbarch)
@@ -377,6 +381,37 @@ spu_lslr (int id)
   return strtoulst (buf, NULL, 16);
 }
 
+static int
+spu_address_class_type_flags (int byte_size, int dwarf2_addr_class)
+{
+  if (dwarf2_addr_class == 1)
+    return TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1;
+  else
+    return 0;
+}
+
+static const char *
+spu_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags)
+{
+  if (type_flags & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1)
+    return "__ea";
+  else
+    return NULL;
+}
+
+static int
+spu_address_class_name_to_type_flags (struct gdbarch *gdbarch,
+				      const char *name, int *type_flags_ptr)
+{
+  if (strcmp (name, "__ea") == 0)
+    {
+      *type_flags_ptr = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1;
+      return 1;
+    }
+  else
+   return 0;
+}
+
 static void
 spu_address_to_pointer (struct gdbarch *gdbarch,
 			struct type *type, gdb_byte *buf, CORE_ADDR addr)
@@ -396,6 +431,10 @@ spu_pointer_to_address (struct gdbarch *
   ULONGEST addr
     = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
 
+  /* Do not convert __ea pointers.  */
+  if (TYPE_ADDRESS_CLASS_1 (type))
+    return addr;
+
   return addr? SPUADDR (id, addr & lslr) : 0;
 }
 
@@ -1820,6 +1859,73 @@ spu_catch_start (struct objfile *objfile
 }
 
 
+/* Look up OBJFILE loaded into FRAME's SPU context.  */
+static struct objfile *
+spu_objfile_from_frame (struct frame_info *frame)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct objfile *obj;
+
+  if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
+    return NULL;
+
+  ALL_OBJFILES (obj)
+    {
+      if (obj->sections != obj->sections_end
+	  && SPUADDR_SPU (obj_section_addr (obj->sections)) == tdep->id)
+	return obj;
+    }
+
+  return NULL;
+}
+
+/* Flush cache for ea pointer access if available.  */
+static void
+flush_ea_cache (void)
+{
+  struct minimal_symbol *msymbol;
+  struct objfile *obj;
+
+  if (!has_stack_frames ())
+    return;
+
+  obj = spu_objfile_from_frame (get_current_frame ());
+  if (obj == NULL)
+    return;
+
+  /* Lookup inferior function __cache_flush.  */
+  msymbol = lookup_minimal_symbol ("__cache_flush", NULL, obj);
+  if (msymbol != NULL)
+    {
+      struct type *type;
+      CORE_ADDR addr;
+
+      type = objfile_type (obj)->builtin_void;
+      type = lookup_function_type (type);
+      type = lookup_pointer_type (type);
+      addr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+      call_function_by_hand (value_from_pointer (type, addr), 0, NULL);
+    }
+}
+
+/* This handler is called when the inferior has stopped.  If it is stopped in
+   SPU architecture then flush the ea cache if used.  */
+static void
+spu_attach_normal_stop (struct bpstats *bs, int print_frame)
+{
+  if (!spu_auto_flush_cache_p)
+    return;
+
+  /* Temporarily reset spu_auto_flush_cache_p to avoid recursively
+     re-entering this function when __cache_flush stops.  */
+  spu_auto_flush_cache_p = 0;
+  flush_ea_cache ();
+  spu_auto_flush_cache_p = 1;
+}
+
+
 /* "info spu" commands.  */
 
 static void
@@ -2411,6 +2517,14 @@ show_spu_stop_on_load (struct ui_file *f
                     value);
 }
 
+static void
+show_spu_auto_flush_cache (struct ui_file *file, int from_tty,
+			   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Automatic software-cache flush is %s.\n"),
+                    value);
+}
+
 
 /* Set up gdbarch struct.  */
 
@@ -2480,10 +2594,16 @@ spu_gdbarch_init (struct gdbarch_info in
   set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
   set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
 
-  /* Address conversion.  */
+  /* Address handling.  */
   set_gdbarch_address_to_pointer (gdbarch, spu_address_to_pointer);
   set_gdbarch_pointer_to_address (gdbarch, spu_pointer_to_address);
   set_gdbarch_integer_to_address (gdbarch, spu_integer_to_address);
+  set_gdbarch_address_class_type_flags (gdbarch, spu_address_class_type_flags);
+  set_gdbarch_address_class_type_flags_to_name
+    (gdbarch, spu_address_class_type_flags_to_name);
+  set_gdbarch_address_class_name_to_type_flags
+    (gdbarch, spu_address_class_name_to_type_flags);
+
 
   /* Inferior function calls.  */
   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
@@ -2536,6 +2656,9 @@ _initialize_spu_tdep (void)
   /* Install spu stop-on-load handler.  */
   observer_attach_new_objfile (spu_catch_start);
 
+  /* Add ourselves to normal_stop event chain.  */
+  observer_attach_normal_stop (spu_attach_normal_stop);
+
   /* Add root prefix command for all "set spu"/"show spu" commands.  */
   add_prefix_cmd ("spu", no_class, set_spu_command,
 		  _("Various SPU specific commands."),
@@ -2559,6 +2682,21 @@ Use \"off\" to disable stopping for new 
                           show_spu_stop_on_load,
                           &setspucmdlist, &showspucmdlist);
 
+  /* Toggle whether or not to automatically flush the software-managed
+     cache whenever SPE execution stops.  */
+  add_setshow_boolean_cmd ("auto-flush-cache", class_support,
+                          &spu_auto_flush_cache_p, _("\
+Set whether to automatically flush the software-managed cache."),
+                           _("\
+Show whether to automatically flush the software-managed cache."),
+                           _("\
+Use \"on\" to automatically flush the software-managed cache\n\
+whenever SPE execution stops.\n\
+Use \"off\" to never automatically flush the software-managed cache."),
+                          NULL,
+                          show_spu_auto_flush_cache,
+                          &setspucmdlist, &showspucmdlist);
+
   /* Add root prefix command for all "info spu" commands.  */
   add_prefix_cmd ("spu", class_info, info_spu_command,
 		  _("Various SPU specific commands."),
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo
+++ src/gdb/doc/gdb.texinfo
@@ -17505,6 +17505,16 @@ function.  The default is @code{off}.
 @kindex show spu
 Show whether to stop for new SPE threads.
 
+@item set spu auto-flush-cache @var{arg}
+Set whether to automatically flush the software-managed cache.  When set to
+@code{on}, @value{GDBN} will automatically cause the SPE software-managed
+cache to be flushed whenever SPE execution stops.  This provides a consistent
+view of PowerPC memory that is accessed via the cache.  If an application
+does not use the software-managed cache, this option has no effect.
+
+@item show spu auto-flush-cache
+Show whether to automatically flush the software-managed cache.
+
 @end table
 
 @node PowerPC
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS
+++ src/gdb/NEWS
@@ -258,6 +258,11 @@ set spu stop-on-load
 show spu stop-on-load
   Control whether to stop for new SPE threads during Cell/B.E. debugging.
 
+set spu auto-flush-cache
+show spu auto-flush-cache
+  Control whether to automatically flush the software-managed cache
+  during Cell/B.E. debugging.
+
 set sh calling-convention
 show sh calling-convention
   Control the calling convention used when calling SH target functions.
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]