diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
index 000d394..ad8b3d3 100644
--- a/lib/ioctl_wrappers.c
+++ b/lib/ioctl_wrappers.c
@@ -964,6 +964,25 @@ bool gem_has_bsd2(int fd)
 {
 	return gem_has_enable_ring(fd,LOCAL_I915_PARAM_HAS_BSD2);
 }
+#define I915_PARAM_HAS_LEGACY_CONTEXT	 35
+bool drm_has_legacy_context(int fd)
+{
+	int tmp = 0;
+	drm_i915_getparam_t gp;
+
+	memset(&gp, 0, sizeof(gp));
+	gp.value = &tmp;
+	gp.param = I915_PARAM_HAS_LEGACY_CONTEXT;
+
+	/*
+	 * if legacy context param is not supported, then it's old and we
+	 * can assume that the HW_LOCKS are supported.
+	 */
+	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) != 0)
+		return true;
+
+	return tmp == 1;
+}
 /**
  * gem_available_aperture_size:
  * @fd: open i915 drm file descriptor
diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
index ced7ef3..3adc700 100644
--- a/lib/ioctl_wrappers.h
+++ b/lib/ioctl_wrappers.h
@@ -120,6 +120,7 @@ bool gem_has_bsd(int fd);
 bool gem_has_blt(int fd);
 bool gem_has_vebox(int fd);
 bool gem_has_bsd2(int fd);
+bool drm_has_legacy_context(int fd);
 bool gem_uses_aliasing_ppgtt(int fd);
 int gem_available_fences(int fd);
 uint64_t gem_available_aperture_size(int fd);
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 71de6de..2f69afc 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -84,6 +84,7 @@ TESTS_progs_M = \
 	pm_sseu \
 	prime_self_import \
 	template \
+	drm_hw_lock \
 	$(NULL)
 
 TESTS_progs = \
diff --git a/tests/drm_hw_lock.c b/tests/drm_hw_lock.c
new file mode 100644
index 0000000..aad50ba
--- /dev/null
+++ b/tests/drm_hw_lock.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright © 2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Peter Antoine <peter.antoine@intel.com>
+ */
+
+/*
+ * Testcase: Test the HW_LOCKs for correct support and non-crashing.
+ *
+ * This test will check that he hw_locks are only g_supported for drivers that
+ * require that support. If it is not g_supported then the functions all return
+ * the correct error code.
+ *
+ * If g_supported it will check that the functions do not crash when the crash
+ * tests are used, also that one of the tests is a security level escalation
+ * that should be rejected.
+ */
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <drm.h>
+#include "drmtest.h"
+#include "igt_core.h"
+#include "ioctl_wrappers.h"
+
+#ifndef DRM_KERNEL_CONTEXT
+#	define DRM_KERNEL_CONTEXT	(0)
+#endif
+
+#ifndef _DRM_LOCK_HELD
+#	define _DRM_LOCK_HELD	0x80000000U /**< Hardware lock is held */
+#endif
+
+#ifndef _DRM_LOCK_CONT
+#	define _DRM_LOCK_CONT	0x40000000U /**< Hardware lock is contended */
+#endif
+
+static bool	g_sig_fired;
+static bool	g_supported;
+static struct sigaction old_action;
+
+static void sig_term_handler(int value)
+{
+	g_sig_fired = true;
+}
+
+static bool set_term_handler(void)
+{
+	static struct sigaction new_action;
+
+	new_action.sa_handler = sig_term_handler;
+	sigemptyset(&new_action.sa_mask);
+	new_action.sa_flags = 0;
+
+	igt_assert(sigaction(SIGTERM, &new_action, &old_action) == 0);
+
+	if (old_action.sa_handler != SIG_IGN)
+		return true;
+	else
+		return false;
+}
+
+static void restore_term_handler(void)
+{
+	sigaction(SIGTERM, &old_action, NULL);
+}
+
+static void does_lock_crash(int fd)
+{
+	struct drm_lock	rubbish;
+	int ret;
+
+	memset(&rubbish, 'A', sizeof(struct drm_lock));
+
+	g_sig_fired = false;
+	igt_assert(set_term_handler());
+
+	ret = ioctl(fd, DRM_IOCTL_LOCK, &rubbish);
+
+	igt_assert(ret == -1 && (!g_supported || g_sig_fired));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	restore_term_handler();
+}
+
+static void does_unlock_crash(int fd)
+{
+	struct drm_lock	rubbish;
+	int ret;
+
+	g_sig_fired = false;
+	igt_assert(set_term_handler());
+
+	memset(&rubbish, 'A', sizeof(struct drm_lock));
+
+	ret = ioctl(fd, DRM_IOCTL_UNLOCK, &rubbish);
+
+	igt_assert(ret == -1 && (!g_supported || g_sig_fired));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	restore_term_handler();
+}
+
+static void priority_escalation(int fd)
+{
+	struct drm_lock	rubbish;
+	int ret;
+
+	g_sig_fired = false;
+	igt_assert(set_term_handler());
+
+	/* this should be rejected */
+	rubbish.context = DRM_KERNEL_CONTEXT;
+	ret = ioctl(fd, DRM_IOCTL_LOCK, &rubbish);
+	igt_assert(ret == -1 && (!g_supported || errno == EPERM));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	/* this should also be rejected */
+	rubbish.context = _DRM_LOCK_HELD | DRM_KERNEL_CONTEXT;
+	g_sig_fired = false;
+	ret = ioctl(fd, DRM_IOCTL_LOCK, &rubbish);
+	igt_assert(ret == -1 && (!g_supported || errno == EPERM));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	/* this should also be rejected */
+	rubbish.context = _DRM_LOCK_CONT | DRM_KERNEL_CONTEXT;
+	g_sig_fired = false;
+	ret = ioctl(fd, DRM_IOCTL_LOCK, &rubbish);
+	igt_assert(ret == -1 && (!g_supported || errno == EPERM));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	/* this should be rejected */
+	rubbish.context = DRM_KERNEL_CONTEXT;
+	g_sig_fired = false;
+	ret = ioctl(fd, DRM_IOCTL_UNLOCK, &rubbish);
+	igt_assert(ret == -1 && (!g_supported || errno == EPERM));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	/* this should also be rejected */
+	rubbish.context = _DRM_LOCK_HELD | DRM_KERNEL_CONTEXT;
+	g_sig_fired = false;
+	ret = ioctl(fd, DRM_IOCTL_UNLOCK, &rubbish);
+	igt_assert(ret == -1 && (!g_supported || errno == EPERM));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	/* this should also be rejected */
+	rubbish.context = _DRM_LOCK_CONT | DRM_KERNEL_CONTEXT;
+	g_sig_fired = false;
+	ret = ioctl(fd, DRM_IOCTL_UNLOCK, &rubbish);
+	igt_assert(ret == -1 && (!g_supported || errno == EPERM));
+	igt_assert(ret == -1 && (g_supported || errno == EINVAL));
+
+	restore_term_handler();
+}
+
+igt_main
+{
+	int fd = -1;
+
+	g_sig_fired = false;
+	g_supported = false;
+
+	igt_fixture {
+		fd = drm_open_any();
+		igt_assert(fd >= 0);
+	}
+
+	g_supported = drm_has_legacy_context(fd);
+
+	igt_info("HW LOCK Supported: %s\n", g_supported?"Yes":"No");
+
+	igt_subtest("lock-crash") {
+		does_lock_crash(fd);
+	}
+
+	igt_subtest("unlock-crash") {
+		does_unlock_crash(fd);
+	}
+
+	igt_subtest("priority-escalation") {
+		priority_escalation(fd);
+	}
+
+	igt_fixture
+		close(fd);
+}
+
