ARCH ?= $(shell uname -m 2>/dev/null || echo not)
 
 ifneq (,$(filter $(ARCH),riscv))
-RISCV_SUBTARGETS ?= hwprobe vector
+RISCV_SUBTARGETS ?= hwprobe vector mm
 else
 RISCV_SUBTARGETS :=
 endif
 
--- /dev/null
+mmap_bottomup
+mmap_default
 
--- /dev/null
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2021 ARM Limited
+# Originally tools/testing/arm64/abi/Makefile
+
+# Additional include paths needed by kselftest.h and local headers
+CFLAGS += -D_GNU_SOURCE -std=gnu99 -I.
+
+TEST_GEN_FILES := testcases/mmap_default testcases/mmap_bottomup
+
+TEST_PROGS := testcases/run_mmap.sh
+
+include ../../lib.mk
+
+$(OUTPUT)/mm: testcases/mmap_default.c testcases/mmap_bottomup.c testcases/mmap_tests.h
+       $(CC) -o$@ $(CFLAGS) $(LDFLAGS) $^
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+#include <sys/mman.h>
+#include <testcases/mmap_test.h>
+
+#include "../../kselftest_harness.h"
+
+TEST(infinite_rlimit)
+{
+// Only works on 64 bit
+#if __riscv_xlen == 64
+       struct addresses mmap_addresses;
+
+       EXPECT_EQ(BOTTOM_UP, memory_layout());
+
+       do_mmaps(&mmap_addresses);
+
+       EXPECT_NE(MAP_FAILED, mmap_addresses.no_hint);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_37_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_38_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_46_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_47_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_55_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_56_addr);
+
+       EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.no_hint);
+       EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_37_addr);
+       EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_38_addr);
+       EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_46_addr);
+       EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_47_addr);
+       EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_55_addr);
+       EXPECT_GT(1UL << 56, (unsigned long)mmap_addresses.on_56_addr);
+#endif
+}
+
+TEST_HARNESS_MAIN
 
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+#include <sys/mman.h>
+#include <testcases/mmap_test.h>
+
+#include "../../kselftest_harness.h"
+
+TEST(default_rlimit)
+{
+// Only works on 64 bit
+#if __riscv_xlen == 64
+       struct addresses mmap_addresses;
+
+       EXPECT_EQ(TOP_DOWN, memory_layout());
+
+       do_mmaps(&mmap_addresses);
+
+       EXPECT_NE(MAP_FAILED, mmap_addresses.no_hint);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_37_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_38_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_46_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_47_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_55_addr);
+       EXPECT_NE(MAP_FAILED, mmap_addresses.on_56_addr);
+
+       EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.no_hint);
+       EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_37_addr);
+       EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_38_addr);
+       EXPECT_GT(1UL << 38, (unsigned long)mmap_addresses.on_46_addr);
+       EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_47_addr);
+       EXPECT_GT(1UL << 47, (unsigned long)mmap_addresses.on_55_addr);
+       EXPECT_GT(1UL << 56, (unsigned long)mmap_addresses.on_56_addr);
+#endif
+}
+
+TEST_HARNESS_MAIN
 
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _TESTCASES_MMAP_TEST_H
+#define _TESTCASES_MMAP_TEST_H
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <stddef.h>
+
+#define TOP_DOWN 0
+#define BOTTOM_UP 1
+
+struct addresses {
+       int *no_hint;
+       int *on_37_addr;
+       int *on_38_addr;
+       int *on_46_addr;
+       int *on_47_addr;
+       int *on_55_addr;
+       int *on_56_addr;
+};
+
+static inline void do_mmaps(struct addresses *mmap_addresses)
+{
+       /*
+        * Place all of the hint addresses on the boundaries of mmap
+        * sv39, sv48, sv57
+        * User addresses end at 1<<38, 1<<47, 1<<56 respectively
+        */
+       void *on_37_bits = (void *)(1UL << 37);
+       void *on_38_bits = (void *)(1UL << 38);
+       void *on_46_bits = (void *)(1UL << 46);
+       void *on_47_bits = (void *)(1UL << 47);
+       void *on_55_bits = (void *)(1UL << 55);
+       void *on_56_bits = (void *)(1UL << 56);
+
+       int prot = PROT_READ | PROT_WRITE;
+       int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+
+       mmap_addresses->no_hint =
+               mmap(NULL, 5 * sizeof(int), prot, flags, 0, 0);
+       mmap_addresses->on_37_addr =
+               mmap(on_37_bits, 5 * sizeof(int), prot, flags, 0, 0);
+       mmap_addresses->on_38_addr =
+               mmap(on_38_bits, 5 * sizeof(int), prot, flags, 0, 0);
+       mmap_addresses->on_46_addr =
+               mmap(on_46_bits, 5 * sizeof(int), prot, flags, 0, 0);
+       mmap_addresses->on_47_addr =
+               mmap(on_47_bits, 5 * sizeof(int), prot, flags, 0, 0);
+       mmap_addresses->on_55_addr =
+               mmap(on_55_bits, 5 * sizeof(int), prot, flags, 0, 0);
+       mmap_addresses->on_56_addr =
+               mmap(on_56_bits, 5 * sizeof(int), prot, flags, 0, 0);
+}
+
+static inline int memory_layout(void)
+{
+       int prot = PROT_READ | PROT_WRITE;
+       int flags = MAP_PRIVATE | MAP_ANONYMOUS;
+
+       void *value1 = mmap(NULL, sizeof(int), prot, flags, 0, 0);
+       void *value2 = mmap(NULL, sizeof(int), prot, flags, 0, 0);
+
+       return value2 > value1;
+}
+#endif /* _TESTCASES_MMAP_TEST_H */
 
--- /dev/null
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+original_stack_limit=$(ulimit -s)
+
+./mmap_default
+
+# Force mmap_bottomup to be ran with bottomup memory due to
+# the unlimited stack
+ulimit -s unlimited
+./mmap_bottomup
+ulimit -s $original_stack_limit