[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