diff --git a/config/riscv64.mk b/config/riscv64.mk
new file mode 100644
index 0000000000..0ec97838f9
--- /dev/null
+++ b/config/riscv64.mk
@@ -0,0 +1,7 @@
+CONFIG_RISCV := y
+CONFIG_RISCV_64 := y
+CONFIG_RISCV_$(XEN_OS) := y
+
+CONFIG_XEN_INSTALL_SUFFIX :=
+
+CFLAGS +=
diff --git a/xen/Makefile b/xen/Makefile
index f36a5bc6c0..0c47899127 100644
--- a/xen/Makefile
+++ b/xen/Makefile
@@ -27,7 +27,7 @@ MAKEFLAGS += -rR
 EFI_MOUNTPOINT ?= $(BOOT_DIR)/efi
 
 ARCH=$(XEN_TARGET_ARCH)
-SRCARCH=$(shell echo $(ARCH) | sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g')
+SRCARCH=$(shell echo $(ARCH) | sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g' -e s'/riscv\(32\|64\)/riscv/g')
 
 # Don't break if the build process wasn't called from the top level
 # we need XEN_TARGET_ARCH to generate the proper config
diff --git a/xen/Rules.mk b/xen/Rules.mk
index 5aba841b0a..1556266679 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -29,7 +29,7 @@ endif
 # Set ARCH/SUBARCH appropriately.
 override TARGET_SUBARCH  := $(XEN_TARGET_ARCH)
 override TARGET_ARCH     := $(shell echo $(XEN_TARGET_ARCH) | \
-                              sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g')
+                              sed -e 's/x86.*/x86/' -e s'/arm\(32\|64\)/arm/g' -e s'/riscv\(32\|64\)/riscv/g')
 
 TARGET := $(BASEDIR)/xen
 
diff --git a/xen/arch/Kconfig b/xen/arch/Kconfig
index 1954d1c5c1..985c023ca6 100644
--- a/xen/arch/Kconfig
+++ b/xen/arch/Kconfig
@@ -7,5 +7,6 @@ config NR_CPUS
 	default "4" if ARM && QEMU
 	default "4" if ARM && MPSOC
 	default "128" if ARM
+	default "4" if RISCV
 	---help---
 	  Specifies the maximum number of physical CPUs which Xen will support.
diff --git a/xen/arch/riscv/Kconfig b/xen/arch/riscv/Kconfig
new file mode 100644
index 0000000000..8bea40af60
--- /dev/null
+++ b/xen/arch/riscv/Kconfig
@@ -0,0 +1,36 @@
+config 64BIT
+	bool
+	default ARCH != "riscv32"
+	help
+	  Say yes to build a 64-bit Xen
+	  Say no to build a 32-bit Xen
+
+config RISCV_32
+	def_bool y
+	depends on !64BIT
+
+config RISCV_64
+	def_bool y
+	depends on 64BIT
+
+config RISCV
+	def_bool y
+	select HAS_PDX
+	select HAS_PASSTHROUGH
+
+config ARCH_DEFCONFIG
+	string
+	default "arch/riscv/configs/arm32_defconfig" if RISCV_32
+	default "arch/riscv/configs/arm64_defconfig" if RISCV_64
+
+menu "Architecture Features"
+
+source "arch/Kconfig"
+
+endmenu
+
+source "arch/riscv/platforms/Kconfig"
+
+source "common/Kconfig"
+
+source "drivers/Kconfig"
diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile
new file mode 100644
index 0000000000..6fe20cb7bf
--- /dev/null
+++ b/xen/arch/riscv/Makefile
@@ -0,0 +1,62 @@
+subdir-y += lib
+
+obj-y   += domctl.o
+obj-y   += domain.o
+obj-y   += delay.o
+# obj-y   += entry.o
+obj-y   += guestcopy.o
+obj-y   += irq.o
+obj-y   += p2m.o
+obj-y   += mm.o
+obj-y   += percpu.o
+obj-y   += setup.o
+obj-y   += shutdown.o
+obj-y   += smp.o
+obj-y   += smpboot.o
+obj-y   += sysctl.o
+obj-y   += traps.o
+obj-y   += time.o
+obj-y   += vm_event.o
+
+#obj-bin-y += ....o
+
+ALL_OBJS := head.o $(ALL_OBJS)
+
+DEPS += .head.o.d
+
+$(TARGET): $(TARGET)-syms
+	$(OBJCOPY) -O binary -S $< $@
+
+prelink.o: $(ALL_OBJS)
+	$(LD) $(LDFLAGS) -r -o $@ $^
+
+$(TARGET)-syms: prelink.o xen.lds
+	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+	    $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0
+	$(NM) -pa --format=sysv $(@D)/.$(@F).0 \
+		| $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).0.S
+	$(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o
+	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
+	    $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1
+	$(NM) -pa --format=sysv $(@D)/.$(@F).1 \
+		| $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).1.S
+	$(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o
+	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \
+	    $(@D)/.$(@F).1.o -o $@
+	$(NM) -pa --format=sysv $(@D)/$(@F) \
+		| $(BASEDIR)/tools/symbols --xensyms --sysv --sort \
+		>$(@D)/$(@F).map
+	rm -f $(@D)/.$(@F).[0-9]*
+
+asm-offsets.s: asm-offsets.c
+	$(CC) $(filter-out -flto,$(CFLAGS)) -S -o $@ $<
+
+xen.lds: xen.lds.S
+	$(CC) -P -E -Ui386 $(AFLAGS) -o $@ $<
+	sed -e 's/xen\.lds\.o:/xen\.lds:/g' <.xen.lds.d >.xen.lds.d.new
+	mv -f .xen.lds.d.new .xen.lds.d
+
+.PHONY: clean
+clean::
+	rm -f asm-offsets.s xen.lds
+	rm -f $(BASEDIR)/.xen-syms.[0-9]*
\ No newline at end of file
diff --git a/xen/arch/riscv/Rules.mk b/xen/arch/riscv/Rules.mk
new file mode 100644
index 0000000000..c6ed2a96a1
--- /dev/null
+++ b/xen/arch/riscv/Rules.mk
@@ -0,0 +1,55 @@
+########################################
+# riscv-specific definitions
+
+#
+# If you change any of these configuration options then you must
+# 'make clean' before rebuilding.
+#
+
+CFLAGS += -I$(BASEDIR)/include
+
+$(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
+$(call cc-option-add,CFLAGS,CC,-Wnested-externs)
+
+EARLY_PRINTK := n
+
+ifeq ($(CONFIG_DEBUG),y)
+
+# See docs/misc/arm/early-printk.txt for syntax
+
+EARLY_PRINTK := 8250,0x1c021000,2
+
+ifneq ($(EARLY_PRINTK_$(CONFIG_EARLY_PRINTK)),)
+EARLY_PRINTK_CFG := $(subst $(comma), ,$(EARLY_PRINTK_$(CONFIG_EARLY_PRINTK)))
+else
+EARLY_PRINTK_CFG := $(subst $(comma), ,$(CONFIG_EARLY_PRINTK))
+endif
+
+# Extract configuration from string
+EARLY_PRINTK_INC := $(word 1,$(EARLY_PRINTK_CFG))
+EARLY_UART_BASE_ADDRESS := $(word 2,$(EARLY_PRINTK_CFG))
+
+# UART specific options
+ifeq ($(EARLY_PRINTK_INC),8250)
+EARLY_UART_REG_SHIFT := $(word 3,$(EARLY_PRINTK_CFG))
+endif
+
+ifneq ($(EARLY_PRINTK_INC),)
+EARLY_PRINTK := y
+endif
+
+CFLAGS-$(EARLY_PRINTK) += -DCONFIG_EARLY_PRINTK
+CFLAGS-$(EARLY_PRINTK_INIT_UART) += -DEARLY_PRINTK_INIT_UART
+CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK_INC=\"debug-$(EARLY_PRINTK_INC).inc\"
+CFLAGS-$(EARLY_PRINTK) += -DEARLY_PRINTK_BAUD=$(EARLY_PRINTK_BAUD)
+CFLAGS-$(EARLY_PRINTK) += -DEARLY_UART_BASE_ADDRESS=$(EARLY_UART_BASE_ADDRESS)
+CFLAGS-$(EARLY_PRINTK) += -DEARLY_UART_REG_SHIFT=$(EARLY_UART_REG_SHIFT)
+
+else # !CONFIG_DEBUG
+
+ifneq ($(CONFIG_EARLY_PRINTK),)
+# Early printk is dependant on a debug build.
+$(error CONFIG_EARLY_PRINTK enabled for non-debug build)
+endif
+
+endif
diff --git a/xen/arch/riscv/configs/riscv32_defconfig b/xen/arch/riscv/configs/riscv32_defconfig
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/xen/arch/riscv/configs/riscv64_defconfig b/xen/arch/riscv/configs/riscv64_defconfig
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/xen/arch/riscv/platforms/Kconfig b/xen/arch/riscv/platforms/Kconfig
new file mode 100644
index 0000000000..6959ec35a2
--- /dev/null
+++ b/xen/arch/riscv/platforms/Kconfig
@@ -0,0 +1,31 @@
+choice
+	prompt "Platform Support"
+	default ALL_PLAT
+	---help---
+	Choose which hardware platform to enable in Xen.
+
+	If unsure, choose ALL_PLAT.
+
+config ALL_PLAT
+	bool "All Platforms"
+	---help---
+	Enable support for all available hardware platforms. It doesn't
+	automatically select any of the related drivers.
+
+config QEMU
+	bool "QEMU RISC-V virt machine support"
+	depends on RISCV
+	select HAS_NS16550
+	---help---
+	Enable all the required drivers for QEMU RISC-V virt emulated
+	machine.
+
+endchoice
+
+config ALL64_PLAT
+	bool
+	default (ALL_PLAT && RISCV_64)
+
+config ALL32_PLAT
+	bool
+	default (ALL_PLAT && RISCV_32)
diff --git a/xen/arch/riscv/xen.lds.S b/xen/arch/riscv/xen.lds.S
new file mode 100644
index 0000000000..37ff8cf6ee
--- /dev/null
+++ b/xen/arch/riscv/xen.lds.S
@@ -0,0 +1,262 @@
+/**
+ * Copyright (c) 2018 Anup Patel.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @file linker.ld
+ * @author Anup Patel (anup@brainfault.org)
+ * @brief CPU specific linker script
+ */
+
+#include <xen/cache.h>
+#include <asm/percpu.h>
+#undef ENTRY
+#undef ALIGN
+
+OUTPUT_ARCH(riscv)
+ENTRY(start)
+
+PHDRS
+{
+  text PT_LOAD ;
+#if defined(BUILD_ID)
+  note PT_NOTE ;
+#endif
+}
+
+SECTIONS
+{
+  . = XEN_VIRT_START;
+  . = ALIGN(PAGE_SIZE); /* Need this to create proper sections */
+  PROVIDE(_code_start = .);
+
+  /* Beginning of the code section */
+
+  .text :
+  {
+    PROVIDE(_text_start = .);
+    _stext = .;            /* Text section */
+    *(.entry)
+    *(.text)
+    . = ALIGN(8);
+    _etext = .;             /* End of text section */
+    PROVIDE(_text_end = .);
+  } :text = 0x9090
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .init :
+  {
+    PROVIDE(_init_start = .);
+
+    *(.init.text)
+    . = ALIGN(8);
+
+    PROVIDE(__setup_start = .);
+    *(.setup.init);
+    PROVIDE(__setup_end = .);
+
+    . = ALIGN(PAGE_SIZE);
+    *(.devtree)
+    . = ALIGN(PAGE_SIZE);
+
+    PROVIDE(_init_end = .);
+
+    . = ALIGN(PAGE_SIZE);
+
+    PROVIDE(_initdata_start = .);
+    *(.init.data)
+    . = ALIGN(8);
+    PROVIDE(_initdata_end = .);
+  }
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .cpuinit :
+  {
+    PROVIDE(_cpuinit_start = .);
+    *(.cpuinit.*)
+    . = ALIGN(8);
+    PROVIDE(_cpuinit_end = .);
+  }
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .spinlock :
+  {
+    PROVIDE(_spinlock_start = .);
+    *(.spinlock.*)
+    . = ALIGN(8);
+    PROVIDE(_spinlock_end = .);
+  }
+
+  /* End of the code sections */
+
+  /* Beginning of the read-only data sections */
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .rodata :
+  {
+    PROVIDE(_rodata_start = .);
+    *(.rodata .rodata.*)
+    . = ALIGN(8);
+     _srodata = .;
+     /* Bug frames table */
+    __start_bug_frames = .;
+    *(.bug_frames.0)
+    __stop_bug_frames_0 = .;
+    *(.bug_frames.1)
+    __stop_bug_frames_1 = .;
+    *(.bug_frames.2)
+    __stop_bug_frames_2 = .;
+    *(.rodata)
+    *(.rodata.*)
+    *(.data.rel.ro)
+    *(.data.rel.ro.*)
+
+   . = ALIGN(POINTER_ALIGN);
+   __param_start = .;
+   *(.data.param)
+   __param_end = .;
+
+   __proc_info_start = .;
+   *(.proc.info)
+   __proc_info_end = .;
+    PROVIDE(_rodata_end = .);
+  }
+
+  . = ALIGN(4);
+  .note.gnu.build-id : {
+       __note_gnu_build_id_start = .;
+       *(.note.gnu.build-id)
+       __note_gnu_build_id_end = .;
+  } :note :text
+
+  /* End of the read-only data sections */
+
+  /* Beginning of the read-write data sections */
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .percpu :
+  {
+    PROVIDE(_percpu_start = .);
+    *(.percpu)
+    . = ALIGN(8);
+    PROVIDE(_percpu_end = .);
+  }
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .data :
+  {
+    PROVIDE(_data_start = .);
+
+   *(.data.page_aligned)
+   *(.data)
+   . = ALIGN(8);
+   __start_schedulers_array = .;
+   *(.data.schedulers)
+   __end_schedulers_array = .;
+   *(.data.rel)
+   *(.data.rel.*)
+   CONSTRUCTORS
+
+    PROVIDE(_data_end = .);
+  }
+
+  . = ALIGN(PAGE_SIZE);             /* Init code and data */
+  __init_begin = .;
+  .init.text : {
+       _sinittext = .;
+       *(.init.text)
+       _einittext = .;
+  } :text
+  . = ALIGN(PAGE_SIZE);
+  .init.data : {
+       *(.init.rodata)
+       *(.init.rodata.rel)
+       *(.init.rodata.str*)
+
+       . = ALIGN(POINTER_ALIGN);
+       __setup_start = .;
+       *(.init.setup)
+       __setup_end = .;
+
+       __initcall_start = .;
+       *(.initcallpresmp.init)
+       __presmp_initcall_end = .;
+       *(.initcall1.init)
+       __initcall_end = .;
+
+       . = ALIGN(4);
+       __alt_instructions = .;
+       *(.altinstructions)
+       __alt_instructions_end = .;
+       . = ALIGN(4);
+       *(.altinstr_replacement)
+
+       *(.init.data)
+       *(.init.data.rel)
+       *(.init.data.rel.*)
+
+       . = ALIGN(8);
+       __ctors_start = .;
+       *(.ctors)
+       *(.init_array)
+       *(SORT(.init_array.*))
+       __ctors_end = .;
+
+  } :text
+  . = ALIGN(STACK_SIZE);
+  __init_end = .;
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .bss :
+  {
+    PROVIDE(_bss_start = .);
+   *(.bss.stack_aligned)
+   . = ALIGN(PAGE_SIZE);
+   *(.bss.page_aligned)
+   *(.bss)
+   . = ALIGN(SMP_CACHE_BYTES);
+   __per_cpu_start = .;
+   *(.bss.percpu)
+   . = ALIGN(SMP_CACHE_BYTES);
+   *(.bss.percpu.read_mostly)
+   . = ALIGN(SMP_CACHE_BYTES);
+   __per_cpu_data_end = .;
+    PROVIDE(_bss_end = .);
+  }
+
+  . = ALIGN(PAGE_SIZE); /* Ensure next section is page aligned */
+
+  .hvc_stack :
+  {
+    PROVIDE(_hvc_stack_start = .);
+    . = . + (STACK_SIZE * CONFIG_NR_CPUS);
+    . = ALIGN(8);
+    PROVIDE(_hvc_stack_end = .);
+  }
+
+  /* End of the read-write data sections */
+
+  . = ALIGN(PAGE_SIZE); /* Need this to create proper pages */
+
+  PROVIDE(_code_end = .);
+}
diff --git a/xen/drivers/passthrough/Makefile b/xen/drivers/passthrough/Makefile
index d50ab188c8..3c8ef68418 100644
--- a/xen/drivers/passthrough/Makefile
+++ b/xen/drivers/passthrough/Makefile
@@ -2,6 +2,7 @@ subdir-$(CONFIG_X86) += vtd
 subdir-$(CONFIG_X86) += amd
 subdir-$(CONFIG_X86) += x86
 subdir-$(CONFIG_ARM) += arm
+subdir-$(CONFIG_RISCV) += riscv
 
 obj-y += iommu.o
 obj-$(CONFIG_HAS_PCI) += pci.o
diff --git a/xen/drivers/passthrough/riscv/Makefile b/xen/drivers/passthrough/riscv/Makefile
new file mode 100644
index 0000000000..0484b796b0
--- /dev/null
+++ b/xen/drivers/passthrough/riscv/Makefile
@@ -0,0 +1 @@
+obj-y += iommu.o
