diff --git a/.travis.yml b/.travis.yml
index cca57f4314..e942175dd3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -149,6 +149,12 @@ matrix:
         - ${SRC_DIR}/scripts/travis/coverage-summary.sh
 
 
+    # We manually include builds which we disable "make check" for
+    - env:
+        - CONFIG="--without-default-devices"
+        - TEST_CMD=""
+
+
     # We manually include builds which we disable "make check" for
     - env:
         - CONFIG="--enable-debug --enable-tcg-interpreter"
diff --git a/Kconfig.host b/Kconfig.host
new file mode 100644
index 0000000000..add5b179f7
--- /dev/null
+++ b/Kconfig.host
@@ -0,0 +1,33 @@
+# These are "proxy" symbols used to pass config-host.mak values
+# down to Kconfig.  See also MINIKCONF_ARGS in the Makefile:
+# these two need to be kept in sync.
+
+config KVM
+    bool
+
+config LINUX
+    bool
+
+config OPENGL
+    bool
+
+config X11
+    bool
+
+config SPICE
+    bool
+
+config IVSHMEM
+    bool
+
+config TPM
+    bool
+
+config VHOST_USER
+    bool
+
+config XEN
+    bool
+
+config VIRTFS
+    bool
diff --git a/Makefile b/Makefile
index cad585b4d6..ba32d810ea 100644
--- a/Makefile
+++ b/Makefile
@@ -327,8 +327,8 @@ DOCS=
 endif
 
 SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory --quiet) BUILD_DIR=$(BUILD_DIR)
-SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
-SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %-config-devices.mak.d, $(TARGET_DIRS))
+SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(filter %-softmmu, $(TARGET_DIRS)))
+SUBDIR_DEVICES_MAK_DEP=$(patsubst %, %.d, $(SUBDIR_DEVICES_MAK))
 
 ifeq ($(SUBDIR_DEVICES_MAK),)
 config-all-devices.mak:
@@ -343,9 +343,26 @@ endif
 
 -include $(SUBDIR_DEVICES_MAK_DEP)
 
-%/config-devices.mak: default-configs/%.mak $(SRC_PATH)/scripts/make_device_config.sh
-	$(call quiet-command, \
-            $(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp,"GEN","$@.tmp")
+# This has to be kept in sync with Kconfig.host.
+MINIKCONF_ARGS = \
+    $(CONFIG_MINIKCONF_MODE) \
+    $@ $*-config.devices.mak.d $< $(MINIKCONF_INPUTS) \
+    CONFIG_KVM=$(CONFIG_KVM) \
+    CONFIG_SPICE=$(CONFIG_SPICE) \
+    CONFIG_IVSHMEM=$(CONFIG_IVSHMEM) \
+    CONFIG_TPM=$(CONFIG_TPM) \
+    CONFIG_XEN=$(CONFIG_XEN) \
+    CONFIG_OPENGL=$(CONFIG_OPENGL) \
+    CONFIG_X11=$(CONFIG_X11) \
+    CONFIG_VHOST_USER=$(CONFIG_VHOST_USER) \
+    CONFIG_VIRTFS=$(CONFIG_VIRTFS) \
+    CONFIG_LINUX=$(CONFIG_LINUX)
+
+MINIKCONF_INPUTS = $(SRC_PATH)/Kconfig.host $(SRC_PATH)/hw/Kconfig
+MINIKCONF = $(PYTHON) $(SRC_PATH)/scripts/minikconf.py \
+
+$(SUBDIR_DEVICES_MAK): %/config-devices.mak: default-configs/%.mak $(MINIKCONF_INPUTS) $(BUILD_DIR)/config-host.mak
+	$(call quiet-command, $(MINIKCONF) $(MINIKCONF_ARGS) > $@.tmp, "GEN", "$@.tmp")
 	$(call quiet-command, if test -f $@; then \
 	  if cmp -s $@.old $@; then \
 	    mv $@.tmp $@; \
diff --git a/Makefile.target b/Makefile.target
index 3b79e7074c..ec72733ace 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -4,9 +4,12 @@ BUILD_DIR?=$(CURDIR)/..
 
 include ../config-host.mak
 include config-target.mak
-include config-devices.mak
 include $(SRC_PATH)/rules.mak
 
+ifdef CONFIG_SOFTMMU
+include config-devices.mak
+endif
+
 $(call set-vpath, $(SRC_PATH):$(BUILD_DIR))
 ifdef CONFIG_LINUX
 QEMU_CFLAGS += -I../linux-headers
@@ -201,7 +204,9 @@ all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
 all-obj-$(CONFIG_SOFTMMU) += $(slirp-obj-y)
 
+ifdef CONFIG_SOFTMMU
 $(QEMU_PROG_BUILD): config-devices.mak
+endif
 
 COMMON_LDADDS = ../libqemuutil.a
 
diff --git a/configure b/configure
index 5921d08cb3..f9177dc479 100755
--- a/configure
+++ b/configure
@@ -466,7 +466,7 @@ gcrypt_hmac="no"
 auth_pam=""
 vte=""
 virglrenderer=""
-tpm="yes"
+tpm=""
 libssh2=""
 live_block_migration="yes"
 numa=""
@@ -487,7 +487,7 @@ libxml2=""
 docker="no"
 debug_mutex="no"
 libpmem=""
-libudev="no"
+default_devices="yes"
 
 # cross compilers defaults, can be overridden with --cross-cc-ARCH
 cross_cc_aarch64="aarch64-linux-gnu-gcc"
@@ -996,6 +996,10 @@ for opt do
   ;;
   --with-trace-file=*) trace_file="$optarg"
   ;;
+  --with-default-devices) default_devices="yes"
+  ;;
+  --without-default-devices) default_devices="no"
+  ;;
   --enable-gprof) gprof="yes"
   ;;
   --enable-gcov) gcov="yes"
@@ -3873,20 +3877,20 @@ EOF
 fi
 
 ##########################################
-# TPM passthrough is only on x86 Linux
+# TPM emulation is only on POSIX
 
-if test "$targetos" = Linux && { test "$cpu" = i386 || test "$cpu" = x86_64; }; then
-  tpm_passthrough=$tpm
-else
-  tpm_passthrough=no
+if test "$tpm" = ""; then
+  if test "$mingw32" = "yes"; then
+    tpm=no
+  else
+    tpm=yes
+  fi
+elif test "$tpm" = "yes"; then
+  if test "$mingw32" = "yes" ; then
+    error_exit "TPM emulation only available on POSIX systems"
+  fi
 fi
 
-# TPM emulator is for all posix systems
-if test "$mingw32" != "yes"; then
-  tpm_emulator=$tpm
-else
-  tpm_emulator=no
-fi
 ##########################################
 # attr probe
 
@@ -6261,6 +6265,7 @@ echo "capstone          $capstone"
 echo "docker            $docker"
 echo "libpmem support   $libpmem"
 echo "libudev           $libudev"
+echo "default devices   $default_devices"
 
 if test "$supported_cpu" = "no"; then
     echo
@@ -6322,6 +6327,11 @@ echo "GIT_UPDATE=$git_update" >> $config_host_mak
 
 echo "ARCH=$ARCH" >> $config_host_mak
 
+if test "$default_devices" = "yes" ; then
+  echo "CONFIG_MINIKCONF_MODE=--defconfig" >> $config_host_mak
+else
+  echo "CONFIG_MINIKCONF_MODE=--allnoconfig" >> $config_host_mak
+fi
 if test "$debug_tcg" = "yes" ; then
   echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
 fi
@@ -7438,12 +7448,18 @@ fi
 
 if supported_xen_target $target; then
     echo "CONFIG_XEN=y" >> $config_target_mak
+    echo "$target/config-devices.mak: CONFIG_XEN=y" >> $config_host_mak
     if test "$xen_pci_passthrough" = yes; then
         echo "CONFIG_XEN_PCI_PASSTHROUGH=y" >> "$config_target_mak"
     fi
+else
+    echo "$target/config-devices.mak: CONFIG_XEN=n" >> $config_host_mak
 fi
 if supported_kvm_target $target; then
     echo "CONFIG_KVM=y" >> $config_target_mak
+    echo "$target/config-devices.mak: CONFIG_KVM=y" >> $config_host_mak
+else
+    echo "$target/config-devices.mak: CONFIG_KVM=n" >> $config_host_mak
 fi
 if supported_hax_target $target; then
     echo "CONFIG_HAX=y" >> $config_target_mak
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
index 49cb7ce351..d186fe8e9b 100644
--- a/default-configs/alpha-softmmu.mak
+++ b/default-configs/alpha-softmmu.mak
@@ -1,22 +1,10 @@
 # Default configuration for alpha-softmmu
 
-include pci.mak
-include usb.mak
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_I82374=y
-CONFIG_I8254=y
-CONFIG_I8257=y
-CONFIG_PARALLEL=y
-CONFIG_FDC=y
-CONFIG_PCKBD=y
-CONFIG_VGA_CIRRUS=y
-CONFIG_IDE_CORE=y
-CONFIG_IDE_QDEV=y
-CONFIG_VMWARE_VGA=y
-CONFIG_IDE_CMD646=y
-CONFIG_I8259=y
-CONFIG_MC146818RTC=y
-CONFIG_ISA_TESTDEV=y
-CONFIG_SMC37C669=y
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
+#CONFIG_TEST_DEVICES=n
+
+# Boards:
+#
 CONFIG_DP264=y
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index bd6943b691..2a7efc1167 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -1,13 +1,11 @@
 # Default configuration for arm-softmmu
 
-include pci.mak
-include usb.mak
+CONFIG_PCI=y
+CONFIG_PCI_DEVICES=y
 CONFIG_VGA=y
 CONFIG_NAND=y
 CONFIG_ECC=y
 CONFIG_SERIAL=y
-CONFIG_PTIMER=y
-CONFIG_SD=y
 CONFIG_MAX7310=y
 CONFIG_WM8750=y
 CONFIG_TWL92230=y
@@ -25,7 +23,6 @@ CONFIG_DDC=y
 CONFIG_SII9022=y
 CONFIG_ADS7846=y
 CONFIG_MAX111X=y
-CONFIG_SSI=y
 CONFIG_SSI_SD=y
 CONFIG_SSI_M25P80=y
 CONFIG_LAN9118=y
@@ -37,7 +34,6 @@ CONFIG_DS1338=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_PFLASH_CFI02=y
 CONFIG_MICRODRIVE=y
-CONFIG_USB=y
 CONFIG_USB_MUSB=y
 CONFIG_USB_EHCI_SYSBUS=y
 CONFIG_PLATFORM_BUS=y
@@ -51,7 +47,6 @@ CONFIG_ARM_V7M=y
 CONFIG_NETDUINO2=y
 
 CONFIG_ARM_GIC=y
-CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
 CONFIG_ARM_TIMER=y
 CONFIG_ARM_MPTIMER=y
 CONFIG_A9_GTIMER=y
@@ -71,7 +66,6 @@ CONFIG_CADENCE=y
 CONFIG_XGMAC=y
 CONFIG_EXYNOS4=y
 CONFIG_PXA2XX=y
-CONFIG_I2C=y
 CONFIG_BITBANG_I2C=y
 CONFIG_FRAMEBUFFER=y
 CONFIG_XILINX_SPIPS=y
@@ -125,11 +119,8 @@ CONFIG_VERSATILE=y
 CONFIG_VERSATILE_PCI=y
 CONFIG_VERSATILE_I2C=y
 
+CONFIG_PCI_EXPRESS=y
 CONFIG_PCI_EXPRESS_GENERIC_BRIDGE=y
-CONFIG_VFIO=$(CONFIG_LINUX)
-CONFIG_VFIO_PLATFORM=y
-CONFIG_VFIO_XGMAC=y
-CONFIG_VFIO_AMD_XGBE=y
 
 CONFIG_SDHCI=y
 CONFIG_INTEGRATOR=y
@@ -165,3 +156,6 @@ CONFIG_PCI_EXPRESS_DESIGNWARE=y
 CONFIG_STRONGARM=y
 CONFIG_HIGHBANK=y
 CONFIG_MUSICPAL=y
+
+# for realview and versatilepb
+CONFIG_LSI_SCSI_PCI=y
diff --git a/default-configs/cris-softmmu.mak b/default-configs/cris-softmmu.mak
index a637c4b4bf..5932cf4d06 100644
--- a/default-configs/cris-softmmu.mak
+++ b/default-configs/cris-softmmu.mak
@@ -1,7 +1,5 @@
 # Default configuration for cris-softmmu
 
-CONFIG_ETRAXFS=y
-CONFIG_NAND=y
-CONFIG_PTIMER=y
-CONFIG_PFLASH_CFI02=y
+# Boards:
+#
 CONFIG_AXIS=y
diff --git a/default-configs/hppa-softmmu.mak b/default-configs/hppa-softmmu.mak
index b594a6ddd9..b64c5eb3ff 100644
--- a/default-configs/hppa-softmmu.mak
+++ b/default-configs/hppa-softmmu.mak
@@ -1,13 +1,9 @@
-include pci.mak
-include usb.mak
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_ISA_BUS=y
-CONFIG_I8259=y
-CONFIG_E1000_PCI=y
-CONFIG_IDE_ISA=y
-CONFIG_IDE_CMD646=y
-# CONFIG_IDE_MMIO=y
-CONFIG_VIRTIO_VGA=y
-CONFIG_MC146818RTC=y
+# Default configuration for hppa-softmmu
+
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
+
+# Boards:
+#
 CONFIG_DINO=y
diff --git a/default-configs/hyperv.mak b/default-configs/hyperv.mak
deleted file mode 100644
index 5d0d9fd830..0000000000
--- a/default-configs/hyperv.mak
+++ /dev/null
@@ -1,2 +0,0 @@
-CONFIG_HYPERV=$(CONFIG_KVM)
-CONFIG_HYPERV_TESTDEV=y
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 15b628757b..ba3fb3ff50 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -1,74 +1,27 @@
 # Default configuration for i386-softmmu
 
-include pci.mak
-include sound.mak
-include usb.mak
-include hyperv.mak
-CONFIG_QXL=$(CONFIG_SPICE)
-CONFIG_VGA_ISA=y
-CONFIG_VGA_CIRRUS=y
-CONFIG_VMWARE_VGA=y
-CONFIG_VMXNET3_PCI=y
-CONFIG_VIRTIO_VGA=y
-CONFIG_VMMOUSE=y
-CONFIG_IPMI=y
-CONFIG_IPMI_LOCAL=y
-CONFIG_IPMI_EXTERN=y
-CONFIG_ISA_IPMI_KCS=y
-CONFIG_ISA_IPMI_BT=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_PARALLEL=y
-CONFIG_I8254=y
-CONFIG_PCSPK=y
-CONFIG_PCKBD=y
-CONFIG_FDC=y
-CONFIG_ACPI=y
-CONFIG_ACPI_X86=y
-CONFIG_ACPI_X86_ICH=y
-CONFIG_ACPI_MEMORY_HOTPLUG=y
-CONFIG_ACPI_CPU_HOTPLUG=y
-CONFIG_APM=y
-CONFIG_I8257=y
-CONFIG_IDE_ISA=y
-CONFIG_IDE_PIIX=y
-CONFIG_NE2000_ISA=y
-CONFIG_HPET=y
-CONFIG_APPLESMC=y
-CONFIG_I8259=y
-CONFIG_PFLASH_CFI01=y
-CONFIG_TPM_TIS=$(CONFIG_TPM)
-CONFIG_TPM_CRB=$(CONFIG_TPM)
-CONFIG_MC146818RTC=y
-CONFIG_PCI_PIIX=y
-CONFIG_WDT_IB700=y
-CONFIG_ISA_DEBUG=y
-CONFIG_ISA_TESTDEV=y
-CONFIG_VMPORT=y
-CONFIG_SGA=y
-CONFIG_LPC_ICH9=y
-CONFIG_PCI_EXPRESS_Q35=y
-CONFIG_APIC=y
-CONFIG_IOAPIC=y
-CONFIG_PVPANIC=y
-CONFIG_MEM_DEVICE=y
-CONFIG_DIMM=y
-CONFIG_NVDIMM=y
-CONFIG_ACPI_NVDIMM=y
-CONFIG_PCIE_PORT=y
-CONFIG_XIO3130=y
-CONFIG_IOH3420=y
-CONFIG_I82801B11=y
-CONFIG_SMBIOS=y
-CONFIG_PXB=y
-CONFIG_ACPI_VMGENID=y
-CONFIG_ACPI_SMBUS=y
-CONFIG_SMBUS_EEPROM=y
-CONFIG_FW_CFG_DMA=y
-CONFIG_I2C=y
-CONFIG_SEV=$(CONFIG_KVM)
-CONFIG_VTD=y
-CONFIG_AMD_IOMMU=y
-CONFIG_PAM=y
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_AMD_IOMMU=n
+#CONFIG_APPLESMC=n
+#CONFIG_FDC=n
+#CONFIG_HPET=n
+#CONFIG_HYPERV=n
+#CONFIG_ISA_DEBUG=n
+#CONFIG_ISA_IPMI_BT=n
+#CONFIG_ISA_IPMI_KCS=n
+#CONFIG_PCI_DEVICES=n
+#CONFIG_PVPANIC=n
+#CONFIG_QXL=n
+#CONFIG_SEV=n
+#CONFIG_SGA=n
+#CONFIG_TEST_DEVICES=n
+#CONFIG_TPM_CRB=n
+#CONFIG_TPM_TIS=n
+#CONFIG_VTD=n
+
+# Boards:
+#
+CONFIG_ISAPC=y
 CONFIG_I440FX=y
 CONFIG_Q35=y
diff --git a/default-configs/lm32-softmmu.mak b/default-configs/lm32-softmmu.mak
index 4049b23562..6d259665d6 100644
--- a/default-configs/lm32-softmmu.mak
+++ b/default-configs/lm32-softmmu.mak
@@ -1,10 +1,10 @@
 # Default configuration for lm32-softmmu
 
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_MILKYMIST_TMU2=n        # disabling it actually causes compile-time failures
+
+# Boards:
+#
 CONFIG_LM32=y
 CONFIG_MILKYMIST=y
-CONFIG_MILKYMIST_TMU2=$(call land,$(CONFIG_X11),$(CONFIG_OPENGL))
-CONFIG_FRAMEBUFFER=y
-CONFIG_PTIMER=y
-CONFIG_PFLASH_CFI01=y
-CONFIG_PFLASH_CFI02=y
-CONFIG_SD=y
diff --git a/default-configs/m68k-softmmu.mak b/default-configs/m68k-softmmu.mak
index 27f5274244..e17495e2a0 100644
--- a/default-configs/m68k-softmmu.mak
+++ b/default-configs/m68k-softmmu.mak
@@ -1,6 +1,6 @@
 # Default configuration for m68k-softmmu
 
-CONFIG_COLDFIRE=y
-CONFIG_PTIMER=y
+# Boards:
+#
 CONFIG_AN5206=y
 CONFIG_MCF5208=y
diff --git a/default-configs/microblaze-softmmu.mak b/default-configs/microblaze-softmmu.mak
index 14837cf74a..db8c6e4bba 100644
--- a/default-configs/microblaze-softmmu.mak
+++ b/default-configs/microblaze-softmmu.mak
@@ -1,15 +1,7 @@
 # Default configuration for microblaze-softmmu
 
-CONFIG_PTIMER=y
-CONFIG_PFLASH_CFI01=y
-CONFIG_SERIAL=y
-CONFIG_XILINX=y
-CONFIG_XILINX_AXI=y
-CONFIG_XILINX_SPI=y
-CONFIG_XILINX_ETHLITE=y
-CONFIG_SSI=y
-CONFIG_SSI_M25P80=y
-CONFIG_XLNX_ZYNQMP=y
+# Boards:
+#
 CONFIG_PETALOGIX_S3ADSP1800=y
 CONFIG_PETALOGIX_ML605=y
 CONFIG_XLNX_ZYNQMP_PMU=y
diff --git a/default-configs/mips-softmmu-common.mak b/default-configs/mips-softmmu-common.mak
index ded74980e1..0795d522db 100644
--- a/default-configs/mips-softmmu-common.mak
+++ b/default-configs/mips-softmmu-common.mak
@@ -1,10 +1,9 @@
 # Common mips*-softmmu CONFIG defines
 
-include pci.mak
-include sound.mak
-include usb.mak
+CONFIG_ISA_BUS=y
+CONFIG_PCI=y
+CONFIG_PCI_DEVICES=y
 CONFIG_ESP=y
-CONFIG_SCSI=y
 CONFIG_VGA_ISA=y
 CONFIG_VGA_ISA_MM=y
 CONFIG_VGA_CIRRUS=y
@@ -31,13 +30,12 @@ CONFIG_MIPSNET=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_I8259=y
 CONFIG_MC146818RTC=y
-CONFIG_ISA_TESTDEV=y
 CONFIG_EMPTY_SLOT=y
 CONFIG_MIPS_CPS=y
 CONFIG_MIPS_ITU=y
-CONFIG_I2C=y
 CONFIG_R4K=y
 CONFIG_MALTA=y
 CONFIG_MIPSSIM=y
 CONFIG_ACPI_SMBUS=y
 CONFIG_SMBUS_EEPROM=y
+CONFIG_TEST_DEVICES=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 9eb1208b58..8b255efc54 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -10,6 +10,8 @@ CONFIG_JAZZ=y
 CONFIG_G364FB=y
 CONFIG_JAZZ_LED=y
 CONFIG_VT82C686=y
+CONFIG_AHCI=y
 CONFIG_MIPS_BOSTON=y
 CONFIG_FITLOADER=y
+CONFIG_PCI_EXPRESS=y
 CONFIG_PCI_EXPRESS_XILINX=y
diff --git a/default-configs/moxie-softmmu.mak b/default-configs/moxie-softmmu.mak
index 17ba906dc2..bd50da3c58 100644
--- a/default-configs/moxie-softmmu.mak
+++ b/default-configs/moxie-softmmu.mak
@@ -1,8 +1,5 @@
 # Default configuration for moxie-softmmu
 
-CONFIG_ISA_BUS=y
-CONFIG_MC146818RTC=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_VGA=y
+# Boards:
+#
 CONFIG_MOXIESIM=y
diff --git a/default-configs/nios2-softmmu.mak b/default-configs/nios2-softmmu.mak
index ab42d0fc28..e11dc54960 100644
--- a/default-configs/nios2-softmmu.mak
+++ b/default-configs/nios2-softmmu.mak
@@ -1,7 +1,5 @@
 # Default configuration for nios2-softmmu
 
-CONFIG_NIOS2=y
-CONFIG_SERIAL=y
-CONFIG_PTIMER=y
-CONFIG_ALTERA_TIMER=y
+# Boards:
+#
 CONFIG_NIOS2_10M50=y
diff --git a/default-configs/or1k-softmmu.mak b/default-configs/or1k-softmmu.mak
index 6a0f2ef6cf..168101c39a 100644
--- a/default-configs/or1k-softmmu.mak
+++ b/default-configs/or1k-softmmu.mak
@@ -1,6 +1,5 @@
 # Default configuration for or1k-softmmu
 
-CONFIG_SERIAL=y
-CONFIG_OPENCORES_ETH=y
-CONFIG_OMPIC=y
+# Boards:
+#
 CONFIG_OR1K_SIM=y
diff --git a/default-configs/pci.mak b/default-configs/pci.mak
deleted file mode 100644
index 037636fa33..0000000000
--- a/default-configs/pci.mak
+++ /dev/null
@@ -1,51 +0,0 @@
-CONFIG_PCI=y
-# For now, CONFIG_IDE_CORE requires ISA, so we enable it here
-CONFIG_ISA_BUS=y
-CONFIG_VIRTIO_PCI=y
-include virtio.mak
-CONFIG_USB_UHCI=y
-CONFIG_USB_OHCI=y
-CONFIG_USB_EHCI=y
-CONFIG_USB_XHCI=y
-CONFIG_USB_XHCI_NEC=y
-CONFIG_NE2000_PCI=y
-CONFIG_EEPRO100_PCI=y
-CONFIG_PCNET_PCI=y
-CONFIG_PCNET_COMMON=y
-CONFIG_AC97=y
-CONFIG_HDA=y
-CONFIG_ES1370=y
-CONFIG_SCSI=y
-CONFIG_LSI_SCSI_PCI=y
-CONFIG_VMW_PVSCSI_SCSI_PCI=y
-CONFIG_MEGASAS_SCSI_PCI=y
-CONFIG_MPTSAS_SCSI_PCI=y
-CONFIG_RTL8139_PCI=y
-CONFIG_E1000_PCI=y
-CONFIG_E1000E_PCI_EXPRESS=y
-CONFIG_IDE_CORE=y
-CONFIG_IDE_QDEV=y
-CONFIG_IDE_PCI=y
-CONFIG_AHCI=y
-CONFIG_ESP=y
-CONFIG_ESP_PCI=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_SERIAL_PCI=y
-CONFIG_CAN_BUS=y
-CONFIG_CAN_SJA1000=y
-CONFIG_CAN_PCI=y
-CONFIG_IPACK=y
-CONFIG_WDT_IB6300ESB=y
-CONFIG_PCI_TESTDEV=y
-CONFIG_NVME_PCI=y
-CONFIG_SD=y
-CONFIG_SDHCI=y
-CONFIG_EDU=y
-CONFIG_VGA=y
-CONFIG_VGA_PCI=y
-CONFIG_BOCHS_DISPLAY=y
-CONFIG_IVSHMEM_DEVICE=$(CONFIG_IVSHMEM)
-CONFIG_ROCKER=y
-CONFIG_VFIO=$(CONFIG_LINUX)
-CONFIG_VFIO_PCI=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 52acb7cf39..6ea36d4090 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -1,77 +1,17 @@
 # Default configuration for ppc-softmmu
 
-include pci.mak
-include sound.mak
-include usb.mak
-
 # For embedded PPCs:
-CONFIG_PPC4XX=y
-CONFIG_M48T59=y
-CONFIG_SERIAL=y
-CONFIG_I8257=y
-CONFIG_OPENPIC=y
-CONFIG_PPCE500_PCI=y
-CONFIG_PFLASH_CFI01=y
-CONFIG_PFLASH_CFI02=y
-CONFIG_PTIMER=y
-CONFIG_I8259=y
-CONFIG_XILINX=y
-CONFIG_XILINX_ETHLITE=y
 CONFIG_E500=y
-CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
-CONFIG_PLATFORM_BUS=y
-CONFIG_ETSEC=y
 CONFIG_PPC405=y
 CONFIG_PPC440=y
 CONFIG_VIRTEX=y
 
 # For Sam460ex
 CONFIG_SAM460EX=y
-CONFIG_USB_EHCI_SYSBUS=y
-CONFIG_SM501=y
-CONFIG_DDC=y
-CONFIG_IDE_SII3112=y
-CONFIG_I2C=y
-CONFIG_AT24C=y
-CONFIG_BITBANG_I2C=y
-CONFIG_M41T80=y
-CONFIG_VGA_CIRRUS=y
-CONFIG_SMBUS_EEPROM=y
 
 # For Macs
-CONFIG_ESCC=y
-CONFIG_MACIO=y
-CONFIG_MACIO_GPIO=y
-CONFIG_SUNGEM=y
-CONFIG_MOS6522=y
-CONFIG_CUDA=y
-CONFIG_ADB=y
-CONFIG_MAC_NVRAM=y
-CONFIG_MAC_DBDMA=y
-CONFIG_MAC_PMU=y
-CONFIG_HEATHROW_PIC=y
-CONFIG_GRACKLE_PCI=y
-CONFIG_UNIN_PCI=y
-CONFIG_DEC_PCI=y
-CONFIG_IDE_MACIO=y
 CONFIG_MAC_OLDWORLD=y
 CONFIG_MAC_NEWWORLD=y
 
 # For PReP
 CONFIG_PREP=y
-CONFIG_PREP_PCI=y
-CONFIG_SERIAL_ISA=y
-CONFIG_MC146818RTC=y
-CONFIG_ISA_TESTDEV=y
-CONFIG_RS6000_MC=y
-CONFIG_PARALLEL=y
-CONFIG_I82374=y
-CONFIG_I82378=y
-CONFIG_I8254=y
-CONFIG_PCKBD=y
-CONFIG_FDC=y
-CONFIG_NE2000_ISA=y
-CONFIG_PC87312=y
-CONFIG_PCSPK=y
-CONFIG_IDE_ISA=y
-CONFIG_CS4231A=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 7f34ad0528..cca52665d9 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -5,19 +5,6 @@ include ppc-softmmu.mak
 
 # For PowerNV
 CONFIG_POWERNV=y
-CONFIG_IPMI=y
-CONFIG_IPMI_LOCAL=y
-CONFIG_IPMI_EXTERN=y
-CONFIG_ISA_IPMI_BT=y
 
 # For pSeries
 CONFIG_PSERIES=y
-CONFIG_VIRTIO_VGA=y
-CONFIG_XICS=$(CONFIG_PSERIES)
-CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
-CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM))
-CONFIG_XIVE=$(CONFIG_PSERIES)
-CONFIG_XIVE_SPAPR=$(CONFIG_PSERIES)
-CONFIG_MEM_DEVICE=y
-CONFIG_DIMM=y
-CONFIG_SPAPR_RNG=y
diff --git a/default-configs/riscv32-softmmu.mak b/default-configs/riscv32-softmmu.mak
index 65337166e1..1ae077ed87 100644
--- a/default-configs/riscv32-softmmu.mak
+++ b/default-configs/riscv32-softmmu.mak
@@ -1,21 +1,12 @@
-# Default configuration for riscv-softmmu
+# Default configuration for riscv32-softmmu
 
-include pci.mak
-include usb.mak
-
-CONFIG_SERIAL=y
-CONFIG_VIRTIO_MMIO=y
-
-CONFIG_CADENCE=y
-
-CONFIG_PCI_EXPRESS_GENERIC_BRIDGE=y
-
-CONFIG_VGA=y
-CONFIG_VGA_PCI=y
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
 
+# Boards:
+#
 CONFIG_SPIKE=y
-CONFIG_HART=y
 CONFIG_SIFIVE_E=y
-CONFIG_SIFIVE=y
 CONFIG_SIFIVE_U=y
 CONFIG_RISCV_VIRT=y
diff --git a/default-configs/riscv64-softmmu.mak b/default-configs/riscv64-softmmu.mak
index 65337166e1..235c6f473f 100644
--- a/default-configs/riscv64-softmmu.mak
+++ b/default-configs/riscv64-softmmu.mak
@@ -1,21 +1,3 @@
-# Default configuration for riscv-softmmu
+# Default configuration for riscv64-softmmu
 
-include pci.mak
-include usb.mak
-
-CONFIG_SERIAL=y
-CONFIG_VIRTIO_MMIO=y
-
-CONFIG_CADENCE=y
-
-CONFIG_PCI_EXPRESS_GENERIC_BRIDGE=y
-
-CONFIG_VGA=y
-CONFIG_VGA_PCI=y
-
-CONFIG_SPIKE=y
-CONFIG_HART=y
-CONFIG_SIFIVE_E=y
-CONFIG_SIFIVE=y
-CONFIG_SIFIVE_U=y
-CONFIG_RISCV_VIRT=y
+include riscv32-softmmu.mak
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index 6f2c6cec18..f2287a133f 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -1,12 +1,13 @@
-CONFIG_PCI=y
-CONFIG_VIRTIO_PCI=$(CONFIG_PCI)
-include virtio.mak
-CONFIG_SCLPCONSOLE=y
-CONFIG_TERMINAL3270=y
-CONFIG_S390_FLIC=y
-CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
-CONFIG_WDT_DIAG288=y
+# Default configuration for s390x-softmmu
+
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_TERMINAL3270=n
+#CONFIG_VFIO_AP=n
+#CONFIG_VFIO_CCW=n
+#CONFIG_VIRTIO_PCI=n
+#CONFIG_WDT_DIAG288=n
+
+# Boards:
+#
 CONFIG_S390_CCW_VIRTIO=y
-CONFIG_VFIO=$(CONFIG_LINUX)
-CONFIG_VFIO_CCW=y
-CONFIG_VFIO_AP=y
diff --git a/default-configs/sh4-softmmu.mak b/default-configs/sh4-softmmu.mak
index 1fdb009151..565e8b0b5d 100644
--- a/default-configs/sh4-softmmu.mak
+++ b/default-configs/sh4-softmmu.mak
@@ -1,23 +1,11 @@
-# Default configuration for sh4-softmmu
+# Default configuration for sh4eb-softmmu
 
-include pci.mak
-include usb.mak
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_PTIMER=y
-CONFIG_PFLASH_CFI02=y
-CONFIG_SH4=y
-CONFIG_IDE_MMIO=y
-CONFIG_SM501=y
-CONFIG_I2C=y
-CONFIG_DDC=y
-CONFIG_ISA_TESTDEV=y
-CONFIG_I82378=y
-CONFIG_I8259=y
-CONFIG_I8254=y
-CONFIG_PCSPK=y
-CONFIG_I82374=y
-CONFIG_I8257=y
-CONFIG_MC146818RTC=y
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
+#CONFIG_TEST_DEVICES=n
+
+# Boards:
+#
 CONFIG_R2D=y
 CONFIG_SHIX=y
diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/sh4eb-softmmu.mak
index 3b550a5fe8..522a7a50fa 100644
--- a/default-configs/sh4eb-softmmu.mak
+++ b/default-configs/sh4eb-softmmu.mak
@@ -1,23 +1,3 @@
 # Default configuration for sh4eb-softmmu
 
-include pci.mak
-include usb.mak
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_PTIMER=y
-CONFIG_PFLASH_CFI02=y
-CONFIG_SH4=y
-CONFIG_IDE_MMIO=y
-CONFIG_SM501=y
-CONFIG_I2C=y
-CONFIG_DDC=y
-CONFIG_ISA_TESTDEV=y
-CONFIG_I82378=y
-CONFIG_I8259=y
-CONFIG_I8254=y
-CONFIG_PCSPK=y
-CONFIG_I82374=y
-CONFIG_I8257=y
-CONFIG_MC146818RTC=y
-CONFIG_R2D=y
-CONFIG_SHIX=y
+include sh4-softmmu.mak
diff --git a/default-configs/sound.mak b/default-configs/sound.mak
deleted file mode 100644
index 4f22c34b5d..0000000000
--- a/default-configs/sound.mak
+++ /dev/null
@@ -1,4 +0,0 @@
-CONFIG_SB16=y
-CONFIG_ADLIB=y
-CONFIG_GUS=y
-CONFIG_CS4231A=y
diff --git a/default-configs/sparc-softmmu.mak b/default-configs/sparc-softmmu.mak
index 59a4a3d693..ee85218115 100644
--- a/default-configs/sparc-softmmu.mak
+++ b/default-configs/sparc-softmmu.mak
@@ -1,23 +1,11 @@
 # Default configuration for sparc-softmmu
 
-CONFIG_ISA_BUS=y
-CONFIG_ECC=y
-CONFIG_SCSI=y
-CONFIG_ESP=y
-CONFIG_ESCC=y
-CONFIG_M48T59=y
-CONFIG_PTIMER=y
-CONFIG_FDC=y
-CONFIG_EMPTY_SLOT=y
-CONFIG_PCNET_COMMON=y
-CONFIG_LANCE=y
-CONFIG_TCX=y
-CONFIG_CG3=y
-CONFIG_SLAVIO=y
-CONFIG_CS4231=y
-CONFIG_GRLIB=y
-CONFIG_STP2000=y
-CONFIG_ECCMEMCTL=y
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_TCX=n
+#CONFIG_CG3=n
 
+# Boards:
+#
 CONFIG_SUN4M=y
 CONFIG_LEON3=y
diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak
index 1fae4888db..e50030a229 100644
--- a/default-configs/sparc64-softmmu.mak
+++ b/default-configs/sparc64-softmmu.mak
@@ -1,21 +1,12 @@
 # Default configuration for sparc64-softmmu
 
-include pci.mak
-include usb.mak
-CONFIG_M48T59=y
-CONFIG_PTIMER=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_ISA=y
-CONFIG_PARALLEL=y
-CONFIG_PCKBD=y
-CONFIG_FDC=y
-CONFIG_IDE_ISA=y
-CONFIG_IDE_CMD646=y
-CONFIG_PCI_SABRE=y
-CONFIG_SIMBA=y
-CONFIG_SUNHME=y
-CONFIG_MC146818RTC=y
-CONFIG_ISA_TESTDEV=y
-CONFIG_SUN4V_RTC=y
+# Uncomment the following lines to disable these optional devices:
+#
+#CONFIG_PCI_DEVICES=n
+#CONFIG_SUNHME=n
+#CONFIG_TEST_DEVICES=n
+
+# Boards:
+#
 CONFIG_SUN4U=y
 CONFIG_NIAGARA=y
diff --git a/default-configs/unicore32-softmmu.mak b/default-configs/unicore32-softmmu.mak
index 5f6c4a8047..0bfce48c6d 100644
--- a/default-configs/unicore32-softmmu.mak
+++ b/default-configs/unicore32-softmmu.mak
@@ -1,5 +1,5 @@
 # Default configuration for unicore32-softmmu
-CONFIG_ISA_BUS=y
+
+# Boards:
+#
 CONFIG_PUV3=y
-CONFIG_PTIMER=y
-CONFIG_PCKBD=y
diff --git a/default-configs/usb.mak b/default-configs/usb.mak
deleted file mode 100644
index e42cfeabbe..0000000000
--- a/default-configs/usb.mak
+++ /dev/null
@@ -1,11 +0,0 @@
-CONFIG_USB=y
-CONFIG_USB_TABLET_WACOM=y
-CONFIG_USB_STORAGE_BOT=y
-CONFIG_USB_STORAGE_UAS=y
-CONFIG_USB_STORAGE_MTP=y
-CONFIG_SCSI=y
-CONFIG_USB_SMARTCARD=y
-CONFIG_USB_AUDIO=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_NETWORK=y
-CONFIG_USB_BLUETOOTH=y
diff --git a/default-configs/virtio.mak b/default-configs/virtio.mak
deleted file mode 100644
index b653aa06b1..0000000000
--- a/default-configs/virtio.mak
+++ /dev/null
@@ -1,15 +0,0 @@
-CONFIG_VHOST_USER_SCSI=$(CONFIG_VHOST_USER)
-CONFIG_VHOST_USER_BLK=$(CONFIG_VHOST_USER)
-CONFIG_VIRTIO=y
-CONFIG_VIRTIO_9P=$(CONFIG_VIRTFS)
-CONFIG_VIRTIO_BALLOON=y
-CONFIG_VIRTIO_BLK=y
-CONFIG_VIRTIO_CRYPTO=y
-CONFIG_VIRTIO_GPU=y
-CONFIG_VIRTIO_INPUT=y
-CONFIG_VIRTIO_NET=y
-CONFIG_VIRTIO_RNG=y
-CONFIG_SCSI=y
-CONFIG_VIRTIO_SCSI=y
-CONFIG_VIRTIO_SERIAL=y
-CONFIG_VIRTIO_INPUT_HOST=$(CONFIG_LINUX)
diff --git a/default-configs/xtensa-softmmu.mak b/default-configs/xtensa-softmmu.mak
index baf90ca162..7e4d1cc097 100644
--- a/default-configs/xtensa-softmmu.mak
+++ b/default-configs/xtensa-softmmu.mak
@@ -1,8 +1,6 @@
 # Default configuration for Xtensa
 
-CONFIG_SERIAL=y
-CONFIG_OPENCORES_ETH=y
-CONFIG_PFLASH_CFI01=y
-
+# Boards:
+#
 CONFIG_XTENSA_SIM=y
-CONFIG_XTENSA_FPGA=y
+CONFIG_XTENSA_XTFPGA=y
diff --git a/default-configs/xtensaeb-softmmu.mak b/default-configs/xtensaeb-softmmu.mak
index baf90ca162..f7e48c750c 100644
--- a/default-configs/xtensaeb-softmmu.mak
+++ b/default-configs/xtensaeb-softmmu.mak
@@ -1,8 +1,3 @@
 # Default configuration for Xtensa
 
-CONFIG_SERIAL=y
-CONFIG_OPENCORES_ETH=y
-CONFIG_PFLASH_CFI01=y
-
-CONFIG_XTENSA_SIM=y
-CONFIG_XTENSA_FPGA=y
+include xtensa-softmmu.mak
diff --git a/docs/devel/build-system.txt b/docs/devel/build-system.txt
index f9fd27fab0..addd274eeb 100644
--- a/docs/devel/build-system.txt
+++ b/docs/devel/build-system.txt
@@ -417,7 +417,6 @@ into each QEMU system and userspace emulator targets. They merely
 contain a long list of config variable definitions. For example,
 default-configs/x86_64-softmmu.mak has:
 
-  include pci.mak
   include sound.mak
   include usb.mak
   CONFIG_QXL=$(CONFIG_SPICE)
diff --git a/docs/devel/index.rst b/docs/devel/index.rst
index cd0fa6c9ba..6b11e49caa 100644
--- a/docs/devel/index.rst
+++ b/docs/devel/index.rst
@@ -13,6 +13,7 @@ Contents:
 .. toctree::
    :maxdepth: 2
 
+   kconfig
    loads-stores
    memory
    migration
diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst
new file mode 100644
index 0000000000..cce146f87d
--- /dev/null
+++ b/docs/devel/kconfig.rst
@@ -0,0 +1,306 @@
+================
+QEMU and Kconfig
+================
+
+QEMU is a very versatile emulator; it can be built for a variety of
+targets, where each target can emulate various boards and at the same
+time different targets can share large amounts of code.  For example,
+a POWER and an x86 board can run the same code to emulate a PCI network
+card, even though the boards use different PCI host bridges, and they
+can run the same code to emulate a SCSI disk while using different
+SCSI adapters.  ARM, s390 and x86 boards can all present a virtio-blk
+disk to their guests, but with three different virtio guest interfaces.
+
+Each QEMU target enables a subset of the boards, devices and buses that
+are included in QEMU's source code.  As a result, each QEMU executable
+only links a small subset of the files that form QEMU's source code;
+anything that is not needed to support a particular target is culled.
+
+QEMU uses a simple domain-specific language to describe the dependencies
+between components.  This is useful for two reasons:
+
+* new targets and boards can be added without knowing in detail the
+  architecture of the hardware emulation subsystems.  Boards only have
+  to list the components they need, and the compiled executable will
+  include all the required dependencies and all the devices that the
+  user can add to that board;
+
+* users can easily build reduced versions of QEMU that support only a subset
+  of boards or devices.  For example, by default most targets will include
+  all emulated PCI devices that QEMU supports, but the build process is
+  configurable and it is easy to drop unnecessary (or otherwise unwanted)
+  code to make a leaner binary.
+
+This domain-specific language is based on the Kconfig language that
+originated in the Linux kernel, though it was heavily simplified and
+the handling of dependencies is stricter in QEMU.
+
+Unlike Linux, there is no user interface to edit the configuration, which
+is instead specified in per-target files under the ``default-configs/``
+directory of the QEMU source tree.  This is because, unlike Linux,
+configuration and dependencies can be treated as a black box when building
+QEMU; the default configuration that QEMU ships with should be okay in
+almost all cases.
+
+The Kconfig language
+--------------------
+
+Kconfig defines configurable components in files named ``hw/*/Kconfig``.
+Note that configurable components are _not_ visible in C code as preprocessor
+symbols; they are only visible in the Makefile.  Each configurable component
+defines a Makefile variable whose name starts with ``CONFIG_``.
+
+All elements have boolean (true/false) type; truth is written as ``y``, while
+falsehood is written ``n``.  They are defined in a Kconfig
+stanza like the following::
+
+      config ARM_VIRT
+         bool
+         imply PCI_DEVICES
+         imply VFIO_AMD_XGBE
+         imply VFIO_XGMAC
+         select A15MPCORE
+         select ACPI
+         select ARM_SMMUV3
+
+The ``config`` keyword introduces a new configuration element.  In the example
+above, Makefiles will have access to a variable named ``CONFIG_ARM_VIRT``,
+with value ``y`` or ``n`` (respectively for boolean true and false).
+
+Boolean expressions can be used within the language, whenever ``<expr>``
+is written in the remainder of this section.  The ``&&``, ``||`` and
+``!`` operators respectively denote conjunction (AND), disjunction (OR)
+and negation (NOT).
+
+The ``bool`` data type declaration is optional, but it is suggested to
+include it for clarity and future-proofing.  After ``bool`` the following
+directives can be included:
+
+**dependencies**: ``depends on <expr>``
+
+  This defines a dependency for this configurable element. Dependencies
+  evaluate an expression and force the value of the variable to false
+  if the expression is false.
+
+**reverse dependencies**: ``select <symbol> [if <expr>]``
+
+  While ``depends on`` can force a symbol to false, reverse dependencies can
+  be used to force another symbol to true.  In the following example,
+  ``CONFIG_BAZ`` will be true whenever ``CONFIG_FOO`` is true::
+
+    config FOO
+      select BAZ
+
+  The optional expression will prevent ``select`` from having any effect
+  unless it is true.
+
+  Note that unlike Linux's Kconfig implementation, QEMU will detect
+  contradictions between ``depends on`` and ``select`` statements and prevent
+  you from building such a configuration.
+
+**default value**: ``default <value> [if <expr>]``
+
+  Default values are assigned to the config symbol if no other value was
+  set by the user via ``default-configs/*.mak`` files, and only if
+  ``select`` or ``depends on`` directives do not force the value to true
+  or false respectively.  ``<value>`` can be ``y`` or ``n``; it cannot
+  be an arbitrary Boolean expression.  However, a condition for applying
+  the default value can be added with ``if``.
+
+  A configuration element can have any number of default values (usually,
+  if more than one default is present, they will have different
+  conditions). If multiple default values satisfy their condition,
+  only the first defined one is active.
+
+**reverse default** (weak reverse dependency): ``imply <symbol> [if <expr>]``
+
+  This is similar to ``select`` as it applies a lower limit of ``y``
+  to another symbol.  However, the lower limit is only a default
+  and the "implied" symbol's value may still be set to ``n`` from a
+  ``default-configs/*.mak`` files.  The following two examples are
+  equivalent::
+
+    config FOO
+      bool
+      imply BAZ
+
+    config BAZ
+      bool
+      default y if FOO
+
+  The next section explains where to use ``imply`` or ``default y``.
+
+Guidelines for writing Kconfig files
+------------------------------------
+
+Configurable elements in QEMU fall under five broad groups.  Each group
+declares its dependencies in different ways:
+
+**subsystems**, of which **buses** are a special case
+
+  Example::
+
+    config SCSI
+      bool
+
+  Subsystems always default to false (they have no ``default`` directive)
+  and are never visible in ``default-configs/*.mak`` files.  It's
+  up to other symbols to ``select`` whatever subsystems they require.
+
+  They sometimes have ``select`` directives to bring in other required
+  subsystems or buses.  For example, ``AUX`` (the DisplayPort auxiliary
+  channel "bus") selects ``I2C`` because it can act as an I2C master too.
+
+**devices**
+
+  Example::
+
+    config MEGASAS_SCSI_PCI
+      bool
+      default y if PCI_DEVICES
+      depends on PCI
+      select SCSI
+
+  Devices are the most complex of the five.  They can have a variety
+  of directives that cooperate so that a default configuration includes
+  all the devices that can be accessed from QEMU.
+
+  Devices *depend on* the bus that they lie on, for example a PCI
+  device would specify ``depends on PCI``.  An MMIO device will likely
+  have no ``depends on`` directive.  Devices also *select* the buses
+  that the device provides, for example a SCSI adapter would specify
+  ``select SCSI``.  Finally, devices are usually ``default y`` if and
+  only if they have at least one ``depends on``; the default could be
+  conditional on a device group.
+
+  Devices also select any optional subsystem that they use; for example
+  a video card might specify ``select EDID`` if it needs to build EDID
+  information and publish it to the guest.
+
+**device groups**
+
+  Example::
+
+    config PCI_DEVICES
+      bool
+
+  Device groups provide a convenient mechanism to enable/disable many
+  devices in one go.  This is useful when a set of devices is likely to
+  be enabled/disabled by several targets.  Device groups usually need
+  no directive and are not used in the Makefile either; they only appear
+  as conditions for ``default y`` directives.
+
+  QEMU currently has two device groups, ``PCI_DEVICES`` and
+  ``TEST_DEVICES``.  PCI devices usually have a ``default y if
+  PCI_DEVICES`` directive rather than just ``default y``.  This lets
+  some boards (notably s390) easily support a subset of PCI devices,
+  for example only VFIO (passthrough) and virtio-pci devices.
+  ``TEST_DEVICES`` instead is used for devices that are rarely used on
+  production virtual machines, but provide useful hooks to test QEMU
+  or KVM.
+
+**boards**
+
+  Example::
+
+    config SUN4M
+      bool
+      imply TCX
+      imply CG3
+      select CS4231
+      select ECCMEMCTL
+      select EMPTY_SLOT
+      select ESCC
+      select ESP
+      select FDC
+      select SLAVIO
+      select LANCE
+      select M48T59
+      select STP2000
+
+  Boards specify their constituent devices using ``imply`` and ``select``
+  directives.  A device should be listed under ``select`` if the board
+  cannot be started at all without it.  It should be listed under
+  ``imply`` if (depending on the QEMU command line) the board may or
+  may not be started without it.  Boards also default to false; they are
+  enabled by the ``default-configs/*.mak`` for the target they apply to.
+
+**internal elements**
+
+  Example::
+
+    config ECCMEMCTL
+      bool
+      select ECC
+
+  Internal elements group code that is useful in several boards or
+  devices.  They are usually enabled with ``select`` and in turn select
+  other elements; they are never visible in ``default-configs/*.mak``
+  files, and often not even in the Makefile.
+
+Writing and modifying default configurations
+--------------------------------------------
+
+In addition to the Kconfig files under hw/, each target also includes
+a file called ``default-configs/TARGETNAME-softmmu.mak``.  These files
+initialize some Kconfig variables to non-default values and provide the
+starting point to turn on devices and subsystems.
+
+A file in ``default-configs/`` looks like the following example::
+
+    # Default configuration for alpha-softmmu
+
+    # Uncomment the following lines to disable these optional devices:
+    #
+    #CONFIG_PCI_DEVICES=n
+    #CONFIG_TEST_DEVICES=n
+
+    # Boards:
+    #
+    CONFIG_DP264=y
+
+The first part, consisting of commented-out ``=n`` assignments, tells
+the user which devices or device groups are implied by the boards.
+The second part, consisting of ``=y`` assignments, tells the user which
+boards are supported by the target.  The user will typically modify
+the default configuration by uncommenting lines in the first group,
+or commenting out lines in the second group.
+
+It is also possible to run QEMU's configure script with the
+``--with-default-devices`` option.  When this is done, everything defaults
+to ``n`` unless it is ``select``ed or explicitly switched on in the
+``.mak`` files.  In other words, ``default`` and ``imply`` directives
+are disabled.  When QEMU is built with this option, the user will probably
+want to change some lines in the first group, for example like this::
+
+   CONFIG_PCI_DEVICES=y
+   #CONFIG_TEST_DEVICES=n
+
+and/or pick a subset of the devices in those device groups.  Right now
+there is no single place that lists all the optional devices for
+``CONFIG_PCI_DEVICES`` and ``CONFIG_TEST_DEVICES``.  In the future,
+we expect that ``.mak`` files will be automatically generated, so that
+they will include all these symbols and some help text on what they do.
+
+``Kconfig.host``
+----------------
+
+In some special cases, a configurable element depends on host features
+that are detected by QEMU's configure script; for example some devices
+depend on the availability of KVM or on the presence of a library on
+the host.
+
+These symbols should be listed in ``Kconfig.host`` like this::
+
+    config KVM
+      bool
+
+and also listed as follows in the top-level Makefile's ``MINIKCONF_ARGS``
+variable::
+
+    MINIKCONF_ARGS = \
+      $@ $*-config.devices.mak.d $< $(MINIKCONF_INPUTS) \
+      CONFIG_KVM=$(CONFIG_KVM) \
+      CONFIG_SPICE=$(CONFIG_SPICE) \
+      CONFIG_TPM=$(CONFIG_TPM) \
+      ...
diff --git a/hw/9pfs/Kconfig b/hw/9pfs/Kconfig
new file mode 100644
index 0000000000..8c5032c575
--- /dev/null
+++ b/hw/9pfs/Kconfig
@@ -0,0 +1,4 @@
+config VIRTIO_9P
+    bool
+    default y
+    depends on VIRTFS && VIRTIO
diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
index 8ac04962bd..70ded6fd8f 100644
--- a/hw/9pfs/Makefile.objs
+++ b/hw/9pfs/Makefile.objs
@@ -1,11 +1,9 @@
-ifeq ($(call lor,$(CONFIG_VIRTIO_9P),$(CONFIG_XEN)),y)
 common-obj-y  = 9p.o 9p-util.o
 common-obj-y += 9p-local.o 9p-xattr.o
 common-obj-y += 9p-xattr-user.o 9p-posix-acl.o
 common-obj-y += coth.o cofs.o codir.o cofile.o
 common-obj-y += coxattr.o 9p-synth.o
 common-obj-y += 9p-proxy.o
-endif
 
 common-obj-$(CONFIG_XEN) += xen-9p-backend.o
 obj-$(CONFIG_VIRTIO_9P) += virtio-9p-device.o
diff --git a/hw/Kconfig b/hw/Kconfig
new file mode 100644
index 0000000000..d5ecd02070
--- /dev/null
+++ b/hw/Kconfig
@@ -0,0 +1,73 @@
+# devices Kconfig
+source 9pfs/Kconfig
+source acpi/Kconfig
+source adc/Kconfig
+source audio/Kconfig
+source block/Kconfig
+source bt/Kconfig
+source char/Kconfig
+source core/Kconfig
+source display/Kconfig
+source dma/Kconfig
+source gpio/Kconfig
+source hyperv/Kconfig
+source i2c/Kconfig
+source ide/Kconfig
+source input/Kconfig
+source intc/Kconfig
+source ipack/Kconfig
+source ipmi/Kconfig
+source isa/Kconfig
+source mem/Kconfig
+source misc/Kconfig
+source net/Kconfig
+source nvram/Kconfig
+source pci-bridge/Kconfig
+source pci-host/Kconfig
+source pcmcia/Kconfig
+source pci/Kconfig
+source scsi/Kconfig
+source sd/Kconfig
+source smbios/Kconfig
+source ssi/Kconfig
+source timer/Kconfig
+source tpm/Kconfig
+source usb/Kconfig
+source virtio/Kconfig
+source vfio/Kconfig
+source watchdog/Kconfig
+
+# arch Kconfig
+source arm/Kconfig
+source alpha/Kconfig
+source cris/Kconfig
+source hppa/Kconfig
+source i386/Kconfig
+source lm32/Kconfig
+source m68k/Kconfig
+source microblaze/Kconfig
+source mips/Kconfig
+source moxie/Kconfig
+source nios2/Kconfig
+source openrisc/Kconfig
+source ppc/Kconfig
+source riscv/Kconfig
+source s390x/Kconfig
+source sh4/Kconfig
+source sparc/Kconfig
+source sparc64/Kconfig
+source tricore/Kconfig
+source unicore32/Kconfig
+source xtensa/Kconfig
+
+# Symbols used by multiple targets
+config TEST_DEVICES
+    bool
+
+config XILINX
+    bool
+    select PTIMER # for hw/timer/xilinx_timer.c
+
+config XILINX_AXI
+    bool
+    select PTIMER # for hw/dma/xilinx_axidma.c
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index e2fcd6aafc..82aa7fab8e 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,4 +1,4 @@
-devices-dirs-$(call land,$(CONFIG_VIRTFS),$(call lor,$(CONFIG_VIRTIO),$(CONFIG_XEN))) += 9pfs/
+devices-dirs-$(call lor,$(CONFIG_VIRTIO_9P),$(call land,$(CONFIG_VIRTFS),$(CONFIG_XEN))) += 9pfs/
 devices-dirs-$(CONFIG_SOFTMMU) += acpi/
 devices-dirs-$(CONFIG_SOFTMMU) += adc/
 devices-dirs-$(CONFIG_SOFTMMU) += audio/
@@ -10,7 +10,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += display/
 devices-dirs-$(CONFIG_SOFTMMU) += dma/
 devices-dirs-$(CONFIG_SOFTMMU) += gpio/
 devices-dirs-$(CONFIG_HYPERV) += hyperv/
-devices-dirs-$(CONFIG_SOFTMMU) += i2c/
+devices-dirs-$(CONFIG_I2C) += i2c/
 devices-dirs-$(CONFIG_SOFTMMU) += ide/
 devices-dirs-$(CONFIG_SOFTMMU) += input/
 devices-dirs-$(CONFIG_SOFTMMU) += intc/
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
new file mode 100644
index 0000000000..eca3beed75
--- /dev/null
+++ b/hw/acpi/Kconfig
@@ -0,0 +1,29 @@
+config ACPI
+    bool
+
+config ACPI_X86
+    bool
+    select ACPI
+    select ACPI_NVDIMM
+    select ACPI_CPU_HOTPLUG
+    select ACPI_MEMORY_HOTPLUG
+
+config ACPI_X86_ICH
+    bool
+    select ACPI_X86
+
+config ACPI_CPU_HOTPLUG
+    bool
+
+config ACPI_MEMORY_HOTPLUG
+    bool
+    select MEM_DEVICE
+
+config ACPI_NVDIMM
+    bool
+    depends on ACPI
+
+config ACPI_VMGENID
+    bool
+    default y
+    depends on PC
diff --git a/hw/adc/Kconfig b/hw/adc/Kconfig
new file mode 100644
index 0000000000..25d2229fb8
--- /dev/null
+++ b/hw/adc/Kconfig
@@ -0,0 +1,2 @@
+config STM32F2XX_ADC
+    bool
diff --git a/hw/alpha/Kconfig b/hw/alpha/Kconfig
new file mode 100644
index 0000000000..22cefd9577
--- /dev/null
+++ b/hw/alpha/Kconfig
@@ -0,0 +1,12 @@
+config DP264
+    bool
+    imply PCI_DEVICES
+    imply TEST_DEVICES
+    select I82374
+    select I8254
+    select I8259
+    select IDE_CMD646
+    select MC146818RTC
+    select PCI
+    select PCKBD
+    select SMC37C669
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
new file mode 100644
index 0000000000..d298fbdc89
--- /dev/null
+++ b/hw/arm/Kconfig
@@ -0,0 +1,124 @@
+config ARM_VIRT
+    bool
+    imply VFIO_PLATFORM
+
+config DIGIC
+    bool
+    select PTIMER
+
+config EXYNOS4
+    bool
+    select PTIMER
+
+config HIGHBANK
+    bool
+
+config INTEGRATOR
+    bool
+
+config MAINSTONE
+    bool
+
+config MUSICPAL
+    bool
+    select PTIMER
+
+config NETDUINO2
+    bool
+
+config NSERIES
+    bool
+
+config OMAP
+    bool
+
+config PXA2XX
+    bool
+
+config REALVIEW
+    bool
+
+config STELLARIS
+    bool
+
+config STRONGARM
+    bool
+
+config VERSATILE
+    bool
+
+config ZYNQ
+    bool
+
+config ARM_V7M
+    bool
+
+config ALLWINNER_A10
+    bool
+
+config RASPI
+    bool
+
+config STM32F205_SOC
+    bool
+
+config XLNX_ZYNQMP_ARM
+    bool
+
+config XLNX_VERSAL
+    bool
+
+config FSL_IMX25
+    bool
+
+config FSL_IMX31
+    bool
+
+config FSL_IMX6
+    bool
+
+config ASPEED_SOC
+    bool
+
+config MPS2
+    bool
+
+config FSL_IMX7
+    bool
+
+config ARM_SMMUV3
+    bool
+
+config FSL_IMX6UL
+    bool
+
+config NRF51_SOC
+    bool
+
+config MSF2
+    bool
+    select PTIMER
+
+config ZAURUS
+    bool
+
+config A9MPCORE
+    bool
+
+config A15MPCORE
+    bool
+
+config ARM11MPCORE
+    bool
+
+config ARMSSE
+    bool
+
+config ARMSSE_CPUID
+    bool
+
+config ARMSSE_MHU
+    bool
+
+config MUSCA
+    bool
diff --git a/hw/audio/Kconfig b/hw/audio/Kconfig
new file mode 100644
index 0000000000..e9c6fed826
--- /dev/null
+++ b/hw/audio/Kconfig
@@ -0,0 +1,52 @@
+config SB16
+    bool
+    default y
+    depends on ISA_BUS
+
+config ES1370
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config AC97
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config ADLIB
+    bool
+    default y
+    depends on ISA_BUS
+
+config GUS
+    bool
+    default y
+    depends on ISA_BUS
+
+config CS4231A
+    bool
+    default y
+    depends on ISA_BUS
+
+config HDA
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config PCSPK
+    bool
+    default y
+    depends on I8254
+
+config WM8750
+    bool
+    depends on I2C
+
+config PL041
+    bool
+
+config CS4231
+    bool
+
+config MARVELL_88W8618
+    bool
diff --git a/hw/block/Kconfig b/hw/block/Kconfig
new file mode 100644
index 0000000000..df96dc5dcc
--- /dev/null
+++ b/hw/block/Kconfig
@@ -0,0 +1,39 @@
+config FDC
+    bool
+    # FIXME: there is no separate file for the MMIO floppy disk controller, so
+    # select ISA_BUS here instead of polluting each board that requires one
+    select ISA_BUS
+
+config SSI_M25P80
+    bool
+
+config NAND
+    bool
+
+config PFLASH_CFI01
+    bool
+
+config PFLASH_CFI02
+    bool
+
+config ECC
+    bool
+
+config ONENAND
+    bool
+
+config NVME_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config VIRTIO_BLK
+    bool
+    default y
+    depends on VIRTIO
+
+config VHOST_USER_BLK
+    bool
+    # Only PCI devices are provided for now
+    default y if VIRTIO_PCI
+    depends on VIRTIO && VHOST_USER && LINUX
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
index e206b8e712..f5f643f0cc 100644
--- a/hw/block/Makefile.objs
+++ b/hw/block/Makefile.objs
@@ -12,5 +12,6 @@ common-obj-$(CONFIG_NVME_PCI) += nvme.o
 obj-$(CONFIG_SH4) += tc58128.o
 
 obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
-obj-$(CONFIG_VIRTIO_BLK) += dataplane/
 obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
+
+obj-y += dataplane/
diff --git a/hw/block/dataplane/Makefile.objs b/hw/block/dataplane/Makefile.objs
index c6c68dbc00..0c5270268e 100644
--- a/hw/block/dataplane/Makefile.objs
+++ b/hw/block/dataplane/Makefile.objs
@@ -1,2 +1,2 @@
-obj-y += virtio-blk.o
+obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
 obj-$(CONFIG_XEN) += xen-block.o
diff --git a/hw/bt/Kconfig b/hw/bt/Kconfig
new file mode 100644
index 0000000000..554a9ee75e
--- /dev/null
+++ b/hw/bt/Kconfig
@@ -0,0 +1,2 @@
+config BLUETOOTH
+    bool
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
new file mode 100644
index 0000000000..6360c9fffa
--- /dev/null
+++ b/hw/char/Kconfig
@@ -0,0 +1,42 @@
+config ESCC
+    bool
+
+config PARALLEL
+    bool
+    default y
+    depends on ISA_BUS
+
+config PL011
+    bool
+
+config SERIAL
+    bool
+
+config SERIAL_ISA
+    bool
+    default y
+    depends on ISA_BUS
+    select SERIAL
+
+config SERIAL_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select SERIAL
+
+config VIRTIO_SERIAL
+    bool
+    default y
+    depends on VIRTIO
+
+config STM32F2XX_USART
+    bool
+
+config CMSDK_APB_UART
+    bool
+
+config SCLPCONSOLE
+    bool
+
+config TERMINAL3270
+    bool
diff --git a/hw/core/Kconfig b/hw/core/Kconfig
new file mode 100644
index 0000000000..c2a1ae8122
--- /dev/null
+++ b/hw/core/Kconfig
@@ -0,0 +1,11 @@
+config EMPTY_SLOT
+    bool
+
+config PTIMER
+    bool
+
+config FITLOADER
+    bool
+
+config PLATFORM_BUS
+    bool
diff --git a/hw/cpu/Kconfig b/hw/cpu/Kconfig
new file mode 100644
index 0000000000..1767d028ac
--- /dev/null
+++ b/hw/cpu/Kconfig
@@ -0,0 +1,8 @@
+config ARM11MPCORE
+    bool
+
+config A9MPCORE
+    bool
+
+config A15MPCORE
+    bool
diff --git a/hw/cris/Kconfig b/hw/cris/Kconfig
new file mode 100644
index 0000000000..884ad2cbc0
--- /dev/null
+++ b/hw/cris/Kconfig
@@ -0,0 +1,9 @@
+config AXIS
+    bool
+    select ETRAXFS
+    select PFLASH_CFI02
+    select NAND
+
+config ETRAXFS
+   bool
+   select PTIMER
diff --git a/hw/display/Kconfig b/hw/display/Kconfig
new file mode 100644
index 0000000000..a96ea763a8
--- /dev/null
+++ b/hw/display/Kconfig
@@ -0,0 +1,108 @@
+config EDID
+    bool
+
+config FW_CFG_DMA
+    bool
+
+config ADS7846
+    bool
+
+config VGA_CIRRUS
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select VGA
+
+config G364FB
+    bool
+
+config JAZZ_LED
+    bool
+
+config PL110
+    bool
+
+config SII9022
+    bool
+    depends on I2C
+
+config SSD0303
+    bool
+    depends on I2C
+
+config SSD0323
+    bool
+
+config VGA_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select VGA
+    select EDID
+
+config VGA_ISA
+    bool
+    depends on ISA_BUS
+    select VGA
+
+config VGA_ISA_MM
+    bool
+    select VGA
+
+config VMWARE_VGA
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select VGA
+
+config BOCHS_DISPLAY
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select VGA
+    select EDID
+
+config BLIZZARD
+    bool
+
+config FRAMEBUFFER
+    bool
+
+config MILKYMIST_TMU2
+    bool
+    depends on OPENGL && X11
+
+config SM501
+    bool
+    select I2C
+    select DDC
+    select SERIAL
+
+config TCX
+    bool
+
+config CG3
+    bool
+
+config VGA
+    bool
+
+config QXL
+    bool
+    depends on SPICE && PCI
+    select VGA
+
+config VIRTIO_GPU
+    bool
+    default y
+    depends on VIRTIO
+    select EDID
+
+config VIRTIO_VGA
+    bool
+    default y if PCI_DEVICES
+    depends on VIRTIO_PCI
+    select VGA
+
+config DPCD
+    bool
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index 7c4ae9a0fd..576fca4eb6 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += edid-generate.o
+common-obj-$(CONFIG_EDID) += edid-generate.o edid-region.o
 
 common-obj-$(CONFIG_FW_CFG_DMA) += ramfb.o
 common-obj-$(CONFIG_FW_CFG_DMA) += ramfb-standalone.o
@@ -15,12 +15,10 @@ common-obj-$(CONFIG_SSD0323) += ssd0323.o
 common-obj-$(CONFIG_XEN) += xenfb.o
 
 common-obj-$(CONFIG_VGA_PCI) += vga-pci.o
-common-obj-$(CONFIG_VGA_PCI) += edid-region.o
 common-obj-$(CONFIG_VGA_ISA) += vga-isa.o
 common-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
 common-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
 common-obj-$(CONFIG_BOCHS_DISPLAY) += bochs-display.o
-common-obj-$(CONFIG_BOCHS_DISPLAY) += edid-region.o
 
 common-obj-$(CONFIG_BLIZZARD) += blizzard.o
 common-obj-$(CONFIG_EXYNOS4) += exynos4210_fimd.o
diff --git a/hw/dma/Kconfig b/hw/dma/Kconfig
new file mode 100644
index 0000000000..751dec5426
--- /dev/null
+++ b/hw/dma/Kconfig
@@ -0,0 +1,21 @@
+config RC4030
+    bool
+
+config PL080
+    bool
+
+config PL330
+    bool
+
+config I82374
+    bool
+    select I8257
+
+config I8257
+    bool
+
+config ZYNQ_DEVCFG
+    bool
+
+config STP2000
+    bool
diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig
new file mode 100644
index 0000000000..9227cb5598
--- /dev/null
+++ b/hw/gpio/Kconfig
@@ -0,0 +1,9 @@
+config MAX7310
+    bool
+    depends on I2C
+
+config PL061
+    bool
+
+config GPIO_KEY
+    bool
diff --git a/hw/hppa/Kconfig b/hw/hppa/Kconfig
new file mode 100644
index 0000000000..2d9b072c21
--- /dev/null
+++ b/hw/hppa/Kconfig
@@ -0,0 +1,10 @@
+config DINO
+    bool
+    imply PCI_DEVICES
+    select PCI
+    select SERIAL
+    select ISA_BUS
+    select I8259
+    select IDE_CMD646
+    select MC146818RTC
+    select LSI_SCSI_PCI
diff --git a/hw/hyperv/Kconfig b/hw/hyperv/Kconfig
new file mode 100644
index 0000000000..a1fa8ff9be
--- /dev/null
+++ b/hw/hyperv/Kconfig
@@ -0,0 +1,8 @@
+config HYPERV
+    bool
+    depends on KVM
+
+config HYPERV_TESTDEV
+    bool
+    default y if TEST_DEVICES
+    depends on HYPERV
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
new file mode 100644
index 0000000000..ef1caa6d89
--- /dev/null
+++ b/hw/i2c/Kconfig
@@ -0,0 +1,27 @@
+config I2C
+    bool
+
+config SMBUS_EEPROM
+    bool
+    depends on I2C
+
+config DDC
+    bool
+    depends on I2C
+    select EDID
+
+config VERSATILE_I2C
+    bool
+    select I2C
+
+config ACPI_SMBUS
+    bool
+    select I2C
+
+config BITBANG_I2C
+    bool
+    select I2C
+
+config IMX_I2C
+    bool
+    select I2C
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index 9205cbee16..2a3c106551 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -2,7 +2,7 @@ common-obj-$(CONFIG_I2C) += core.o smbus_slave.o smbus_master.o
 common-obj-$(CONFIG_SMBUS_EEPROM) += smbus_eeprom.o
 common-obj-$(CONFIG_DDC) += i2c-ddc.o
 common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
-common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
+common-obj-$(CONFIG_ACPI_X86_ICH) += smbus_ich9.o
 common-obj-$(CONFIG_ACPI_SMBUS) += pm_smbus.o
 common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
 common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
new file mode 100644
index 0000000000..78fd70396a
--- /dev/null
+++ b/hw/i386/Kconfig
@@ -0,0 +1,99 @@
+config SEV
+    bool
+    depends on KVM
+
+config PC
+    bool
+    imply APPLESMC
+    imply HYPERV
+    imply ISA_IPMI_KCS
+    imply ISA_IPMI_BT
+    imply ISA_DEBUG
+    imply PCI_DEVICES
+    imply PVPANIC
+    imply QXL
+    imply SEV
+    imply SGA
+    imply TEST_DEVICES
+    imply TPM_CRB
+    imply TPM_TIS
+    select FDC
+    select I8259
+    select I8254
+    select PCKBD
+    select PCSPK
+    select I82374
+    select I8257
+    select MC146818RTC
+    # Needed by the board code:
+    select PARALLEL
+    # For ACPI builder:
+    select SERIAL_ISA
+    select ACPI_VMGENID
+
+config PC_PCI
+    bool
+    select APIC
+    select IOAPIC
+    select APM
+    select PC
+
+config PC_ACPI
+    bool
+    select ACPI_X86
+    select ACPI_CPU_HOTPLUG
+    select ACPI_MEMORY_HOTPLUG
+    select SMBUS_EEPROM
+    select PFLASH_CFI01
+    depends on ACPI_SMBUS
+
+config I440FX
+    bool
+    select PC_PCI
+    select PC_ACPI
+    select ACPI_SMBUS
+    select PCI_PIIX
+    select IDE_PIIX
+    select DIMM
+    select SMBIOS
+    select VMPORT
+    select VMMOUSE
+    select FW_CFG_DMA
+
+config ISAPC
+    bool
+    select ISA_BUS
+    select PC
+    select IDE_ISA
+    select VGA_ISA
+    # FIXME: it is in the same file as i440fx, and does not compile
+    # if separated
+    depends on I440FX
+
+config Q35
+    bool
+    imply VTD
+    imply AMD_IOMMU
+    select PC_PCI
+    select PC_ACPI
+    select PCI_EXPRESS_Q35
+    select LPC_ICH9
+    select AHCI
+    select DIMM
+    select SMBIOS
+    select VMPORT
+    select VMMOUSE
+    select FW_CFG_DMA
+
+config VTD
+    bool
+
+config AMD_IOMMU
+    bool
+
+config VMPORT
+    bool
+
+config VMMOUSE
+    bool
+    depends on VMPORT
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 3de7ca2bb9..27248a0777 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -4,8 +4,9 @@ obj-y += pc.o
 obj-$(CONFIG_I440FX) += pc_piix.o
 obj-$(CONFIG_Q35) += pc_q35.o
 obj-y += pc_sysfw.o
-obj-$(CONFIG_VTD) += x86-iommu.o intel_iommu.o
-obj-$(CONFIG_AMD_IOMMU) += x86-iommu.o amd_iommu.o
+obj-y += x86-iommu.o
+obj-$(CONFIG_VTD) += intel_iommu.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 obj-$(CONFIG_VMPORT) += vmport.o
 obj-$(CONFIG_VMMOUSE) += vmmouse.o
diff --git a/hw/ide/Kconfig b/hw/ide/Kconfig
new file mode 100644
index 0000000000..ab47b6a7a3
--- /dev/null
+++ b/hw/ide/Kconfig
@@ -0,0 +1,54 @@
+config IDE_CORE
+    bool
+
+config IDE_QDEV
+    bool
+    select IDE_CORE
+
+config IDE_PCI
+    bool
+    depends on PCI
+    select IDE_CORE
+
+config IDE_ISA
+    bool
+    depends on ISA_BUS
+    select IDE_QDEV
+
+config IDE_PIIX
+    bool
+    select IDE_PCI
+    select IDE_QDEV
+
+config IDE_CMD646
+    bool
+    select IDE_PCI
+    select IDE_QDEV
+
+config IDE_MACIO
+    bool
+    select IDE_QDEV
+
+config IDE_MMIO
+    bool
+    select IDE_QDEV
+
+config IDE_VIA
+    bool
+    select IDE_PCI
+    select IDE_QDEV
+
+config MICRODRIVE
+    bool
+    select IDE_QDEV
+
+config AHCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select IDE_QDEV
+
+config IDE_SII3112
+    bool
+    select IDE_PCI
+    select IDE_QDEV
diff --git a/hw/input/Kconfig b/hw/input/Kconfig
new file mode 100644
index 0000000000..e2e66f0858
--- /dev/null
+++ b/hw/input/Kconfig
@@ -0,0 +1,33 @@
+config ADB
+    bool
+
+config LM832X
+    bool
+    depends on I2C
+
+config PCKBD
+    bool
+    default y
+    depends on ISA_BUS
+
+config PL050
+    bool
+
+config STELLARIS_INPUT
+    bool
+
+config TSC2005
+    bool
+
+config VIRTIO_INPUT
+    bool
+    default y
+    depends on VIRTIO
+
+config VIRTIO_INPUT_HOST
+    bool
+    default y
+    depends on VIRTIO && LINUX
+
+config TSC210X
+    bool
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
new file mode 100644
index 0000000000..de10a6bcbf
--- /dev/null
+++ b/hw/intc/Kconfig
@@ -0,0 +1,57 @@
+config HEATHROW_PIC
+    bool
+
+config I8259
+    bool
+
+config PL190
+    bool
+
+config IOAPIC
+    bool
+
+config ARM_GIC
+    bool
+
+config OPENPIC
+    bool
+
+config APIC
+    bool
+
+config ARM_GIC_KVM
+    bool
+    default y
+    depends on ARM_GIC && KVM
+
+config OPENPIC_KVM
+    bool
+    default y
+    depends on OPENPIC && KVM
+
+config XICS
+    bool
+    depends on POWERNV || PSERIES
+
+config XICS_SPAPR
+    bool
+    select XICS
+
+config XICS_KVM
+    bool
+    default y
+    depends on XICS && KVM
+
+config ALLWINNER_A10_PIC
+    bool
+
+config S390_FLIC
+    bool
+
+config S390_FLIC_KVM
+    bool
+    default y
+    depends on S390_FLIC && KVM
+
+config OMPIC
+    bool
diff --git a/hw/ipack/Kconfig b/hw/ipack/Kconfig
new file mode 100644
index 0000000000..f8da24a62b
--- /dev/null
+++ b/hw/ipack/Kconfig
@@ -0,0 +1,4 @@
+config IPACK
+    bool
+    default y if PCI_DEVICES
+	    depends on PCI
diff --git a/hw/ipmi/Kconfig b/hw/ipmi/Kconfig
new file mode 100644
index 0000000000..b944fae100
--- /dev/null
+++ b/hw/ipmi/Kconfig
@@ -0,0 +1,22 @@
+config IPMI
+    bool
+
+config IPMI_LOCAL
+    bool
+    default y
+    depends on IPMI
+
+config IPMI_EXTERN
+    bool
+    default y
+    depends on IPMI
+
+config ISA_IPMI_KCS
+    bool
+    depends on ISA_BUS
+    select IPMI
+
+config ISA_IPMI_BT
+    bool
+    depends on ISA_BUS
+    select IPMI
diff --git a/hw/isa/Kconfig b/hw/isa/Kconfig
new file mode 100644
index 0000000000..57e09a0cb8
--- /dev/null
+++ b/hw/isa/Kconfig
@@ -0,0 +1,53 @@
+config ISA_BUS
+    bool
+
+config APM
+    bool
+
+config I82378
+    bool
+    select ISA_BUS
+    select I8259
+    select I8254
+    select I82374
+    select MC146818RTC
+
+config PC87312
+    bool
+    select ISA_BUS
+    select I8259
+    select I8254
+    select I8257
+    select MC146818RTC
+    select SERIAL_ISA
+    select PARALLEL
+    select FDC
+    select IDE_ISA
+
+config PIIX4
+    bool
+    # For historical reasons, SuperIO devices are created in the board
+    # for PIIX4.
+    select ISA_BUS
+
+config VT82C686
+    bool
+    select ISA_BUS
+    select ACPI_SMBUS
+    select SERIAL_ISA
+    select FDC
+
+config SMC37C669
+    bool
+    select ISA_BUS
+    select SERIAL_ISA
+    select PARALLEL
+    select FDC
+
+config LPC_ICH9
+    bool
+    # For historical reasons, SuperIO devices are created in the board
+    # for ICH9.
+    select ISA_BUS
+    select ACPI_SMBUS
+    select ACPI_X86_ICH
diff --git a/hw/lm32/Kconfig b/hw/lm32/Kconfig
new file mode 100644
index 0000000000..3d09c2dd6f
--- /dev/null
+++ b/hw/lm32/Kconfig
@@ -0,0 +1,13 @@
+config LM32
+    bool
+    select PTIMER
+    select PFLASH_CFI02
+
+config MILKYMIST
+    bool
+    # FIXME: disabling it results in compile-time errors
+    select MILKYMIST_TMU2 if OPENGL && X11
+    select PTIMER
+    select PFLASH_CFI01
+    select FRAMEBUFFER
+    select SD
diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig
new file mode 100644
index 0000000000..49ef0b3f6d
--- /dev/null
+++ b/hw/m68k/Kconfig
@@ -0,0 +1,9 @@
+config AN5206
+    bool
+    select COLDFIRE
+    select PTIMER
+
+config MCF5208
+    bool
+    select COLDFIRE
+    select PTIMER
diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig
new file mode 100644
index 0000000000..620fd4cb59
--- /dev/null
+++ b/hw/mem/Kconfig
@@ -0,0 +1,11 @@
+config DIMM
+    bool
+    select MEM_DEVICE
+
+config MEM_DEVICE
+    bool
+
+config NVDIMM
+    bool
+    default y
+    depends on PC
diff --git a/hw/microblaze/Kconfig b/hw/microblaze/Kconfig
new file mode 100644
index 0000000000..c4dc120973
--- /dev/null
+++ b/hw/microblaze/Kconfig
@@ -0,0 +1,20 @@
+config PETALOGIX_S3ADSP1800
+    bool
+    select PFLASH_CFI01
+    select XILINX
+    select XILINX_AXI
+    select XILINX_ETHLITE
+
+config PETALOGIX_ML605
+    bool
+    select PFLASH_CFI01
+    select SERIAL
+    select SSI_M25P80
+    select XILINX
+    select XILINX_AXI
+    select XILINX_ETHLITE
+    select XILINX_SPI
+
+config XLNX_ZYNQMP_PMU
+    bool
+    select XLNX_ZYNQMP
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
new file mode 100644
index 0000000000..cdc07e59b6
--- /dev/null
+++ b/hw/mips/Kconfig
@@ -0,0 +1,21 @@
+config R4K
+    bool
+
+config MALTA
+    bool
+
+config MIPSSIM
+    bool
+
+config JAZZ
+    bool
+
+config FULONG
+    bool
+
+config MIPS_CPS
+    bool
+    select PTIMER
+
+config MIPS_BOSTON
+    bool
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
new file mode 100644
index 0000000000..2c60be99bc
--- /dev/null
+++ b/hw/misc/Kconfig
@@ -0,0 +1,118 @@
+config APPLESMC
+    bool
+    depends on ISA_BUS
+
+config MAX111X
+    bool
+
+config TMP105
+    bool
+    depends on I2C
+
+config TMP421
+    bool
+    depends on I2C
+
+config ISA_DEBUG
+    bool
+    depends on ISA_BUS
+
+config SGA
+    bool
+    depends on ISA_BUS
+
+config ISA_TESTDEV
+    bool
+    default y if TEST_DEVICES
+    depends on ISA_BUS
+
+config PCI_TESTDEV
+    bool
+    default y if TEST_DEVICES
+    depends on PCI
+
+config EDU
+    bool
+    default y if TEST_DEVICES
+    depends on PCI
+
+config PCA9552
+    bool
+    depends on I2C
+
+config PL310
+    bool
+
+config INTEGRATOR_DEBUG
+    bool
+
+config A9SCU
+    bool
+
+config ARM11SCU
+    bool
+
+config MOS6522
+    bool
+
+config MACIO
+    bool
+    select CUDA
+    select ESCC
+    select IDE_MACIO
+    select MAC_DBDMA
+    select MAC_NVRAM
+    select MOS6522
+
+config IVSHMEM_DEVICE
+    bool
+    default y if PCI_DEVICES
+    depends on PCI && LINUX && IVSHMEM
+
+config ECCMEMCTL
+    bool
+    select ECC
+
+config IMX
+    bool
+    select PTIMER
+
+config STM32F2XX_SYSCFG
+    bool
+
+config MIPS_ITU
+    bool
+
+config MPS2_FPGAIO
+    bool
+
+config MPS2_SCC
+    bool
+
+config TZ_MPC
+    bool
+
+config TZ_MSC
+    bool
+
+config TZ_PPC
+    bool
+
+config IOTKIT_SECCTL
+    bool
+
+config IOTKIT_SYSCTL
+    bool
+
+config IOTKIT_SYSINFO
+    bool
+
+config PVPANIC
+    bool
+    depends on ISA_BUS
+
+config AUX
+    bool
+    select I2C
+
+source macio/Kconfig
diff --git a/hw/misc/macio/Kconfig b/hw/misc/macio/Kconfig
new file mode 100644
index 0000000000..c6caeb672f
--- /dev/null
+++ b/hw/misc/macio/Kconfig
@@ -0,0 +1,11 @@
+config CUDA
+    bool
+
+config MAC_PMU
+    bool
+
+config MAC_DBDMA
+    bool
+
+config MACIO_GPIO
+    bool
diff --git a/hw/moxie/Kconfig b/hw/moxie/Kconfig
new file mode 100644
index 0000000000..3793ef0372
--- /dev/null
+++ b/hw/moxie/Kconfig
@@ -0,0 +1,3 @@
+config MOXIESIM
+    bool
+    select SERIAL
diff --git a/hw/net/Kconfig b/hw/net/Kconfig
new file mode 100644
index 0000000000..c00ec03cd1
--- /dev/null
+++ b/hw/net/Kconfig
@@ -0,0 +1,125 @@
+config DP8393X
+    bool
+
+config NE2000_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config EEPRO100_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config PCNET_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select PCNET_COMMON
+
+config PCNET_COMMON
+    bool
+
+config E1000_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config E1000E_PCI_EXPRESS
+    bool
+    default y if PCI_DEVICES
+    depends on PCI_EXPRESS
+
+config RTL8139_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config VMXNET3_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config SMC91C111
+    bool
+
+config LAN9118
+    bool
+    select PTIMER
+
+config NE2000_ISA
+    bool
+    default y
+    depends on ISA_BUS
+    depends on PCI # for NE2000State
+    select NE2000_PCI
+
+config OPENCORES_ETH
+    bool
+
+config XGMAC
+    bool
+
+config MIPSNET
+    bool
+
+config ALLWINNER_EMAC
+    bool
+
+config IMX_FEC
+    bool
+
+config CADENCE
+    bool
+
+config STELLARIS_ENET
+    bool
+
+config LANCE
+    bool
+    select PCNET_COMMON
+
+config SUNHME
+    bool
+
+config FTGMAC100
+    bool
+
+config SUNGEM
+    bool
+    depends on PCI
+
+config COLDFIRE
+    bool
+
+config XILINX_ETHLITE
+    bool
+
+config VIRTIO_NET
+    bool
+    default y
+    depends on VIRTIO
+
+config ETSEC
+    bool
+    select PTIMER
+
+config ROCKER
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config CAN_BUS
+    bool
+
+config CAN_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select CAN_BUS
+
+config CAN_SJA1000
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select CAN_BUS
diff --git a/hw/nios2/Kconfig b/hw/nios2/Kconfig
new file mode 100644
index 0000000000..ab953e0077
--- /dev/null
+++ b/hw/nios2/Kconfig
@@ -0,0 +1,8 @@
+config NIOS2_10M50
+    bool
+    select NIOS2
+    select SERIAL
+    select ALTERA_TIMER
+
+config NIOS2
+    bool
diff --git a/hw/nvram/Kconfig b/hw/nvram/Kconfig
new file mode 100644
index 0000000000..ebaa749ce9
--- /dev/null
+++ b/hw/nvram/Kconfig
@@ -0,0 +1,9 @@
+config DS1225Y
+    bool
+
+config AT24C
+    bool
+    depends on I2C
+
+config MAC_NVRAM
+    bool
diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig
new file mode 100644
index 0000000000..6c1e86884e
--- /dev/null
+++ b/hw/openrisc/Kconfig
@@ -0,0 +1,5 @@
+config OR1K_SIM
+    bool
+    select SERIAL
+    select OPENCORES_ETH
+    select OMPIC
diff --git a/hw/pci-bridge/Kconfig b/hw/pci-bridge/Kconfig
new file mode 100644
index 0000000000..b167b98497
--- /dev/null
+++ b/hw/pci-bridge/Kconfig
@@ -0,0 +1,29 @@
+config PCIE_PORT
+    bool
+    default y if PCI_DEVICES
+    depends on PCI_EXPRESS
+
+config PXB
+    bool
+    default y if Q35
+
+config XIO3130
+    bool
+    default y if PCI_DEVICES
+    depends on PCI_EXPRESS
+
+config IOH3420
+    bool
+    default y if PCI_DEVICES
+    depends on PCI_EXPRESS
+
+config I82801B11
+    bool
+    default y if PCI_DEVICES
+    depends on PCI_EXPRESS
+
+config DEC_PCI
+    bool
+
+config SIMBA
+    bool
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
new file mode 100644
index 0000000000..b39ea297ba
--- /dev/null
+++ b/hw/pci-host/Kconfig
@@ -0,0 +1,51 @@
+config PAM
+    bool
+
+config PREP_PCI
+    select PCI
+    bool
+
+config GRACKLE_PCI
+    select PCI
+    bool
+
+config UNIN_PCI
+    bool
+    select PCI
+    select DEC_PCI
+    select OPENPIC
+
+config PPCE500_PCI
+    select PCI
+    bool
+
+config VERSATILE_PCI
+    select PCI
+    bool
+
+config PCI_SABRE
+    select PCI
+    bool
+
+config PCI_PIIX
+    bool
+    select PCI
+    select PAM
+    select ISA_BUS
+
+config PCI_EXPRESS_Q35
+    bool
+    select PCI_EXPRESS
+    select PAM
+
+config PCI_EXPRESS_GENERIC_BRIDGE
+    bool
+    select PCI_EXPRESS
+
+config PCI_EXPRESS_XILINX
+    bool
+    select PCI_EXPRESS
+
+config PCI_EXPRESS_DESIGNWARE
+    bool
+    select PCI_EXPRESS
diff --git a/hw/pci/Kconfig b/hw/pci/Kconfig
new file mode 100644
index 0000000000..3b8638b51d
--- /dev/null
+++ b/hw/pci/Kconfig
@@ -0,0 +1,9 @@
+config PCI
+    bool
+
+config PCI_EXPRESS
+    bool
+    select PCI
+
+config PCI_DEVICES
+    bool
diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs
index 9f905e6344..c78f2fb24b 100644
--- a/hw/pci/Makefile.objs
+++ b/hw/pci/Makefile.objs
@@ -2,8 +2,13 @@ common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
 common-obj-$(CONFIG_PCI) += msix.o msi.o
 common-obj-$(CONFIG_PCI) += shpc.o
 common-obj-$(CONFIG_PCI) += slotid_cap.o
-common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
-common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
+common-obj-$(CONFIG_PCI) += pci_host.o
+
+# The functions in these modules can be used by devices too.  Since we
+# allow plugging PCIe devices into PCI buses, include them even if
+# CONFIG_PCI_EXPRESS=n.
+common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o
+common-obj-$(CONFIG_PCI_EXPRESS) += pcie_port.o pcie_host.o
 
 common-obj-$(call lnot,$(CONFIG_PCI)) += pci-stub.o
 common-obj-$(CONFIG_ALL) += pci-stub.o
diff --git a/hw/pcmcia/Kconfig b/hw/pcmcia/Kconfig
new file mode 100644
index 0000000000..41f2df9136
--- /dev/null
+++ b/hw/pcmcia/Kconfig
@@ -0,0 +1,2 @@
+config PCMCIA
+    bool
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
new file mode 100644
index 0000000000..2b83637511
--- /dev/null
+++ b/hw/ppc/Kconfig
@@ -0,0 +1,121 @@
+config PSERIES
+    bool
+    imply PCI_DEVICES
+    imply TEST_DEVICES
+    select DIMM
+    select PCI
+    select SPAPR_VSCSI
+    select VFIO if LINUX   # needed by spapr_pci_vfio.c
+    select XICS_SPAPR
+    select XIVE_SPAPR
+
+config SPAPR_RNG
+    bool
+    default y
+    depends on PSERIES
+
+config POWERNV
+    bool
+    imply PCI_DEVICES
+    imply TEST_DEVICES
+    select ISA_IPMI_BT
+    select IPMI_LOCAL
+    select ISA_BUS
+    select MC146818RTC
+    select XICS
+    select XIVE
+
+config PPC405
+    bool
+    select M48T59
+    select PFLASH_CFI02
+    select PPC4XX
+    select SERIAL
+
+config PPC440
+    bool
+    imply PCI_DEVICES
+    imply TEST_DEVICES
+    select PCI_EXPRESS
+    select PPC4XX
+    select SERIAL
+
+config PPC4XX
+    bool
+    select BITBANG_I2C
+    select PCI
+
+config SAM460EX
+    bool
+    select PFLASH_CFI01
+    select IDE_SII3112
+    select M41T80
+    select PPC440
+    select SERIAL
+    select SM501
+    select SMBUS_EEPROM
+    select USB_EHCI_SYSBUS
+    select USB_OHCI
+
+config PREP
+    bool
+    imply PCI_DEVICES
+    imply TEST_DEVICES
+    select CS4231A
+    select PREP_PCI
+    select I82374
+    select I82378
+    select LSI_SCSI_PCI
+    select M48T59
+    select PC87312
+    select RS6000_MC
+
+config RS6000_MC
+    bool
+
+config MAC_OLDWORLD
+    bool
+    imply PCI_DEVICES
+    imply SUNGEM
+    imply TEST_DEVICES
+    select ADB
+    select GRACKLE_PCI
+    select HEATHROW_PIC
+    select MACIO
+
+config MAC_NEWWORLD
+    bool
+    imply PCI_DEVICES
+    imply SUNGEM
+    imply TEST_DEVICES
+    select ADB
+    select MACIO
+    select MACIO_GPIO
+    select MAC_PMU
+    select UNIN_PCI
+
+config E500
+    bool
+    imply AT24C
+    select ETSEC
+    select OPENPIC
+    select PLATFORM_BUS
+    select PPCE500_PCI
+    select SERIAL
+
+config VIRTEX
+    bool
+    select PFLASH_CFI01
+    select SERIAL
+    select XILINX
+    select XILINX_ETHLITE
+
+config XIVE
+    bool
+    depends on POWERNV || PSERIES
+
+config XIVE_SPAPR
+    bool
+    default y
+    depends on PSERIES
+    select XIVE
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
new file mode 100644
index 0000000000..e0ee3043a6
--- /dev/null
+++ b/hw/riscv/Kconfig
@@ -0,0 +1,33 @@
+config HTIF
+    bool
+
+config HART
+    bool
+
+config SIFIVE
+    bool
+
+config SIFIVE_E
+    bool
+    select HART
+    select SIFIVE
+
+config SIFIVE_U
+    bool
+    select CADENCE
+    select HART
+    select SIFIVE
+
+config SPIKE
+    bool
+    select HART
+    select HTIF
+    select SIFIVE
+
+config RISCV_VIRT
+    bool
+    select HART
+    select SERIAL
+    select VIRTIO_MMIO
+    select PCI_EXPRESS_GENERIC_BRIDGE
+    select SIFIVE
diff --git a/hw/s390x/Kconfig b/hw/s390x/Kconfig
new file mode 100644
index 0000000000..a7046ea41f
--- /dev/null
+++ b/hw/s390x/Kconfig
@@ -0,0 +1,11 @@
+config S390_CCW_VIRTIO
+    bool
+    imply VIRTIO_PCI
+    imply TERMINAL3270
+    imply VFIO_AP
+    imply VFIO_CCW
+    imply WDT_DIAG288
+    select PCI
+    select S390_FLIC
+    select SCLPCONSOLE
+    select VIRTIO_CCW
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index bfd5326d7c..e02ed80b68 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -6,7 +6,8 @@ obj-y += sclpcpu.o
 obj-y += ipl.o
 obj-y += css.o
 obj-$(CONFIG_S390_CCW_VIRTIO) += s390-virtio-ccw.o
-obj-y += 3270-ccw.o
+obj-$(CONFIG_TERMINAL3270) += 3270-ccw.o
+ifeq ($(CONFIG_VIRTIO_CCW),y)
 obj-y += virtio-ccw.o
 obj-$(CONFIG_VIRTIO_SERIAL) += virtio-ccw-serial.o
 obj-$(CONFIG_VIRTIO_BALLOON) += virtio-ccw-balloon.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_VIRTIO_NET) += virtio-ccw-net.o
 obj-$(CONFIG_VIRTIO_BLK) += virtio-ccw-blk.o
 obj-$(call land,$(CONFIG_VIRTIO_9P),$(CONFIG_VIRTFS)) += virtio-ccw-9p.o
 obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-ccw.o
+endif
 obj-y += css-bridge.o
 obj-y += ccw-device.o
 obj-y += s390-pci-bus.o s390-pci-inst.o
diff --git a/hw/scsi/Kconfig b/hw/scsi/Kconfig
new file mode 100644
index 0000000000..b3ba540c17
--- /dev/null
+++ b/hw/scsi/Kconfig
@@ -0,0 +1,54 @@
+config SCSI
+    bool
+
+config LSI_SCSI_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select SCSI
+
+config MPTSAS_SCSI_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select SCSI
+
+config MEGASAS_SCSI_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select SCSI
+
+config VMW_PVSCSI_SCSI_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select SCSI
+
+config ESP
+    bool
+    select SCSI
+
+config ESP_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select ESP
+
+config SPAPR_VSCSI
+    bool
+    default y
+    depends on PSERIES
+    select SCSI
+
+config VIRTIO_SCSI
+    bool
+    default y
+    depends on VIRTIO
+    select SCSI
+
+config VHOST_USER_SCSI
+    bool
+    # Only PCI devices are provided for now
+    default y if VIRTIO_PCI
+    depends on VIRTIO && VHOST_USER && LINUX
diff --git a/hw/scsi/Makefile.objs b/hw/scsi/Makefile.objs
index 45167baeaf..54b36ed8b1 100644
--- a/hw/scsi/Makefile.objs
+++ b/hw/scsi/Makefile.objs
@@ -6,7 +6,7 @@ common-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o
 common-obj-$(CONFIG_VMW_PVSCSI_SCSI_PCI) += vmw_pvscsi.o
 common-obj-$(CONFIG_ESP) += esp.o
 common-obj-$(CONFIG_ESP_PCI) += esp-pci.o
-obj-$(CONFIG_PSERIES) += spapr_vscsi.o
+obj-$(CONFIG_SPAPR_VSCSI) += spapr_vscsi.o
 
 ifeq ($(CONFIG_VIRTIO_SCSI),y)
 obj-y += virtio-scsi.o virtio-scsi-dataplane.o
diff --git a/hw/sd/Kconfig b/hw/sd/Kconfig
new file mode 100644
index 0000000000..864f535011
--- /dev/null
+++ b/hw/sd/Kconfig
@@ -0,0 +1,17 @@
+config PL181
+    bool
+    select SD
+
+config SSI_SD
+    bool
+    depends on SSI
+    select SD
+
+config SD
+    bool
+
+config SDHCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select SD
diff --git a/hw/sh4/Kconfig b/hw/sh4/Kconfig
new file mode 100644
index 0000000000..8597613a35
--- /dev/null
+++ b/hw/sh4/Kconfig
@@ -0,0 +1,23 @@
+config R2D
+    bool
+    imply PCI_DEVICES
+    imply TEST_DEVICES
+    select I82378 if TEST_DEVICES
+    select IDE_MMIO
+    select PFLASH_CFI02
+    select USB_OHCI
+    select PCI
+    select SM501
+    select SH4
+
+config SHIX
+    bool
+    select SH7750
+    select SH4
+
+config SH7750
+    bool
+
+config SH4
+    bool
+    select PTIMER
diff --git a/hw/smbios/Kconfig b/hw/smbios/Kconfig
new file mode 100644
index 0000000000..553adf4bfc
--- /dev/null
+++ b/hw/smbios/Kconfig
@@ -0,0 +1,2 @@
+config SMBIOS
+    bool
diff --git a/hw/sparc/Kconfig b/hw/sparc/Kconfig
new file mode 100644
index 0000000000..2a83a8010e
--- /dev/null
+++ b/hw/sparc/Kconfig
@@ -0,0 +1,26 @@
+config SUN4M
+    bool
+    imply TCX
+    imply CG3
+    select CS4231
+    select ECCMEMCTL
+    select EMPTY_SLOT
+    select ESCC
+    select ESP
+    select FDC
+    select SLAVIO
+    select LANCE
+    select M48T59
+    select STP2000
+
+config LEON3
+    bool
+    select GRLIB
+
+config GRLIB
+    bool
+    select PTIMER
+
+config SLAVIO
+    bool
+    select PTIMER
diff --git a/hw/sparc64/Kconfig b/hw/sparc64/Kconfig
new file mode 100644
index 0000000000..4a8166ebb7
--- /dev/null
+++ b/hw/sparc64/Kconfig
@@ -0,0 +1,19 @@
+config SUN4U
+    bool
+    imply PCI_DEVICES
+    imply SUNHME
+    imply TEST_DEVICES
+    select M48T59
+    select ISA_BUS
+    select FDC
+    select SERIAL_ISA
+    select PCI_SABRE
+    select IDE_CMD646
+    select PARALLEL
+    select PCKBD
+    select SIMBA
+
+config NIAGARA
+    bool
+    select EMPTY_SLOT
+    select SUN4V_RTC
diff --git a/hw/ssi/Kconfig b/hw/ssi/Kconfig
new file mode 100644
index 0000000000..9e54a0c8dd
--- /dev/null
+++ b/hw/ssi/Kconfig
@@ -0,0 +1,18 @@
+config PL022
+    bool
+    select SSI
+
+config SSI
+    bool
+
+config XILINX_SPI
+    bool
+    select SSI
+
+config XILINX_SPIPS
+    bool
+    select SSI
+
+config STM32F2XX_SPI
+    bool
+    select SSI
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
new file mode 100644
index 0000000000..51921eb63f
--- /dev/null
+++ b/hw/timer/Kconfig
@@ -0,0 +1,63 @@
+config ARM_TIMER
+    bool
+    select PTIMER
+
+config ARM_MPTIMER
+    bool
+    select PTIMER
+
+config A9_GTIMER
+    bool
+
+config DS1338
+    bool
+    depends on I2C
+
+config HPET
+    bool
+    default y if PC
+
+config I8254
+    bool
+
+config M41T80
+    bool
+    depends on I2C
+
+config M48T59
+    bool
+
+config PL031
+    bool
+
+config TWL92230
+    bool
+    depends on I2C
+
+config XLNX_ZYNQMP
+    bool
+
+config ALTERA_TIMER
+    bool
+    select PTIMER
+
+config MC146818RTC
+    bool
+
+config ALLWINNER_A10_PIT
+    bool
+    select PTIMER
+
+config STM32F2XX_TIMER
+    bool
+
+config SUN4V_RTC
+    bool
+
+config CMSDK_APB_TIMER
+    bool
+    select PTIMER
+
+config CMSDK_APB_DUALTIMER
+    bool
+    select PTIMER
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
new file mode 100644
index 0000000000..4c8ee87d67
--- /dev/null
+++ b/hw/tpm/Kconfig
@@ -0,0 +1,24 @@
+config TPMDEV
+    bool
+    depends on TPM
+
+config TPM_TIS
+    bool
+    depends on TPM && ISA_BUS
+    select TPMDEV
+
+config TPM_CRB
+    bool
+    depends on TPM && PC
+    select TPMDEV
+
+config TPM_PASSTHROUGH
+    bool
+    default y
+    # FIXME: should check for x86 host as well
+    depends on TPMDEV && LINUX
+
+config TPM_EMULATOR
+    bool
+    default y
+    depends on TPMDEV
diff --git a/hw/tricore/Kconfig b/hw/tricore/Kconfig
new file mode 100644
index 0000000000..9313409309
--- /dev/null
+++ b/hw/tricore/Kconfig
@@ -0,0 +1,2 @@
+config TRICORE
+    bool
diff --git a/hw/unicore32/Kconfig b/hw/unicore32/Kconfig
new file mode 100644
index 0000000000..4443a29dd2
--- /dev/null
+++ b/hw/unicore32/Kconfig
@@ -0,0 +1,5 @@
+config PUV3
+    bool
+    select ISA_BUS
+    select PCKBD
+    select PTIMER
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
new file mode 100644
index 0000000000..a1b7acb12a
--- /dev/null
+++ b/hw/usb/Kconfig
@@ -0,0 +1,91 @@
+config USB
+    bool
+
+config USB_UHCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select USB
+
+config USB_OHCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select USB
+
+config USB_EHCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select USB
+
+config USB_EHCI_SYSBUS
+    bool
+    select USB
+
+config USB_XHCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select USB
+
+config USB_XHCI_NEC
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select USB
+
+config USB_MUSB
+    bool
+    select USB
+
+config TUSB6010
+    bool
+    select USB_MUSB
+
+config USB_TABLET_WACOM
+    bool
+    default y
+    depends on USB
+
+config USB_STORAGE_BOT
+    bool
+    default y
+    depends on USB
+    select SCSI
+
+config USB_STORAGE_UAS
+    bool
+    default y
+    depends on USB
+    select SCSI
+
+config USB_AUDIO
+    bool
+    default y
+    depends on USB
+
+config USB_SERIAL
+    bool
+    default y
+    depends on USB
+
+config USB_NETWORK
+    bool
+    default y
+    depends on USB
+
+config USB_BLUETOOTH
+    bool
+    default y
+    depends on USB
+
+config USB_SMARTCARD
+    bool
+    default y
+    depends on USB
+
+config USB_STORAGE_MTP
+    bool
+    default y
+    depends on USB
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index 41be700812..2b929649ac 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -6,7 +6,7 @@ common-obj-$(CONFIG_USB) += desc.o desc-msos.o
 common-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o
 common-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o
 common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o hcd-ehci-pci.o
-common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o
+common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci.o hcd-ehci-sysbus.o
 common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o
 common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
 common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
diff --git a/hw/vfio/Kconfig b/hw/vfio/Kconfig
new file mode 100644
index 0000000000..ebda9fdf22
--- /dev/null
+++ b/hw/vfio/Kconfig
@@ -0,0 +1,36 @@
+config VFIO
+    bool
+    depends on LINUX
+
+config VFIO_PCI
+    bool
+    select VFIO
+    depends on LINUX
+
+config VFIO_CCW
+    bool
+    default y
+    select VFIO
+    depends on LINUX && S390_CCW_VIRTIO
+
+config VFIO_PLATFORM
+    bool
+    default y
+    select VFIO
+    depends on LINUX && PLATFORM_BUS
+
+config VFIO_XGMAC
+    bool
+    default y
+    depends on VFIO_PLATFORM
+
+config VFIO_AMD_XGBE
+    bool
+    default y
+    depends on VFIO_PLATFORM
+
+config VFIO_AP
+    bool
+    default y
+    select VFIO
+    depends on LINUX && S390_CCW_VIRTIO
diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig
new file mode 100644
index 0000000000..e0452de4ba
--- /dev/null
+++ b/hw/virtio/Kconfig
@@ -0,0 +1,31 @@
+config VIRTIO
+    bool
+
+config VIRTIO_RNG
+    bool
+    default y
+    depends on VIRTIO
+
+config VIRTIO_PCI
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+    select VIRTIO
+
+config VIRTIO_MMIO
+    bool
+    select VIRTIO
+
+config VIRTIO_CCW
+    bool
+    select VIRTIO
+
+config VIRTIO_BALLOON
+    bool
+    default y
+    depends on VIRTIO
+
+config VIRTIO_CRYPTO
+    bool
+    default y
+    depends on VIRTIO
diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index a3eb8ed866..f2ab667a21 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -29,6 +29,8 @@ obj-$(CONFIG_VIRTIO_BLK) += virtio-blk-pci.o
 obj-$(CONFIG_VIRTIO_NET) += virtio-net-pci.o
 obj-$(CONFIG_VIRTIO_SERIAL) += virtio-serial-pci.o
 endif
+else
+common-obj-y += vhost-stub.o
 endif
 
 common-obj-$(CONFIG_ALL) += vhost-stub.o
diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig
new file mode 100644
index 0000000000..2118d897c9
--- /dev/null
+++ b/hw/watchdog/Kconfig
@@ -0,0 +1,16 @@
+config CMSDK_APB_WATCHDOG
+    bool
+    select PTIMER
+
+config WDT_IB6300ESB
+    bool
+    default y if PCI_DEVICES
+    depends on PCI
+
+config WDT_IB700
+    bool
+    default y
+    depends on ISA_BUS
+
+config WDT_DIAG288
+    bool
diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig
new file mode 100644
index 0000000000..d72817d012
--- /dev/null
+++ b/hw/xtensa/Kconfig
@@ -0,0 +1,8 @@
+config XTENSA_SIM
+    bool
+
+config XTENSA_XTFPGA
+    bool
+    select OPENCORES_ETH
+    select PFLASH_CFI01
+    select SERIAL
diff --git a/hw/xtensa/Makefile.objs b/hw/xtensa/Makefile.objs
index fa86730e23..0bbfccd6de 100644
--- a/hw/xtensa/Makefile.objs
+++ b/hw/xtensa/Makefile.objs
@@ -2,4 +2,4 @@ obj-y += mx_pic.o
 obj-y += pic_cpu.o
 obj-y += xtensa_memory.o
 obj-$(CONFIG_XTENSA_SIM) += sim.o
-obj-$(CONFIG_XTENSA_FPGA) += xtfpga.o
+obj-$(CONFIG_XTENSA_XTFPGA) += xtfpga.o
diff --git a/rules.mak b/rules.mak
index 19f3d2c126..df45bcffb4 100644
--- a/rules.mak
+++ b/rules.mak
@@ -144,7 +144,7 @@ cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
 cc-c-option = $(if $(shell $(CC) $1 $2 -c -o /dev/null -xc /dev/null \
                 >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.cc %.cpp %.m %.mak %.texi %.sh %.rc
+VPATH_SUFFIXES = %.c %.h %.S %.cc %.cpp %.m %.mak %.texi %.sh %.rc Kconfig%
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # install-prog list, dir
diff --git a/scripts/make_device_config.sh b/scripts/make_device_config.sh
deleted file mode 100644
index 354af317b3..0000000000
--- a/scripts/make_device_config.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#! /bin/sh
-# Writes a target device config file to stdout, from a default and from
-# include directives therein.  Also emits Makefile dependencies.
-#
-# Usage: make_device_config.sh SRC DEPFILE-NAME DEPFILE-TARGET > DEST
-
-src=$1
-dep=$2
-target=$3
-src_dir=$(dirname $src)
-all_includes=
-
-process_includes () {
-  cat $1 | grep '^include' | \
-  while read include file ; do
-    all_includes="$all_includes $src_dir/$file"
-    process_includes $src_dir/$file
-  done
-}
-
-f=$src
-while [ -n "$f" ] ; do
-  f=$(cat $f | tr -d '\r' | awk '/^include / {printf "'$src_dir'/%s ", $2}')
-  [ $? = 0 ] || exit 1
-  all_includes="$all_includes $f"
-done
-process_includes $src
-
-cat $src $all_includes | grep -v '^include'
-echo "$target: $all_includes" > $dep
diff --git a/scripts/minikconf.py b/scripts/minikconf.py
new file mode 100644
index 0000000000..5421db0ed0
--- /dev/null
+++ b/scripts/minikconf.py
@@ -0,0 +1,708 @@
+#
+# Mini-Kconfig parser
+#
+# Copyright (c) 2015 Red Hat Inc.
+#
+# Authors:
+#  Paolo Bonzini <pbonzini@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or, at your option, any later version.  See the COPYING file in
+# the top-level directory.
+
+from __future__ import print_function
+import os
+import sys
+import re
+import random
+
+__all__ = [ 'KconfigDataError', 'KconfigParserError',
+            'KconfigData', 'KconfigParser' ,
+            'defconfig', 'allyesconfig', 'allnoconfig', 'randconfig' ]
+
+def debug_print(*args):
+    #print('# ' + (' '.join(str(x) for x in args)))
+    pass
+
+# -------------------------------------------
+# KconfigData implements the Kconfig semantics.  For now it can only
+# detect undefined symbols, i.e. symbols that were referenced in
+# assignments or dependencies but were not declared with "config FOO".
+#
+# Semantic actions are represented by methods called do_*.  The do_var
+# method return the semantic value of a variable (which right now is
+# just its name).
+# -------------------------------------------
+
+class KconfigDataError(Exception):
+    def __init__(self, msg):
+        self.msg = msg
+
+    def __str__(self):
+        return self.msg
+
+allyesconfig = lambda x: True
+allnoconfig = lambda x: False
+defconfig = lambda x: x
+randconfig = lambda x: random.randint(0, 1) == 1
+
+class KconfigData:
+    class Expr:
+        def __and__(self, rhs):
+            return KconfigData.AND(self, rhs)
+        def __or__(self, rhs):
+            return KconfigData.OR(self, rhs)
+        def __invert__(self):
+            return KconfigData.NOT(self)
+
+        # Abstract methods
+        def add_edges_to(self, var):
+            pass
+        def evaluate(self):
+            assert False
+
+    class AND(Expr):
+        def __init__(self, lhs, rhs):
+            self.lhs = lhs
+            self.rhs = rhs
+        def __str__(self):
+            return "(%s && %s)" % (self.lhs, self.rhs)
+
+        def add_edges_to(self, var):
+            self.lhs.add_edges_to(var)
+            self.rhs.add_edges_to(var)
+        def evaluate(self):
+            return self.lhs.evaluate() and self.rhs.evaluate()
+
+    class OR(Expr):
+        def __init__(self, lhs, rhs):
+            self.lhs = lhs
+            self.rhs = rhs
+        def __str__(self):
+            return "(%s || %s)" % (self.lhs, self.rhs)
+
+        def add_edges_to(self, var):
+            self.lhs.add_edges_to(var)
+            self.rhs.add_edges_to(var)
+        def evaluate(self):
+            return self.lhs.evaluate() or self.rhs.evaluate()
+
+    class NOT(Expr):
+        def __init__(self, lhs):
+            self.lhs = lhs
+        def __str__(self):
+            return "!%s" % (self.lhs)
+
+        def add_edges_to(self, var):
+            self.lhs.add_edges_to(var)
+        def evaluate(self):
+            return not self.lhs.evaluate()
+
+    class Var(Expr):
+        def __init__(self, name):
+            self.name = name
+            self.value = None
+            self.outgoing = set()
+            self.clauses_for_var = list()
+        def __str__(self):
+            return self.name
+
+        def has_value(self):
+            return not (self.value is None)
+        def set_value(self, val, clause):
+            self.clauses_for_var.append(clause)
+            if self.has_value() and self.value != val:
+                print("The following clauses were found for " + self.name)
+                for i in self.clauses_for_var:
+                    print("    " + str(i), file=sys.stderr)
+                raise KconfigDataError('contradiction between clauses when setting %s' % self)
+            debug_print("=> %s is now %s" % (self.name, val))
+            self.value = val
+
+        # depth first search of the dependency graph
+        def dfs(self, visited, f):
+            if self in visited:
+                return
+            visited.add(self)
+            for v in self.outgoing:
+                v.dfs(visited, f)
+            f(self)
+
+        def add_edges_to(self, var):
+            self.outgoing.add(var)
+        def evaluate(self):
+            if not self.has_value():
+                raise KconfigDataError('cycle found including %s' % self)
+            return self.value
+
+    class Clause:
+        def __init__(self, dest):
+            self.dest = dest
+        def priority(self):
+            return 0
+        def process(self):
+            pass
+
+    class AssignmentClause(Clause):
+        def __init__(self, dest, value):
+            KconfigData.Clause.__init__(self, dest)
+            self.value = value
+        def __str__(self):
+            return "CONFIG_%s=%s" % (self.dest, 'y' if self.value else 'n')
+
+        def process(self):
+            self.dest.set_value(self.value, self)
+
+    class DefaultClause(Clause):
+        def __init__(self, dest, value, cond=None):
+            KconfigData.Clause.__init__(self, dest)
+            self.value = value
+            self.cond = cond
+            if not (self.cond is None):
+                self.cond.add_edges_to(self.dest)
+        def __str__(self):
+            value = 'y' if self.value else 'n'
+            if self.cond is None:
+                return "config %s default %s" % (self.dest, value)
+            else:
+                return "config %s default %s if %s" % (self.dest, value, self.cond)
+
+        def priority(self):
+            # Defaults are processed just before leaving the variable
+            return -1
+        def process(self):
+            if not self.dest.has_value() and \
+                    (self.cond is None or self.cond.evaluate()):
+                self.dest.set_value(self.value, self)
+
+    class DependsOnClause(Clause):
+        def __init__(self, dest, expr):
+            KconfigData.Clause.__init__(self, dest)
+            self.expr = expr
+            self.expr.add_edges_to(self.dest)
+        def __str__(self):
+            return "config %s depends on %s" % (self.dest, self.expr)
+
+        def process(self):
+            if not self.expr.evaluate():
+                self.dest.set_value(False, self)
+
+    class SelectClause(Clause):
+        def __init__(self, dest, cond):
+            KconfigData.Clause.__init__(self, dest)
+            self.cond = cond
+            self.cond.add_edges_to(self.dest)
+        def __str__(self):
+            return "select %s if %s" % (self.dest, self.cond)
+
+        def process(self):
+            if self.cond.evaluate():
+                self.dest.set_value(True, self)
+
+    def __init__(self, value_mangler=defconfig):
+        self.value_mangler = value_mangler
+        self.previously_included = []
+        self.incl_info = None
+        self.defined_vars = set()
+        self.referenced_vars = dict()
+        self.clauses = list()
+
+    # semantic analysis -------------
+
+    def check_undefined(self):
+        undef = False
+        for i in self.referenced_vars:
+            if not (i in self.defined_vars):
+                print("undefined symbol %s" % (i), file=sys.stderr)
+                undef = True
+        return undef
+
+    def compute_config(self):
+        if self.check_undefined():
+            raise KconfigDataError("there were undefined symbols")
+            return None
+
+        debug_print("Input:")
+        for clause in self.clauses:
+            debug_print(clause)
+
+        debug_print("\nDependency graph:")
+        for i in self.referenced_vars:
+            debug_print(i, "->", [str(x) for x in self.referenced_vars[i].outgoing])
+
+        # The reverse of the depth-first order is the topological sort
+        dfo = dict()
+        visited = set()
+        debug_print("\n")
+        def visit_fn(var):
+            debug_print(var, "has DFS number", len(dfo))
+            dfo[var] = len(dfo)
+
+        for name, v in self.referenced_vars.items():
+            self.do_default(v, False)
+            v.dfs(visited, visit_fn)
+
+        # Put higher DFS numbers and higher priorities first.  This
+        # places the clauses in topological order and places defaults
+        # after assignments and dependencies.
+        self.clauses.sort(key=lambda x: (-dfo[x.dest], -x.priority()))
+
+        debug_print("\nSorted clauses:")
+        for clause in self.clauses:
+            debug_print(clause)
+            clause.process()
+
+        debug_print("")
+        values = dict()
+        for name, v in self.referenced_vars.items():
+            debug_print("Evaluating", name)
+            values[name] = v.evaluate()
+
+        return values
+
+    # semantic actions -------------
+
+    def do_declaration(self, var):
+        if (var in self.defined_vars):
+            raise KconfigDataError('variable "' + var + '" defined twice')
+
+        self.defined_vars.add(var.name)
+
+    # var is a string with the variable's name.
+    def do_var(self, var):
+        if (var in self.referenced_vars):
+            return self.referenced_vars[var]
+
+        var_obj = self.referenced_vars[var] = KconfigData.Var(var)
+        return var_obj
+
+    def do_assignment(self, var, val):
+        self.clauses.append(KconfigData.AssignmentClause(var, val))
+
+    def do_default(self, var, val, cond=None):
+        val = self.value_mangler(val)
+        self.clauses.append(KconfigData.DefaultClause(var, val, cond))
+
+    def do_depends_on(self, var, expr):
+        self.clauses.append(KconfigData.DependsOnClause(var, expr))
+
+    def do_select(self, var, symbol, cond=None):
+        cond = (cond & var) if cond is not None else var
+        self.clauses.append(KconfigData.SelectClause(symbol, cond))
+
+    def do_imply(self, var, symbol, cond=None):
+        # "config X imply Y [if COND]" is the same as
+        # "config Y default y if X [&& COND]"
+        cond = (cond & var) if cond is not None else var
+        self.do_default(symbol, True, cond)
+
+# -------------------------------------------
+# KconfigParser implements a recursive descent parser for (simplified)
+# Kconfig syntax.
+# -------------------------------------------
+
+# tokens table
+TOKENS = {}
+TOK_NONE = -1
+TOK_LPAREN = 0;   TOKENS[TOK_LPAREN] = '"("';
+TOK_RPAREN = 1;   TOKENS[TOK_RPAREN] = '")"';
+TOK_EQUAL = 2;    TOKENS[TOK_EQUAL] = '"="';
+TOK_AND = 3;      TOKENS[TOK_AND] = '"&&"';
+TOK_OR = 4;       TOKENS[TOK_OR] = '"||"';
+TOK_NOT = 5;      TOKENS[TOK_NOT] = '"!"';
+TOK_DEPENDS = 6;  TOKENS[TOK_DEPENDS] = '"depends"';
+TOK_ON = 7;       TOKENS[TOK_ON] = '"on"';
+TOK_SELECT = 8;   TOKENS[TOK_SELECT] = '"select"';
+TOK_IMPLY = 9;    TOKENS[TOK_IMPLY] = '"imply"';
+TOK_CONFIG = 10;  TOKENS[TOK_CONFIG] = '"config"';
+TOK_DEFAULT = 11; TOKENS[TOK_DEFAULT] = '"default"';
+TOK_Y = 12;       TOKENS[TOK_Y] = '"y"';
+TOK_N = 13;       TOKENS[TOK_N] = '"n"';
+TOK_SOURCE = 14;  TOKENS[TOK_SOURCE] = '"source"';
+TOK_BOOL = 15;    TOKENS[TOK_BOOL] = '"bool"';
+TOK_IF = 16;      TOKENS[TOK_IF] = '"if"';
+TOK_ID = 17;      TOKENS[TOK_ID] = 'identifier';
+TOK_EOF = 18;     TOKENS[TOK_EOF] = 'end of file';
+
+class KconfigParserError(Exception):
+    def __init__(self, parser, msg, tok=None):
+        self.loc = parser.location()
+        tok = tok or parser.tok
+        if tok != TOK_NONE:
+            location = TOKENS.get(tok, None) or ('"%s"' % tok)
+            msg = '%s before %s' % (msg, location)
+        self.msg = msg
+
+    def __str__(self):
+        return "%s: %s" % (self.loc, self.msg)
+
+class KconfigParser:
+
+    @classmethod
+    def parse(self, fp, mode=None):
+        data = KconfigData(mode or KconfigParser.defconfig)
+        parser = KconfigParser(data)
+        parser.parse_file(fp)
+        return data
+
+    def __init__(self, data):
+        self.data = data
+
+    def parse_file(self, fp):
+        self.abs_fname = os.path.abspath(fp.name)
+        self.fname = fp.name
+        self.data.previously_included.append(self.abs_fname)
+        self.src = fp.read()
+        if self.src == '' or self.src[-1] != '\n':
+            self.src += '\n'
+        self.cursor = 0
+        self.line = 1
+        self.line_pos = 0
+        self.get_token()
+        self.parse_config()
+
+    def do_assignment(self, var, val):
+        if not var.startswith("CONFIG_"):
+            raise Error('assigned variable should start with CONFIG_')
+        var = self.data.do_var(var[7:])
+        self.data.do_assignment(var, val)
+
+    # file management -----
+
+    def error_path(self):
+        inf = self.data.incl_info
+        res = ""
+        while inf:
+            res = ("In file included from %s:%d:\n" % (inf['file'],
+                                                       inf['line'])) + res
+            inf = inf['parent']
+        return res
+
+    def location(self):
+        col = 1
+        for ch in self.src[self.line_pos:self.pos]:
+            if ch == '\t':
+                col += 8 - ((col - 1) % 8)
+            else:
+                col += 1
+        return '%s%s:%d:%d' %(self.error_path(), self.fname, self.line, col)
+
+    def do_include(self, include):
+        incl_abs_fname = os.path.join(os.path.dirname(self.abs_fname),
+                                      include)
+        # catch inclusion cycle
+        inf = self.data.incl_info
+        while inf:
+            if incl_abs_fname == os.path.abspath(inf['file']):
+                raise KconfigParserError(self, "Inclusion loop for %s"
+                                    % include)
+            inf = inf['parent']
+
+        # skip multiple include of the same file
+        if incl_abs_fname in self.data.previously_included:
+            return
+        try:
+            fp = open(incl_abs_fname, 'r')
+        except IOError as e:
+            raise KconfigParserError(self,
+                                '%s: %s' % (e.strerror, include))
+
+        inf = self.data.incl_info
+        self.data.incl_info = { 'file': self.fname, 'line': self.line,
+                'parent': inf }
+        KconfigParser(self.data).parse_file(fp)
+        self.data.incl_info = inf
+
+    # recursive descent parser -----
+
+    # y_or_n: Y | N
+    def parse_y_or_n(self):
+        if self.tok == TOK_Y:
+            self.get_token()
+            return True
+        if self.tok == TOK_N:
+            self.get_token()
+            return False
+        raise KconfigParserError(self, 'Expected "y" or "n"')
+
+    # var: ID
+    def parse_var(self):
+        if self.tok == TOK_ID:
+            val = self.val
+            self.get_token()
+            return self.data.do_var(val)
+        else:
+            raise KconfigParserError(self, 'Expected identifier')
+
+    # assignment_var: ID (starting with "CONFIG_")
+    def parse_assignment_var(self):
+        if self.tok == TOK_ID:
+            val = self.val
+            if not val.startswith("CONFIG_"):
+                raise KconfigParserError(self,
+                           'Expected identifier starting with "CONFIG_"', TOK_NONE)
+            self.get_token()
+            return self.data.do_var(val[7:])
+        else:
+            raise KconfigParserError(self, 'Expected identifier')
+
+    # assignment: var EQUAL y_or_n
+    def parse_assignment(self):
+        var = self.parse_assignment_var()
+        if self.tok != TOK_EQUAL:
+            raise KconfigParserError(self, 'Expected "="')
+        self.get_token()
+        self.data.do_assignment(var, self.parse_y_or_n())
+
+    # primary: NOT primary
+    #       | LPAREN expr RPAREN
+    #       | var
+    def parse_primary(self):
+        if self.tok == TOK_NOT:
+            self.get_token()
+            val = ~self.parse_primary()
+        elif self.tok == TOK_LPAREN:
+            self.get_token()
+            val = self.parse_expr()
+            if self.tok != TOK_RPAREN:
+                raise KconfigParserError(self, 'Expected ")"')
+            self.get_token()
+        elif self.tok == TOK_ID:
+            val = self.parse_var()
+        else:
+            raise KconfigParserError(self, 'Expected "!" or "(" or identifier')
+        return val
+
+    # disj: primary (OR primary)*
+    def parse_disj(self):
+        lhs = self.parse_primary()
+        while self.tok == TOK_OR:
+            self.get_token()
+            lhs = lhs | self.parse_primary()
+        return lhs
+
+    # expr: disj (AND disj)*
+    def parse_expr(self):
+        lhs = self.parse_disj()
+        while self.tok == TOK_AND:
+            self.get_token()
+            lhs = lhs & self.parse_disj()
+        return lhs
+
+    # condition: IF expr
+    #       | empty
+    def parse_condition(self):
+        if self.tok == TOK_IF:
+            self.get_token()
+            return self.parse_expr()
+        else:
+            return None
+
+    # property: DEFAULT y_or_n condition
+    #       | DEPENDS ON expr
+    #       | SELECT var condition
+    #       | BOOL
+    def parse_property(self, var):
+        if self.tok == TOK_DEFAULT:
+            self.get_token()
+            val = self.parse_y_or_n()
+            cond = self.parse_condition()
+            self.data.do_default(var, val, cond)
+        elif self.tok == TOK_DEPENDS:
+            self.get_token()
+            if self.tok != TOK_ON:
+                raise KconfigParserError(self, 'Expected "on"')
+            self.get_token()
+            self.data.do_depends_on(var, self.parse_expr())
+        elif self.tok == TOK_SELECT:
+            self.get_token()
+            symbol = self.parse_var()
+            cond = self.parse_condition()
+            self.data.do_select(var, symbol, cond)
+        elif self.tok == TOK_IMPLY:
+            self.get_token()
+            symbol = self.parse_var()
+            cond = self.parse_condition()
+            self.data.do_imply(var, symbol, cond)
+        elif self.tok == TOK_BOOL:
+            self.get_token()
+        else:
+            raise KconfigParserError(self, 'Error in recursive descent?')
+
+    # properties: properties property
+    #       | /* empty */
+    def parse_properties(self, var):
+        had_default = False
+        while self.tok == TOK_DEFAULT or self.tok == TOK_DEPENDS or \
+              self.tok == TOK_SELECT or self.tok == TOK_BOOL or \
+              self.tok == TOK_IMPLY:
+            self.parse_property(var)
+
+        # for nicer error message
+        if self.tok != TOK_SOURCE and self.tok != TOK_CONFIG and \
+           self.tok != TOK_ID and self.tok != TOK_EOF:
+            raise KconfigParserError(self, 'expected "source", "config", identifier, '
+                    + '"default", "depends on", "imply" or "select"')
+
+    # declaration: config var properties
+    def parse_declaration(self):
+        if self.tok == TOK_CONFIG:
+            self.get_token()
+            var = self.parse_var()
+            self.data.do_declaration(var)
+            self.parse_properties(var)
+        else:
+            raise KconfigParserError(self, 'Error in recursive descent?')
+
+    # clause: SOURCE
+    #       | declaration
+    #       | assignment
+    def parse_clause(self):
+        if self.tok == TOK_SOURCE:
+            val = self.val
+            self.get_token()
+            self.do_include(val)
+        elif self.tok == TOK_CONFIG:
+            self.parse_declaration()
+        elif self.tok == TOK_ID:
+            self.parse_assignment()
+        else:
+            raise KconfigParserError(self, 'expected "source", "config" or identifier')
+
+    # config: clause+ EOF
+    def parse_config(self):
+        while self.tok != TOK_EOF:
+            self.parse_clause()
+        return self.data
+
+    # scanner -----
+
+    def get_token(self):
+        while True:
+            self.tok = self.src[self.cursor]
+            self.pos = self.cursor
+            self.cursor += 1
+
+            self.val = None
+            self.tok = self.scan_token()
+            if self.tok is not None:
+                return
+
+    def check_keyword(self, rest):
+        if not self.src.startswith(rest, self.cursor):
+            return False
+        length = len(rest)
+        if self.src[self.cursor + length].isalnum() or self.src[self.cursor + length] == '|':
+            return False
+        self.cursor += length
+        return True
+
+    def scan_token(self):
+        if self.tok == '#':
+            self.cursor = self.src.find('\n', self.cursor)
+            return None
+        elif self.tok == '=':
+            return TOK_EQUAL
+        elif self.tok == '(':
+            return TOK_LPAREN
+        elif self.tok == ')':
+            return TOK_RPAREN
+        elif self.tok == '&' and self.src[self.pos+1] == '&':
+            self.cursor += 1
+            return TOK_AND
+        elif self.tok == '|' and self.src[self.pos+1] == '|':
+            self.cursor += 1
+            return TOK_OR
+        elif self.tok == '!':
+            return TOK_NOT
+        elif self.tok == 'd' and self.check_keyword("epends"):
+            return TOK_DEPENDS
+        elif self.tok == 'o' and self.check_keyword("n"):
+            return TOK_ON
+        elif self.tok == 's' and self.check_keyword("elect"):
+            return TOK_SELECT
+        elif self.tok == 'i' and self.check_keyword("mply"):
+            return TOK_IMPLY
+        elif self.tok == 'c' and self.check_keyword("onfig"):
+            return TOK_CONFIG
+        elif self.tok == 'd' and self.check_keyword("efault"):
+            return TOK_DEFAULT
+        elif self.tok == 'b' and self.check_keyword("ool"):
+            return TOK_BOOL
+        elif self.tok == 'i' and self.check_keyword("f"):
+            return TOK_IF
+        elif self.tok == 'y' and self.check_keyword(""):
+            return TOK_Y
+        elif self.tok == 'n' and self.check_keyword(""):
+            return TOK_N
+        elif (self.tok == 's' and self.check_keyword("ource")) or \
+              self.tok == 'i' and self.check_keyword("nclude"):
+            # source FILENAME
+            # include FILENAME
+            while self.src[self.cursor].isspace():
+                self.cursor += 1
+            start = self.cursor
+            self.cursor = self.src.find('\n', self.cursor)
+            self.val = self.src[start:self.cursor]
+            return TOK_SOURCE
+        elif self.tok.isalpha():
+            # identifier
+            while self.src[self.cursor].isalnum() or self.src[self.cursor] == '_':
+                self.cursor += 1
+            self.val = self.src[self.pos:self.cursor]
+            return TOK_ID
+        elif self.tok == '\n':
+            if self.cursor == len(self.src):
+                return TOK_EOF
+            self.line += 1
+            self.line_pos = self.cursor
+        elif not self.tok.isspace():
+            raise KconfigParserError(self, 'invalid input')
+
+        return None
+
+if __name__ == '__main__':
+    argv = sys.argv
+    mode = defconfig
+    if len(sys.argv) > 1:
+        if argv[1] == '--defconfig':
+            del argv[1]
+        elif argv[1] == '--randconfig':
+            random.seed()
+            mode = randconfig
+            del argv[1]
+        elif argv[1] == '--allyesconfig':
+            mode = allyesconfig
+            del argv[1]
+        elif argv[1] == '--allnoconfig':
+            mode = allnoconfig
+            del argv[1]
+
+    if len(argv) == 1:
+        print ("%s: at least one argument is required" % argv[0], file=sys.stderr)
+        sys.exit(1)
+
+    if argv[1].startswith('-'):
+        print ("%s: invalid option %s" % (argv[0], argv[1]), file=sys.stderr)
+        sys.exit(1)
+
+    data = KconfigData(mode)
+    parser = KconfigParser(data)
+    for arg in argv[3:]:
+        m = re.match(r'^(CONFIG_[A-Z0-9_]+)=([yn]?)$', arg)
+        if m is not None:
+            name, value = m.groups()
+            parser.do_assignment(name, value == 'y')
+        else:
+            fp = open(arg, 'r')
+            parser.parse_file(fp)
+            fp.close()
+
+    config = data.compute_config()
+    for key in sorted(config.keys()):
+        print ('CONFIG_%s=%s' % (key, ('y' if config[key] else 'n')))
+
+    deps = open(argv[2], 'w')
+    for fname in data.previously_included:
+        print ('%s: %s' % (argv[1], fname), file=deps)
+    deps.close()