diff --git a/Documentation/lkl.txt b/Documentation/lkl.txt
index c9e30f7455c86e..4da91f11d7f995 100644
--- a/Documentation/lkl.txt
+++ b/Documentation/lkl.txt
@@ -19,6 +19,21 @@ LKL is implemented as an architecture port in arch/lkl. It uses host operations
 defined by the application or a host library (tools/lkl/lib).
 
 
+Building LKL on FreeBSD
+-----------------------
+
+$ pkg install binutils gcc49
+
+If you don't have a gcc binary:
+$ ln -sf /usr/local/bin/gcc49 /usr/local/bin/gcc
+
+Prefer ports binutils:
+$ export PATH=/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/lib64/ccache
+
+$ cd tools/lkl
+$ gmake
+
+
 Building LKL the host library and LKL applications
 --------------------------------------------------
 
diff --git a/arch/lkl/Kconfig b/arch/lkl/Kconfig
index 567533bd0004c2..77fe2e3c2b7f2a 100644
--- a/arch/lkl/Kconfig
+++ b/arch/lkl/Kconfig
@@ -19,6 +19,7 @@ config LKL
        select PHYS_ADDR_T_64BIT if 64BIT
        select 64BIT if OUTPUT_FORMAT = "elf64-x86-64"
        select HAVE_UNDERSCORE_SYMBOL_PREFIX if OUTPUT_FORMAT = "pe-i386"
+       select 64BIT if OUTPUT_FORMAT = "elf64-x86-64-freebsd"
 
 config OUTPUTFORMAT
        string
diff --git a/arch/lkl/Makefile b/arch/lkl/Makefile
index 51ad096f6ee99a..9b23c736fd9c35 100644
--- a/arch/lkl/Makefile
+++ b/arch/lkl/Makefile
@@ -2,12 +2,20 @@ include arch/lkl/auto.conf
 
 KBUILD_CFLAGS += -fno-builtin
 
-ifeq ($(OUTPUT_FORMAT),elf64-x86-64)
+ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64 elf64-x86-64-freebsd))
 KBUILD_CFLAGS += -fPIC
 else ifeq ($(OUTPUT_FORMAT),pe-i386)
 prefix=_
 # workaround for #include_next<stdarg.h> errors
 LINUXINCLUDE := -isystem arch/lkl/include/system $(LINUXINCLUDE)
+else
+$(error Unrecognized platform: $(OUTPUT_FORMAT))
+endif
+
+ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64-freebsd))
+NPROC=$(shell sysctl -n hw.ncpu)
+else
+NPROC=$(shell nproc)
 endif
 
 LDFLAGS_vmlinux += -r
@@ -22,10 +30,10 @@ lkl.o: vmlinux
 	$(OBJCOPY) $(foreach sym,$(LKL_ENTRY_POINTS),-G$(prefix)$(sym)) vmlinux lkl.o
 
 install: lkl.o __headers
-	@echo "  INSTALL\t$(INSTALL_PATH)/lib/lkl.o"
+	@echo "  INSTALL	$(INSTALL_PATH)/lib/lkl.o"
 	@cp lkl.o $(INSTALL_PATH)/lib/
 	@arch/lkl/scripts/headers_install.py \
-		$(subst -j,-j$(shell nproc),$(findstring -j,$(MAKEFLAGS))) \
+		$(subst -j,-j$(NPROC),$(findstring -j,$(MAKEFLAGS))) \
 		$(INSTALL_PATH)/include
 
 archclean:
diff --git a/arch/lkl/include/uapi/asm/unistd.h b/arch/lkl/include/uapi/asm/unistd.h
index b2e89f198e32e1..224a4c08df046f 100644
--- a/arch/lkl/include/uapi/asm/unistd.h
+++ b/arch/lkl/include/uapi/asm/unistd.h
@@ -240,7 +240,8 @@ LKL_SYSCALL4(fstatat64, unsigned int, dfd, const char *, filname,
 	     struct lkl_stat64 *, statbuf, int, flag);
 LKL_SYSCALL2(stat64, const char *, filename, struct lkl_stat64 *, statbuf);
 LKL_SYSCALL2(lstat64, const char *, filename, struct lkl_stat64 *, statbuf);
-LKL_SYSCALL2(statfs64, const char *, path, struct lkl_statfs64 *, buf);
+LKL_SYSCALL3(statfs64, const char *, path, __lkl__kernel_size_t, sz,
+	     struct lkl_statfs64 *, buf);
 LKL_SYSCALL3(readlink, const char *, path, char *, buf, int, bufsiz);
 LKL_SYSCALL3(listxattr, const char *, path, char *, list, int, bufsiz);
 LKL_SYSCALL3(llistxattr, const char *, path, char *, list, int, bufsiz);
diff --git a/arch/lkl/scripts/headers_install.py b/arch/lkl/scripts/headers_install.py
index eb69a5e4098d86..cada8e9c66ba8b 100755
--- a/arch/lkl/scripts/headers_install.py
+++ b/arch/lkl/scripts/headers_install.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 import re, os, sys, argparse, multiprocessing
 
 header_paths = [ "include/uapi/", "arch/lkl/include/uapi/",
diff --git a/tools/lkl/Makefile b/tools/lkl/Makefile
index 1a53e74d3beb9f..6b50988d701e91 100644
--- a/tools/lkl/Makefile
+++ b/tools/lkl/Makefile
@@ -1,35 +1,42 @@
-CFLAGS := -Iinclude -Wall -g
+CFLAGS := -Iinclude -Wall -g -O2 -Wextra -Wno-unused-parameter \
+	  -Wno-missing-field-initializers -fno-strict-aliasing
 
 ifdef CROSS_COMPILE
 CC=$(CROSS_COMPILE)gcc
 AR=$(CROSS_COMPILE)ar
 LD=$(CROSS_COMPILE)ld
+else
+CC=gcc
 endif
 
+OUTPUT_FORMAT=$(shell $(LD) -r -print-output-format)
+
 lib_source = $(filter-out %-host.c,$(wildcard lib/*.c))
 source = $(wildcard tests/*.c)
-ifneq (,$(filter $(shell $(LD) -r -print-output-format),elf64-x86-64 elf32-i386))
+ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64 elf32-i386 elf64-x86-64-freebsd))
 source += $(wildcard *.c)
 lib_source += lib/posix-host.c
 LDFLAGS += -lpthread -lrt
 source += $(wildcard *.c)
 execs =  cpfromfs
-else ifeq ($(shell $(LD) -r -print-output-format),pe-i386)
+else ifeq ($(OUTPUT_FORMAT),pe-i386)
 lib_source += lib/nt-host.c
 KOPT="KALLSYMS_EXTRA_PASS=1"
+else
+$(error Unrecognized platform: $(OUTPUT_FORMAT))
 endif
 
-ifeq ($(shell $(LD) -r -print-output-format),elf64-x86-64)
+ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64 elf64-x86-64-freebsd))
 CFLAGS += -D_FILE_OFFSET_BITS=64
 endif
 
-lib_objs = $(patsubst %.c,%.o, $(lib_source)) lib/lkl.o
+lib_objs = $(patsubst %.c,%.o, $(lib_source))
 objs = $(patsubst %.c,%.o, $(source))
 execs += $(patsubst %.c,%, $(source))
 
 all: lib/liblkl.a $(execs)
 
-lib/liblkl.a: $(lib_objs)
+lib/liblkl.a: $(lib_objs) lib/lkl.o
 	$(AR) -rc $@ $^
 
 lib/lkl.o:
@@ -44,9 +51,14 @@ $(objs): lib/lkl.o
 $(execs): lib/liblkl.a
 
 clean:
-	-rm -rf include/lkl/ lib/liblkl.a $(lib_objs) $(objs) $(execs)
+	-rm -rf include/lkl/ lib/liblkl.a $(lib_objs) lib/lkl.o $(objs) $(execs)
+	$(MAKE) -C ../.. ARCH=lkl clean
 
 fs2tar: LDFLAGS += -larchive
 lklfuse: LDFLAGS += -lfuse
+ifneq (,$(filter $(OUTPUT_FORMAT),elf64-x86-64-freebsd))
+cptofs: LDFLAGS += -largp
+fs2tar: LDFLAGS += -largp
+endif
 cpfromfs: cptofs
 	if ! [ -e $@ ]; then ln -s $< $@; fi
diff --git a/tools/lkl/cptofs.c b/tools/lkl/cptofs.c
index 0017395eacf119..051e1e961076ed 100644
--- a/tools/lkl/cptofs.c
+++ b/tools/lkl/cptofs.c
@@ -1,3 +1,7 @@
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#endif
+
 #include <stdio.h>
 #include <time.h>
 #include <argp.h>
@@ -425,11 +429,12 @@ int main(int argc, char **argv)
 		goto out;
 	}
 
-	disk_id = lkl_disk_add(bs);
-	if (disk_id < 0) {
+	ret = lkl_disk_add(bs);
+	if (ret < 0) {
 		fprintf(stderr, "can't add disk: %s\n", lkl_strerror(ret));
 		goto out_close;
 	}
+	disk_id = ret;
 
 	lkl_start_kernel(&lkl_host_ops, 100 * 1024 * 1024, "");
 
diff --git a/tools/lkl/fs2tar.c b/tools/lkl/fs2tar.c
index b74da6628fd85f..02f5ba75e0347b 100644
--- a/tools/lkl/fs2tar.c
+++ b/tools/lkl/fs2tar.c
@@ -1,3 +1,7 @@
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#endif
+
 #include <stdio.h>
 #include <time.h>
 #include <argp.h>
@@ -351,11 +355,12 @@ int main(int argc, char **argv)
 		goto out;
 	}
 
-	disk_id = lkl_disk_add(bs);
-	if (disk_id < 0) {
+	ret = lkl_disk_add(bs);
+	if (ret < 0) {
 		fprintf(stderr, "can't add disk: %s\n", lkl_strerror(ret));
 		goto out_close;
 	}
+	disk_id = ret;
 
 	lkl_start_kernel(&lkl_host_ops, 10 * 1024 * 1024, "");
 
diff --git a/tools/lkl/include/lkl.h b/tools/lkl/include/lkl.h
index 220235b14bc3a1..a59c872fa4c613 100644
--- a/tools/lkl/include/lkl.h
+++ b/tools/lkl/include/lkl.h
@@ -57,7 +57,7 @@ int lkl_disk_add(union lkl_disk_backstore backstore);
  * @returns - 0 on success, a negative value on error
  */
 long lkl_mount_dev(unsigned int disk_id, const char *fs_type, int flags,
-		   void *data, char *mnt_str, int mnt_str_len);
+		   void *data, char *mnt_str, unsigned int mnt_str_len);
 
 /**
  * lkl_umount_dev - umount a disk
diff --git a/tools/lkl/lib/fs.c b/tools/lkl/lib/fs.c
index d09ae061a60abc..70e55f17da90ad 100644
--- a/tools/lkl/lib/fs.c
+++ b/tools/lkl/lib/fs.c
@@ -63,13 +63,13 @@ static long get_virtio_blkdev(int disk_id)
 }
 
 long lkl_mount_dev(unsigned int disk_id, const char *fs_type, int flags,
-		   void *data, char *mnt_str, int mnt_str_len)
+		   void *data, char *mnt_str, unsigned int mnt_str_len)
 {
 	char dev_str[] = { "/dev/xxxxxxxx" };
 	unsigned int dev;
 	int err;
 
-	if (mnt_str_len < sizeof("/mnt/xxxxxxxx"))
+	if (mnt_str_len < sizeof(dev_str))
 		return -LKL_ENOMEM;
 
 	dev = get_virtio_blkdev(disk_id);
diff --git a/tools/lkl/lib/posix-host.c b/tools/lkl/lib/posix-host.c
index 4bc1de70c3d715..71fa943bf206c5 100644
--- a/tools/lkl/lib/posix-host.c
+++ b/tools/lkl/lib/posix-host.c
@@ -1,5 +1,5 @@
 #include <pthread.h>
-#include <malloc.h>
+#include <stdlib.h>
 #include <sys/time.h>
 #include <time.h>
 #include <signal.h>
@@ -17,7 +17,9 @@
 
 static void print(const char *str, int len)
 {
-	write(STDOUT_FILENO, str, len);
+	int ret __attribute__((unused));
+
+	ret = write(STDOUT_FILENO, str, len);
 }
 
 struct pthread_sem {
@@ -187,7 +189,11 @@ void fd_do_rw(union lkl_disk_backstore bs, unsigned int type, unsigned int prio,
 		break;
 	case LKL_DEV_BLK_TYPE_FLUSH:
 	case LKL_DEV_BLK_TYPE_FLUSH_OUT:
+#ifdef __linux__
 		err = fdatasync(bs.fd);
+#else
+		err = fsync(bs.fd);
+#endif
 		break;
 	default:
 		lkl_dev_blk_complete(bufs, LKL_DEV_BLK_STATUS_UNSUP, 0);
diff --git a/tools/lkl/lib/utils.c b/tools/lkl/lib/utils.c
index f8b676f983037a..d6a76e69556bc1 100644
--- a/tools/lkl/lib/utils.c
+++ b/tools/lkl/lib/utils.c
@@ -144,7 +144,7 @@ const char *lkl_strerror(int err)
 	if (err < 0)
 		err = -err;
 
-	if (err >= sizeof(lkl_err_strings) / sizeof(const char *))
+	if ((size_t)err >= sizeof(lkl_err_strings) / sizeof(const char *))
 		return "Bad error code";
 
 	return lkl_err_strings[err];
diff --git a/tools/lkl/lib/virtio.c b/tools/lkl/lib/virtio.c
index 17522b2aeb106a..5b961ef5e2a93b 100644
--- a/tools/lkl/lib/virtio.c
+++ b/tools/lkl/lib/virtio.c
@@ -165,7 +165,6 @@ static int virtio_read(void *data, int offset, void *res, int size)
 {
 	uint32_t val;
 	struct virtio_dev *dev = (struct virtio_dev *)data;
-	int ret = 0;
 
 	if (offset >= VIRTIO_MMIO_CONFIG) {
 		offset -= VIRTIO_MMIO_CONFIG;
@@ -210,12 +209,12 @@ static int virtio_read(void *data, int offset, void *res, int size)
 		val = dev->config_gen;
 		break;
 	default:
-		ret = -1;
+		return -1;
 	}
 
 	*(uint32_t *)res = htole32(val);
 
-	return ret;
+	return 0;
 }
 
 static inline void set_ptr_low(void **ptr, uint32_t val)
diff --git a/tools/lkl/lib/virtio.h b/tools/lkl/lib/virtio.h
index b76b18b74ca560..4ca774ba26e2e1 100644
--- a/tools/lkl/lib/virtio.h
+++ b/tools/lkl/lib/virtio.h
@@ -82,13 +82,17 @@ void virtio_dev_complete(struct virtio_dev_req *req, uint32_t len);
 	(type *)((char *)(ptr) - __builtin_offsetof(type, member))
 
 #ifndef __MINGW32__
-#include <endian.h>
+#ifdef __FreeBSD__
+#include <sys/endian.h>
 #else
+#include <endian.h>
+#endif  /* __FreeBSD__ */
+#else  /* !__MINGW32__ */
 #define le32toh(x) (x)
 #define le16toh(x) (x)
 #define htole32(x) (x)
 #define htole16(x) (x)
 #define le64toh(x) (x)
-#endif
+#endif  /* __MINGW32__ */
 
 #endif /* _LKL_LIB_VIRTIO_H */
diff --git a/tools/lkl/lklfuse.c b/tools/lkl/lklfuse.c
index 4f0ae97c1cc1bb..0823ab07c268f8 100644
--- a/tools/lkl/lklfuse.c
+++ b/tools/lkl/lklfuse.c
@@ -133,8 +133,8 @@ static int lklfuse_readlink(const char *path, char *buf, size_t len)
 	if (ret < 0)
 		return ret;
 
-	if (ret == len)
-		ret  = len - 1;
+	if ((size_t)ret == len)
+		ret = len - 1;
 
 	buf[ret] = 0;
 
@@ -220,7 +220,7 @@ static int lklfuse_read(const char *path, char *buf, size_t size, off_t offset,
 		      struct fuse_file_info *fi)
 {
 	long ret;
-	int orig_size = size;
+	ssize_t orig_size = size;
 
 	do {
 		ret = lkl_sys_pread64(fi->fh, buf, size, offset);
@@ -231,7 +231,7 @@ static int lklfuse_read(const char *path, char *buf, size_t size, off_t offset,
 		buf += ret;
 	} while (size > 0);
 
-	return ret < 0 ? ret : orig_size - size;
+	return ret < 0 ? ret : orig_size - (ssize_t)size;
 
 }
 
@@ -239,7 +239,7 @@ static int lklfuse_write(const char *path, const char *buf, size_t size,
 		       off_t offset, struct fuse_file_info *fi)
 {
 	long ret;
-	int orig_size = size;
+	ssize_t orig_size = size;
 
 	do {
 		ret = lkl_sys_pwrite64(fi->fh, buf, size, offset);
@@ -250,7 +250,7 @@ static int lklfuse_write(const char *path, const char *buf, size_t size,
 		buf += ret;
 	} while (size > 0);
 
-	return ret < 0 ? ret : orig_size - size;
+	return ret < 0 ? ret : orig_size - (ssize_t)size;
 }
 
 
@@ -259,7 +259,7 @@ static int lklfuse_statfs(const char *path, struct statvfs *stat)
 	long ret;
 	struct lkl_statfs64 lkl_statfs;
 
-	ret = lkl_sys_statfs64(path, &lkl_statfs);
+	ret = lkl_sys_statfs64(path, sizeof(lkl_statfs), &lkl_statfs);
 	if (ret < 0)
 		return ret;
 
diff --git a/tools/lkl/tests/boot.c b/tools/lkl/tests/boot.c
index 8b401b729ba817..19d97c903b5987 100644
--- a/tools/lkl/tests/boot.c
+++ b/tools/lkl/tests/boot.c
@@ -50,8 +50,10 @@ static int parse_opt(int key, char *arg)
 
 void printk(const char *str, int len)
 {
+	int ret __attribute__((unused));
+
 	if (cla.printk)
-		write(STDOUT_FILENO, str, len);
+		ret = write(STDOUT_FILENO, str, len);
 }
 
 #define TEST(name) do_test(#name, test_##name)
