diff --git a/arch/x86/kernel/include/arch/shm.h b/arch/x86/kernel/include/arch/shm.h index 94c1f57e..20bbcafa 100644 --- a/arch/x86/kernel/include/arch/shm.h +++ b/arch/x86/kernel/include/arch/shm.h @@ -13,6 +13,11 @@ #ifndef HEADER_ARCH_SHM_H #define HEADER_ARCH_SHM_H +/* shmflg */ +#define SHM_HUGE_SHIFT 26 +#define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT) +#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT) + struct ipc_perm { key_t key; uid_t uid; diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 277a839a..7f78f708 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -1332,13 +1332,33 @@ SYSCALL_DECLARE(shmget) { const key_t key = ihk_mc_syscall_arg0(ctx); const size_t size = ihk_mc_syscall_arg1(ctx); - const int shmflg = ihk_mc_syscall_arg2(ctx); + const int shmflg0 = ihk_mc_syscall_arg2(ctx); int shmid; + int error; + int shmflg = shmflg0; - dkprintf("shmget(%#lx,%#lx,%#x)\n", key, size, shmflg); + dkprintf("shmget(%#lx,%#lx,%#x)\n", key, size, shmflg0); + + if (shmflg & SHM_HUGETLB) { + switch (shmflg & (0x3F << SHM_HUGE_SHIFT)) { + case 0: + shmflg |= SHM_HUGE_2MB; /* default hugepage size */ + break; + + case SHM_HUGE_2MB: + case SHM_HUGE_1GB: + break; + + default: + error = -EINVAL; + goto out; + } + } shmid = do_shmget(key, size, shmflg); - dkprintf("shmget(%#lx,%#lx,%#x): %d\n", key, size, shmflg, shmid); - return shmid; + error = 0; +out: + dkprintf("shmget(%#lx,%#lx,%#x): %d %d\n", key, size, shmflg0, error, shmid); + return (error)?: shmid; } /* sys_shmget() */ diff --git a/kernel/include/shm.h b/kernel/include/shm.h index 77c4e6cf..7532967a 100644 --- a/kernel/include/shm.h +++ b/kernel/include/shm.h @@ -25,6 +25,7 @@ enum { IPC_CREAT = 01000, IPC_EXCL = 02000, + SHM_HUGETLB = 04000, SHM_RDONLY = 010000, SHM_RND = 020000, SHM_REMAP = 040000, @@ -49,7 +50,7 @@ enum { struct shmobj { struct memobj memobj; /* must be first */ int index; - uint8_t padding[4]; + int pgshift; size_t real_segsz; struct shmid_ds ds; struct list_head page_list; diff --git a/kernel/shmobj.c b/kernel/shmobj.c index ae20dea2..251cd76c 100644 --- a/kernel/shmobj.c +++ b/kernel/shmobj.c @@ -136,6 +136,7 @@ int shmobj_create(struct shmid_ds *ds, struct memobj **objp) obj->ds.shm_perm.seq = the_seq++; obj->ds.shm_nattch = 1; obj->index = -1; + obj->pgshift = PAGE_SHIFT; obj->real_segsz = (obj->ds.shm_segsz + PAGE_SIZE - 1) & PAGE_MASK; page_list_init(obj); ihk_mc_spinlock_init(&obj->memobj.lock); diff --git a/kernel/syscall.c b/kernel/syscall.c index 6f3e88f6..d6aeee17 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -3536,6 +3536,7 @@ int do_shmget(const key_t key, const size_t size, const int shmflg) int error; struct shmid_ds ads; struct shmobj *obj; + int pgshift; dkprintf("do_shmget(%#lx,%#lx,%#x)\n", key, size, shmflg); @@ -3610,6 +3611,11 @@ int do_shmget(const key_t key, const size_t size, const int shmflg) return -ENOSPC; } + pgshift = PAGE_SHIFT; + if (shmflg & SHM_HUGETLB) { + pgshift = (shmflg >> SHM_HUGE_SHIFT) & 0x3F; + } + memset(&ads, 0, sizeof(ads)); ads.shm_perm.key = key; ads.shm_perm.uid = proc->euid; @@ -3629,6 +3635,7 @@ int do_shmget(const key_t key, const size_t size, const int shmflg) } obj->index = ++the_maxi; + obj->pgshift = pgshift; list_add(&obj->chain, &kds_list); ++the_shm_info.used_ids;