diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h
index 6ea8cf0..e9d03bb 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -61,7 +61,6 @@ enum init_stage {
 	SYSINFO_INIT,
 	FDSERVER_INIT,
 	ISHM_INIT,
-	SHM_INIT,
 	THREAD_INIT,
 	POOL_INIT,
 	QUEUE_INIT,
@@ -91,10 +90,6 @@ int odp_thread_init_local(odp_thread_type_t type);
 int odp_thread_term_local(void);
 int odp_thread_term_global(void);
 
-int odp_shm_init_global(void);
-int odp_shm_term_global(void);
-int odp_shm_init_local(void);
-
 int odp_pool_init_global(void);
 int odp_pool_init_local(void);
 int odp_pool_term_global(void);
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index d33a3ae..90662c6 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -63,12 +63,6 @@ int odp_init_global(odp_instance_t *instance,
 	}
 	stage = ISHM_INIT;
 
-	if (odp_shm_init_global()) {
-		ODP_ERR("ODP shm init failed.\n");
-		goto init_failed;
-	}
-	stage = SHM_INIT;
-
 	if (odp_thread_init_global()) {
 		ODP_ERR("ODP thread init failed.\n");
 		goto init_failed;
@@ -223,13 +217,6 @@ int _odp_term_global(enum init_stage stage)
 		}
 		/* Fall through */
 
-	case SHM_INIT:
-		if (odp_shm_term_global()) {
-			ODP_ERR("ODP shm term failed.\n");
-			rc = -1;
-		}
-		/* Fall through */
-
 	case ISHM_INIT:
 		if (_odp_ishm_term_global()) {
 			ODP_ERR("ODP ishm term failed.\n");
@@ -287,12 +274,6 @@ int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
 	}
 	stage = ISHM_INIT;
 
-	if (odp_shm_init_local()) {
-		ODP_ERR("ODP shm local init failed.\n");
-		goto init_fail;
-	}
-	stage = SHM_INIT;
-
 	if (odp_thread_init_local(thr_type)) {
 		ODP_ERR("ODP thread local init failed.\n");
 		goto init_fail;
diff --git a/platform/linux-generic/odp_shared_memory.c b/platform/linux-generic/odp_shared_memory.c
index 550af27..609b324 100644
--- a/platform/linux-generic/odp_shared_memory.c
+++ b/platform/linux-generic/odp_shared_memory.c
@@ -4,434 +4,85 @@
  * SPDX-License-Identifier:     BSD-3-Clause
  */
 
-#include <odp_posix_extensions.h>
-
-#include <odp/api/shared_memory.h>
-#include <odp_internal.h>
-#include <odp/api/spinlock.h>
-#include <odp/api/align.h>
-#include <odp/api/system_info.h>
-#include <odp/api/debug.h>
-#include <odp_shm_internal.h>
-#include <odp_debug_internal.h>
-#include <odp_align_internal.h>
 #include <odp_config_internal.h>
-
-#include <unistd.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <asm/mman.h>
-#include <fcntl.h>
-
-#include <stdio.h>
+#include <odp/api/debug.h>
+#include <odp/api/std_types.h>
+#include <odp/api/shared_memory.h>
+#include <_ishm_internal.h>
 #include <string.h>
-#include <errno.h>
-#include <inttypes.h>
 
 ODP_STATIC_ASSERT(ODP_CONFIG_SHM_BLOCKS >= ODP_CONFIG_POOLS,
 		  "ODP_CONFIG_SHM_BLOCKS < ODP_CONFIG_POOLS");
 
-typedef struct {
-	char      name[ODP_SHM_NAME_LEN];
-	uint64_t  size;
-	uint64_t  align;
-	uint64_t  alloc_size;
-	void      *addr_orig;
-	void      *addr;
-	int       huge;
-	odp_shm_t hdl;
-	uint32_t  flags;
-	uint64_t  page_sz;
-	int       fd;
-
-} odp_shm_block_t;
-
-
-typedef struct {
-	odp_shm_block_t block[ODP_CONFIG_SHM_BLOCKS];
-	odp_spinlock_t  lock;
-
-} odp_shm_table_t;
-
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-
-/* Global shared memory table */
-static odp_shm_table_t *odp_shm_tbl;
-
-
 static inline uint32_t from_handle(odp_shm_t shm)
 {
 	return _odp_typeval(shm) - 1;
 }
 
-
 static inline odp_shm_t to_handle(uint32_t index)
 {
 	return _odp_cast_scalar(odp_shm_t, index + 1);
 }
 
-
-int odp_shm_init_global(void)
-{
-	void *addr;
-
-#ifndef MAP_HUGETLB
-	ODP_DBG("NOTE: mmap does not support huge pages\n");
-#endif
-
-	addr = mmap(NULL, sizeof(odp_shm_table_t),
-		    PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
-
-	if (addr == MAP_FAILED)
-		return -1;
-
-	odp_shm_tbl = addr;
-
-	memset(odp_shm_tbl, 0, sizeof(odp_shm_table_t));
-	odp_spinlock_init(&odp_shm_tbl->lock);
-
-	return 0;
-}
-
-int odp_shm_term_global(void)
-{
-	int ret;
-
-	ret = munmap(odp_shm_tbl, sizeof(odp_shm_table_t));
-	if (ret)
-		ODP_ERR("unable to munmap\n.");
-
-	return ret;
-}
-
-
-int odp_shm_init_local(void)
-{
-	return 0;
-}
-
 int odp_shm_capability(odp_shm_capability_t *capa)
 {
 	memset(capa, 0, sizeof(odp_shm_capability_t));
 
 	capa->max_blocks = ODP_CONFIG_SHM_BLOCKS;
-	capa->max_size   = 0;
-	capa->max_align  = 0;
-
-	return 0;
-}
-
-static int find_block(const char *name, uint32_t *index)
-{
-	uint32_t i;
-
-	for (i = 0; i < ODP_CONFIG_SHM_BLOCKS; i++) {
-		if (strcmp(name, odp_shm_tbl->block[i].name) == 0) {
-			/* found it */
-			if (index != NULL)
-				*index = i;
-
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-int odp_shm_free(odp_shm_t shm)
-{
-	uint32_t i;
-	int ret;
-	odp_shm_block_t *block;
-	char shm_devname[SHM_DEVNAME_MAXLEN];
+	capa->max_size = 0;
+	capa->max_align = 0;
 
-	if (shm == ODP_SHM_INVALID) {
-		ODP_DBG("odp_shm_free: Invalid handle\n");
-		return -1;
-	}
-
-	i = from_handle(shm);
-
-	if (i >= ODP_CONFIG_SHM_BLOCKS) {
-		ODP_DBG("odp_shm_free: Bad handle\n");
-		return -1;
-	}
-
-	odp_spinlock_lock(&odp_shm_tbl->lock);
-
-	block = &odp_shm_tbl->block[i];
-
-	if (block->addr == NULL) {
-		ODP_DBG("odp_shm_free: Free block\n");
-		odp_spinlock_unlock(&odp_shm_tbl->lock);
-		return 0;
-	}
-
-	ret = munmap(block->addr_orig, block->alloc_size);
-	if (0 != ret) {
-		ODP_DBG("odp_shm_free: munmap failed: %s, id %u, addr %p\n",
-			strerror(errno), i, block->addr_orig);
-		odp_spinlock_unlock(&odp_shm_tbl->lock);
-		return -1;
-	}
-
-	if (block->flags & ODP_SHM_PROC || block->flags & _ODP_SHM_PROC_NOCREAT) {
-		int shm_ns_id;
-
-		if (odp_global_data.ipc_ns)
-			shm_ns_id = odp_global_data.ipc_ns;
-		else
-			shm_ns_id = odp_global_data.main_pid;
-
-		snprintf(shm_devname, SHM_DEVNAME_MAXLEN,
-			 SHM_DEVNAME_FORMAT, shm_ns_id, block->name);
-		ret = shm_unlink(shm_devname);
-		if (0 != ret) {
-			ODP_DBG("odp_shm_free: shm_unlink failed\n");
-			odp_spinlock_unlock(&odp_shm_tbl->lock);
-			return -1;
-		}
-	}
-	memset(block, 0, sizeof(odp_shm_block_t));
-	odp_spinlock_unlock(&odp_shm_tbl->lock);
 	return 0;
 }
 
 odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align,
 			  uint32_t flags)
 {
-	uint32_t i;
-	char shm_devname[SHM_DEVNAME_MAXLEN];
-	odp_shm_block_t *block;
-	void *addr;
-	int fd = -1;
-	int map_flag = MAP_SHARED;
-	/* If already exists: O_EXCL: error, O_TRUNC: truncate to zero */
-	int oflag = O_RDWR;
-	uint64_t alloc_size;
-	uint64_t page_sz, huge_sz;
-#ifdef MAP_HUGETLB
-	int need_huge_page = 0;
-	uint64_t alloc_hp_size;
-#endif
-
-	page_sz = odp_sys_page_size();
-	alloc_size = size + align;
-
-#ifdef MAP_HUGETLB
-	huge_sz = odp_sys_huge_page_size();
-	need_huge_page =  (huge_sz && alloc_size > page_sz);
-	/* munmap for huge pages requires sizes round up by page */
-	alloc_hp_size = (size + align + (huge_sz - 1)) & (-huge_sz);
-#endif
+	int block_index;
+	int flgs = 0; /* internal ishm flags */
 
-	if (flags & ODP_SHM_PROC)
-		oflag |= O_CREAT | O_TRUNC;
-	if (flags & _ODP_SHM_O_EXCL)
-		oflag |= O_EXCL;
+	/* set internal ishm flags according to API flags: */
+	flgs |= (flags & ODP_SHM_PROC) ? _ODP_ISHM_LINK : 0;
 
-	if (flags & (ODP_SHM_PROC | _ODP_SHM_PROC_NOCREAT)) {
-		int shm_ns_id;
-
-		if (odp_global_data.ipc_ns)
-			shm_ns_id = odp_global_data.ipc_ns;
-		else
-			shm_ns_id = odp_global_data.main_pid;
-
-		need_huge_page = 0;
-
-		/* Creates a file to /dev/shm/odp */
-		snprintf(shm_devname, SHM_DEVNAME_MAXLEN,
-			 SHM_DEVNAME_FORMAT, shm_ns_id, name);
-		fd = shm_open(shm_devname, oflag,
-			      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-		if (fd == -1) {
-			ODP_DBG("%s: shm_open failed.\n", shm_devname);
-			return ODP_SHM_INVALID;
-		}
-	} else {
-		map_flag |= MAP_ANONYMOUS;
-	}
-
-	odp_spinlock_lock(&odp_shm_tbl->lock);
-
-	if (find_block(name, NULL)) {
-		/* Found a block with the same name */
-		odp_spinlock_unlock(&odp_shm_tbl->lock);
-		ODP_DBG("name \"%s\" already used.\n", name);
+	block_index = _odp_ishm_reserve(name, size, -1, align, flgs, flags);
+	if (block_index >= 0)
+		return to_handle(block_index);
+	else
 		return ODP_SHM_INVALID;
-	}
-
-	for (i = 0; i < ODP_CONFIG_SHM_BLOCKS; i++) {
-		if (odp_shm_tbl->block[i].addr == NULL) {
-			/* Found free block */
-			break;
-		}
-	}
-
-	if (i > ODP_CONFIG_SHM_BLOCKS - 1) {
-		/* Table full */
-		odp_spinlock_unlock(&odp_shm_tbl->lock);
-		ODP_DBG("%s: no more blocks.\n", name);
-		return ODP_SHM_INVALID;
-	}
-
-	block = &odp_shm_tbl->block[i];
-
-	block->hdl  = to_handle(i);
-	addr        = MAP_FAILED;
-
-#ifdef MAP_HUGETLB
-	/* Try first huge pages */
-	if (need_huge_page) {
-		if ((flags & ODP_SHM_PROC) &&
-		    (ftruncate(fd, alloc_hp_size) == -1)) {
-			odp_spinlock_unlock(&odp_shm_tbl->lock);
-			ODP_DBG("%s: ftruncate huge pages failed.\n", name);
-			return ODP_SHM_INVALID;
-		}
-
-		addr = mmap(NULL, alloc_hp_size, PROT_READ | PROT_WRITE,
-				map_flag | MAP_HUGETLB, fd, 0);
-		if (addr == MAP_FAILED) {
-			ODP_DBG(" %s:\n"
-				"\tNo huge pages, fall back to normal pages,\n"
-				"\tcheck: /proc/sys/vm/nr_hugepages.\n", name);
-		} else {
-			block->alloc_size = alloc_hp_size;
-			block->huge = 1;
-			block->page_sz = huge_sz;
-		}
-	}
-#endif
-
-	/* Use normal pages for small or failed huge page allocations */
-	if (addr == MAP_FAILED) {
-		if ((flags & ODP_SHM_PROC) &&
-		    (ftruncate(fd, alloc_size) == -1)) {
-			odp_spinlock_unlock(&odp_shm_tbl->lock);
-			ODP_ERR("%s: ftruncate failed.\n", name);
-			return ODP_SHM_INVALID;
-		}
-
-		addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
-				map_flag, fd, 0);
-		if (addr == MAP_FAILED) {
-			odp_spinlock_unlock(&odp_shm_tbl->lock);
-			ODP_DBG("%s mmap failed.\n", name);
-			return ODP_SHM_INVALID;
-		} else {
-			block->alloc_size = alloc_size;
-			block->huge = 0;
-			block->page_sz = page_sz;
-		}
-	}
-
-	block->addr_orig = addr;
-
-	/* move to correct alignment */
-	addr = ODP_ALIGN_ROUNDUP_PTR(addr, align);
-
-	strncpy(block->name, name, ODP_SHM_NAME_LEN - 1);
-	block->name[ODP_SHM_NAME_LEN - 1] = 0;
-	block->size       = size;
-	block->align      = align;
-	block->flags      = flags;
-	block->fd         = fd;
-	block->addr       = addr;
+}
 
-	odp_spinlock_unlock(&odp_shm_tbl->lock);
-	return block->hdl;
+int odp_shm_free(odp_shm_t shm)
+{
+	return _odp_ishm_free_by_index(from_handle(shm));
 }
 
 odp_shm_t odp_shm_lookup(const char *name)
 {
-	uint32_t i;
-	odp_shm_t hdl;
-
-	odp_spinlock_lock(&odp_shm_tbl->lock);
-
-	if (find_block(name, &i) == 0) {
-		odp_spinlock_unlock(&odp_shm_tbl->lock);
-		return ODP_SHM_INVALID;
-	}
-
-	hdl = odp_shm_tbl->block[i].hdl;
-	odp_spinlock_unlock(&odp_shm_tbl->lock);
-
-	return hdl;
+	return to_handle(_odp_ishm_lookup_by_name(name));
 }
 
-
 void *odp_shm_addr(odp_shm_t shm)
 {
-	uint32_t i;
-
-	i = from_handle(shm);
-
-	if (i > (ODP_CONFIG_SHM_BLOCKS - 1))
-		return NULL;
-
-	return odp_shm_tbl->block[i].addr;
+	return _odp_ishm_address(from_handle(shm));
 }
 
-
 int odp_shm_info(odp_shm_t shm, odp_shm_info_t *info)
 {
-	odp_shm_block_t *block;
-	uint32_t i;
+	_odp_ishm_info_t ishm_info;
 
-	i = from_handle(shm);
-
-	if (i > (ODP_CONFIG_SHM_BLOCKS - 1))
+	if (_odp_ishm_info(from_handle(shm), &ishm_info))
 		return -1;
 
-	block = &odp_shm_tbl->block[i];
-
-	info->name      = block->name;
-	info->addr      = block->addr;
-	info->size      = block->size;
-	info->page_size = block->page_sz;
-	info->flags     = block->flags;
+	info->name = ishm_info.name;
+	info->addr = ishm_info.addr;
+	info->size = ishm_info.size;
+	info->page_size = ishm_info.page_size;
+	info->flags = ishm_info.user_flags;
 
 	return 0;
 }
 
-
 void odp_shm_print_all(void)
 {
-	int i;
-
-	ODP_PRINT("\nShared memory\n");
-	ODP_PRINT("--------------\n");
-	ODP_PRINT("  page size:      %"PRIu64" kB\n",
-		  odp_sys_page_size() / 1024);
-	ODP_PRINT("  huge page size: %"PRIu64" kB\n",
-		  odp_sys_huge_page_size() / 1024);
-	ODP_PRINT("\n");
-
-	ODP_PRINT("  id name                       kB align huge addr\n");
-
-	for (i = 0; i < ODP_CONFIG_SHM_BLOCKS; i++) {
-		odp_shm_block_t *block;
-
-		block = &odp_shm_tbl->block[i];
-
-		if (block->addr) {
-			ODP_PRINT("  %2i %-24s %4"PRIu64"  %4"PRIu64
-				  " %2c   %p\n",
-				  i,
-				  block->name,
-				  block->size/1024,
-				  block->align,
-				  (block->huge ? '*' : ' '),
-				  block->addr);
-		}
-	}
-
-	ODP_PRINT("\n");
+	_odp_ishm_status("Memory allocation status:");
 }
diff --git a/test/linux-generic/validation/api/shmem/shmem_linux.c b/test/linux-generic/validation/api/shmem/shmem_linux.c
index 212a6c1..7e2ff04 100644
--- a/test/linux-generic/validation/api/shmem/shmem_linux.c
+++ b/test/linux-generic/validation/api/shmem/shmem_linux.c
@@ -48,9 +48,9 @@
 #include "shmem_linux.h"
 #include "shmem_common.h"
 
-#define ODP_APP_NAME "shmem_odp" /* name of the odp program, in this dir */
-#define DEVNAME_FMT "odp-%d-%s"  /* shm device format: odp-<pid>-<name>  */
-#define MAX_FIFO_WAIT 30         /* Max time waiting for the fifo (sec)  */
+#define ODP_APP_NAME "shmem_odp" /* name of the odp program, in this dir     */
+#define DEVNAME_FMT "/tmp/odp-%d-shm-%s"  /* shm link: odp-<pid>-shm-<name>  */
+#define MAX_FIFO_WAIT 30         /* Max time waiting for the fifo (sec)      */
 
 void test_success(char *fifo_name, int fd, pid_t odp_app)
 {
@@ -134,23 +134,20 @@ int main(int argc __attribute__((unused)), char *argv[])
 
 	/* O_CREAT flag not given => failure if shm_devname does not already
 	 * exist */
-	shm_fd = shm_open(shm_devname, O_RDONLY,
-			  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+	shm_fd = open(shm_devname, O_RDONLY,
+		      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 	if (shm_fd == -1)
 		test_failure(fifo_name, shm_fd, odp_app);
 
-	/* we know that the linux generic ODP actually allocates the required
-	 * size + alignment and aligns the returned address after.
-	 * we must do the same here: */
-	size = sizeof(test_shared_linux_data_t) + ALIGN_SIZE;
+	/* linux ODP guarantees page size alignement. Larger alignment may
+	 * fail as 2 different processes will have fully unrelated
+	 * virtual spaces.
+	 */
+	size = sizeof(test_shared_linux_data_t);
 	addr = mmap(NULL, size, PROT_READ, MAP_SHARED, shm_fd, 0);
 	if (addr == MAP_FAILED)
 		test_failure(fifo_name, shm_fd, odp_app);
 
-	/* perform manual alignment */
-	addr = (test_shared_linux_data_t *)((((unsigned long int)addr +
-				 ALIGN_SIZE - 1) / ALIGN_SIZE) * ALIGN_SIZE);
-
 	/* check that we see what the ODP application wrote in the memory */
 	if ((addr->foo == TEST_SHARE_FOO) && (addr->bar == TEST_SHARE_BAR))
 		test_success(fifo_name, fifo_fd, odp_app);
