[Cbe-oss-dev] [PATCH 2/2] libspe2: Add emulated isolated mode support

Kanna Shimizu kannas at us.ibm.com
Thu Jun 28 16:26:35 EST 2007


libspe2: Add emulated isolated mode support

Using a userspace loader, we can add an 'emulated' isolated mode, which
provides a facility to run contexts with an isolated-mode environment,
but without restricted access to SPE hardware. Contexts can be created
in emulated isolated mode by providing the SPE_ISOLATE_EMULATE flag to
spe_context_create.

This functionality depends on an emulated loader - a SPE program to
load the "emulated isolated" SPE application, using the same ABI as the
real isolated mode loader. We check for this in the file:

  $libdir/spe/emulated-loader.bin

- if this isn't present (or isn't a valid SPE binary) then we refuse to
create emulated-isolated contexts.

Signed-off-by: Jeremy Kerr <jk at ozlabs.org>
Signed-off-by: Kanna Shimizu <kannas at us.ibm.com>

Index: libspe2/spebase/Makefile
===================================================================
--- libspe2.orig/spebase/Makefile
+++ libspe2/spebase/Makefile
@@ -23,6 +23,7 @@ include $(TOP)/make.defines
 
 MAJOR_VERSION           := 2
 MINOR_VERSION           := 0.0
+EMULATED_LOADER := $(libdir)/spe/emulated-loader.bin
 
 libspebase_A            := libspebase.a
 libspebase_SO           := 
libspebase.so.${MAJOR_VERSION}.${MINOR_VERSION}
@@ -35,6 +36,8 @@ libspebase_OBJS := create.o  elf_loader.
 CFLAGS += -I..
 CFLAGS += -D_ATFILE_SOURCE
 
+load.o: CPPFLAGS+='-DSPE_EMULATED_LOADER_FILE="$(EMULATED_LOADER)"'
+
 all: $(libspebase_SO) $(libspebase_A)
 
 install-so: $(libspebase_SO) $(libspebase_A)
Index: libspe2/libspe2-types.h
===================================================================
--- libspe2.orig/libspe2-types.h
+++ libspe2/libspe2-types.h
@@ -176,6 +176,7 @@ enum ps_area { SPE_MSSYNC_AREA, SPE_MFC_
 #define SPE_CFG_SIGNOTIFY2_OR   0x00000020
 #define SPE_MAP_PS  0x00000040
 #define SPE_ISOLATE  0x00000080
+#define SPE_ISOLATE_EMULATE 0x00000100
 #define SPE_EVENTS_ENABLE 0x00001000
 #define SPE_AFFINITY_MEMORY 0x00002000
 
Index: libspe2/spebase/load.c
===================================================================
--- libspe2.orig/spebase/load.c
+++ libspe2/spebase/load.c
@@ -26,6 +26,10 @@
 #include "elf_loader.h"
 #include "spebase.h"
 
+#ifndef SPE_EMULATED_LOADER_FILE
+#define SPE_EMULATED_LOADER_FILE "/usr/lib/spe/emulated-loader.bin"
+#endif
+
 /**
  * Send data to a SPU in mbox when space is available.
  *
@@ -86,6 +90,74 @@ static int spe_start_isolated_app(struct
                 return 0;
 }
 
+/**
+ * Load the emulated isolation loader program from the filesystem
+ *
+ * @return The loader program, or NULL if it can't be loaded. The loader 
binary
+ *                 is cached between calls.
+ */
+static spe_program_handle_t *emulated_loader_program(void)
+{
+                static spe_program_handle_t *loader = NULL;
+
+                if (!loader)
+                                loader = 
_base_spe_image_open(SPE_EMULATED_LOADER_FILE);
+
+                if (!loader)
+                                DEBUG_PRINTF("Can't load emulated loader 
'%s': %s\n",
+ SPE_EMULATED_LOADER_FILE, strerror(errno));
+
+                return loader;
+}
+
+/**
+ * Check if the emulated loader is present in the filesystem
+ * @return Non-zero if the loader is available, otherwise zero.
+ */
+int _base_spe_emulated_loader_present(void)
+{
+                spe_program_handle_t *loader = emulated_loader_program();
+
+                if (!loader)
+                                return 0;
+
+                return !verify_spe_elf_image(loader);
+}
+
+/**
+ * Initiate transfer of an emulated isolated SPE app by the loader 
kernel.
+ *
+ * Helper function for internal libspe use.
+ *
+ * @param thread The SPE thread to load the app to
+ * @param handle The handle to the (isolated) spe program
+ * @param ld_info[out] Loader information about the entry point of the 
SPE.
+ *                              This will reference the loader, not the 
SPE program, as
+ *                              we will be running the loader first.
+ * @return zero on success, non-zero on failure;
+ */
+static int spe_start_emulated_isolated_app(struct spe_context *spe,
+                                spe_program_handle_t *handle, struct 
spe_ld_info *ld_info)
+
+{
+                int rc;
+                spe_program_handle_t *loader;
+
+                /* load emulated loader from the filesystem */
+                loader = emulated_loader_program();
+
+                if (!loader)
+                                return -1;
+
+                rc = load_spe_elf(loader, 
spe->base_private->mem_mmap_base, ld_info);
+                if (rc != 0) {
+                                DEBUG_PRINTF("%s: No loader available\n", 
__FUNCTION__);
+                                return rc;
+                }
+
+                return spe_start_isolated_app(spe, handle);
+}
+
 int _base_spe_program_load(spe_context_ptr_t spe, spe_program_handle_t 
*program)
 {
                 int rc = 0, objfd;
@@ -93,6 +165,10 @@ int _base_spe_program_load(spe_context_p
 
                 if (spe->base_private->flags & SPE_ISOLATE) {
                                 rc = spe_start_isolated_app(spe, 
program);
+
+                } else if (spe->base_private->flags & 
SPE_ISOLATE_EMULATE) {
+                                rc = spe_start_emulated_isolated_app(spe, 
program, &ld_info);
+
                 } else {
                                 rc = load_spe_elf(program, 
spe->base_private->mem_mmap_base,
 &ld_info);
@@ -114,7 +190,8 @@ int _base_spe_program_load(spe_context_p
 
                 __spe_context_update_event(); 
 
-                spe->base_private->entry=ld_info.entry;
- 
+                spe->base_private->entry = ld_info.entry;
+                spe->base_private->emulated_entry = ld_info.entry;
+
                 return 0;
 }
Index: libspe2/spebase/create.c
===================================================================
--- libspe2.orig/spebase/create.c
+++ libspe2/spebase/create.c
@@ -189,6 +189,13 @@ spe_context_ptr_t _base_spe_context_crea
                 struct spe_context *spe = NULL;
                 struct spe_context_base_priv *priv;
 
+                /* We need a loader present to run in emulated isolated 
mode */
+                if (flags & SPE_ISOLATE_EMULATE
+                                                && 
!_base_spe_emulated_loader_present()) {
+                                errno = EINVAL;
+                                return NULL;
+                }
+
                 /* Put some sane defaults into the SPE context */
                 spe = malloc(sizeof(*spe));
                 if (!spe) {
Index: libspe2/spebase/spebase.h
===================================================================
--- libspe2.orig/spebase/spebase.h
+++ libspe2/spebase/spebase.h
@@ -91,6 +91,10 @@ struct spe_context_base_priv {
 
                 /* SPE program entry point generated by elf_load() */
                 int                             entry;
+
+                /* We need to keep the entry point for emulated isolated 
contexts,
+                 * and ignore the value provided to spe_context_run */
+                int                             emulated_entry;
 };
 
 
@@ -110,6 +114,12 @@ struct spe_context_base_priv {
 #define SIGNAL1_OFFSET                                          0x14000
 #define SIGNAL2_OFFSET                                          0x1c000
 
+/**
+ * Location of the PPE-assisted library call buffer
+ * for emulated isolation contexts.
+ */
+#define SPE_EMULATE_PARAM_BUFFER                0x3e000
+
 /* 
  */
 #define SPE_PROGRAM_NORMAL_END                          0x2000
@@ -168,6 +178,12 @@ extern spe_gang_context_ptr_t _base_spe_
 extern int _base_spe_program_load(spe_context_ptr_t spectx, 
spe_program_handle_t *program);
 
 /**
+ * Check if the emulated loader is present in the filesystem
+ * @return Non-zero if the loader is available, otherwise zero.
+ */
+int _base_spe_emulated_loader_present(void);
+
+/**
  * _base_spe_context_destroy cleans up what is left when an SPE 
executable has exited. 
  * Closes open file handles and unmaps memory areas.
  * 
Index: libspe2/spebase/run.c
===================================================================
--- libspe2.orig/spebase/run.c
+++ libspe2/spebase/run.c
@@ -102,7 +102,7 @@ int _base_spe_context_run(spe_context_pt
                                 spe_stop_info_t *stopinfo)
 {
                 int retval = 0, run_rc;
-                unsigned int run_status;
+                unsigned int run_status, tmp_entry;
                 spe_stop_info_t                 stopinfo_buf;
                 struct spe_context_info this_context_info 
__attribute__((cleanup(cleanupspeinfo)));
 
@@ -111,13 +111,20 @@ int _base_spe_context_run(spe_context_pt
                 if (!stopinfo)
                                 stopinfo = &stopinfo_buf;
 
-                if (*entry == SPE_DEFAULT_ENTRY)
-                                *entry = spe->base_private->entry;
+
+                /* In emulated isolated mode, the npc will always return 
as zero.
+                 * use our private entry point instead */
+                if (spe->base_private->flags & SPE_ISOLATE_EMULATE)
+                                tmp_entry = 
spe->base_private->emulated_entry;
+
+                else if (*entry == SPE_DEFAULT_ENTRY)
+                                tmp_entry = spe->base_private->entry;
 
                 /* If we're starting the SPE binary from its original 
entry point,
                  * setup the arguments to main() */
-                if (*entry == spe->base_private->entry &&
- !(spe->base_private->flags & SPE_ISOLATE)) {
+                if (tmp_entry == spe->base_private->entry &&
+ !(spe->base_private->flags &
+ (SPE_ISOLATE | SPE_ISOLATE_EMULATE))) {
 
                                 addr64 argp64, envp64, tid64, ls64;
                                 unsigned int regs[128][4];
@@ -179,23 +186,32 @@ int _base_spe_context_run(spe_context_pt
 
 do_run:
                 /*Remember the npc value*/
-                __spe_current_active_context->npc = *entry;
+                __spe_current_active_context->npc = tmp_entry;
 
                 /* run SPE context */
-                run_rc = spu_run(spe->base_private->fd_spe_dir, entry, 
&run_status);
+                run_rc = spu_run(spe->base_private->fd_spe_dir,
+                                                &tmp_entry, &run_status);
 
                 /*Remember the npc value*/
-                __spe_current_active_context->npc = *entry;
+                __spe_current_active_context->npc = tmp_entry;
                 __spe_current_active_context->status = run_status;
 
                 DEBUG_PRINTF("spu_run returned run_rc=0x%08x, 
entry=0x%04x, "
-                                                "ext_status=0x%04x.\n", 
run_rc, *entry, run_status);
+                                                "ext_status=0x%04x.\n", 
run_rc, tmp_entry, run_status);
 
                 /* set up return values and stopinfo according to spu_run 
exit
                  * conditions. This is overwritten on error.
                  */
                 stopinfo->spu_status = run_rc;
 
+                if (spe->base_private->flags & SPE_ISOLATE_EMULATE) {
+                                /* save the entry point, and pretend that 
the npc is zero */
+                                spe->base_private->emulated_entry = 
tmp_entry;
+                                *entry = 0;
+                } else {
+                                *entry = tmp_entry;
+                }
+
                 /* Return with stopinfo set on syscall error paths */
                 if (run_rc == -1) {
                                 DEBUG_PRINTF("spu_run returned error %d, 
errno=%d\n",
@@ -265,7 +281,7 @@ do_run:
                                                 } else {
                                                                 /* 
successful library callback - restart the SPE
                                                                  * 
program at the next instruction */
-                                                                *entry += 
4;
+                                                                tmp_entry 
+= 4;
                                                                 goto 
do_run;
                                                 }
 
Index: libspe2/spebase/lib_builtin.c
===================================================================
--- libspe2.orig/spebase/lib_builtin.c
+++ libspe2/spebase/lib_builtin.c
@@ -150,6 +150,12 @@ int handle_library_callback(struct spe_c
 
                 handler=handlers[callnum];
 
+                /* For emulated isolation mode, position the
+                 * npc so that the buffer for the PPE-assisted
+                 * library calls can be accessed. */
+                if (spe->base_private->flags & SPE_ISOLATE_EMULATE)
+                                npc = SPE_EMULATE_PARAM_BUFFER;
+
                 rc = handler(spe->base_private->mem_mmap_base, npc);
                 if (rc) {
                                 DEBUG_PRINTF ("SPE library call 
unsupported.\n");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/cbe-oss-dev/attachments/20070628/5e75b7b9/attachment.htm>


More information about the cbe-oss-dev mailing list