Upgrade syzkaller to 148296f4787895d1b148d29a2f48140bcfd245a3

Exempt-From-Owner-Approval: owner is not accurate
Test: None
Change-Id: Ieab69878d627646fa16d135263f7fc9056a74bca
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..443aa5d
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,73 @@
+# Copyright 2019 syzkaller project authors. All rights reserved.
+# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+run:
+  deadline: 8m
+  skip-dirs:
+    - pkg/kd
+    - pkg/ifuzz/generated
+    - sys/akaros/gen
+    - sys/freebsd/gen
+    - sys/fuchsia/gen
+    - sys/linux/gen
+    - sys/netbsd/gen
+    - sys/openbsd/gen
+    - sys/windows/gen
+    - sys/test/gen
+    - sys/trusty/gen
+  skip-files:
+    - "tools/syz-trace2syz/parser/(lex.go|strace.go|straceLex.rl|yaccpar)"
+
+linters:
+  enable:
+    - lll
+    - vet
+    - gofmt
+    - golint
+    - structcheck
+    - unconvert
+    - deadcode
+    - goconst
+    - unused
+    - gosimple
+    - varcheck
+    - misspell
+    - gocyclo
+    - vetshadow
+    - megacheck
+    - stylecheck
+    - govet
+  disable:
+    - typecheck
+    - ineffassign
+    - errcheck
+    - interfacer
+    - unparam
+    - nakedret
+    - prealloc
+    - scopelint
+    - gocritic
+
+linters-settings:
+  lll:
+    line-length: 120
+  gocyclo:
+    min-complexity: 24
+  dupl:
+    threshold: 60
+  goconst:
+    min-len: 7
+    min-occurrences: 4
+
+issues:
+  exclude-use-default: false
+  exclude:
+    - "exported .* should have comment"
+    - "comment on .* should be of the form"
+    - "declaration of \"err\" shadows"
+  exclude-rules:
+    - path: (pkg/csource/generated.go|pkg/report/linux.go|pkg/build/linux_generated.go)
+      linters:
+        - lll
+    - path: (sys/.*/init.*|sys/targets/common.go)
+      text: "don't use ALL_CAPS in Go names"
diff --git a/.gometalinter.json b/.gometalinter.json
index 856e892..71561e3 100644
--- a/.gometalinter.json
+++ b/.gometalinter.json
@@ -15,8 +15,10 @@
 		"sys/fuchsia/gen",
 		"sys/linux/gen",
 		"sys/netbsd/gen",
+		"sys/openbsd/gen",
 		"sys/windows/gen",
-		"sys/test/gen"
+		"sys/test/gen",
+		"sys/trusty/gen"
 	],
 	"enable": [
 		"gofmt",
@@ -36,7 +38,8 @@
 		"lll"
 	],
 	"exclude": [
-		"(sys/(akaros|freebsd|fuchsia|linux|netbsd|test|windows)/init.*|sys/targets/common.go).* don't use ALL_CAPS in Go names",
+		"(sys/.*/init.*|sys/targets/common.go).* don't use ALL_CAPS in Go names",
+		"(tools/syz-trace2syz/parser/(lex|strace).go)",
 		"exported .* should have comment",
 		"comment on .* should be of the form",
 		"declaration of \"err\" shadows",
diff --git a/.travis.yml b/.travis.yml
index ee01dab..91c2507 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,9 @@
 language: go
-dist: trusty
+dist: xenial
 
 go:
-  - "1.9"
-  - "1.10"
+  - "1.11"
+  - "1.12"
 
 before_install:
   - echo $PATH
@@ -24,6 +24,9 @@
   - make install_prerequisites
   - make presubmit
 
+after_success:
+  - bash <(curl -s https://codecov.io/bash)
+
 # If the build fails because some code in not formatted, it's nice to see the diffs after formatting.
 after_failure:
   - git diff --name-only
diff --git a/AUTHORS b/AUTHORS
index be77931..6891156 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -24,3 +24,13 @@
 Denis Efremov
 Ondrej Mosnacek
 Chi Pham
+Anton Lindqvist
+Greg Steuck
+Shankara Pailoor
+Michael Tuexen
+Kamil Rytarowski
+Siddharth Muralee
+Dan Robertson
+Mark Johnston
+Mellanox Technologies
+Cody Holliday
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..f6d9622
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,76 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at opensource@google.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 171fd85..6601238 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -17,6 +17,7 @@
  Atul Prakash
  Julia Hansbrough
  Dan Austin
+ Victor Hsieh
 Baozeng Ding
 Lorenzo Stoakes
 Jeremy Huang
@@ -35,3 +36,15 @@
 Ondrej Mosnacek
 Daniel Borkmann
 Joey Jiao
+Anton Lindqvist
+Tobin Harding
+Shankara Pailoor
+Michael Tuexen
+Hou Jingyi
+Kamil Rytarowski
+Siddharth Muralee
+Dan Robertson
+Mark Johnston
+Mellanox Technologies
+ Noa Osherovich
+Cody Holliday
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index e613f4e..ffa3fea 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -68,31 +68,38 @@
 		},
 		{
 			"ImportPath": "github.com/google/go-cmp/cmp",
-			"Rev": "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
+			"Comment": "v0.2.0-34-g6f77996",
+			"Rev": "6f77996f0c42f7b84e5a2b252227263f93432e9b"
 		},
 		{
 			"ImportPath": "github.com/google/go-cmp/cmp/cmpopts",
-			"Rev": "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
+			"Comment": "v0.2.0-34-g6f77996",
+			"Rev": "6f77996f0c42f7b84e5a2b252227263f93432e9b"
 		},
 		{
 			"ImportPath": "github.com/google/go-cmp/cmp/internal/diff",
-			"Rev": "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
+			"Comment": "v0.2.0-34-g6f77996",
+			"Rev": "6f77996f0c42f7b84e5a2b252227263f93432e9b"
 		},
 		{
 			"ImportPath": "github.com/google/go-cmp/cmp/internal/function",
-			"Rev": "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
+			"Comment": "v0.2.0-34-g6f77996",
+			"Rev": "6f77996f0c42f7b84e5a2b252227263f93432e9b"
 		},
 		{
 			"ImportPath": "github.com/google/go-cmp/cmp/internal/testprotos",
-			"Rev": "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
+			"Comment": "v0.2.0-34-g6f77996",
+			"Rev": "6f77996f0c42f7b84e5a2b252227263f93432e9b"
 		},
 		{
 			"ImportPath": "github.com/google/go-cmp/cmp/internal/teststructs",
-			"Rev": "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
+			"Comment": "v0.2.0-34-g6f77996",
+			"Rev": "6f77996f0c42f7b84e5a2b252227263f93432e9b"
 		},
 		{
 			"ImportPath": "github.com/google/go-cmp/cmp/internal/value",
-			"Rev": "8099a9787ce5dc5984ed879a3bda47dc730a8e97"
+			"Comment": "v0.2.0-34-g6f77996",
+			"Rev": "6f77996f0c42f7b84e5a2b252227263f93432e9b"
 		},
 		{
 			"ImportPath": "github.com/googleapis/gax-go",
diff --git a/METADATA b/METADATA
index 8bfec28..390d930 100644
--- a/METADATA
+++ b/METADATA
@@ -1,14 +1,14 @@
 name: "syzkaller"
-description:
-    "syzkaller is an unsupervised coverage-guided kernel fuzzer. Linux kernel "
-    "fuzzing has the most support, akaros, freebsd, fuchsia, netbsd, windows "
-    "and gvisor are supported to varying degrees."
-
+description: "syzkaller is an unsupervised coverage-guided kernel fuzzer. Linux kernel fuzzing has the most support, akaros, freebsd, fuchsia, netbsd, windows and gvisor are supported to varying degrees."
 third_party {
   url {
     type: GIT
     value: "https://github.com/google/syzkaller"
   }
-  version: "2e0e3130f967984ba51ac1387b67040f0d953942"
-  last_upgrade_date { year: 2018 month: 7 day: 10 }
+  version: "148296f4787895d1b148d29a2f48140bcfd245a3"
+  last_upgrade_date {
+    year: 2019
+    month: 5
+    day: 6
+  }
 }
diff --git a/Makefile b/Makefile
index 976a7cf..71fd97c 100644
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@
 
 ifeq ("$(TARGETOS)", "fuchsia")
 	# SOURCEDIR should point to fuchsia checkout.
-	GO = "$(SOURCEDIR)/scripts/devshell/go"
+	GO = "$(SOURCEDIR)/tools/devshell/contrib/go"
 endif
 
 GITREV=$(shell git rev-parse HEAD)
@@ -55,12 +55,14 @@
 else
 	REV=$(GITREV)+
 endif
+GITREVDATE=$(shell git log -n 1 --format="%ad")
 
 # Don't generate symbol table and DWARF debug info.
 # Reduces build time and binary sizes considerably.
 # That's only needed if you use gdb or nm.
 # If you need that, build manually without these flags.
-GOFLAGS := "-ldflags=-s -w -X github.com/google/syzkaller/sys.GitRevision=$(REV)"
+GOFLAGS := "-ldflags=-s -w -X github.com/google/syzkaller/sys.GitRevision=$(REV) -X 'github.com/google/syzkaller/sys.gitRevisionDate=$(GITREVDATE)'"
+
 GOHOSTFLAGS := $(GOFLAGS)
 GOTARGETFLAGS := $(GOFLAGS)
 ifneq ("$(GOTAGS)", "")
@@ -78,10 +80,15 @@
 	TARGETGOARCH := $(HOSTARCH)
 endif
 
+ifeq ("$(TARGETOS)", "trusty")
+	TARGETGOOS := $(HOSTOS)
+	TARGETGOARCH := $(HOSTARCH)
+endif
+
 .PHONY: all host target \
 	manager runtest fuzzer executor \
 	ci hub \
-	execprog mutate prog2c stress repro upgrade db \
+	execprog mutate prog2c trace2syz stress repro upgrade db \
 	bin/syz-sysgen bin/syz-extract bin/syz-fmt \
 	extract generate generate_go generate_sys \
 	format format_go format_cpp format_sys \
@@ -105,10 +112,22 @@
 
 # executor uses stacks of limited size, so no jumbo frames.
 executor:
+ifneq ("$(BUILDOS)", "$(NATIVEBUILDOS)")
+	$(info ************************************************************************************)
+	$(info Building executor for ${TARGETOS} is not supported on ${BUILDOS}. Executor will not be built.)
+	$(info ************************************************************************************)
+else
+ifneq ("$(NO_CROSS_COMPILER)", "")
+	$(info ************************************************************************************)
+	$(info Native cross-compiler $(CC) is missing. Executor will not be built.)
+	$(info ************************************************************************************)
+else
 	mkdir -p ./bin/$(TARGETOS)_$(TARGETARCH)
 	$(CC) -o ./bin/$(TARGETOS)_$(TARGETARCH)/syz-executor$(EXE) executor/executor.cc \
-		-pthread -Wall -Wframe-larger-than=8192 -Wparentheses -Werror -O2 $(ADDCFLAGS) $(CFLAGS) \
-		-DGOOS_$(TARGETOS)=1 -DGOARCH_$(TARGETARCH)=1  -DGIT_REVISION=\"$(REV)\"
+		$(ADDCFLAGS) $(CFLAGS) -DGOOS_$(TARGETOS)=1 -DGOARCH_$(TARGETARCH)=1 \
+		-DHOSTGOOS_$(HOSTOS)=1 -DGIT_REVISION=\"$(REV)\"
+endif
+endif
 
 manager:
 	GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-manager github.com/google/syzkaller/syz-manager
@@ -146,20 +165,46 @@
 upgrade:
 	GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-upgrade github.com/google/syzkaller/tools/syz-upgrade
 
+trace2syz:
+	GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-trace2syz github.com/google/syzkaller/tools/syz-trace2syz
+
+usbgen:
+	GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-usbgen github.com/google/syzkaller/tools/syz-usbgen
+
+# `extract` extracts const files from various kernel sources, and may only
+# re-generate parts of files.
 extract: bin/syz-extract
+ifeq ($(TARGETOS),fuchsia)
+	$(MAKE) generate_fidl TARGETARCH=amd64
+	$(MAKE) generate_fidl TARGETARCH=arm64
+else
+endif
 	bin/syz-extract -build -os=$(TARGETOS) -sourcedir=$(SOURCEDIR) $(FILES)
 bin/syz-extract:
 	GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o $@ ./sys/syz-extract
 
+# `generate` does *not* depend on any kernel sources, and generates everything
+# in one pass, for all arches. It can be run on a bare syzkaller checkout.
 generate: generate_go generate_sys
 	$(MAKE) format
 
 generate_go: bin/syz-sysgen format_cpp
-	$(GO) generate ./pkg/csource ./executor ./pkg/ifuzz ./pkg/build
+	$(GO) generate ./pkg/csource ./executor ./pkg/ifuzz ./pkg/build ./pkg/html
 
 generate_sys: bin/syz-sysgen
 	bin/syz-sysgen
 
+generate_fidl:
+ifeq ($(TARGETOS),fuchsia)
+	$(HOSTGO) generate ./sys/fuchsia
+	$(MAKE) format_sys
+else
+endif
+
+generate_trace2syz:
+	(cd tools/syz-trace2syz/parser; ragel -Z -G2 -o lex.go straceLex.rl)
+	(cd tools/syz-trace2syz/parser; goyacc -o strace.go -p Strace -v="" strace.y)
+
 bin/syz-sysgen:
 	$(GO) build $(GOHOSTFLAGS) -o $@ ./sys/syz-sysgen
 
@@ -172,31 +217,40 @@
 	clang-format --style=file -i executor/*.cc executor/*.h tools/kcovtrace/*.c
 
 format_sys: bin/syz-fmt
-	bin/syz-fmt sys/test
-	bin/syz-fmt sys/akaros
-	bin/syz-fmt sys/freebsd
-	bin/syz-fmt sys/netbsd
-	bin/syz-fmt sys/linux
-	bin/syz-fmt sys/fuchsia
-	bin/syz-fmt sys/windows
+	bin/syz-fmt all
 
 bin/syz-fmt:
-	$(GO) build $(GOHOSTFLAGS) -o $@ ./tools/syz-fmt
+	$(HOSTGO) build $(GOHOSTFLAGS) -o $@ ./tools/syz-fmt
 
 tidy:
 	# A single check is enabled for now. But it's always fixable and proved to be useful.
-	clang-tidy -quiet -header-filter=.* -checks=-*,misc-definitions-in-headers -warnings-as-errors=* executor/*.cc
+	clang-tidy -quiet -header-filter=.* -checks=-*,misc-definitions-in-headers -warnings-as-errors=* \
+		-extra-arg=-DGOOS_$(TARGETOS)=1 -extra-arg=-DGOARCH_$(TARGETARCH)=1 \
+		executor/*.cc
 	# Just check for compiler warnings.
 	$(CC) executor/test_executor.cc -c -o /dev/null -Wparentheses -Wno-unused -Wall
 
 gometalinter:
+ifeq ($(TRAVIS),)
 	env CGO_ENABLED=1 gometalinter.v2 ./...
+else
+	# GOMAXPROCS/GOGC settings help to reduce memory usage,
+	# otherwise this gets OOM-killed on travis.
+	env CGO_ENABLED=1 GOMAXPROCS=1 GOGC=50 gometalinter.v2 ./...
+endif
 
-arch: arch_darwin_amd64_host arch_linux_amd64_host arch_freebsd_amd64_host arch_netbsd_amd64_host \
+lint:
+	# To install run:
+	# go get -u github.com/golangci/golangci-lint/cmd/golangci-lint
+	# Currently it consumes too much memory to run on Travis (see #977).
+	golangci-lint run ./...
+
+arch: arch_darwin_amd64_host arch_linux_amd64_host arch_freebsd_amd64_host \
+	arch_netbsd_amd64_host arch_openbsd_amd64_host \
 	arch_linux_amd64_target arch_linux_386_target \
 	arch_linux_arm64_target arch_linux_arm_target arch_linux_ppc64le_target \
-	arch_freebsd_amd64_target arch_netbsd_amd64_target arch_windows_amd64_target \
-	arch_test
+	arch_freebsd_amd64_target arch_netbsd_amd64_target arch_openbsd_amd64_target \
+	arch_windows_amd64_target arch_test
 
 arch_darwin_amd64_host:
 	env HOSTOS=darwin HOSTARCH=amd64 $(MAKE) host
@@ -237,9 +291,15 @@
 arch_netbsd_amd64_target:
 	env TARGETOS=netbsd TARGETARCH=amd64 $(MAKE) target
 
+arch_openbsd_amd64_host:
+	env HOSTOS=openbsd HOSTARCH=amd64 $(MAKE) host
+
+arch_openbsd_amd64_target:
+	env TARGETOS=openbsd TARGETARCH=amd64 $(MAKE) target
+
 arch_windows_amd64_target:
 	env GOOG=windows GOARCH=amd64 $(GO) install ./syz-fuzzer
-	env TARGETOS=windows TARGETARCH=amd64 $(MAKE) fuzzer execprog stress
+	env TARGETOS=windows TARGETARCH=amd64 $(MAKE) target
 
 arch_test:
 	env TARGETOS=test TARGETARCH=64 $(MAKE) executor
@@ -261,11 +321,18 @@
 presubmit_parallel: test test_race arch check_links
 
 test:
+ifeq ("$(TRAVIS)$(shell go version | grep 1.11)", "true")
+	# Collect coverage report for codecov.io when testing Go 1.12 on travis (uploaded in .travis.yml).
+	env CGO_ENABLED=1 $(GO) test -short -coverprofile=coverage.txt ./...
+else
 	# Executor tests use cgo.
 	env CGO_ENABLED=1 $(GO) test -short ./...
+endif
 
 test_race:
-	env CGO_ENABLED=1 $(GO) test -short -race -bench=.* -benchtime=.2s ./...
+	env CGO_ENABLED=1 $(GO) test -race; if test $$? -ne 2; then \
+	env CGO_ENABLED=1 $(GO) test -race -short -bench=.* -benchtime=.2s ./... ;\
+	fi
 
 clean:
 	rm -rf ./bin/
@@ -277,10 +344,12 @@
 	uname -a
 	sudo apt-get update
 	sudo apt-get install -y -q libc6-dev-i386 linux-libc-dev \
-		gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf gcc-powerpc64le-linux-gnu || true
+		gcc-aarch64-linux-gnu gcc-arm-linux-gnueabi gcc-powerpc64le-linux-gnu || true
 	sudo apt-get install -y -q g++-aarch64-linux-gnu || true
 	sudo apt-get install -y -q g++-powerpc64le-linux-gnu || true
-	sudo apt-get install -y -q g++-arm-linux-gnueabihf || true
+	sudo apt-get install -y -q g++-arm-linux-gnueabi || true
+	sudo apt-get install -y -q ragel
+	go get -u golang.org/x/tools/cmd/goyacc
 	go get -u gopkg.in/alecthomas/gometalinter.v2
 	gometalinter.v2 --install
 
diff --git a/README.md b/README.md
index 581fa52..cac7abd 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,32 @@
 # syzkaller - kernel fuzzer
 
-[![Build Status](https://travis-ci.org/google/syzkaller.svg?branch=master)](https://travis-ci.org/google/syzkaller) [![Go Report Card](https://goreportcard.com/badge/github.com/google/syzkaller)](https://goreportcard.com/report/github.com/google/syzkaller) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
+[![Build Status](https://travis-ci.org/google/syzkaller.svg?branch=master)](https://travis-ci.org/google/syzkaller)
+[![Go Report Card](https://goreportcard.com/badge/github.com/google/syzkaller)](https://goreportcard.com/report/github.com/google/syzkaller)
+[![Coverage Status](https://codecov.io/gh/google/syzkaller/graph/badge.svg)](https://codecov.io/gh/google/syzkaller)
+[![GoDoc](https://godoc.org/github.com/google/syzkaller?status.svg)](https://godoc.org/github.com/google/syzkaller)
+[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
 
-`syzkaller` is an unsupervised coverage-guided kernel fuzzer. `Linux` kernel fuzzing has the most support, `akaros`, `freebsd`, `fuchsia`, `netbsd`, `windows` and `gvisor` are supported to varying degrees.
+`syzkaller` is an unsupervised coverage-guided kernel fuzzer.\
+Supported OSes: `Akaros`, `FreeBSD`, `Fuchsia`, `gVisor`, `Linux`, `NetBSD`, `OpenBSD`, `Windows`.
 
-The project mailing list is [syzkaller@googlegroups.com](https://groups.google.com/forum/#!forum/syzkaller).
-You can subscribe to it with a google account or by sending an email to syzkaller+subscribe@googlegroups.com.
+Mailing list: [syzkaller@googlegroups.com](https://groups.google.com/forum/#!forum/syzkaller) (join on [web](https://groups.google.com/forum/#!forum/syzkaller) or by [email](mailto:syzkaller+subscribe@googlegroups.com)).
 
-[List of found bugs](docs/found_bugs.md).
+Found bugs: [Akaros](docs/akaros/found_bugs.md), [Darwin/XNU](docs/darwin/README.md), [FreeBSD](docs/freebsd/found_bugs.md), [Linux](docs/linux/found_bugs.md), [NetBSD](docs/netbsd/found_bugs.md), [OpenBSD](docs/openbsd/found_bugs.md), [Windows](docs/windows/README.md).
 
 ## Documentation
 
-Initially, syzkaller was developed with Linux kernel fuzzing in mind, but now it's being extended to support other OS kernels as well.
+Initially, syzkaller was developed with Linux kernel fuzzing in mind, but now
+it's being extended to support other OS kernels as well.
 Most of the documentation at this moment is related to the Linux kernel.
-For other OS kernels check: [Akaros](docs/akaros/README.md), [FreeBSD](docs/freebsd.md), [Fuchsia](docs/fuchsia.md), [NetBSD](docs/netbsd.md), [Windows](docs/windows.md), [gVisor](docs/gvisor.md).
+For other OS kernels check:
+[Akaros](docs/akaros/README.md),
+[Darwin/XNU](docs/darwin/README.md),
+[FreeBSD](docs/freebsd/README.md),
+[Fuchsia](docs/fuchsia/README.md),
+[NetBSD](docs/netbsd/README.md),
+[OpenBSD](docs/openbsd/setup.md),
+[Windows](docs/windows/README.md),
+[gVisor](docs/gvisor/README.md).
 
 - [How to install syzkaller](docs/setup.md)
 - [How to use syzkaller](docs/usage.md)
@@ -23,6 +36,7 @@
 
 ## External Articles
 
+ - [Research work based on syzkaller](docs/research.md)
  - From [HardenedLinux](https://github.com/hardenedlinux) project:
    - [Kernel QA with syzkaller and qemu](https://github.com/hardenedlinux/Debian-GNU-Linux-Profiles/blob/master/docs/harbian_qa/fuzz_testing/syzkaller_general.md) (tutorial on how to setup syzkaller with qemu)
    - [Syzkaller crash DEMO](https://github.com/hardenedlinux/Debian-GNU-Linux-Profiles/blob/master/docs/harbian_qa/fuzz_testing/syzkaller_crash_demo.md) (tutorial on how to extend syzkaller with new syscalls)
@@ -34,6 +48,7 @@
  - [Debugging a kernel crash found by syzkaller](http://vegardno.blogspot.de/2016/08/sync-debug.html) (by Quentin Casasnovas)
  - [Linux Plumbers 2016 talk slides](https://docs.google.com/presentation/d/1iAuTvzt_xvDzS2misXwlYko_VDvpvCmDevMOq2rXIcA/edit?usp=sharing)
  - [syzkaller: the next gen kernel fuzzer](https://www.slideshare.net/DmitryVyukov/syzkaller-the-next-gen-kernel-fuzzer) (basics of operations, tutorial on how to run syzkaller and how to extend it to fuzz new drivers)
+ - [syzbot and the tale of thousand kernel bugs](https://events.linuxfoundation.org/wp-content/uploads/2017/11/Syzbot-and-the-Tale-of-Thousand-Kernel-Bugs-Dmitry-Vyukov-Google.pdf) [[video](https://www.youtube.com/watch?v=qrBVXxZDVQY)]
 
 ## Disclaimer
 
diff --git a/dashboard/app/README.md b/dashboard/app/README.md
new file mode 100644
index 0000000..b3e118b
--- /dev/null
+++ b/dashboard/app/README.md
@@ -0,0 +1,11 @@
+# Dashboard
+
+`dashboard` is an App Engine app that powers [syzbot](/docs/syzbot.md).
+The main deployment is at [syzkaller.appspot.com](https://syzkaller.appspot.com).
+
+It is so-called "Standard environment Go app" managed with
+[original App Engine SDK](https://cloud.google.com/appengine/docs/standard/go/download).\
+For more details about App Engine refer to the [docs](https://cloud.google.com/appengine/docs/)
+and in particular [support package docs](https://cloud.google.com/appengine/docs/standard/go/reference).
+
+**Note**: The app is not stable and is not officially supported. It's here only to power the main deployment.
diff --git a/dashboard/app/access.go b/dashboard/app/access.go
index 725aa45..3a93cf7 100644
--- a/dashboard/app/access.go
+++ b/dashboard/app/access.go
@@ -11,7 +11,7 @@
 
 	"golang.org/x/net/context"
 	"google.golang.org/appengine"
-	"google.golang.org/appengine/datastore"
+	db "google.golang.org/appengine/datastore"
 	"google.golang.org/appengine/log"
 	"google.golang.org/appengine/user"
 )
@@ -72,6 +72,8 @@
 		return nil, checkAccessLevel(c, r, AccessAdmin)
 	case textPatch:
 		return nil, checkJobTextAccess(c, r, "Patch", id)
+	case textLog:
+		return nil, checkJobTextAccess(c, r, "Log", id)
 	case textError:
 		return nil, checkJobTextAccess(c, r, "Error", id)
 	case textKernelConfig:
@@ -99,7 +101,7 @@
 
 func checkCrashTextAccess(c context.Context, r *http.Request, field string, id int64) (*Crash, error) {
 	var crashes []*Crash
-	keys, err := datastore.NewQuery("Crash").
+	keys, err := db.NewQuery("Crash").
 		Filter(field+"=", id).
 		GetAll(c, &crashes)
 	if err != nil {
@@ -111,7 +113,7 @@
 	}
 	crash := crashes[0]
 	bug := new(Bug)
-	if err := datastore.Get(c, keys[0].Parent(), bug); err != nil {
+	if err := db.Get(c, keys[0].Parent(), bug); err != nil {
 		return nil, fmt.Errorf("failed to get bug: %v", err)
 	}
 	bugLevel := bug.sanitizeAccess(accessLevel(c, r))
@@ -119,7 +121,7 @@
 }
 
 func checkJobTextAccess(c context.Context, r *http.Request, field string, id int64) error {
-	keys, err := datastore.NewQuery("Job").
+	keys, err := db.NewQuery("Job").
 		Filter(field+"=", id).
 		KeysOnly().
 		GetAll(c, nil)
@@ -131,7 +133,7 @@
 			len(keys), field, id)
 	}
 	bug := new(Bug)
-	if err := datastore.Get(c, keys[0].Parent(), bug); err != nil {
+	if err := db.Get(c, keys[0].Parent(), bug); err != nil {
 		return fmt.Errorf("failed to get bug: %v", err)
 	}
 	bugLevel := bug.sanitizeAccess(accessLevel(c, r))
diff --git a/dashboard/app/access_test.go b/dashboard/app/access_test.go
index bc03ec9..0be3721 100644
--- a/dashboard/app/access_test.go
+++ b/dashboard/app/access_test.go
@@ -8,10 +8,12 @@
 import (
 	"bytes"
 	"fmt"
+	"net/http"
 	"strconv"
 	"testing"
 
 	"github.com/google/syzkaller/dashboard/dashapi"
+	"google.golang.org/appengine/user"
 )
 
 // TestAccessConfig checks that access level were properly assigned throughout the config.
@@ -40,6 +42,9 @@
 
 // TestAccess checks that all UIs respect access levels.
 func TestAccess(t *testing.T) {
+	if testing.Short() {
+		t.Skip()
+	}
 	c := NewCtx(t)
 	defer c.Close()
 
@@ -50,10 +55,34 @@
 		url   string      // url at which this entity can be requested.
 	}
 	entities := []entity{
+		// Main pages.
 		{
-			// Main page.
-			level: config.AccessLevel,
-			url:   "/",
+			level: AccessAdmin,
+			url:   "/admin",
+		},
+		{
+			level: AccessPublic,
+			url:   "/access-public",
+		},
+		{
+			level: AccessPublic,
+			url:   "/access-public/fixed",
+		},
+		{
+			level: AccessUser,
+			url:   "/access-user",
+		},
+		{
+			level: AccessUser,
+			url:   "/access-user/fixed",
+		},
+		{
+			level: AccessAdmin,
+			url:   "/access-admin",
+		},
+		{
+			level: AccessAdmin,
+			url:   "/access-admin/fixed",
 		},
 		{
 			// Any references to namespace, reporting, links, etc.
@@ -70,14 +99,10 @@
 	// noteBugAccessLevel collects all entities associated with the extID bug.
 	noteBugAccessLevel := func(extID string, level AccessLevel) {
 		bug, _, err := findBugByReportingID(c.ctx, extID)
-		if err != nil {
-			t.Fatal(err)
-		}
+		c.expectOK(err)
 		crash, _, err := findCrashForBug(c.ctx, bug)
-		if err != nil {
-			t.Fatal(err)
-		}
-		bugID := bugKeyHash(bug.Namespace, bug.Title, bug.Seq)
+		c.expectOK(err)
+		bugID := bug.keyHash()
 		entities = append(entities, []entity{
 			{
 				level: level,
@@ -144,9 +169,7 @@
 	// noteBuildccessLevel collects all entities associated with the kernel build buildID.
 	noteBuildccessLevel := func(ns, buildID string) {
 		build, err := loadBuild(c.ctx, ns, buildID)
-		if err != nil {
-			t.Fatal(err)
-		}
+		c.expectOK(err)
 		entities = append(entities, entity{
 			level: config.Namespaces[ns].AccessLevel,
 			ref:   build.ID,
@@ -285,6 +308,16 @@
 		reply, err := c.AuthGET(requestLevel, url)
 		if requestLevel >= pageLevel {
 			c.expectOK(err)
+		} else if requestLevel == AccessPublic {
+			loginURL, err1 := user.LoginURL(c.ctx, url)
+			if err1 != nil {
+				t.Fatal(err1)
+			}
+			c.expectNE(err, nil)
+			httpErr, ok := err.(HttpError)
+			c.expectTrue(ok)
+			c.expectEQ(httpErr.Code, http.StatusTemporaryRedirect)
+			c.expectEQ(httpErr.Headers["Location"], []string{loginURL})
 		} else {
 			c.expectForbidden(err)
 		}
diff --git a/dashboard/app/admin.go b/dashboard/app/admin.go
index 19a963f..fcc48b6 100644
--- a/dashboard/app/admin.go
+++ b/dashboard/app/admin.go
@@ -8,14 +8,14 @@
 	"net/http"
 
 	"golang.org/x/net/context"
-	"google.golang.org/appengine/datastore"
+	db "google.golang.org/appengine/datastore"
 	"google.golang.org/appengine/log"
 )
 
 // dropNamespace drops all entities related to a single namespace.
 // Use with care. There is no undo.
 // This functionality is intentionally not connected to any handler.
-// To use it, first make a backup of the datastore. Then, specify the target
+// To use it, first make a backup of the db. Then, specify the target
 // namespace in the ns variable, connect the function to a handler, invoke it
 // and double check the output. Finally, set dryRun to false and invoke again.
 func dropNamespace(c context.Context, w http.ResponseWriter, r *http.Request) error {
@@ -39,6 +39,7 @@
 		{textReproSyz, ""},
 		{textKernelConfig, ""},
 		{"Job", ""},
+		{textLog, ""},
 		{textError, ""},
 		{textCrashLog, ""},
 		{textCrashReport, ""},
@@ -47,7 +48,7 @@
 		{"Bug", "Crash"},
 	}
 	for _, entity := range entities {
-		keys, err := datastore.NewQuery(entity.name).
+		keys, err := db.NewQuery(entity.name).
 			Filter("Namespace=", ns).
 			KeysOnly().
 			GetAll(c, nil)
@@ -56,9 +57,9 @@
 		}
 		fmt.Fprintf(w, "%v: %v\n", entity.name, len(keys))
 		if entity.child != "" {
-			var childKeys []*datastore.Key
+			var childKeys []*db.Key
 			for _, key := range keys {
-				keys1, err := datastore.NewQuery(entity.child).
+				keys1, err := db.NewQuery(entity.child).
 					Ancestor(key).
 					KeysOnly().
 					GetAll(c, nil)
@@ -79,8 +80,6 @@
 	return nil
 }
 
-var _ = dropNamespace // prevent warnings about dead code
-
 func dropNamespaceReportingState(c context.Context, w http.ResponseWriter, ns string, dryRun bool) error {
 	tx := func(c context.Context) error {
 		state, err := loadReportingState(c)
@@ -101,10 +100,10 @@
 		fmt.Fprintf(w, "ReportingState: %v\n", len(state.Entries)-len(newState.Entries))
 		return nil
 	}
-	return datastore.RunInTransaction(c, tx, nil)
+	return db.RunInTransaction(c, tx, nil)
 }
 
-func dropEntities(c context.Context, keys []*datastore.Key, dryRun bool) error {
+func dropEntities(c context.Context, keys []*db.Key, dryRun bool) error {
 	if dryRun {
 		return nil
 	}
@@ -113,10 +112,77 @@
 		if batch > len(keys) {
 			batch = len(keys)
 		}
-		if err := datastore.DeleteMulti(c, keys[:batch]); err != nil {
+		if err := db.DeleteMulti(c, keys[:batch]); err != nil {
 			return err
 		}
 		keys = keys[batch:]
 	}
 	return nil
 }
+
+// updateBugReporting adds missing reporting stages to bugs in a single namespace.
+// Use with care. There is no undo.
+// This can be used to migrate datastore to a new config with more reporting stages.
+// This functionality is intentionally not connected to any handler.
+// Before invoking it is recommended to stop all connected instances just in case.
+func updateBugReporting(c context.Context, w http.ResponseWriter, r *http.Request) error {
+	if accessLevel(c, r) != AccessAdmin {
+		return fmt.Errorf("admin only")
+	}
+	ns := r.FormValue("ns")
+	if ns == "" {
+		return fmt.Errorf("no ns parameter")
+	}
+	var bugs []*Bug
+	keys, err := db.NewQuery("Bug").
+		Filter("Namespace=", ns).
+		GetAll(c, &bugs)
+	if err != nil {
+		return err
+	}
+	log.Warningf(c, "fetched %v bugs for namespce %v", len(bugs), ns)
+	cfg := config.Namespaces[ns]
+	var batchKeys []*db.Key
+	const batchSize = 20
+	for i, bug := range bugs {
+		if len(bug.Reporting) >= len(cfg.Reporting) {
+			continue
+		}
+		batchKeys = append(batchKeys, keys[i])
+		if len(batchKeys) == batchSize {
+			if err := updateBugReportingBatch(c, cfg, batchKeys); err != nil {
+				return err
+			}
+			batchKeys = nil
+		}
+	}
+	if len(batchKeys) != 0 {
+		if err := updateBugReportingBatch(c, cfg, batchKeys); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func updateBugReportingBatch(c context.Context, cfg *Config, keys []*db.Key) error {
+	tx := func(c context.Context) error {
+		bugs := make([]*Bug, len(keys))
+		if err := db.GetMulti(c, keys, bugs); err != nil {
+			return err
+		}
+		for _, bug := range bugs {
+			createBugReporting(bug, cfg)
+		}
+		_, err := db.PutMulti(c, keys, bugs)
+		return err
+	}
+	err := db.RunInTransaction(c, tx, &db.TransactionOptions{XG: true})
+	log.Warningf(c, "updated %v bugs: %v", len(keys), err)
+	return err
+}
+
+// Prevent warnings about dead code.
+var (
+	_ = dropNamespace
+	_ = updateBugReporting
+)
diff --git a/dashboard/app/admin.html b/dashboard/app/admin.html
new file mode 100644
index 0000000..edbdc9f
--- /dev/null
+++ b/dashboard/app/admin.html
@@ -0,0 +1,84 @@
+{{/*
+Copyright 2019 syzkaller project authors. All rights reserved.
+Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+Main page.
+*/}}
+
+<!doctype html>
+<html>
+<head>
+	{{template "head" .Header}}
+	<title>syzbot</title>
+</head>
+<body>
+	{{template "header" .Header}}
+
+	<a class="plain" href="#log"><div id="log"><b>Error log:</b></div></a>
+	<textarea id="log_textarea" readonly rows="20" wrap=off>{{printf "%s" .Log}}</textarea>
+	<script>
+		var textarea = document.getElementById("log_textarea");
+		textarea.scrollTop = textarea.scrollHeight;
+	</script>
+	<br><br>
+
+	{{template "manager_list" $.Managers}}
+
+	<table class="list_table">
+		<caption id="jobs"><a class="plain" href="#jobs">Recent jobs:</a></caption>
+		<thead>
+		<tr>
+			<th>Bug</th>
+			<th>Created</th>
+			<th>Duration</th>
+			<th>User</th>
+			<th>Patch</th>
+			<th>Repo</th>
+			<th>Manager</th>
+			<th>Result</th>
+		</tr>
+		</thead>
+		<tbody>
+		{{range $job := $.Jobs}}
+			<tr>
+				<td class="title"><a href="{{$job.BugLink}}">{{$job.BugTitle}}</a></td>
+				<td class="time">{{link $job.ExternalLink (formatTime $job.Created)}}</td>
+				<td class="time" title="started: {{formatTime $job.Started}}&#013;finished: {{formatTime $job.Finished}}">
+					{{formatDuration $job.Duration}}{{if gt $job.Attempts 1}} ({{$job.Attempts}}){{end}}
+				</td>
+				<td>
+					{{if eq $job.Type 0}}
+						{{$job.User}}
+					{{else if eq $job.Type 1}}
+						bisect
+					{{else if eq $job.Type 2}}
+						bisect fix
+					{{end}}
+				</td>
+				<td>{{optlink $job.PatchLink "patch"}}</td>
+				<td class="kernel" title="{{$job.KernelAlias}}">{{$job.KernelAlias}}</td>
+				<td title="{{$job.Namespace}}/{{$job.Reporting}}">{{$job.Manager}}</td>
+				<td class="result">
+					{{if $job.ErrorLink}}
+						{{link $job.ErrorLink "error"}}
+					{{else if $job.LogLink}}
+						{{link $job.LogLink "log"}}
+						({{if $job.Commit}}1{{else}}{{len $job.Commits}}{{end}})
+					{{else if $job.CrashTitle}}
+						{{optlink $job.CrashReportLink "report"}}
+						{{optlink $job.CrashLogLink "log"}}
+					{{else if formatTime $job.Finished}}
+						OK
+					{{else if formatTime $job.Started}}
+						running
+					{{else}}
+						pending
+					{{end}}
+				</td>
+			</tr>
+		{{end}}
+		</tbody>
+	</table>
+	<br><br>
+</body>
+</html>
diff --git a/dashboard/app/aetest.go b/dashboard/app/aetest.go
new file mode 100644
index 0000000..c21503c
--- /dev/null
+++ b/dashboard/app/aetest.go
@@ -0,0 +1,10 @@
+// Copyright 2019 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// +build aetest
+
+package dash
+
+// isAppEngineTest is meant to be used in prod config to either
+// load the config or just check its correctness.
+const isAppEngineTest = true
diff --git a/dashboard/app/api.go b/dashboard/app/api.go
index 4ca7948..de64e5d 100644
--- a/dashboard/app/api.go
+++ b/dashboard/app/api.go
@@ -21,7 +21,7 @@
 	"github.com/google/syzkaller/pkg/hash"
 	"golang.org/x/net/context"
 	"google.golang.org/appengine"
-	"google.golang.org/appengine/datastore"
+	db "google.golang.org/appengine/datastore"
 	"google.golang.org/appengine/log"
 )
 
@@ -34,6 +34,7 @@
 	"job_poll":              apiJobPoll,
 	"job_done":              apiJobDone,
 	"reporting_poll_bugs":   apiReportingPollBugs,
+	"reporting_poll_notifs": apiReportingPollNotifications,
 	"reporting_poll_closed": apiReportingPollClosed,
 	"reporting_update":      apiReportingUpdate,
 }
@@ -46,6 +47,8 @@
 	"report_failed_repro": apiReportFailedRepro,
 	"need_repro":          apiNeedRepro,
 	"manager_stats":       apiManagerStats,
+	"commit_poll":         apiCommitPoll,
+	"upload_commits":      apiUploadCommits,
 }
 
 type JSONHandler func(c context.Context, r *http.Request) (interface{}, error)
@@ -173,7 +176,7 @@
 		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
 	}
 	var bugs []*Bug
-	_, err := datastore.NewQuery("Bug").
+	_, err := db.NewQuery("Bug").
 		Filter("Namespace=", ns).
 		Filter("Status<", BugStatusFixed).
 		GetAll(c, &bugs)
@@ -201,18 +204,151 @@
 		commits = append(commits, com)
 	}
 	sort.Strings(commits)
-	reportEmail := ""
+	resp := &dashapi.BuilderPollResp{
+		PendingCommits: commits,
+		ReportEmail:    reportEmail(c, ns),
+	}
+	return resp, nil
+}
+
+func reportEmail(c context.Context, ns string) string {
 	for _, reporting := range config.Namespaces[ns].Reporting {
 		if _, ok := reporting.Config.(*EmailConfig); ok {
-			reportEmail = ownEmail(c)
+			return ownEmail(c)
+		}
+	}
+	return ""
+}
+
+func apiCommitPoll(c context.Context, ns string, r *http.Request, payload []byte) (interface{}, error) {
+	resp := &dashapi.CommitPollResp{
+		ReportEmail: reportEmail(c, ns),
+	}
+	for _, repo := range config.Namespaces[ns].Repos {
+		resp.Repos = append(resp.Repos, dashapi.Repo{
+			URL:    repo.URL,
+			Branch: repo.Branch,
+		})
+	}
+	var bugs []*Bug
+	_, err := db.NewQuery("Bug").
+		Filter("Namespace=", ns).
+		Filter("NeedCommitInfo=", true).
+		Project("Commits").
+		Limit(100).
+		GetAll(c, &bugs)
+	if err != nil {
+		return nil, fmt.Errorf("failed to query bugs: %v", err)
+	}
+	commits := make(map[string]bool)
+	for _, bug := range bugs {
+		for _, com := range bug.Commits {
+			commits[com] = true
+		}
+	}
+	for com := range commits {
+		resp.Commits = append(resp.Commits, com)
+	}
+	return resp, nil
+}
+
+func apiUploadCommits(c context.Context, ns string, r *http.Request, payload []byte) (interface{}, error) {
+	req := new(dashapi.CommitPollResultReq)
+	if err := json.Unmarshal(payload, req); err != nil {
+		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
+	}
+	// This adds fixing commits to bugs.
+	err := addCommitsToBugs(c, ns, "", nil, req.Commits)
+	if err != nil {
+		return nil, err
+	}
+	// Now add commit info to commits.
+	for _, com := range req.Commits {
+		if com.Hash == "" {
+			continue
+		}
+		if err := addCommitInfo(c, ns, com); err != nil {
+			return nil, err
+		}
+	}
+	return nil, nil
+}
+
+func addCommitInfo(c context.Context, ns string, com dashapi.Commit) error {
+	var bugs []*Bug
+	keys, err := db.NewQuery("Bug").
+		Filter("Namespace=", ns).
+		Filter("Commits=", com.Title).
+		GetAll(c, &bugs)
+	if err != nil {
+		return fmt.Errorf("failed to query bugs: %v", err)
+	}
+	for i, bug := range bugs {
+		if err := addCommitInfoToBug(c, bug, keys[i], com); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func addCommitInfoToBug(c context.Context, bug *Bug, bugKey *db.Key, com dashapi.Commit) error {
+	if needUpdate, err := addCommitInfoToBugImpl(c, bug, com); err != nil {
+		return err
+	} else if !needUpdate {
+		return nil
+	}
+	tx := func(c context.Context) error {
+		bug := new(Bug)
+		if err := db.Get(c, bugKey, bug); err != nil {
+			return fmt.Errorf("failed to get bug %v: %v", bugKey.StringID(), err)
+		}
+		if needUpdate, err := addCommitInfoToBugImpl(c, bug, com); err != nil {
+			return err
+		} else if !needUpdate {
+			return nil
+		}
+		if _, err := db.Put(c, bugKey, bug); err != nil {
+			return fmt.Errorf("failed to put bug: %v", err)
+		}
+		return nil
+	}
+	return db.RunInTransaction(c, tx, nil)
+}
+
+func addCommitInfoToBugImpl(c context.Context, bug *Bug, com dashapi.Commit) (bool, error) {
+	ci := -1
+	for i, title := range bug.Commits {
+		if title == com.Title {
+			ci = i
 			break
 		}
 	}
-	resp := &dashapi.BuilderPollResp{
-		PendingCommits: commits,
-		ReportEmail:    reportEmail,
+	if ci < 0 {
+		return false, nil
 	}
-	return resp, nil
+	for len(bug.CommitInfo) < len(bug.Commits) {
+		bug.CommitInfo = append(bug.CommitInfo, Commit{})
+	}
+	hash0 := bug.CommitInfo[ci].Hash
+	date0 := bug.CommitInfo[ci].Date
+	author0 := bug.CommitInfo[ci].Author
+	needCommitInfo0 := bug.NeedCommitInfo
+
+	bug.CommitInfo[ci].Hash = com.Hash
+	bug.CommitInfo[ci].Date = com.Date
+	bug.CommitInfo[ci].Author = com.Author
+	bug.NeedCommitInfo = false
+	for i := range bug.CommitInfo {
+		if bug.CommitInfo[i].Hash == "" {
+			bug.NeedCommitInfo = true
+			break
+		}
+	}
+	changed := hash0 != bug.CommitInfo[ci].Hash ||
+		date0 != bug.CommitInfo[ci].Date ||
+		author0 != bug.CommitInfo[ci].Author ||
+		needCommitInfo0 != bug.NeedCommitInfo
+	return changed, nil
 }
 
 func apiJobPoll(c context.Context, r *http.Request, payload []byte) (interface{}, error) {
@@ -220,10 +356,10 @@
 	if err := json.Unmarshal(payload, req); err != nil {
 		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
 	}
-	if len(req.Managers) == 0 {
+	if len(req.PatchTestManagers) == 0 && len(req.BisectManagers) == 0 {
 		return nil, fmt.Errorf("no managers")
 	}
-	return pollPendingJobs(c, req.Managers)
+	return pollPendingJobs(c, req.PatchTestManagers, req.BisectManagers)
 }
 
 func apiJobDone(c context.Context, r *http.Request, payload []byte) (interface{}, error) {
@@ -241,29 +377,56 @@
 		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
 	}
 	now := timeNow(c)
-	isNewBuild, err := uploadBuild(c, now, ns, req, BuildNormal)
+	_, isNewBuild, err := uploadBuild(c, now, ns, req, BuildNormal)
 	if err != nil {
 		return nil, err
 	}
-	if len(req.Commits) != 0 || len(req.FixCommits) != 0 {
-		if err := addCommitsToBugs(c, ns, req.Manager, req.Commits, req.FixCommits); err != nil {
+	if isNewBuild {
+		err := updateManager(c, ns, req.Manager, func(mgr *Manager, stats *ManagerStats) error {
+			prevKernel, prevSyzkaller := "", ""
+			if mgr.CurrentBuild != "" {
+				prevBuild, err := loadBuild(c, ns, mgr.CurrentBuild)
+				if err != nil {
+					return err
+				}
+				prevKernel = prevBuild.KernelCommit
+				prevSyzkaller = prevBuild.SyzkallerCommit
+			}
+			log.Infof(c, "new build on %v: kernel %v->%v syzkaller %v->%v",
+				req.Manager, prevKernel, req.KernelCommit, prevSyzkaller, req.SyzkallerCommit)
+			mgr.CurrentBuild = req.ID
+			if req.KernelCommit != prevKernel {
+				mgr.FailedBuildBug = ""
+			}
+			if req.SyzkallerCommit != prevSyzkaller {
+				mgr.FailedSyzBuildBug = ""
+			}
+			return nil
+		})
+		if err != nil {
 			return nil, err
 		}
 	}
-	if isNewBuild {
-		if err := updateManager(c, ns, req.Manager, func(mgr *Manager, stats *ManagerStats) {
-			mgr.CurrentBuild = req.ID
-			mgr.FailedBuildBug = ""
-		}); err != nil {
-			return nil, err
+	if len(req.Commits) != 0 || len(req.FixCommits) != 0 {
+		for i := range req.FixCommits {
+			// Reset hashes just to make sure,
+			// the build does not necessary come from the master repo, so we must not remember hashes.
+			req.FixCommits[i].Hash = ""
+		}
+		if err := addCommitsToBugs(c, ns, req.Manager, req.Commits, req.FixCommits); err != nil {
+			// We've already uploaded the build successfully and manager can use it.
+			// Moreover, addCommitsToBugs scans all bugs and can take long time.
+			// So just log the error.
+			log.Errorf(c, "failed to add commits to bugs: %v", err)
 		}
 	}
 	return nil, nil
 }
 
-func uploadBuild(c context.Context, now time.Time, ns string, req *dashapi.Build, typ BuildType) (bool, error) {
-	if _, err := loadBuild(c, ns, req.ID); err == nil {
-		return false, nil
+func uploadBuild(c context.Context, now time.Time, ns string, req *dashapi.Build, typ BuildType) (
+	*Build, bool, error) {
+	if build, err := loadBuild(c, ns, req.ID); err == nil {
+		return build, false, nil
 	}
 
 	checkStrLen := func(str, name string, maxLen int) error {
@@ -276,56 +439,56 @@
 		return nil
 	}
 	if err := checkStrLen(req.Manager, "Build.Manager", MaxStringLen); err != nil {
-		return false, err
+		return nil, false, err
 	}
 	if err := checkStrLen(req.ID, "Build.ID", MaxStringLen); err != nil {
-		return false, err
+		return nil, false, err
 	}
 	if err := checkStrLen(req.KernelRepo, "Build.KernelRepo", MaxStringLen); err != nil {
-		return false, err
+		return nil, false, err
 	}
 	if len(req.KernelBranch) > MaxStringLen {
-		return false, fmt.Errorf("Build.KernelBranch is too long (%v)", len(req.KernelBranch))
+		return nil, false, fmt.Errorf("Build.KernelBranch is too long (%v)", len(req.KernelBranch))
 	}
 	if err := checkStrLen(req.SyzkallerCommit, "Build.SyzkallerCommit", MaxStringLen); err != nil {
-		return false, err
+		return nil, false, err
 	}
 	if len(req.CompilerID) > MaxStringLen {
-		return false, fmt.Errorf("Build.CompilerID is too long (%v)", len(req.CompilerID))
+		return nil, false, fmt.Errorf("Build.CompilerID is too long (%v)", len(req.CompilerID))
 	}
-	if err := checkStrLen(req.KernelCommit, "Build.KernelCommit", MaxStringLen); err != nil {
-		return false, err
+	if len(req.KernelCommit) > MaxStringLen {
+		return nil, false, fmt.Errorf("Build.KernelCommit is too long (%v)", len(req.KernelCommit))
 	}
 	configID, err := putText(c, ns, textKernelConfig, req.KernelConfig, true)
 	if err != nil {
-		return false, err
+		return nil, false, err
 	}
 	build := &Build{
-		Namespace:         ns,
-		Manager:           req.Manager,
-		ID:                req.ID,
-		Type:              typ,
-		Time:              now,
-		OS:                req.OS,
-		Arch:              req.Arch,
-		VMArch:            req.VMArch,
-		SyzkallerCommit:   req.SyzkallerCommit,
-		CompilerID:        req.CompilerID,
-		KernelRepo:        req.KernelRepo,
-		KernelBranch:      req.KernelBranch,
-		KernelCommit:      req.KernelCommit,
-		KernelCommitTitle: req.KernelCommitTitle,
-		KernelCommitDate:  req.KernelCommitDate,
-		KernelConfig:      configID,
+		Namespace:           ns,
+		Manager:             req.Manager,
+		ID:                  req.ID,
+		Type:                typ,
+		Time:                now,
+		OS:                  req.OS,
+		Arch:                req.Arch,
+		VMArch:              req.VMArch,
+		SyzkallerCommit:     req.SyzkallerCommit,
+		SyzkallerCommitDate: req.SyzkallerCommitDate,
+		CompilerID:          req.CompilerID,
+		KernelRepo:          req.KernelRepo,
+		KernelBranch:        req.KernelBranch,
+		KernelCommit:        req.KernelCommit,
+		KernelCommitTitle:   req.KernelCommitTitle,
+		KernelCommitDate:    req.KernelCommitDate,
+		KernelConfig:        configID,
 	}
-	if _, err := datastore.Put(c, buildKey(c, ns, req.ID), build); err != nil {
-		return false, err
+	if _, err := db.Put(c, buildKey(c, ns, req.ID), build); err != nil {
+		return nil, false, err
 	}
-	return true, nil
+	return build, true, nil
 }
 
-func addCommitsToBugs(c context.Context, ns, manager string,
-	titles []string, fixCommits []dashapi.FixCommit) error {
+func addCommitsToBugs(c context.Context, ns, manager string, titles []string, fixCommits []dashapi.Commit) error {
 	presentCommits := make(map[string]bool)
 	bugFixedBy := make(map[string][]string)
 	for _, com := range titles {
@@ -333,28 +496,38 @@
 	}
 	for _, com := range fixCommits {
 		presentCommits[com.Title] = true
-		bugFixedBy[com.BugID] = append(bugFixedBy[com.BugID], com.Title)
+		for _, bugID := range com.BugIDs {
+			bugFixedBy[bugID] = append(bugFixedBy[bugID], com.Title)
+		}
 	}
 	managers, err := managerList(c, ns)
 	if err != nil {
 		return err
 	}
+	// Fetching all bugs in a namespace can be slow, and there is no way to filter only Open/Dup statuses.
+	// So we run a separate query for each status, this both avoids fetching unnecessary data
+	// and splits a long query into two (two smaller queries have lower chances of trigerring
+	// timeouts than one huge).
+	for _, status := range []int{BugStatusOpen, BugStatusDup} {
+		err := addCommitsToBugsInStatus(c, status, ns, manager, managers, presentCommits, bugFixedBy)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func addCommitsToBugsInStatus(c context.Context, status int, ns, manager string, managers []string,
+	presentCommits map[string]bool, bugFixedBy map[string][]string) error {
 	var bugs []*Bug
-	_, err = datastore.NewQuery("Bug").
+	_, err := db.NewQuery("Bug").
 		Filter("Namespace=", ns).
+		Filter("Status=", status).
 		GetAll(c, &bugs)
 	if err != nil {
 		return fmt.Errorf("failed to query bugs: %v", err)
 	}
-nextBug:
 	for _, bug := range bugs {
-		switch bug.Status {
-		case BugStatusOpen, BugStatusDup:
-		case BugStatusFixed, BugStatusInvalid:
-			continue nextBug
-		default:
-			return fmt.Errorf("addCommitsToBugs: unknown bug status %v", bug.Status)
-		}
 		var fixCommits []string
 		for i := range bug.Reporting {
 			fixCommits = append(fixCommits, bugFixedBy[bug.Reporting[i].ID]...)
@@ -385,44 +558,64 @@
 		return nil
 	}
 	now := timeNow(c)
-	bugKey := datastore.NewKey(c, "Bug", bugKeyHash(bug.Namespace, bug.Title, bug.Seq), 0, nil)
+	bugKey := bug.key(c)
 	tx := func(c context.Context) error {
 		bug := new(Bug)
-		if err := datastore.Get(c, bugKey, bug); err != nil {
+		if err := db.Get(c, bugKey, bug); err != nil {
 			return fmt.Errorf("failed to get bug %v: %v", bugKey.StringID(), err)
 		}
 		if !bugNeedsCommitUpdate(c, bug, manager, fixCommits, presentCommits, false) {
 			return nil
 		}
 		if len(fixCommits) != 0 && !reflect.DeepEqual(bug.Commits, fixCommits) {
-			bug.Commits = fixCommits
-			bug.PatchedOn = nil
+			bug.updateCommits(fixCommits, now)
 		}
-		bug.PatchedOn = append(bug.PatchedOn, manager)
-		if bug.Status == BugStatusOpen {
-			fixed := true
-			for _, mgr := range managers {
-				if !stringInList(bug.PatchedOn, mgr) {
-					fixed = false
-					break
+		if manager != "" {
+			bug.PatchedOn = append(bug.PatchedOn, manager)
+			if bug.Status == BugStatusOpen {
+				fixed := true
+				for _, mgr := range managers {
+					if !stringInList(bug.PatchedOn, mgr) {
+						fixed = false
+						break
+					}
+				}
+				if fixed {
+					bug.Status = BugStatusFixed
+					bug.Closed = now
 				}
 			}
-			if fixed {
-				bug.Status = BugStatusFixed
-				bug.Closed = now
-			}
 		}
-		if _, err := datastore.Put(c, bugKey, bug); err != nil {
+		if _, err := db.Put(c, bugKey, bug); err != nil {
 			return fmt.Errorf("failed to put bug: %v", err)
 		}
 		return nil
 	}
-	return datastore.RunInTransaction(c, tx, nil)
+	return db.RunInTransaction(c, tx, nil)
+}
+
+func bugNeedsCommitUpdate(c context.Context, bug *Bug, manager string, fixCommits []string,
+	presentCommits map[string]bool, dolog bool) bool {
+	if len(fixCommits) != 0 && !reflect.DeepEqual(bug.Commits, fixCommits) {
+		if dolog {
+			log.Infof(c, "bug %q is fixed with %q", bug.Title, fixCommits)
+		}
+		return true
+	}
+	if len(bug.Commits) == 0 || manager == "" || stringInList(bug.PatchedOn, manager) {
+		return false
+	}
+	for _, com := range bug.Commits {
+		if !presentCommits[com] {
+			return false
+		}
+	}
+	return true
 }
 
 func managerList(c context.Context, ns string) ([]string, error) {
 	var builds []*Build
-	_, err := datastore.NewQuery("Build").
+	_, err := db.NewQuery("Build").
 		Filter("Namespace=", ns).
 		Project("Manager").
 		Distinct().
@@ -441,25 +634,6 @@
 	return managers, nil
 }
 
-func bugNeedsCommitUpdate(c context.Context, bug *Bug, manager string, fixCommits []string,
-	presentCommits map[string]bool, dolog bool) bool {
-	if len(fixCommits) != 0 && !reflect.DeepEqual(bug.Commits, fixCommits) {
-		if dolog {
-			log.Infof(c, "bug %q is fixed with %q", bug.Title, fixCommits)
-		}
-		return true
-	}
-	if len(bug.Commits) == 0 || stringInList(bug.PatchedOn, manager) {
-		return false
-	}
-	for _, com := range bug.Commits {
-		if !presentCommits[com] {
-			return false
-		}
-	}
-	return true
-}
-
 func stringInList(list []string, str string) bool {
 	for _, s := range list {
 		if s == str {
@@ -469,31 +643,29 @@
 	return false
 }
 
-func stringsInList(list, str []string) bool {
-	for _, s := range str {
-		if !stringInList(list, s) {
-			return false
-		}
-	}
-	return true
-}
-
 func apiReportBuildError(c context.Context, ns string, r *http.Request, payload []byte) (interface{}, error) {
 	req := new(dashapi.BuildErrorReq)
 	if err := json.Unmarshal(payload, req); err != nil {
 		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
 	}
 	now := timeNow(c)
-	if _, err := uploadBuild(c, now, ns, &req.Build, BuildFailed); err != nil {
-		return nil, err
-	}
-	req.Crash.BuildID = req.Build.ID
-	bug, err := reportCrash(c, ns, &req.Crash)
+	build, _, err := uploadBuild(c, now, ns, &req.Build, BuildFailed)
 	if err != nil {
 		return nil, err
 	}
-	if err := updateManager(c, ns, req.Build.Manager, func(mgr *Manager, stats *ManagerStats) {
-		mgr.FailedBuildBug = bugKeyHash(bug.Namespace, bug.Title, bug.Seq)
+	req.Crash.BuildID = req.Build.ID
+	bug, err := reportCrash(c, build, &req.Crash)
+	if err != nil {
+		return nil, err
+	}
+	if err := updateManager(c, ns, req.Build.Manager, func(mgr *Manager, stats *ManagerStats) error {
+		log.Infof(c, "failed build on %v: kernel=%v", req.Build.Manager, req.Build.KernelCommit)
+		if req.Build.KernelCommit != "" {
+			mgr.FailedBuildBug = bug.keyHash()
+		} else {
+			mgr.FailedSyzBuildBug = bug.keyHash()
+		}
+		return nil
 	}); err != nil {
 		return nil, err
 	}
@@ -507,7 +679,14 @@
 	if err := json.Unmarshal(payload, req); err != nil {
 		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
 	}
-	bug, err := reportCrash(c, ns, req)
+	build, err := loadBuild(c, ns, req.BuildID)
+	if err != nil {
+		return nil, err
+	}
+	if !config.Namespaces[ns].TransformCrash(build, req) {
+		return new(dashapi.ReportCrashResp), nil
+	}
+	bug, err := reportCrash(c, build, req)
 	if err != nil {
 		return nil, err
 	}
@@ -517,7 +696,7 @@
 	return resp, nil
 }
 
-func reportCrash(c context.Context, ns string, req *dashapi.Crash) (*Bug, error) {
+func reportCrash(c context.Context, build *Build, req *dashapi.Crash) (*Bug, error) {
 	req.Title = limitLength(req.Title, maxTextLen)
 	req.Maintainers = email.MergeEmailLists(req.Maintainers)
 	if req.Corrupted {
@@ -527,6 +706,7 @@
 		req.Title = corruptedReportTitle
 	}
 
+	ns := build.Namespace
 	bug, bugKey, err := findBugForCrash(c, ns, req.Title)
 	if err != nil {
 		return nil, err
@@ -539,10 +719,6 @@
 			return nil, err
 		}
 	}
-	build, err := loadBuild(c, ns, req.BuildID)
-	if err != nil {
-		return nil, err
-	}
 
 	now := timeNow(c)
 	reproLevel := ReproLevelNone
@@ -565,7 +741,7 @@
 
 	tx := func(c context.Context) error {
 		bug = new(Bug)
-		if err := datastore.Get(c, bugKey, bug); err != nil {
+		if err := db.Get(c, bugKey, bug); err != nil {
 			return fmt.Errorf("failed to get bug: %v", err)
 		}
 		bug.NumCrashes++
@@ -586,12 +762,12 @@
 		if !stringInList(bug.HappenedOn, build.Manager) {
 			bug.HappenedOn = append(bug.HappenedOn, build.Manager)
 		}
-		if _, err = datastore.Put(c, bugKey, bug); err != nil {
+		if _, err = db.Put(c, bugKey, bug); err != nil {
 			return fmt.Errorf("failed to put bug: %v", err)
 		}
 		return nil
 	}
-	if err := datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{XG: true}); err != nil {
+	if err := db.RunInTransaction(c, tx, &db.TransactionOptions{XG: true}); err != nil {
 		return nil, err
 	}
 	if save {
@@ -600,7 +776,7 @@
 	return bug, nil
 }
 
-func saveCrash(c context.Context, ns string, req *dashapi.Crash, bugKey *datastore.Key, build *Build) error {
+func saveCrash(c context.Context, ns string, req *dashapi.Crash, bugKey *db.Key, build *Build) error {
 	// Reporting priority of this crash.
 	prio := int64(kernelRepoInfo(build).ReportingPriority) * 1e6
 	if len(req.ReproC) != 0 {
@@ -632,32 +808,28 @@
 	if crash.ReproC, err = putText(c, ns, textReproC, req.ReproC, false); err != nil {
 		return err
 	}
-	crashKey := datastore.NewIncompleteKey(c, "Crash", bugKey)
-	if _, err = datastore.Put(c, crashKey, crash); err != nil {
+	crashKey := db.NewIncompleteKey(c, "Crash", bugKey)
+	if _, err = db.Put(c, crashKey, crash); err != nil {
 		return fmt.Errorf("failed to put crash: %v", err)
 	}
 	return nil
 }
 
-func purgeOldCrashes(c context.Context, bug *Bug, bugKey *datastore.Key) {
-	if bug.NumCrashes <= maxCrashes || (bug.NumCrashes-1)%10 != 0 {
+func purgeOldCrashes(c context.Context, bug *Bug, bugKey *db.Key) {
+	const purgeEvery = 10
+	if bug.NumCrashes <= 2*maxCrashes || (bug.NumCrashes-1)%purgeEvery != 0 {
 		return
 	}
 	var crashes []*Crash
-	keys, err := datastore.NewQuery("Crash").
+	keys, err := db.NewQuery("Crash").
 		Ancestor(bugKey).
-		Filter("ReproC=", 0).
-		Filter("ReproSyz=", 0).
 		Filter("Reported=", time.Time{}).
 		GetAll(c, &crashes)
 	if err != nil {
 		log.Errorf(c, "failed to fetch purge crashes: %v", err)
 		return
 	}
-	if len(keys) <= maxCrashes {
-		return
-	}
-	keyMap := make(map[*Crash]*datastore.Key)
+	keyMap := make(map[*Crash]*db.Key)
 	for i, crash := range crashes {
 		keyMap[crash] = keys[i]
 	}
@@ -665,42 +837,54 @@
 	sort.Slice(crashes, func(i, j int) bool {
 		return crashes[i].Time.After(crashes[j].Time)
 	})
-	// Find latest crash on each manager.
-	latestOnManager := make(map[string]*Crash)
+	var toDelete []*db.Key
+	latestOnManager := make(map[string]bool)
+	deleted, reproCount, noreproCount := 0, 0, 0
 	for _, crash := range crashes {
-		if latestOnManager[crash.Manager] == nil {
-			latestOnManager[crash.Manager] = crash
+		if !crash.Reported.IsZero() {
+			log.Errorf(c, "purging reported crash?")
+			continue
 		}
-	}
-	// Oldest first but move latest crash on each manager to the end (preserve them).
-	sort.Slice(crashes, func(i, j int) bool {
-		latesti := latestOnManager[crashes[i].Manager] == crashes[i]
-		latestj := latestOnManager[crashes[j].Manager] == crashes[j]
-		if latesti != latestj {
-			return latestj
+		// Preserve latest crash on each manager.
+		if !latestOnManager[crash.Manager] {
+			latestOnManager[crash.Manager] = true
+			continue
 		}
-		return crashes[i].Time.Before(crashes[j].Time)
-	})
-	crashes = crashes[:len(crashes)-maxCrashes]
-	var toDelete []*datastore.Key
-	for _, crash := range crashes {
-		if crash.ReproSyz != 0 || crash.ReproC != 0 || !crash.Reported.IsZero() {
-			log.Errorf(c, "purging reproducer?")
+		// Preserve maxCrashes latest crashes with repro and without repro.
+		count := &noreproCount
+		if crash.ReproSyz != 0 || crash.ReproC != 0 {
+			count = &reproCount
+		}
+		if *count < maxCrashes {
+			*count++
 			continue
 		}
 		toDelete = append(toDelete, keyMap[crash])
 		if crash.Log != 0 {
-			toDelete = append(toDelete, datastore.NewKey(c, textCrashLog, "", crash.Log, nil))
+			toDelete = append(toDelete, db.NewKey(c, textCrashLog, "", crash.Log, nil))
 		}
 		if crash.Report != 0 {
-			toDelete = append(toDelete, datastore.NewKey(c, textCrashReport, "", crash.Report, nil))
+			toDelete = append(toDelete, db.NewKey(c, textCrashReport, "", crash.Report, nil))
+		}
+		if crash.ReproSyz != 0 {
+			toDelete = append(toDelete, db.NewKey(c, textReproSyz, "", crash.ReproSyz, nil))
+		}
+		if crash.ReproC != 0 {
+			toDelete = append(toDelete, db.NewKey(c, textReproC, "", crash.ReproC, nil))
+		}
+		deleted++
+		if deleted == 2*purgeEvery {
+			break
 		}
 	}
-	if err := datastore.DeleteMulti(c, toDelete); err != nil {
+	if len(toDelete) == 0 {
+		return
+	}
+	if err := db.DeleteMulti(c, toDelete); err != nil {
 		log.Errorf(c, "failed to delete old crashes: %v", err)
 		return
 	}
-	log.Infof(c, "deleted %v crashes for bug %q", len(crashes), bug.Title)
+	log.Infof(c, "deleted %v crashes for bug %q", deleted, bug.Title)
 }
 
 func apiReportFailedRepro(c context.Context, ns string, r *http.Request, payload []byte) (interface{}, error) {
@@ -720,17 +904,17 @@
 	now := timeNow(c)
 	tx := func(c context.Context) error {
 		bug := new(Bug)
-		if err := datastore.Get(c, bugKey, bug); err != nil {
+		if err := db.Get(c, bugKey, bug); err != nil {
 			return fmt.Errorf("failed to get bug: %v", err)
 		}
 		bug.NumRepro++
 		bug.LastReproTime = now
-		if _, err := datastore.Put(c, bugKey, bug); err != nil {
+		if _, err := db.Put(c, bugKey, bug); err != nil {
 			return fmt.Errorf("failed to put bug: %v", err)
 		}
 		return nil
 	}
-	err = datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{
+	err = db.RunInTransaction(c, tx, &db.TransactionOptions{
 		XG:       true,
 		Attempts: 30,
 	})
@@ -769,7 +953,7 @@
 		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
 	}
 	now := timeNow(c)
-	err := updateManager(c, ns, req.Name, func(mgr *Manager, stats *ManagerStats) {
+	err := updateManager(c, ns, req.Name, func(mgr *Manager, stats *ManagerStats) error {
 		mgr.Link = req.Addr
 		mgr.LastAlive = now
 		mgr.CurrentUpTime = req.UpTime
@@ -782,13 +966,14 @@
 		stats.TotalFuzzingTime += req.FuzzingTime
 		stats.TotalCrashes += int64(req.Crashes)
 		stats.TotalExecs += int64(req.Execs)
+		return nil
 	})
 	return nil, err
 }
 
-func findBugForCrash(c context.Context, ns, title string) (*Bug, *datastore.Key, error) {
+func findBugForCrash(c context.Context, ns, title string) (*Bug, *db.Key, error) {
 	var bugs []*Bug
-	keys, err := datastore.NewQuery("Bug").
+	keys, err := db.NewQuery("Bug").
 		Filter("Namespace=", ns).
 		Filter("Title=", title).
 		Order("-Seq").
@@ -803,17 +988,17 @@
 	return bugs[0], keys[0], nil
 }
 
-func createBugForCrash(c context.Context, ns string, req *dashapi.Crash) (*Bug, *datastore.Key, error) {
+func createBugForCrash(c context.Context, ns string, req *dashapi.Crash) (*Bug, *db.Key, error) {
 	var bug *Bug
-	var bugKey *datastore.Key
+	var bugKey *db.Key
 	now := timeNow(c)
 	tx := func(c context.Context) error {
 		for seq := int64(0); ; seq++ {
 			bug = new(Bug)
 			bugHash := bugKeyHash(ns, req.Title, seq)
-			bugKey = datastore.NewKey(c, "Bug", bugHash, 0, nil)
-			if err := datastore.Get(c, bugKey, bug); err != nil {
-				if err != datastore.ErrNoSuchEntity {
+			bugKey = db.NewKey(c, "Bug", bugHash, 0, nil)
+			if err := db.Get(c, bugKey, bug); err != nil {
+				if err != db.ErrNoSuchEntity {
 					return fmt.Errorf("failed to get bug: %v", err)
 				}
 				bug = &Bug{
@@ -828,13 +1013,8 @@
 					FirstTime:  now,
 					LastTime:   now,
 				}
-				for _, rep := range config.Namespaces[ns].Reporting {
-					bug.Reporting = append(bug.Reporting, BugReporting{
-						Name: rep.Name,
-						ID:   bugReportingHash(bugHash, rep.Name),
-					})
-				}
-				if bugKey, err = datastore.Put(c, bugKey, bug); err != nil {
+				createBugReporting(bug, config.Namespaces[ns])
+				if bugKey, err = db.Put(c, bugKey, bug); err != nil {
 					return fmt.Errorf("failed to put new bug: %v", err)
 				}
 				return nil
@@ -849,7 +1029,7 @@
 			return nil
 		}
 	}
-	if err := datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{
+	if err := db.RunInTransaction(c, tx, &db.TransactionOptions{
 		XG:       true,
 		Attempts: 30,
 	}); err != nil {
@@ -858,6 +1038,16 @@
 	return bug, bugKey, nil
 }
 
+func createBugReporting(bug *Bug, cfg *Config) {
+	for len(bug.Reporting) < len(cfg.Reporting) {
+		rep := &cfg.Reporting[len(bug.Reporting)]
+		bug.Reporting = append(bug.Reporting, BugReporting{
+			Name: rep.Name,
+			ID:   bugReportingHash(bug.keyHash(), rep.Name),
+		})
+	}
+}
+
 func isActiveBug(c context.Context, bug *Bug) (bool, error) {
 	if bug == nil {
 		return false, nil
@@ -885,8 +1075,10 @@
 	return bug.ReproLevel < ReproLevelC &&
 		len(bug.Commits) == 0 &&
 		bug.Title != corruptedReportTitle &&
+		config.Namespaces[bug.Namespace].NeedRepro(bug) &&
 		(bug.NumRepro < maxReproPerBug ||
-			bug.ReproLevel == ReproLevelNone && timeSince(c, bug.LastReproTime) > reproRetryPeriod)
+			bug.ReproLevel == ReproLevelNone &&
+				timeSince(c, bug.LastReproTime) > reproRetryPeriod)
 }
 
 func putText(c context.Context, ns, tag string, data []byte, dedup bool) (int64, error) {
@@ -914,18 +1106,18 @@
 		data = data[:len(data)/10*9]
 		b.Reset()
 	}
-	var key *datastore.Key
+	var key *db.Key
 	if dedup {
 		h := hash.Hash([]byte(ns), b.Bytes())
-		key = datastore.NewKey(c, tag, "", h.Truncate64(), nil)
+		key = db.NewKey(c, tag, "", h.Truncate64(), nil)
 	} else {
-		key = datastore.NewIncompleteKey(c, tag, nil)
+		key = db.NewIncompleteKey(c, tag, nil)
 	}
 	text := &Text{
 		Namespace: ns,
 		Text:      b.Bytes(),
 	}
-	key, err := datastore.Put(c, key, text)
+	key, err := db.Put(c, key, text)
 	if err != nil {
 		return 0, err
 	}
@@ -937,7 +1129,7 @@
 		return nil, "", nil
 	}
 	text := new(Text)
-	if err := datastore.Get(c, datastore.NewKey(c, tag, "", id, nil), text); err != nil {
+	if err := db.Get(c, db.NewKey(c, tag, "", id, nil), text); err != nil {
 		return nil, "", fmt.Errorf("failed to read text %v: %v", tag, err)
 	}
 	d, err := gzip.NewReader(bytes.NewBuffer(text.Text))
diff --git a/dashboard/app/app.yaml b/dashboard/app/app.yaml
index e3300bf..0e5ca35 100644
--- a/dashboard/app/app.yaml
+++ b/dashboard/app/app.yaml
@@ -19,16 +19,13 @@
 - url: /static
   static_dir: static
   secure: always
-- url: /(|bug|text|x/.+)
-  script: _go_app
-  secure: always
-- url: /(api)
-  script: _go_app
-  secure: always
-- url: /(email_poll)
+- url: /(admin|email_poll)
   script: _go_app
   login: admin
   secure: always
 - url: /_ah/(mail/.+|bounce)
   script: _go_app
   login: admin
+- url: /(|api|bug|text|x/.+|.*)
+  script: _go_app
+  secure: always
diff --git a/dashboard/app/app_test.go b/dashboard/app/app_test.go
index f782c5e..a131e40 100644
--- a/dashboard/app/app_test.go
+++ b/dashboard/app/app_test.go
@@ -7,11 +7,14 @@
 
 import (
 	"fmt"
+	"net/http"
+	"strconv"
 	"strings"
 	"testing"
 	"time"
 
 	"github.com/google/syzkaller/dashboard/dashapi"
+	"google.golang.org/appengine/user"
 )
 
 func init() {
@@ -29,6 +32,7 @@
 	EmailBlacklist: []string{
 		"\"Bar\" <BlackListed@Domain.com>",
 	},
+	DefaultNamespace: "test1",
 	Namespaces: map[string]*Config{
 		"test1": {
 			AccessLevel: AccessAdmin,
@@ -36,20 +40,29 @@
 			Clients: map[string]string{
 				client1: key1,
 			},
+			Repos: []KernelRepo{
+				{
+					URL:    "git://syzkaller.org",
+					Branch: "branch10",
+					Alias:  "repo10alias",
+					CC:     []string{"maintainers@repo10.org", "bugs@repo10.org"},
+				},
+				{
+					URL:    "git://github.com/google/syzkaller",
+					Branch: "master",
+					Alias:  "repo10alias",
+					CC:     []string{"maintainers@repo10.org", "bugs@repo10.org"},
+				},
+			},
 			Reporting: []Reporting{
 				{
 					Name:       "reporting1",
 					DailyLimit: 3,
+					Embargo:    14 * 24 * time.Hour,
+					Filter:     skipWithRepro,
 					Config: &TestConfig{
 						Index: 1,
 					},
-					Filter: func(bug *Bug) FilterResult {
-						if strings.HasPrefix(bug.Title, "skip without repro") &&
-							bug.ReproLevel != dashapi.ReproLevelNone {
-							return FilterSkip
-						}
-						return FilterReport
-					},
 				},
 				{
 					Name:       "reporting2",
@@ -66,6 +79,14 @@
 			Clients: map[string]string{
 				client2: key2,
 			},
+			Repos: []KernelRepo{
+				{
+					URL:    "git://syzkaller.org",
+					Branch: "branch10",
+					Alias:  "repo10alias",
+					CC:     []string{"maintainers@repo10.org", "bugs@repo10.org"},
+				},
+			},
 			Managers: map[string]ConfigManager{
 				"restricted-manager": {
 					RestrictedTestingRepo:   "git://restricted.git/restricted.git",
@@ -76,20 +97,31 @@
 				{
 					Name:       "reporting1",
 					DailyLimit: 5,
+					Embargo:    14 * 24 * time.Hour,
+					Filter:     skipWithRepro,
 					Config: &EmailConfig{
-						Email:      "test@syzkaller.com",
-						Moderation: true,
+						Email: "test@syzkaller.com",
 					},
 				},
 				{
 					Name:       "reporting2",
 					DailyLimit: 3,
+					Filter:     skipWithRepro2,
 					Config: &EmailConfig{
 						Email:              "bugs@syzkaller.com",
 						DefaultMaintainers: []string{"default@maintainers.com"},
 						MailMaintainers:    true,
 					},
 				},
+				{
+					Name:       "reporting3",
+					DailyLimit: 3,
+					Config: &EmailConfig{
+						Email:              "bugs2@syzkaller.com",
+						DefaultMaintainers: []string{"default2@maintainers.com"},
+						MailMaintainers:    true,
+					},
+				},
 			},
 		},
 		// Namespaces for access level testing.
@@ -99,6 +131,13 @@
 			Clients: map[string]string{
 				clientAdmin: keyAdmin,
 			},
+			Repos: []KernelRepo{
+				{
+					URL:    "git://syzkaller.org/access-admin.git",
+					Branch: "access-admin",
+					Alias:  "access-admin",
+				},
+			},
 			Reporting: []Reporting{
 				{
 					Name:   "access-admin-reporting1",
@@ -116,6 +155,13 @@
 			Clients: map[string]string{
 				clientUser: keyUser,
 			},
+			Repos: []KernelRepo{
+				{
+					URL:    "git://syzkaller.org/access-user.git",
+					Branch: "access-user",
+					Alias:  "access-user",
+				},
+			},
 			Reporting: []Reporting{
 				{
 					AccessLevel: AccessAdmin,
@@ -134,6 +180,13 @@
 			Clients: map[string]string{
 				clientPublic: keyPublic,
 			},
+			Repos: []KernelRepo{
+				{
+					URL:    "git://syzkaller.org/access-public.git",
+					Branch: "access-public",
+					Alias:  "access-public",
+				},
+			},
 			Reporting: []Reporting{
 				{
 					AccessLevel: AccessUser,
@@ -162,6 +215,22 @@
 	keyPublic    = "clientpublickeyclientpublickey"
 )
 
+func skipWithRepro(bug *Bug) FilterResult {
+	if strings.HasPrefix(bug.Title, "skip with repro") &&
+		bug.ReproLevel != dashapi.ReproLevelNone {
+		return FilterSkip
+	}
+	return FilterReport
+}
+
+func skipWithRepro2(bug *Bug) FilterResult {
+	if strings.HasPrefix(bug.Title, "skip reporting2 with repro") &&
+		bug.ReproLevel != dashapi.ReproLevelNone {
+		return FilterSkip
+	}
+	return FilterReport
+}
+
 type TestConfig struct {
 	Index int
 }
@@ -170,10 +239,6 @@
 	return "test"
 }
 
-func (cfg *TestConfig) NeedMaintainers() bool {
-	return false
-}
-
 func (cfg *TestConfig) Validate() error {
 	return nil
 }
@@ -182,6 +247,9 @@
 	return &dashapi.Build{
 		Manager:           fmt.Sprintf("manager%v", id),
 		ID:                fmt.Sprintf("build%v", id),
+		OS:                "linux",
+		Arch:              "amd64",
+		VMArch:            "amd64",
 		SyzkallerCommit:   fmt.Sprintf("syzkaller_commit%v", id),
 		CompilerID:        fmt.Sprintf("compiler%v", id),
 		KernelRepo:        fmt.Sprintf("repo%v", id),
@@ -223,7 +291,7 @@
 	c := NewCtx(t)
 	defer c.Close()
 
-	c.expectOK(c.GET("/"))
+	c.expectOK(c.GET("/test1"))
 
 	apiClient1 := c.makeClient(client1, key1, false)
 	apiClient2 := c.makeClient(client2, key2, false)
@@ -271,3 +339,217 @@
 		ReproLevel: dashapi.ReproLevelC,
 	})
 }
+
+func TestRedirects(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	checkRedirect(c, AccessUser, "/", "/test1", http.StatusFound) // redirect to default namespace
+	checkRedirect(c, AccessAdmin, "/", "/admin", http.StatusFound)
+	checkLoginRedirect(c, AccessPublic, "/access-user") // not accessible namespace
+
+	_, err := c.httpRequest("GET", "/access-user", "", AccessUser)
+	c.expectOK(err)
+}
+
+func checkLoginRedirect(c *Ctx, accessLevel AccessLevel, url string) {
+	to, err := user.LoginURL(c.ctx, url)
+	if err != nil {
+		c.t.Fatal(err)
+	}
+	checkRedirect(c, accessLevel, url, to, http.StatusTemporaryRedirect)
+}
+
+func checkRedirect(c *Ctx, accessLevel AccessLevel, from, to string, status int) {
+	_, err := c.httpRequest("GET", from, "", accessLevel)
+	c.expectNE(err, nil)
+	httpErr, ok := err.(HttpError)
+	c.expectTrue(ok)
+	c.expectEQ(httpErr.Code, status)
+	c.expectEQ(httpErr.Headers["Location"], []string{to})
+}
+
+// Test purging of old crashes for bugs with lots of crashes.
+func TestPurgeOldCrashes(t *testing.T) {
+	if testing.Short() {
+		t.Skip()
+	}
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client.UploadBuild(build)
+
+	// First, send 3 crashes that are reported. These need to be preserved regardless.
+	crash := testCrash(build, 1)
+	crash.ReproOpts = []byte("no repro")
+	c.client.ReportCrash(crash)
+	rep := c.client.pollBug()
+
+	crash.ReproSyz = []byte("getpid()")
+	crash.ReproOpts = []byte("syz repro")
+	c.client.ReportCrash(crash)
+	c.client.pollBug()
+
+	crash.ReproC = []byte("int main() {}")
+	crash.ReproOpts = []byte("C repro")
+	c.client.ReportCrash(crash)
+	c.client.pollBug()
+
+	// Now report lots of bugs with/without repros. Some of the older ones should be purged.
+	const totalReported = 3 * maxCrashes
+	for i := 0; i < totalReported; i++ {
+		c.advanceTime(2 * time.Hour) // This ensures that crashes are saved.
+		crash.ReproSyz = nil
+		crash.ReproC = nil
+		crash.ReproOpts = []byte(fmt.Sprintf("%v", i))
+		c.client.ReportCrash(crash)
+
+		crash.ReproSyz = []byte("syz repro")
+		crash.ReproC = []byte("C repro")
+		crash.ReproOpts = []byte(fmt.Sprintf("%v", i))
+		c.client.ReportCrash(crash)
+	}
+	bug, _, _ := c.loadBug(rep.ID)
+	crashes, _, err := queryCrashesForBug(c.ctx, bug.key(c.ctx), 10*totalReported)
+	c.expectOK(err)
+	// First, count how many crashes of different types we have.
+	// We should get all 3 reported crashes + some with repros and some without repros.
+	reported, norepro, repro := 0, 0, 0
+	for _, crash := range crashes {
+		if !crash.Reported.IsZero() {
+			reported++
+		} else if crash.ReproSyz == 0 {
+			norepro++
+		} else {
+			repro++
+		}
+	}
+	c.t.Logf("got reported=%v, norepro=%v, repro=%v, maxCrashes=%v",
+		reported, norepro, repro, maxCrashes)
+	if reported != 3 ||
+		norepro < maxCrashes || norepro > maxCrashes+10 ||
+		repro < maxCrashes || repro > maxCrashes+10 {
+		c.t.Fatalf("bad purged crashes")
+	}
+	// Then, check that latest crashes were preserved.
+	for _, crash := range crashes {
+		if !crash.Reported.IsZero() {
+			continue
+		}
+		idx, err := strconv.Atoi(string(crash.ReproOpts))
+		c.expectOK(err)
+		count := norepro
+		if crash.ReproSyz != 0 {
+			count = repro
+		}
+		if idx < totalReported-count {
+			c.t.Errorf("preserved bad crash repro=%v: %v", crash.ReproC != 0, idx)
+		}
+	}
+}
+
+func TestManagerFailedBuild(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	// Upload and check first build.
+	build := testBuild(1)
+	c.client.UploadBuild(build)
+	checkManagerBuild(c, build, nil, nil)
+
+	// Upload and check second build.
+	build.ID = "id1"
+	build.KernelCommit = "kern1"
+	build.SyzkallerCommit = "syz1"
+	c.client.UploadBuild(build)
+	checkManagerBuild(c, build, nil, nil)
+
+	// Upload failed kernel build.
+	failedBuild := new(dashapi.Build)
+	*failedBuild = *build
+	failedBuild.ID = "id2"
+	failedBuild.KernelCommit = "kern2"
+	failedBuild.KernelCommitTitle = "failed build 1"
+	failedBuild.SyzkallerCommit = "syz2"
+	c.expectOK(c.client.ReportBuildError(&dashapi.BuildErrorReq{
+		Build: *failedBuild,
+		Crash: dashapi.Crash{
+			Title: "failed build 1",
+		},
+	}))
+	checkManagerBuild(c, build, failedBuild, nil)
+
+	// Now the old good build again, nothing should change.
+	c.client.UploadBuild(build)
+	checkManagerBuild(c, build, failedBuild, nil)
+
+	// New good kernel build, failed build must reset.
+	build.ID = "id3"
+	build.KernelCommit = "kern3"
+	c.client.UploadBuild(build)
+	checkManagerBuild(c, build, nil, nil)
+
+	// Now more complex scenario: OK -> failed kernel -> failed kernel+syzkaller -> failed syzkaller -> OK.
+	failedBuild.ID = "id4"
+	failedBuild.KernelCommit = "kern4"
+	failedBuild.KernelCommitTitle = "failed build 4"
+	failedBuild.SyzkallerCommit = "syz4"
+	c.expectOK(c.client.ReportBuildError(&dashapi.BuildErrorReq{
+		Build: *failedBuild,
+		Crash: dashapi.Crash{
+			Title: "failed build 4",
+		},
+	}))
+	checkManagerBuild(c, build, failedBuild, nil)
+
+	failedBuild2 := new(dashapi.Build)
+	*failedBuild2 = *failedBuild
+	failedBuild2.ID = "id5"
+	failedBuild2.KernelCommit = ""
+	failedBuild2.KernelCommitTitle = "failed build 5"
+	failedBuild2.SyzkallerCommit = "syz5"
+	c.expectOK(c.client.ReportBuildError(&dashapi.BuildErrorReq{
+		Build: *failedBuild2,
+		Crash: dashapi.Crash{
+			Title: "failed build 5",
+		},
+	}))
+	checkManagerBuild(c, build, failedBuild, failedBuild2)
+
+	build.ID = "id6"
+	build.KernelCommit = "kern6"
+	c.client.UploadBuild(build)
+	checkManagerBuild(c, build, nil, failedBuild2)
+
+	build.ID = "id7"
+	build.KernelCommit = "kern6"
+	build.SyzkallerCommit = "syz7"
+	c.client.UploadBuild(build)
+	checkManagerBuild(c, build, nil, nil)
+}
+
+func checkManagerBuild(c *Ctx, build, failedKernelBuild, failedSyzBuild *dashapi.Build) {
+	mgr, dbBuild := c.loadManager("test1", build.Manager)
+	c.expectEQ(mgr.CurrentBuild, build.ID)
+	compareBuilds(c, dbBuild, build)
+	checkBuildBug(c, mgr.FailedBuildBug, failedKernelBuild)
+	checkBuildBug(c, mgr.FailedSyzBuildBug, failedSyzBuild)
+}
+
+func checkBuildBug(c *Ctx, hash string, build *dashapi.Build) {
+	if build == nil {
+		c.expectEQ(hash, "")
+		return
+	}
+	c.expectNE(hash, "")
+	bug, _, dbBuild := c.loadBugByHash(hash)
+	c.expectEQ(bug.Title, build.KernelCommitTitle)
+	compareBuilds(c, dbBuild, build)
+}
+
+func compareBuilds(c *Ctx, dbBuild *Build, build *dashapi.Build) {
+	c.expectEQ(dbBuild.ID, build.ID)
+	c.expectEQ(dbBuild.KernelCommit, build.KernelCommit)
+	c.expectEQ(dbBuild.SyzkallerCommit, build.SyzkallerCommit)
+}
diff --git a/dashboard/app/bisect_test.go b/dashboard/app/bisect_test.go
new file mode 100644
index 0000000..57ce55c
--- /dev/null
+++ b/dashboard/app/bisect_test.go
@@ -0,0 +1,630 @@
+// Copyright 2019 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// +build aetest
+
+package dash
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/google/syzkaller/dashboard/dashapi"
+	"github.com/google/syzkaller/pkg/email"
+)
+
+func TestBisectCause(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+	crash := testCrash(build, 1)
+	c.client2.ReportCrash(crash)
+	c.client2.pollEmailBug()
+
+	// No repro - no bisection.
+	pollResp := c.client2.pollJobs(build.Manager)
+	c.expectEQ(pollResp.ID, "")
+
+	// Now upload 4 crashes with repros.
+	crash2 := testCrashWithRepro(build, 2)
+	c.client2.ReportCrash(crash2)
+	msg2 := c.client2.pollEmailBug()
+
+	// This is later, so will be bisected before the previous crash.
+	c.advanceTime(time.Hour)
+	crash3 := testCrashWithRepro(build, 3)
+	c.client2.ReportCrash(crash3)
+	c.client2.pollEmailBug()
+
+	// This does not have C repro, so will be bisected after the previous ones.
+	c.advanceTime(time.Hour)
+	crash4 := testCrashWithRepro(build, 4)
+	crash4.Title = "skip reporting2 with repro"
+	crash4.ReproC = nil
+	c.client2.ReportCrash(crash4)
+	msg4 := c.client2.pollEmailBug()
+
+	// This is from a different manager, so won't be bisected.
+	c.advanceTime(time.Hour)
+	build2 := testBuild(2)
+	c.client2.UploadBuild(build2)
+	crash5 := testCrashWithRepro(build2, 5)
+	c.client2.ReportCrash(crash5)
+	c.client2.pollEmailBug()
+
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectNE(pollResp.ID, "")
+	c.expectEQ(pollResp.Type, dashapi.JobBisectCause)
+	c.expectEQ(pollResp.Manager, build.Manager)
+	c.expectEQ(pollResp.KernelConfig, build.KernelConfig)
+	c.expectEQ(pollResp.SyzkallerCommit, build.SyzkallerCommit)
+	c.expectEQ(pollResp.ReproOpts, []byte("repro opts 3"))
+	c.expectEQ(pollResp.ReproSyz, []byte("syncfs(3)"))
+	c.expectEQ(pollResp.ReproC, []byte("int main() { return 3; }"))
+
+	// Since we did not reply, we should get the same response.
+	c.advanceTime(5 * 24 * time.Hour)
+	pollResp2 := c.client2.pollJobs(build.Manager)
+	c.expectEQ(pollResp, pollResp2)
+
+	// Bisection failed with an error.
+	done := &dashapi.JobDoneReq{
+		ID:    pollResp.ID,
+		Log:   []byte("bisect log 3"),
+		Error: []byte("bisect error 3"),
+	}
+	c.expectOK(c.client2.JobDone(done))
+
+	// Now we should get bisect for crash 2.
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectNE(pollResp.ID, pollResp2.ID)
+	c.expectEQ(pollResp.ReproOpts, []byte("repro opts 2"))
+
+	// Bisection succeeded.
+	jobID := pollResp.ID
+	done = &dashapi.JobDoneReq{
+		ID:          jobID,
+		Build:       *build,
+		Log:         []byte("bisect log 2"),
+		CrashTitle:  "bisect crash title",
+		CrashLog:    []byte("bisect crash log"),
+		CrashReport: []byte("bisect crash report"),
+		Commits: []dashapi.Commit{
+			{
+				Hash:       "36e65cb4a0448942ec316b24d60446bbd5cc7827",
+				Title:      "kernel: add a bug",
+				Author:     "author@kernel.org",
+				AuthorName: "Author Kernelov",
+				CC: []string{
+					"reviewer1@kernel.org", "\"Reviewer2\" <reviewer2@kernel.org>",
+					// These must be filtered out:
+					"syzbot@testapp.appspotmail.com",
+					"syzbot+1234@testapp.appspotmail.com",
+					"\"syzbot\" <syzbot+1234@testapp.appspotmail.com>",
+				},
+				Date: time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC),
+			},
+		},
+	}
+	done.Build.ID = jobID
+	c.expectOK(c.client2.JobDone(done))
+
+	_, extBugID, err := email.RemoveAddrContext(msg2.Sender)
+	c.expectOK(err)
+	_, dbCrash, _ := c.loadBug(extBugID)
+	reproSyzLink := externalLink(c.ctx, textReproSyz, dbCrash.ReproSyz)
+	reproCLink := externalLink(c.ctx, textReproC, dbCrash.ReproC)
+	dbJob, dbBuild, dbJobCrash := c.loadJob(jobID)
+	kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
+	bisectCrashReportLink := externalLink(c.ctx, textCrashReport, dbJob.CrashReport)
+	bisectCrashLogLink := externalLink(c.ctx, textCrashLog, dbJob.CrashLog)
+	bisectLogLink := externalLink(c.ctx, textLog, dbJob.Log)
+	crashLogLink := externalLink(c.ctx, textCrashLog, dbJobCrash.Log)
+
+	{
+		msg := c.pollEmailBug()
+		// Not mailed to commit author/cc because !MailMaintainers.
+		c.expectEQ(msg.To, []string{"test@syzkaller.com"})
+		c.expectEQ(msg.Subject, crash2.Title)
+		c.expectEQ(len(msg.Attachments), 0)
+		c.expectEQ(msg.Body, fmt.Sprintf(`syzbot has bisected this bug to:
+
+commit 36e65cb4a0448942ec316b24d60446bbd5cc7827
+Author: Author Kernelov <author@kernel.org>
+Date:   Wed Feb 9 04:05:06 2000 +0000
+
+    kernel: add a bug
+
+bisection log:  %[2]v
+start commit:   11111111 kernel_commit_title1
+git tree:       repo1 branch1
+final crash:    %[3]v
+console output: %[4]v
+kernel config:  %[5]v
+dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
+syz repro:      %[6]v
+C reproducer:   %[7]v
+
+Reported-by: syzbot+%[1]v@testapp.appspotmail.com
+Fixes: 36e65cb4a044 ("kernel: add a bug")
+
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection
+`, extBugID, bisectLogLink, bisectCrashReportLink, bisectCrashLogLink, kernelConfigLink, reproSyzLink, reproCLink))
+
+		syzRepro := []byte(fmt.Sprintf("%s#%s\n%s", syzReproPrefix, crash2.ReproOpts, crash2.ReproSyz))
+		c.checkURLContents(bisectLogLink, []byte("bisect log 2"))
+		c.checkURLContents(bisectCrashReportLink, []byte("bisect crash report"))
+		c.checkURLContents(bisectCrashLogLink, []byte("bisect crash log"))
+		c.checkURLContents(kernelConfigLink, []byte("config1"))
+		c.checkURLContents(reproSyzLink, syzRepro)
+		c.checkURLContents(reproCLink, crash2.ReproC)
+	}
+
+	// The next reporting must get bug report with bisection results.
+	c.incomingEmail(msg2.Sender, "#syz upstream")
+	{
+		msg := c.pollEmailBug()
+		_, extBugID2, err := email.RemoveAddrContext(msg.Sender)
+		c.expectOK(err)
+
+		c.expectEQ(msg.To, []string{
+			"author@kernel.org",
+			"bugs@syzkaller.com",
+			"default@maintainers.com",
+			"reviewer1@kernel.org",
+			"reviewer2@kernel.org",
+		})
+		c.expectEQ(msg.Subject, crash2.Title)
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
+
+syzbot found the following crash on:
+
+HEAD commit:    11111111 kernel_commit_title1
+git tree:       repo1 branch1
+console output: %[2]v
+kernel config:  %[3]v
+dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
+compiler:       compiler1
+syz repro:      %[4]v
+C reproducer:   %[5]v
+CC:             [author@kernel.org reviewer1@kernel.org reviewer2@kernel.org]
+
+The bug was bisected to:
+
+commit 36e65cb4a0448942ec316b24d60446bbd5cc7827
+Author: Author Kernelov <author@kernel.org>
+Date:   Wed Feb 9 04:05:06 2000 +0000
+
+    kernel: add a bug
+
+bisection log:  %[6]v
+final crash:    %[7]v
+console output: %[8]v
+
+IMPORTANT: if you fix the bug, please add the following tag to the commit:
+Reported-by: syzbot+%[1]v@testapp.appspotmail.com
+Fixes: 36e65cb4a044 ("kernel: add a bug")
+
+report2
+
+---
+This bug is generated by a bot. It may contain errors.
+See https://goo.gl/tpsmEJ for more information about syzbot.
+syzbot engineers can be reached at syzkaller@googlegroups.com.
+
+syzbot will keep track of this bug report. See:
+https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection
+syzbot can test patches for this bug, for details see:
+https://goo.gl/tpsmEJ#testing-patches`,
+			extBugID2, crashLogLink, kernelConfigLink, reproSyzLink, reproCLink,
+			bisectLogLink, bisectCrashReportLink, bisectCrashLogLink))
+	}
+
+	// Crash 4 is bisected in reporting with MailMaintainers.
+	// It also skipped second reporting because of the title.
+	c.incomingEmail(msg4.Sender, "#syz upstream")
+	msg4 = c.pollEmailBug()
+	c.expectEQ(msg4.To, []string{
+		"bugs2@syzkaller.com",
+		"default2@maintainers.com",
+	})
+	pollResp = c.client2.pollJobs(build.Manager)
+
+	// Bisection succeeded.
+	jobID = pollResp.ID
+	done = &dashapi.JobDoneReq{
+		ID:          jobID,
+		Build:       *build,
+		Log:         []byte("bisect log 4"),
+		CrashTitle:  "bisect crash title 4",
+		CrashLog:    []byte("bisect crash log 4"),
+		CrashReport: []byte("bisect crash report 4"),
+		Commits: []dashapi.Commit{
+			{
+				Hash:       "36e65cb4a0448942ec316b24d60446bbd5cc7827",
+				Title:      "kernel: add a bug",
+				Author:     "author@kernel.org",
+				AuthorName: "Author Kernelov",
+				CC: []string{
+					"reviewer1@kernel.org", "\"Reviewer2\" <reviewer2@kernel.org>",
+					// These must be filtered out:
+					"syzbot@testapp.appspotmail.com",
+					"syzbot+1234@testapp.appspotmail.com",
+					"\"syzbot\" <syzbot+1234@testapp.appspotmail.com>",
+				},
+				Date: time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC),
+			},
+		},
+	}
+	done.Build.ID = jobID
+	c.expectOK(c.client2.JobDone(done))
+
+	{
+		msg := c.pollEmailBug()
+		c.expectEQ(msg.Subject, crash4.Title)
+		c.expectEQ(msg.To, []string{
+			"author@kernel.org",
+			"bugs2@syzkaller.com",
+			"default2@maintainers.com",
+			"reviewer1@kernel.org",
+			"reviewer2@kernel.org",
+		})
+	}
+
+	// No more bisection jobs.
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectEQ(pollResp.ID, "")
+}
+
+func TestBisectCauseInconclusive(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+	crash := testCrashWithRepro(build, 1)
+	c.client2.ReportCrash(crash)
+	msg := c.client2.pollEmailBug()
+
+	pollResp := c.client2.pollJobs(build.Manager)
+	jobID := pollResp.ID
+	done := &dashapi.JobDoneReq{
+		ID:    jobID,
+		Build: *build,
+		Log:   []byte("bisect log"),
+		Commits: []dashapi.Commit{
+			{
+				Hash:       "111111111111111111111111",
+				Title:      "kernel: break build",
+				Author:     "hacker@kernel.org",
+				AuthorName: "Hacker Kernelov",
+				CC:         []string{"reviewer1@kernel.org", "reviewer2@kernel.org"},
+				Date:       time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC),
+			},
+			{
+				Hash:       "222222222222222222222222",
+				Title:      "kernel: now add a bug to the broken build",
+				Author:     "author@kernel.org",
+				AuthorName: "Author Kernelov",
+				CC:         []string{"reviewer3@kernel.org", "reviewer4@kernel.org"},
+				Date:       time.Date(2001, 2, 9, 4, 5, 6, 7, time.UTC),
+			},
+		},
+	}
+	done.Build.ID = jobID
+	c.expectOK(c.client2.JobDone(done))
+
+	_, extBugID, err := email.RemoveAddrContext(msg.Sender)
+	c.expectOK(err)
+	_, dbCrash, _ := c.loadBug(extBugID)
+	reproSyzLink := externalLink(c.ctx, textReproSyz, dbCrash.ReproSyz)
+	reproCLink := externalLink(c.ctx, textReproC, dbCrash.ReproC)
+	dbJob, dbBuild, dbJobCrash := c.loadJob(jobID)
+	kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
+	bisectLogLink := externalLink(c.ctx, textLog, dbJob.Log)
+	crashLogLink := externalLink(c.ctx, textCrashLog, dbJobCrash.Log)
+
+	{
+		msg := c.pollEmailBug()
+		// Not mailed to commit author/cc because !MailMaintainers.
+		c.expectEQ(msg.To, []string{"test@syzkaller.com"})
+		c.expectEQ(msg.Subject, crash.Title)
+		c.expectEQ(len(msg.Attachments), 0)
+		c.expectEQ(msg.Body, fmt.Sprintf(`Bisection is inconclusive: the first bad commit could be any of:
+
+11111111 kernel: break build
+22222222 kernel: now add a bug to the broken build
+
+bisection log:  %[2]v
+start commit:   11111111 kernel_commit_title1
+git tree:       repo1 branch1
+kernel config:  %[3]v
+dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
+syz repro:      %[4]v
+C reproducer:   %[5]v
+
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection
+`, extBugID, bisectLogLink, kernelConfigLink, reproSyzLink, reproCLink))
+	}
+
+	// The next reporting must get bug report with bisection results.
+	c.incomingEmail(msg.Sender, "#syz upstream")
+	{
+		msg := c.pollEmailBug()
+		_, extBugID2, err := email.RemoveAddrContext(msg.Sender)
+		c.expectOK(err)
+		c.expectEQ(msg.To, []string{
+			"bugs@syzkaller.com",
+			"default@maintainers.com",
+		})
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
+
+syzbot found the following crash on:
+
+HEAD commit:    11111111 kernel_commit_title1
+git tree:       repo1 branch1
+console output: %[2]v
+kernel config:  %[3]v
+dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
+compiler:       compiler1
+syz repro:      %[4]v
+C reproducer:   %[5]v
+
+Bisection is inconclusive: the first bad commit could be any of:
+
+11111111 kernel: break build
+22222222 kernel: now add a bug to the broken build
+
+bisection log:  %[6]v
+
+IMPORTANT: if you fix the bug, please add the following tag to the commit:
+Reported-by: syzbot+%[1]v@testapp.appspotmail.com
+
+report1
+
+---
+This bug is generated by a bot. It may contain errors.
+See https://goo.gl/tpsmEJ for more information about syzbot.
+syzbot engineers can be reached at syzkaller@googlegroups.com.
+
+syzbot will keep track of this bug report. See:
+https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection
+syzbot can test patches for this bug, for details see:
+https://goo.gl/tpsmEJ#testing-patches`,
+			extBugID2, crashLogLink, kernelConfigLink, reproSyzLink, reproCLink, bisectLogLink))
+	}
+}
+
+func TestBisectCauseAncient(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+	crash := testCrashWithRepro(build, 1)
+	c.client2.ReportCrash(crash)
+	msg := c.client2.pollEmailBug()
+
+	pollResp := c.client2.pollJobs(build.Manager)
+	jobID := pollResp.ID
+	done := &dashapi.JobDoneReq{
+		ID:          jobID,
+		Build:       *build,
+		Log:         []byte("bisect log"),
+		CrashTitle:  "bisect crash title",
+		CrashLog:    []byte("bisect crash log"),
+		CrashReport: []byte("bisect crash report"),
+	}
+	done.Build.ID = jobID
+	c.expectOK(c.client2.JobDone(done))
+
+	_, extBugID, err := email.RemoveAddrContext(msg.Sender)
+	c.expectOK(err)
+	_, dbCrash, _ := c.loadBug(extBugID)
+	reproSyzLink := externalLink(c.ctx, textReproSyz, dbCrash.ReproSyz)
+	reproCLink := externalLink(c.ctx, textReproC, dbCrash.ReproC)
+	dbJob, dbBuild, dbJobCrash := c.loadJob(jobID)
+	bisectCrashReportLink := externalLink(c.ctx, textCrashReport, dbJob.CrashReport)
+	bisectCrashLogLink := externalLink(c.ctx, textCrashLog, dbJob.CrashLog)
+	kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
+	bisectLogLink := externalLink(c.ctx, textLog, dbJob.Log)
+	crashLogLink := externalLink(c.ctx, textCrashLog, dbJobCrash.Log)
+
+	{
+		msg := c.pollEmailBug()
+		// Not mailed to commit author/cc because !MailMaintainers.
+		c.expectEQ(msg.To, []string{"test@syzkaller.com"})
+		c.expectEQ(msg.Subject, crash.Title)
+		c.expectEQ(len(msg.Attachments), 0)
+		c.expectEQ(msg.Body, fmt.Sprintf(`Bisection is inconclusive: the bug happens on the oldest tested release.
+
+bisection log:  %[2]v
+start commit:   11111111 kernel_commit_title1
+git tree:       repo1 branch1
+final crash:    %[3]v
+console output: %[4]v
+kernel config:  %[5]v
+dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
+syz repro:      %[6]v
+C reproducer:   %[7]v
+
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection
+`, extBugID, bisectLogLink, bisectCrashReportLink, bisectCrashLogLink,
+			kernelConfigLink, reproSyzLink, reproCLink))
+	}
+
+	// The next reporting must get bug report with bisection results.
+	c.incomingEmail(msg.Sender, "#syz upstream")
+	{
+		msg := c.pollEmailBug()
+		_, extBugID2, err := email.RemoveAddrContext(msg.Sender)
+		c.expectOK(err)
+		c.expectEQ(msg.To, []string{
+			"bugs@syzkaller.com",
+			"default@maintainers.com",
+		})
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
+
+syzbot found the following crash on:
+
+HEAD commit:    11111111 kernel_commit_title1
+git tree:       repo1 branch1
+console output: %[2]v
+kernel config:  %[3]v
+dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
+compiler:       compiler1
+syz repro:      %[4]v
+C reproducer:   %[5]v
+
+Bisection is inconclusive: the bug happens on the oldest tested release.
+
+bisection log:  %[6]v
+final crash:    %[7]v
+console output: %[8]v
+
+IMPORTANT: if you fix the bug, please add the following tag to the commit:
+Reported-by: syzbot+%[1]v@testapp.appspotmail.com
+
+report1
+
+---
+This bug is generated by a bot. It may contain errors.
+See https://goo.gl/tpsmEJ for more information about syzbot.
+syzbot engineers can be reached at syzkaller@googlegroups.com.
+
+syzbot will keep track of this bug report. See:
+https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection
+syzbot can test patches for this bug, for details see:
+https://goo.gl/tpsmEJ#testing-patches`,
+			extBugID2, crashLogLink, kernelConfigLink, reproSyzLink, reproCLink,
+			bisectLogLink, bisectCrashReportLink, bisectCrashLogLink))
+	}
+}
+
+func TestBisectCauseExternal(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client.UploadBuild(build)
+	crash := testCrashWithRepro(build, 1)
+	c.client.ReportCrash(crash)
+	rep := c.client.pollBug()
+
+	pollResp := c.client.pollJobs(build.Manager)
+	jobID := pollResp.ID
+	done := &dashapi.JobDoneReq{
+		ID:    jobID,
+		Build: *build,
+		Log:   []byte("bisect log"),
+		Commits: []dashapi.Commit{
+			{
+				Hash:       "111111111111111111111111",
+				Title:      "kernel: break build",
+				Author:     "hacker@kernel.org",
+				AuthorName: "Hacker Kernelov",
+				CC:         []string{"reviewer1@kernel.org", "reviewer2@kernel.org"},
+				Date:       time.Date(2000, 2, 9, 4, 5, 6, 7, time.UTC),
+			},
+		},
+	}
+	done.Build.ID = jobID
+	c.expectOK(c.client2.JobDone(done))
+
+	resp, _ := c.client.ReportingPollBugs("test")
+	c.expectEQ(len(resp.Reports), 1)
+	// Still reported because we did not ack.
+	bisect := c.client.pollBug()
+	// pollBug acks, must not be reported after that.
+	c.client.pollBugs(0)
+
+	c.expectEQ(bisect.Type, dashapi.ReportBisectCause)
+	c.expectEQ(bisect.Title, rep.Title)
+}
+
+func TestBisectCauseReproSyz(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+	crash := testCrashWithRepro(build, 1)
+	crash.ReproC = nil
+	c.client2.ReportCrash(crash)
+
+	pollResp := c.client2.pollJobs(build.Manager)
+	jobID := pollResp.ID
+	done := &dashapi.JobDoneReq{
+		ID:         jobID,
+		Build:      *build,
+		Log:        []byte("bisect log"),
+		CrashTitle: "bisect crash title",
+		CrashLog:   []byte("bisect crash log"),
+	}
+	done.Build.ID = jobID
+	c.expectOK(c.client2.JobDone(done))
+
+	crash.ReproC = []byte("int main")
+	c.client2.ReportCrash(crash)
+
+	msg := c.client2.pollEmailBug()
+	if !strings.Contains(msg.Body, "syzbot found the following crash") {
+		t.Fatalf("wrong email header:\n%v", msg.Body)
+	}
+	if !strings.Contains(msg.Body, "Bisection is inconclusive") {
+		t.Fatalf("report does not contain bisection results:\n%v", msg.Body)
+	}
+}
+
+func TestBisectCauseReproSyz2(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+	crash := testCrashWithRepro(build, 1)
+	crash.ReproC = nil
+	c.client2.ReportCrash(crash)
+
+	pollResp := c.client2.pollJobs(build.Manager)
+	jobID := pollResp.ID
+	done := &dashapi.JobDoneReq{
+		ID:         jobID,
+		Build:      *build,
+		Log:        []byte("bisect log"),
+		CrashTitle: "bisect crash title",
+		CrashLog:   []byte("bisect crash log"),
+	}
+	done.Build.ID = jobID
+	c.expectOK(c.client2.JobDone(done))
+
+	msg := c.client2.pollEmailBug()
+	if !strings.Contains(msg.Body, "syzbot found the following crash") {
+		t.Fatalf("wrong email header:\n%v", msg.Body)
+	}
+	if !strings.Contains(msg.Body, "Bisection is inconclusive") {
+		t.Fatalf("report does not contain bisection results:\n%v", msg.Body)
+	}
+
+	crash.ReproC = []byte("int main")
+	c.client2.ReportCrash(crash)
+
+	msg = c.client2.pollEmailBug()
+	if !strings.Contains(msg.Body, "syzbot has found a reproducer for the following crash") {
+		t.Fatalf("wrong email header:\n%v", msg.Body)
+	}
+	// Do we need bisection results in this email as well?
+	// We already mailed them, so we could not mail them here.
+	// But if we don't include bisection results, need to check that CC is correct
+	// (includes bisection CC).
+	if !strings.Contains(msg.Body, "Bisection is inconclusive") {
+		t.Fatalf("report still contains bisection results:\n%v", msg.Body)
+	}
+}
diff --git a/dashboard/app/bug.html b/dashboard/app/bug.html
index 2cdfc8d..6bbf30f 100644
--- a/dashboard/app/bug.html
+++ b/dashboard/app/bug.html
@@ -14,16 +14,51 @@
 <body>
 	{{template "header" .Header}}
 
-	<b>[{{.Bug.Namespace}}] {{.Bug.Title}}</b><br>
+	<b>{{.Bug.Title}}</b><br>
 	Status: {{if .Bug.ExternalLink}}<a href="{{.Bug.ExternalLink}}">{{.Bug.Status}}</a>{{else}}{{.Bug.Status}}{{end}}<br>
 	Reported-by: {{.Bug.CreditEmail}}<br>
 	{{if .Bug.Commits}}
-		Commits: {{.Bug.Commits}}<br>
+		Fix commit: {{template "fix_commits" .Bug.Commits}}<br>
 		{{if .Bug.ClosedTime.IsZero}}
 			Patched on: {{.Bug.PatchedOn}}, missing on: {{.Bug.MissingOn}}<br>
 		{{end}}
 	{{end}}
-	First: {{formatLateness $.Now $.Bug.FirstTime}}, last: {{formatLateness $.Now $.Bug.LastTime}}<br>
+	First crash: {{formatLateness $.Now $.Bug.FirstTime}}, last: {{formatLateness $.Now $.Bug.LastTime}}<br>
+
+	{{with $bisect := .BisectCause}}<br>
+		{{if $bisect.ErrorLink}}
+			<b>Bisection: {{link $bisect.ErrorLink "error"}}
+			({{link $bisect.LogLink "bisect log"}})</b><br>
+		{{else if $bisect.Commit}}{{with $com := $bisect.Commit}}
+			<b>Bisection: introduced by
+			({{link $bisect.LogLink "bisect log"}}):</b><br>
+			<br><span class="mono">
+			commit {{$com.Hash}}<br>
+			Author: {{$com.Author}}<br>
+			Date:   {{formatKernelTime $com.Date}}<br>
+			<br>
+			&nbsp;&nbsp;{{$com.Title}}<br>
+			</span><br>
+		{{end}}{{else if $bisect.Commits}}{{with $bisect.Commits}}
+			<b>Bisection: the first bad commit could be any of
+			({{link $bisect.LogLink "bisect log"}}):</b><br>
+			<br><span class="mono">
+			{{range $com := $bisect.Commits}}
+				&nbsp;&nbsp;{{formatTagHash $com.Hash}} {{$com.Title}}<br>
+			{{end}}
+			</span><br>
+		{{end}}{{else}}
+			<b>Bisection: the bug happens on the oldest tested release
+			({{link $bisect.LogLink "bisect log"}})</b><br>
+		{{end}}
+		Tree: <span title="{{$bisect.Manager}}">{{$bisect.KernelAlias}}</span><br>
+		{{if $bisect.CrashLogLink}}
+			Crash: {{link $bisect.CrashReportLink $bisect.CrashTitle}} ({{link $bisect.CrashLogLink "log"}})<br>
+		{{end}}
+		Repro: {{optlink $bisect.Crash.ReproCLink "C"}}
+			{{optlink $bisect.Crash.ReproSyzLink "syz"}}
+			{{optlink $bisect.Crash.KernelConfigLink ".config"}}<br>
+	{{end}}
 
 	{{template "bug_list" .DupOf}}
 	{{template "bug_list" .Dups}}
@@ -36,9 +71,10 @@
 
 	<table class="list_table">
 		<caption>All crashes ({{.Bug.NumCrashes}}):</caption>
+		<thead>
 		<tr>
 			<th><a onclick="return sortTable(this, 'Manager', textSort)" href="#">Manager</a></th>
-			<th><a onclick="return sortTable(this, 'Time', textSort)" href="#">Time</a></th>
+			<th><a onclick="return sortTable(this, 'Time', textSort, true)" href="#">Time</a></th>
 			<th><a onclick="return sortTable(this, 'Kernel', textSort)" href="#">Kernel</a></th>
 			<th><a onclick="return sortTable(this, 'Commit', textSort)" href="#">Commit</a></th>
 			<th><a onclick="return sortTable(this, 'Syzkaller', textSort)" href="#">Syzkaller</a></th>
@@ -47,23 +83,31 @@
 			<th><a onclick="return sortTable(this, 'Report', reproSort)" href="#">Report</a></th>
 			<th><a onclick="return sortTable(this, 'Syz repro', reproSort)" href="#">Syz repro</a></th>
 			<th><a onclick="return sortTable(this, 'C repro', textSort)" href="#">C repro</a></th>
+			{{if $.HasMaintainers}}
 			<th><a onclick="return sortTable(this, 'Maintainers', textSort)" href="#">Maintainers</a></th>
+			{{end}}
 		</tr>
+		</thead>
+		<tbody>
 		{{range $c := $.Crashes}}
 			<tr>
 				<td class="manager">{{$c.Manager}}</td>
 				<td class="time">{{formatTime $c.Time}}</td>
 				<td class="kernel" title="{{$c.KernelAlias}}">{{$c.KernelAlias}}</td>
-				<td class="tag">{{$c.KernelCommit}}</td>
-				<td class="tag">{{$c.SyzkallerCommit}}</td>
+				<td class="tag" title="{{$c.KernelCommit}}
+{{formatTime $c.KernelCommitDate}}">{{link $c.KernelCommitLink (formatShortHash $c.KernelCommit)}}</td>
+				<td class="tag">{{link $c.SyzkallerCommitLink (formatShortHash $c.SyzkallerCommit)}}</td>
 				<td class="config">{{if $c.KernelConfigLink}}<a href="{{$c.KernelConfigLink}}">.config</a>{{end}}</td>
 				<td class="repro">{{if $c.LogLink}}<a href="{{$c.LogLink}}">log</a>{{end}}</td>
 				<td class="repro">{{if $c.ReportLink}}<a href="{{$c.ReportLink}}">report</a>{{end}}</td>
 				<td class="repro">{{if $c.ReproSyzLink}}<a href="{{$c.ReproSyzLink}}">syz</a>{{end}}</td>
 				<td class="repro">{{if $c.ReproCLink}}<a href="{{$c.ReproCLink}}">C</a>{{end}}</td>
+				{{if $.HasMaintainers}}
 				<td class="maintainers" title="{{$c.Maintainers}}">{{$c.Maintainers}}</td>
+				{{end}}
 			</tr>
 		{{end}}
+		</tbody>
 	</table>
 </body>
 </html>
diff --git a/dashboard/app/commit_poll_test.go b/dashboard/app/commit_poll_test.go
new file mode 100644
index 0000000..48c8629
--- /dev/null
+++ b/dashboard/app/commit_poll_test.go
@@ -0,0 +1,94 @@
+// Copyright 2019 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// +build aetest
+
+package dash
+
+import (
+	"sort"
+	"testing"
+
+	"github.com/google/syzkaller/dashboard/dashapi"
+)
+
+func TestCommitPoll(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build1 := testBuild(1)
+	c.client.UploadBuild(build1)
+
+	crash1 := testCrash(build1, 1)
+	c.client.ReportCrash(crash1)
+	rep1 := c.client.pollBug()
+
+	crash2 := testCrash(build1, 2)
+	c.client.ReportCrash(crash2)
+	rep2 := c.client.pollBug()
+
+	// No commits in commit poll.
+	commitPollResp, err := c.client.CommitPoll()
+	c.expectOK(err)
+	c.expectEQ(len(commitPollResp.Repos), 2)
+	c.expectEQ(commitPollResp.Repos[0].URL, testConfig.Namespaces["test1"].Repos[0].URL)
+	c.expectEQ(commitPollResp.Repos[0].Branch, testConfig.Namespaces["test1"].Repos[0].Branch)
+	c.expectEQ(commitPollResp.Repos[1].URL, testConfig.Namespaces["test1"].Repos[1].URL)
+	c.expectEQ(commitPollResp.Repos[1].Branch, testConfig.Namespaces["test1"].Repos[1].Branch)
+	c.expectEQ(len(commitPollResp.Commits), 0)
+
+	// Specify fixing commit for the bug.
+	reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
+		ID:         rep1.ID,
+		Status:     dashapi.BugStatusOpen,
+		FixCommits: []string{"foo: fix1", "foo: fix2"},
+	})
+	c.expectEQ(reply.OK, true)
+
+	// The commit should appear in commit poll.
+	for i := 0; i < 2; i++ {
+		commitPollResp, err = c.client.CommitPoll()
+		c.expectOK(err)
+		c.expectEQ(len(commitPollResp.Commits), 2)
+		sort.Strings(commitPollResp.Commits)
+		c.expectEQ(commitPollResp.Commits[0], "foo: fix1")
+		c.expectEQ(commitPollResp.Commits[1], "foo: fix2")
+	}
+
+	// Upload hash for the first commit and fixing commit for the second bug.
+	c.expectOK(c.client.UploadCommits([]dashapi.Commit{
+		{Hash: "hash1", Title: "foo: fix1"},
+		{Hash: "hash2", Title: "bar: fix3", BugIDs: []string{rep2.ID}},
+		{Hash: "hash3", Title: "some unrelated commit", BugIDs: []string{"does not exist"}},
+		{Hash: "hash4", Title: "another unrelated commit"},
+	}))
+
+	commitPollResp, err = c.client.CommitPoll()
+	c.expectOK(err)
+	c.expectEQ(len(commitPollResp.Commits), 2)
+	sort.Strings(commitPollResp.Commits)
+	c.expectEQ(commitPollResp.Commits[0], "foo: fix1")
+	c.expectEQ(commitPollResp.Commits[1], "foo: fix2")
+
+	// Upload hash for the second commit and a new fixing commit for the second bug.
+	c.expectOK(c.client.UploadCommits([]dashapi.Commit{
+		{Hash: "hash5", Title: "foo: fix2"},
+		{Title: "bar: fix4", BugIDs: []string{rep2.ID}},
+	}))
+
+	commitPollResp, err = c.client.CommitPoll()
+	c.expectOK(err)
+	c.expectEQ(len(commitPollResp.Commits), 1)
+	c.expectEQ(commitPollResp.Commits[0], "bar: fix4")
+
+	// Upload hash for the second commit and a new fixing commit for the second bug.
+	c.expectOK(c.client.UploadCommits([]dashapi.Commit{
+		{Hash: "hash1", Title: "foo: fix1"},
+		{Hash: "hash5", Title: "foo: fix2"},
+		{Hash: "hash6", Title: "bar: fix4"},
+	}))
+
+	commitPollResp, err = c.client.CommitPoll()
+	c.expectOK(err)
+	c.expectEQ(len(commitPollResp.Commits), 0)
+}
diff --git a/dashboard/app/config.go b/dashboard/app/config.go
index 8c60e78..c8a84ee 100644
--- a/dashboard/app/config.go
+++ b/dashboard/app/config.go
@@ -6,10 +6,13 @@
 import (
 	"encoding/json"
 	"fmt"
+	"net/mail"
 	"regexp"
 	"time"
 
+	"github.com/google/syzkaller/dashboard/dashapi"
 	"github.com/google/syzkaller/pkg/email"
+	"github.com/google/syzkaller/pkg/vcs"
 )
 
 // There are multiple configurable aspects of the app (namespaces, reporting, API clients, etc).
@@ -22,18 +25,22 @@
 	AuthDomain string
 	// Google Analytics Tracking ID.
 	AnalyticsTrackingID string
+	// URL prefix of source coverage reports.
+	// Dashboard will append manager_name.html to that prefix.
+	// syz-ci can upload these reports to GCS.
+	CoverPath string
 	// Global API clients that work across namespaces (e.g. external reporting).
 	Clients map[string]string
 	// List of emails blacklisted from issuing test requests.
 	EmailBlacklist []string
+	// Namespace that is shown by default (no namespace selected yet).
+	DefaultNamespace string
 	// Per-namespace config.
 	// Namespaces are a mechanism to separate groups of different kernels.
 	// E.g. Debian 4.4 kernels and Ubuntu 4.9 kernels.
 	// Each namespace has own reporting config, own API clients
 	// and bugs are not merged across namespaces.
 	Namespaces map[string]*Config
-	// Maps full repository address/branch to description of this repo.
-	KernelRepos map[string]KernelRepo
 }
 
 // Per-namespace config.
@@ -42,9 +49,9 @@
 	AccessLevel AccessLevel
 	// Name used in UI.
 	DisplayTitle string
-	// URL of a source coverage report for this namespace
-	// (uploading/updating the report is out of scope of the system for now).
-	CoverLink string
+	// Unique string that allows to show "similar bugs" across different namespaces.
+	// Similar bugs are shown only across namespaces with the same value of SimilarityDomain.
+	SimilarityDomain string
 	// Per-namespace clients that act only on a particular namespace.
 	Clients map[string]string
 	// A unique key for hashing, can be anything.
@@ -59,6 +66,16 @@
 	Managers map[string]ConfigManager
 	// Reporting config.
 	Reporting []Reporting
+	// TransformCrash hook is called when a manager uploads a crash.
+	// The hook can transform the crash or discard the crash by returning false.
+	TransformCrash func(build *Build, crash *dashapi.Crash) bool
+	// NeedRepro hook can be used to prevent reproduction of some bugs.
+	NeedRepro func(bug *Bug) bool
+	// List of kernel repositories for this namespace.
+	// The first repo considered the "main" repo (e.g. fixing commit info is shown against this repo).
+	// Other repos are secondary repos, they may be tested or not.
+	// If not tested they are used to poll for fixing commits.
+	Repos []KernelRepo
 }
 
 // ConfigManager describes a single syz-manager instance.
@@ -87,32 +104,40 @@
 	Filter ReportingFilter
 	// How many new bugs report per day.
 	DailyLimit int
+	// Upstream reports into next reporting after this period.
+	Embargo time.Duration
 	// Type of reporting and its configuration.
 	// The app has one built-in type, EmailConfig, which reports bugs by email.
 	// And ExternalConfig which can be used to attach any external reporting system (e.g. Bugzilla).
 	Config ReportingType
+
+	// Set for all but last reporting stages.
+	moderation bool
 }
 
 type ReportingType interface {
 	// Type returns a unique string that identifies this reporting type (e.g. "email").
 	Type() string
-	// NeedMaintainers says if this reporting requires non-empty maintainers list.
-	NeedMaintainers() bool
 	// Validate validates the current object, this is called only during init.
 	Validate() error
 }
 
 type KernelRepo struct {
+	URL    string
+	Branch string
 	// Alias is a short, readable name of a kernel repository.
 	Alias string
 	// ReportingPriority says if we need to prefer to report crashes in this
 	// repo over crashes in repos with lower value. Must be in [0-9] range.
 	ReportingPriority int
+	// Additional CC list to add to all bugs reported on this repo.
+	CC []string
 }
 
 var (
-	clientNameRe = regexp.MustCompile("^[a-zA-Z0-9-_]{4,100}$")
-	clientKeyRe  = regexp.MustCompile("^[a-zA-Z0-9]{16,128}$")
+	namespaceNameRe = regexp.MustCompile("^[a-zA-Z0-9-_.]{4,32}$")
+	clientNameRe    = regexp.MustCompile("^[a-zA-Z0-9-_.]{4,100}$")
+	clientKeyRe     = regexp.MustCompile("^[a-zA-Z0-9]{16,128}$")
 )
 
 type (
@@ -142,7 +167,7 @@
 
 func init() {
 	// Prevents gometalinter from considering everything as dead code.
-	if false {
+	if false && isAppEngineTest {
 		installConfig(nil)
 	}
 }
@@ -151,7 +176,14 @@
 	if config != nil {
 		panic("another config is already installed")
 	}
-	// Validate the global cfg.
+	checkConfig(cfg)
+	config = cfg
+	initEmailReporting()
+	initHTTPHandlers()
+	initAPIHandlers()
+}
+
+func checkConfig(cfg *GlobalConfig) {
 	if len(cfg.Namespaces) == 0 {
 		panic("no namespaces found")
 	}
@@ -162,26 +194,17 @@
 	clientNames := make(map[string]bool)
 	checkClients(clientNames, cfg.Clients)
 	checkConfigAccessLevel(&cfg.AccessLevel, AccessPublic, "global")
+	if cfg.Namespaces[cfg.DefaultNamespace] == nil {
+		panic(fmt.Sprintf("default namespace %q is not found", cfg.DefaultNamespace))
+	}
 	for ns, cfg := range cfg.Namespaces {
 		checkNamespace(ns, cfg, namespaces, clientNames)
 	}
-	for repo, info := range cfg.KernelRepos {
-		if info.Alias == "" {
-			panic(fmt.Sprintf("empty kernel repo alias for %q", repo))
-		}
-		if prio := info.ReportingPriority; prio < 0 || prio > 9 {
-			panic(fmt.Sprintf("bad kernel repo reporting priority %v for %q", prio, repo))
-		}
-	}
-	config = cfg
-	initEmailReporting()
-	initHTTPHandlers()
-	initAPIHandlers()
 }
 
 func checkNamespace(ns string, cfg *Config, namespaces, clientNames map[string]bool) {
-	if ns == "" {
-		panic("empty namespace name")
+	if !namespaceNameRe.MatchString(ns) {
+		panic(fmt.Sprintf("bad namespace name: %q", ns))
 	}
 	if namespaces[ns] {
 		panic(fmt.Sprintf("duplicate namespace %q", ns))
@@ -190,6 +213,9 @@
 	if cfg.DisplayTitle == "" {
 		cfg.DisplayTitle = ns
 	}
+	if cfg.SimilarityDomain == "" {
+		cfg.SimilarityDomain = ns
+	}
 	checkClients(clientNames, cfg.Clients)
 	for name, mgr := range cfg.Managers {
 		checkManager(ns, name, mgr)
@@ -200,6 +226,46 @@
 	if len(cfg.Reporting) == 0 {
 		panic(fmt.Sprintf("no reporting in namespace %q", ns))
 	}
+	if cfg.TransformCrash == nil {
+		cfg.TransformCrash = func(build *Build, crash *dashapi.Crash) bool {
+			return true
+		}
+	}
+	if cfg.NeedRepro == nil {
+		cfg.NeedRepro = func(bug *Bug) bool {
+			return true
+		}
+	}
+	checkKernelRepos(ns, cfg)
+	checkNamespaceReporting(ns, cfg)
+}
+
+func checkKernelRepos(ns string, cfg *Config) {
+	if len(cfg.Repos) == 0 {
+		panic(fmt.Sprintf("no repos in namespace %q", ns))
+	}
+	for _, repo := range cfg.Repos {
+		if !vcs.CheckRepoAddress(repo.URL) {
+			panic(fmt.Sprintf("%v: bad repo URL %q", ns, repo.URL))
+		}
+		if !vcs.CheckBranch(repo.Branch) {
+			panic(fmt.Sprintf("%v: bad repo branch %q", ns, repo.Branch))
+		}
+		if repo.Alias == "" {
+			panic(fmt.Sprintf("%v: empty repo alias for %q", ns, repo.Alias))
+		}
+		if prio := repo.ReportingPriority; prio < 0 || prio > 9 {
+			panic(fmt.Sprintf("%v: bad kernel repo reporting priority %v for %q", ns, prio, repo.Alias))
+		}
+		for _, email := range repo.CC {
+			if _, err := mail.ParseAddress(email); err != nil {
+				panic(fmt.Sprintf("bad email address %q: %v", email, err))
+			}
+		}
+	}
+}
+
+func checkNamespaceReporting(ns string, cfg *Config) {
 	checkConfigAccessLevel(&cfg.AccessLevel, cfg.AccessLevel, fmt.Sprintf("namespace %q", ns))
 	parentAccessLevel := cfg.AccessLevel
 	reportingNames := make(map[string]bool)
@@ -215,6 +281,10 @@
 		if reporting.DisplayTitle == "" {
 			reporting.DisplayTitle = reporting.Name
 		}
+		reporting.moderation = ri < len(cfg.Reporting)-1
+		if !reporting.moderation && reporting.Embargo != 0 {
+			panic(fmt.Sprintf("embargo in the last reporting %v", reporting.Name))
+		}
 		checkConfigAccessLevel(&reporting.AccessLevel, parentAccessLevel,
 			fmt.Sprintf("reporting %q/%q", ns, reporting.Name))
 		parentAccessLevel = reporting.AccessLevel
diff --git a/dashboard/app/cron.yaml b/dashboard/app/cron.yaml
index 21f0d97..0bf56c5 100644
--- a/dashboard/app/cron.yaml
+++ b/dashboard/app/cron.yaml
@@ -1,6 +1,6 @@
 cron:
 - url: /email_poll
   schedule: every 1 minutes
-- url: /_ah/datastore_admin/backup.create?name=backup&filesystem=gs&gs_bucket_name=syzkaller&kind=Bug&kind=Build&kind=Crash&kind=CrashLog&kind=CrashReport&kind=Error&kind=Job&kind=KernelConfig&kind=Manager&kind=ManagerStats&kind=Patch&kind=ReportingState&kind=ReproC&kind=ReproSyz
+- url: /_ah/datastore_admin/backup.create?name=backup&filesystem=gs&gs_bucket_name=syzkaller-backups&kind=Bug&kind=Build&kind=Crash&kind=CrashLog&kind=CrashReport&kind=Error&kind=Job&kind=KernelConfig&kind=Manager&kind=ManagerStats&kind=Patch&kind=ReportingState&kind=ReproC&kind=ReproSyz
   schedule: every monday 00:00
   target: ah-builtin-python-bundle
diff --git a/dashboard/app/email_test.go b/dashboard/app/email_test.go
index b314998..2d848c9 100644
--- a/dashboard/app/email_test.go
+++ b/dashboard/app/email_test.go
@@ -9,6 +9,7 @@
 	"fmt"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/google/syzkaller/pkg/email"
 )
@@ -21,21 +22,17 @@
 	c.client2.UploadBuild(build)
 
 	crash := testCrash(build, 1)
-	crash.Maintainers = []string{`"Foo Bar" <foo@bar.com>`, `bar@foo.com`}
+	crash.Maintainers = []string{`"Foo Bar" <foo@bar.com>`, `bar@foo.com`, `idont@want.EMAILS`}
 	c.client2.ReportCrash(crash)
 
 	// Report the crash over email and check all fields.
 	var sender0, extBugID0, body0 string
 	{
-		c.expectOK(c.GET("/email_poll"))
-		c.expectEQ(len(c.emailSink), 1)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		sender0 = msg.Sender
 		body0 = msg.Body
 		sender, extBugID, err := email.RemoveAddrContext(msg.Sender)
-		if err != nil {
-			t.Fatalf("failed to remove sender context: %v", err)
-		}
+		c.expectOK(err)
 		extBugID0 = extBugID
 		_, dbCrash, dbBuild := c.loadBug(extBugID0)
 		crashLogLink := externalLink(c.ctx, textCrashLog, dbCrash.Log)
@@ -45,17 +42,17 @@
 		c.expectEQ(msg.To, []string{to})
 		c.expectEQ(msg.Subject, crash.Title)
 		c.expectEQ(len(msg.Attachments), 0)
-		body := fmt.Sprintf(`Hello,
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
 
 syzbot found the following crash on:
 
-HEAD commit:    111111111111 kernel_commit_title1
-git tree:       repo1/branch1
+HEAD commit:    11111111 kernel_commit_title1
+git tree:       repo1 branch1
 console output: %[2]v
 kernel config:  %[3]v
 dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
 compiler:       compiler1
-CC:             [bar@foo.com foo@bar.com]
+CC:             [bar@foo.com foo@bar.com idont@want.EMAILS]
 
 Unfortunately, I don't have any reproducer for this crash yet.
 
@@ -70,11 +67,8 @@
 syzbot engineers can be reached at syzkaller@googlegroups.com.
 
 syzbot will keep track of this bug report. See:
-https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot.`,
-			extBugID0, crashLogLink, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+https://goo.gl/tpsmEJ#status for how to communicate with syzbot.`,
+			extBugID0, crashLogLink, kernelConfigLink))
 		c.checkURLContents(crashLogLink, crash.Log)
 		c.checkURLContents(kernelConfigLink, build.KernelConfig)
 	}
@@ -115,28 +109,40 @@
 	// We used to extract "#syz fix: exact-commit-title" from it.
 	c.incomingEmail(sender0, body0)
 
+	c.incomingEmail(sender0, "I don't want emails", EmailOptFrom(`"idont" <idont@WANT.emails>`))
+	c.expectNoEmail()
+
+	// This person sends an email and is listed as a maintainer, but opt-out of emails.
+	// We should not send anything else to them for this bug. Also don't warn about no mailing list in CC.
+	c.incomingEmail(sender0, "#syz uncc", EmailOptFrom(`"IDONT" <Idont@want.emails>`), EmailOptCC(nil))
+	c.expectNoEmail()
+
 	// Now report syz reproducer and check updated email.
+	build2 := testBuild(10)
+	build2.Arch = "386"
+	build2.KernelRepo = testConfig.Namespaces["test2"].Repos[0].URL
+	build2.KernelBranch = testConfig.Namespaces["test2"].Repos[0].Branch
+	build2.KernelCommitTitle = "a really long title, longer than 80 chars, really long-long-long-long-long-long title"
+	c.client2.UploadBuild(build2)
+	crash.BuildID = build2.ID
 	crash.ReproOpts = []byte("repro opts")
 	crash.ReproSyz = []byte("getpid()")
 	syzRepro := []byte(fmt.Sprintf("%s#%s\n%s", syzReproPrefix, crash.ReproOpts, crash.ReproSyz))
 	c.client2.ReportCrash(crash)
 
 	{
-		c.expectOK(c.GET("/email_poll"))
-		c.expectEQ(len(c.emailSink), 1)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(msg.Sender, sender0)
 		sender, _, err := email.RemoveAddrContext(msg.Sender)
-		if err != nil {
-			t.Fatalf("failed to remove sender context: %v", err)
-		}
+		c.expectOK(err)
 		_, dbCrash, dbBuild := c.loadBug(extBugID0)
 		reproSyzLink := externalLink(c.ctx, textReproSyz, dbCrash.ReproSyz)
 		crashLogLink := externalLink(c.ctx, textCrashLog, dbCrash.Log)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
 		c.expectEQ(sender, fromAddr(c.ctx))
 		to := []string{
-			"bugs@syzkaller.com",
+			"bugs2@syzkaller.com",
+			"bugs@syzkaller.com", // This is from incomingEmail.
 			"default@sender.com", // This is from incomingEmail.
 			"foo@bar.com",
 			config.Namespaces["test2"].Reporting[0].Config.(*EmailConfig).Email,
@@ -145,28 +151,26 @@
 		c.expectEQ(msg.Subject, "Re: "+crash.Title)
 		c.expectEQ(len(msg.Attachments), 0)
 		c.expectEQ(msg.Headers["In-Reply-To"], []string{"<1234>"})
-		body := fmt.Sprintf(`syzbot has found a reproducer for the following crash on:
+		c.expectEQ(msg.Body, fmt.Sprintf(`syzbot has found a reproducer for the following crash on:
 
-HEAD commit:    111111111111 kernel_commit_title1
-git tree:       repo1/branch1
+HEAD commit:    10101010 a really long title, longer than 80 chars, really..
+git tree:       repo10alias
 console output: %[3]v
 kernel config:  %[4]v
 dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
-compiler:       compiler1
-syzkaller repro:%[2]v
-CC:             [bar@foo.com foo@bar.com]
+compiler:       compiler10
+userspace arch: i386
+syz repro:      %[2]v
+CC:             [bar@foo.com foo@bar.com maintainers@repo10.org bugs@repo10.org]
 
 IMPORTANT: if you fix the bug, please add the following tag to the commit:
 Reported-by: syzbot+%[1]v@testapp.appspotmail.com
 
 report1
-`, extBugID0, reproSyzLink, crashLogLink, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+`, extBugID0, reproSyzLink, crashLogLink, kernelConfigLink))
 		c.checkURLContents(reproSyzLink, syzRepro)
 		c.checkURLContents(crashLogLink, crash.Log)
-		c.checkURLContents(kernelConfigLink, build.KernelConfig)
+		c.checkURLContents(kernelConfigLink, build2.KernelConfig)
 	}
 
 	// Now upstream the bug and check that it reaches the next reporting.
@@ -174,38 +178,35 @@
 
 	sender1, extBugID1 := "", ""
 	{
-		c.expectOK(c.GET("/email_poll"))
-		c.expectEQ(len(c.emailSink), 1)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		sender1 = msg.Sender
-		if sender1 == sender0 {
-			t.Fatalf("same ID in different reporting")
-		}
+		c.expectNE(sender1, sender0)
 		sender, extBugID, err := email.RemoveAddrContext(msg.Sender)
-		if err != nil {
-			t.Fatalf("failed to remove sender context: %v", err)
-		}
+		c.expectOK(err)
 		extBugID1 = extBugID
 		_, dbCrash, dbBuild := c.loadBug(extBugID1)
 		reproSyzLink := externalLink(c.ctx, textReproSyz, dbCrash.ReproSyz)
 		crashLogLink := externalLink(c.ctx, textCrashLog, dbCrash.Log)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
 		c.expectEQ(sender, fromAddr(c.ctx))
-		c.expectEQ(msg.To, []string{"bar@foo.com", "bugs@syzkaller.com",
-			"default@maintainers.com", "foo@bar.com"})
+		c.expectEQ(msg.To, []string{
+			"bar@foo.com", "bugs@repo10.org", "bugs@syzkaller.com",
+			"default@maintainers.com", "foo@bar.com", "maintainers@repo10.org"})
 		c.expectEQ(msg.Subject, crash.Title)
 		c.expectEQ(len(msg.Attachments), 0)
-		body := fmt.Sprintf(`Hello,
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
 
 syzbot found the following crash on:
 
-HEAD commit:    111111111111 kernel_commit_title1
-git tree:       repo1/branch1
+HEAD commit:    10101010 a really long title, longer than 80 chars, really..
+git tree:       repo10alias
 console output: %[3]v
 kernel config:  %[4]v
 dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
-compiler:       compiler1
-syzkaller repro:%[2]v
+compiler:       compiler10
+userspace arch: i386
+syz repro:      %[2]v
+CC:             [bar@foo.com foo@bar.com maintainers@repo10.org bugs@repo10.org]
 
 IMPORTANT: if you fix the bug, please add the following tag to the commit:
 Reported-by: syzbot+%[1]v@testapp.appspotmail.com
@@ -218,16 +219,13 @@
 syzbot engineers can be reached at syzkaller@googlegroups.com.
 
 syzbot will keep track of this bug report. See:
-https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot.
+https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
 syzbot can test patches for this bug, for details see:
 https://goo.gl/tpsmEJ#testing-patches`,
-			extBugID1, reproSyzLink, crashLogLink, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+			extBugID1, reproSyzLink, crashLogLink, kernelConfigLink))
 		c.checkURLContents(reproSyzLink, syzRepro)
 		c.checkURLContents(crashLogLink, crash.Log)
-		c.checkURLContents(kernelConfigLink, build.KernelConfig)
+		c.checkURLContents(kernelConfigLink, build2.KernelConfig)
 	}
 
 	// Model that somebody adds more emails to CC list.
@@ -246,52 +244,45 @@
 	c.expectOK(c.POST("/_ah/mail/", incoming3))
 
 	// Now upload a C reproducer.
-	build2 := testBuild(2)
-	build2.KernelCommitTitle = "a really long title, longer than 80 chars, really long-long-long-long-long-long title"
-	c.client2.UploadBuild(build2)
-	crash.BuildID = build2.ID
 	crash.ReproC = []byte("int main() {}")
 	crash.Maintainers = []string{"\"qux\" <qux@qux.com>"}
 	c.client2.ReportCrash(crash)
 
 	{
-		c.expectOK(c.GET("/email_poll"))
-		c.expectEQ(len(c.emailSink), 1)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(msg.Sender, sender1)
 		sender, _, err := email.RemoveAddrContext(msg.Sender)
-		if err != nil {
-			t.Fatalf("failed to remove sender context: %v", err)
-		}
+		c.expectOK(err)
 		_, dbCrash, dbBuild := c.loadBug(extBugID1)
 		reproCLink := externalLink(c.ctx, textReproC, dbCrash.ReproC)
 		reproSyzLink := externalLink(c.ctx, textReproSyz, dbCrash.ReproSyz)
 		crashLogLink := externalLink(c.ctx, textCrashLog, dbCrash.Log)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
 		c.expectEQ(sender, fromAddr(c.ctx))
-		c.expectEQ(msg.To, []string{"another@another.com", "bar@foo.com", "bugs@syzkaller.com",
-			"default@maintainers.com", "foo@bar.com", "new@new.com", "qux@qux.com"})
+		c.expectEQ(msg.To, []string{
+			"another@another.com", "bar@foo.com", "bugs@repo10.org",
+			"bugs@syzkaller.com", "default@maintainers.com", "foo@bar.com",
+			"maintainers@repo10.org", "new@new.com", "qux@qux.com"})
 		c.expectEQ(msg.Subject, "Re: "+crash.Title)
 		c.expectEQ(len(msg.Attachments), 0)
-		body := fmt.Sprintf(`syzbot has found a reproducer for the following crash on:
+		c.expectEQ(msg.Body, fmt.Sprintf(`syzbot has found a reproducer for the following crash on:
 
-HEAD commit:    222222222222 a really long title, longer than 80 chars, re..
-git tree:       repo2/branch2
+HEAD commit:    10101010 a really long title, longer than 80 chars, really..
+git tree:       repo10alias
 console output: %[4]v
 kernel config:  %[5]v
 dashboard link: https://testapp.appspot.com/bug?extid=%[1]v
-compiler:       compiler2
-syzkaller repro:%[3]v
+compiler:       compiler10
+userspace arch: i386
+syz repro:      %[3]v
 C reproducer:   %[2]v
+CC:             [qux@qux.com maintainers@repo10.org bugs@repo10.org]
 
 IMPORTANT: if you fix the bug, please add the following tag to the commit:
 Reported-by: syzbot+%[1]v@testapp.appspotmail.com
 
 report1
-`, extBugID1, reproCLink, reproSyzLink, crashLogLink, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+`, extBugID1, reproCLink, reproSyzLink, crashLogLink, kernelConfigLink))
 		c.checkURLContents(reproCLink, crash.ReproC)
 		c.checkURLContents(reproSyzLink, syzRepro)
 		c.checkURLContents(crashLogLink, crash.Log)
@@ -313,9 +304,7 @@
 	c.expectOK(c.POST("/_ah/mail/", incoming4))
 
 	{
-		c.expectOK(c.GET("/email_poll"))
-		c.expectEQ(len(c.emailSink), 1)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(msg.To, []string{"<foo@bar.com>"})
 		c.expectEQ(msg.Subject, "Re: title1")
 		c.expectEQ(msg.Headers["In-Reply-To"], []string{"<abcdef>"})
@@ -329,8 +318,7 @@
 
 	// Now mark the bug as fixed.
 	c.incomingEmail(sender1, "#syz fix: some: commit title")
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.expectNoEmail()
 
 	// Check that the commit is now passed to builders.
 	builderPollResp, _ := c.client2.BuilderPoll(build.Manager)
@@ -350,13 +338,9 @@
 	// New crash must produce new bug in the first reporting.
 	c.client2.ReportCrash(crash)
 	{
-		c.expectOK(c.GET("/email_poll"))
-		c.expectEQ(len(c.emailSink), 1)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(msg.Subject, crash.Title+" (2)")
-		if msg.Sender == sender0 {
-			t.Fatalf("same reporting ID for new bug")
-		}
+		c.expectNE(msg.Sender, sender0)
 	}
 }
 
@@ -371,9 +355,7 @@
 	crash := testCrash(build, 1)
 	c.client2.ReportCrash(crash)
 
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
-	sender := (<-c.emailSink).Sender
+	sender := c.pollEmailBug().Sender
 
 	incoming1 := fmt.Sprintf(`Sender: syzkaller@googlegroups.com
 Date: Tue, 15 Aug 2017 14:59:00 -0700
@@ -386,9 +368,6 @@
 #syz upstream
 `, sender)
 	c.expectOK(c.POST("/_ah/mail/", incoming1))
-
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
 }
 
 // Basic dup scenario: mark one bug as dup of another.
@@ -408,30 +387,29 @@
 	c.client2.ReportCrash(crash2)
 
 	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 2)
-	msg1 := <-c.emailSink
-	msg2 := <-c.emailSink
+	msg1 := c.pollEmailBug()
+	msg2 := c.pollEmailBug()
 
 	// Dup crash2 to crash1.
 	c.incomingEmail(msg2.Sender, "#syz dup: BUG: slightly more elaborate title")
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.expectNoEmail()
 
 	// Second crash happens again
 	crash2.ReproC = []byte("int main() {}")
 	c.client2.ReportCrash(crash2)
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.expectNoEmail()
 
 	// Now close the original bug, and check that new bugs for dup are now created.
 	c.incomingEmail(msg1.Sender, "#syz invalid")
 
+	// uncc command must not trugger error reply even for closed bug.
+	c.incomingEmail(msg1.Sender, "#syz uncc", EmailOptCC(nil))
+	c.expectNoEmail()
+
 	// New crash must produce new bug in the first reporting.
 	c.client2.ReportCrash(crash2)
 	{
-		c.expectOK(c.GET("/email_poll"))
-		c.expectEQ(len(c.emailSink), 1)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(msg.Subject, crash2.Title+" (2)")
 	}
 }
@@ -452,23 +430,107 @@
 	c.client2.ReportCrash(crash2)
 
 	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 2)
-	msg1 := <-c.emailSink
-	msg2 := <-c.emailSink
+	msg1 := c.pollEmailBug()
+	msg2 := c.pollEmailBug()
 
 	// Dup crash2 to crash1.
-	c.incomingEmail(msg2.Sender, "#syz dup: BUG: slightly more elaborate title")
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.incomingEmail(msg2.Sender, "#syz dup BUG: slightly more elaborate title")
+	c.expectNoEmail()
 
 	// Undup crash2.
 	c.incomingEmail(msg2.Sender, "#syz undup")
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.expectNoEmail()
 
 	// Now close the original bug, and check that new crashes for the dup does not create bugs.
 	c.incomingEmail(msg1.Sender, "#syz invalid")
 	c.client2.ReportCrash(crash2)
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.expectNoEmail()
+}
+
+func TestEmailCrossReportingDup(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+
+	tests := []struct {
+		bug    int
+		dup    int
+		result bool
+	}{
+		{0, 0, true},
+		{0, 1, false},
+		{0, 2, false},
+		{1, 0, false},
+		{1, 1, true},
+		{1, 2, true},
+		{2, 0, false},
+		{2, 1, false},
+		{2, 2, true},
+	}
+	for i, test := range tests {
+		t.Logf("duping %v->%v, expect %v", test.bug, test.dup, test.result)
+		c.advanceTime(24 * time.Hour) // to not hit email limit per day
+		crash1 := testCrash(build, 1)
+		crash1.Title = fmt.Sprintf("bug_%v", i)
+		c.client2.ReportCrash(crash1)
+		bugSender := c.pollEmailBug().Sender
+		for j := 0; j < test.bug; j++ {
+			c.incomingEmail(bugSender, "#syz upstream")
+			bugSender = c.pollEmailBug().Sender
+		}
+
+		crash2 := testCrash(build, 2)
+		crash2.Title = fmt.Sprintf("dup_%v", i)
+		c.client2.ReportCrash(crash2)
+		dupSender := c.pollEmailBug().Sender
+		for j := 0; j < test.dup; j++ {
+			c.incomingEmail(dupSender, "#syz upstream")
+			dupSender = c.pollEmailBug().Sender
+		}
+
+		c.incomingEmail(bugSender, "#syz dup: "+crash2.Title)
+		if test.result {
+			c.expectNoEmail()
+		} else {
+			msg := c.pollEmailBug()
+			if !strings.Contains(msg.Body, "> #syz dup:") ||
+				!strings.Contains(msg.Body, "Can't dup bug to a bug in different reporting") {
+				c.t.Fatalf("bad reply body:\n%v", msg.Body)
+			}
+		}
+	}
+}
+
+func TestEmailErrors(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	// No reply for email without bug hash and no commands.
+	c.incomingEmail("syzbot@testapp.appspotmail.com", "Investment Proposal")
+	c.expectNoEmail()
+
+	// If email contains a command we need to reply.
+	c.incomingEmail("syzbot@testapp.appspotmail.com", "#syz invalid")
+	reply := c.pollEmailBug()
+	c.expectEQ(reply.To, []string{"<default@sender.com>"})
+	c.expectEQ(reply.Body, `> #syz invalid
+
+I see the command but can't find the corresponding bug.
+Please resend the email to syzbot+HASH@testapp.appspotmail.com address
+that is the sender of the bug report (also present in the Reported-by tag).
+
+`)
+
+	c.incomingEmail("syzbot+123@testapp.appspotmail.com", "#syz invalid")
+	reply = c.pollEmailBug()
+	c.expectEQ(reply.Body, `> #syz invalid
+
+I see the command but can't find the corresponding bug.
+The email is sent to  syzbot+HASH@testapp.appspotmail.com address
+but the HASH does not correspond to any known bug.
+Please double check the address.
+
+`)
 }
diff --git a/dashboard/app/entities.go b/dashboard/app/entities.go
index 56ff8fb..c6d26c4 100644
--- a/dashboard/app/entities.go
+++ b/dashboard/app/entities.go
@@ -12,7 +12,7 @@
 	"github.com/google/syzkaller/dashboard/dashapi"
 	"github.com/google/syzkaller/pkg/hash"
 	"golang.org/x/net/context"
-	"google.golang.org/appengine/datastore"
+	db "google.golang.org/appengine/datastore"
 )
 
 // This file contains definitions of entities stored in datastore.
@@ -25,13 +25,14 @@
 )
 
 type Manager struct {
-	Namespace      string
-	Name           string
-	Link           string
-	CurrentBuild   string
-	FailedBuildBug string
-	LastAlive      time.Time
-	CurrentUpTime  time.Duration
+	Namespace         string
+	Name              string
+	Link              string
+	CurrentBuild      string
+	FailedBuildBug    string
+	FailedSyzBuildBug string
+	LastAlive         time.Time
+	CurrentUpTime     time.Duration
 }
 
 // ManagerStats holds per-day manager runtime stats.
@@ -46,22 +47,23 @@
 }
 
 type Build struct {
-	Namespace         string
-	Manager           string
-	ID                string // unique ID generated by syz-ci
-	Type              BuildType
-	Time              time.Time
-	OS                string
-	Arch              string
-	VMArch            string
-	SyzkallerCommit   string
-	CompilerID        string
-	KernelRepo        string
-	KernelBranch      string
-	KernelCommit      string
-	KernelCommitTitle string    `datastore:",noindex"`
-	KernelCommitDate  time.Time `datastore:",noindex"`
-	KernelConfig      int64     // reference to KernelConfig text entity
+	Namespace           string
+	Manager             string
+	ID                  string // unique ID generated by syz-ci
+	Type                BuildType
+	Time                time.Time
+	OS                  string
+	Arch                string
+	VMArch              string
+	SyzkallerCommit     string
+	SyzkallerCommitDate time.Time
+	CompilerID          string
+	KernelRepo          string
+	KernelBranch        string
+	KernelCommit        string
+	KernelCommitTitle   string    `datastore:",noindex"`
+	KernelCommitDate    time.Time `datastore:",noindex"`
+	KernelConfig        int64     // reference to KernelConfig text entity
 }
 
 type Bug struct {
@@ -73,16 +75,32 @@
 	NumCrashes     int64
 	NumRepro       int64
 	ReproLevel     dashapi.ReproLevel
+	BisectCause    BisectStatus
+	BisectFix      BisectStatus
 	HasReport      bool
+	NeedCommitInfo bool
 	FirstTime      time.Time
 	LastTime       time.Time
 	LastSavedCrash time.Time
 	LastReproTime  time.Time
+	FixTime        time.Time // when we become aware of the fixing commit
+	LastActivity   time.Time // last time we observed any activity related to the bug
 	Closed         time.Time
 	Reporting      []BugReporting
-	Commits        []string
+	Commits        []string // titles of fixing commmits
+	CommitInfo     []Commit // additional info for commits (for historical reasons parallel array to Commits)
 	HappenedOn     []string `datastore:",noindex"` // list of managers
 	PatchedOn      []string `datastore:",noindex"` // list of managers
+	UNCC           []string // don't CC these emails on this bug
+}
+
+type Commit struct {
+	Hash       string
+	Title      string
+	Author     string
+	AuthorName string
+	CC         string `datastore:",noindex"` // (|-delimited list)
+	Date       time.Time
 }
 
 type BugReporting struct {
@@ -90,9 +108,11 @@
 	ID         string // unique ID per BUG/BugReporting used in commucation with external systems
 	ExtID      string // arbitrary reporting ID that is passed back in dashapi.BugReport
 	Link       string
-	CC         string // additional emails added to CC list (|-delimited list)
-	CrashID    int64  // crash that we've last reported in this reporting
-	ReproLevel dashapi.ReproLevel
+	CC         string             // additional emails added to CC list (|-delimited list)
+	CrashID    int64              // crash that we've last reported in this reporting
+	Auto       bool               // was it auto-upstreamed/obsoleted?
+	ReproLevel dashapi.ReproLevel // may be less then bug.ReproLevel if repro arrived but we didn't report it yet
+	OnHold     time.Time          // if set, the bug must not be upstreamed
 	Reported   time.Time
 	Closed     time.Time
 }
@@ -127,14 +147,14 @@
 	Date int // YYYYMMDD
 }
 
-// Job represent a single patch testing job for syz-ci.
-// Later we may want to extend this to other types of jobs (hense the generic name):
+// Job represent a single patch testing or bisection job for syz-ci.
+// Later we may want to extend this to other types of jobs:
 //   - test of a committed fix
 //   - reproduce crash
 //   - test that crash still happens on HEAD
-//   - crash bisect
 // Job has Bug as parent entity.
 type Job struct {
+	Type      JobType
 	Created   time.Time
 	User      string
 	CC        []string
@@ -159,12 +179,22 @@
 	CrashTitle  string // if empty, we did not hit crash during testing
 	CrashLog    int64  // reference to CrashLog text entity
 	CrashReport int64  // reference to CrashReport text entity
+	Commits     []Commit
 	BuildID     string
+	Log         int64 // reference to Log text entity
 	Error       int64 // reference to Error text entity, if set job failed
 
 	Reported bool // have we reported result back to user?
 }
 
+type JobType int
+
+const (
+	JobTestPatch JobType = iota
+	JobBisectCause
+	JobBisectFix
+)
+
 // Text holds text blobs (crash logs, reports, reproducers, etc).
 type Text struct {
 	Namespace string
@@ -178,6 +208,7 @@
 	textReproC       = "ReproC"
 	textKernelConfig = "KernelConfig"
 	textPatch        = "Patch"
+	textLog          = "Log"
 	textError        = "Error"
 )
 
@@ -205,25 +236,50 @@
 	BuildJob
 )
 
+type BisectStatus int
+
+const (
+	BisectNot BisectStatus = iota
+	BisectPending
+	BisectError
+	BisectYes
+)
+
+func mgrKey(c context.Context, ns, name string) *db.Key {
+	return db.NewKey(c, "Manager", fmt.Sprintf("%v-%v", ns, name), 0, nil)
+}
+
+func (mgr *Manager) key(c context.Context) *db.Key {
+	return mgrKey(c, mgr.Namespace, mgr.Name)
+}
+
+func loadManager(c context.Context, ns, name string) (*Manager, error) {
+	mgr := new(Manager)
+	if err := db.Get(c, mgrKey(c, ns, name), mgr); err != nil {
+		if err != db.ErrNoSuchEntity {
+			return nil, fmt.Errorf("failed to get manager %v/%v: %v", ns, name, err)
+		}
+		mgr = &Manager{
+			Namespace: ns,
+			Name:      name,
+		}
+	}
+	return mgr, nil
+}
+
 // updateManager does transactional compare-and-swap on the manager and its current stats.
-func updateManager(c context.Context, ns, name string, fn func(mgr *Manager, stats *ManagerStats)) error {
+func updateManager(c context.Context, ns, name string, fn func(mgr *Manager, stats *ManagerStats) error) error {
 	date := timeDate(timeNow(c))
 	tx := func(c context.Context) error {
-		mgr := new(Manager)
-		mgrKey := datastore.NewKey(c, "Manager", fmt.Sprintf("%v-%v", ns, name), 0, nil)
-		if err := datastore.Get(c, mgrKey, mgr); err != nil {
-			if err != datastore.ErrNoSuchEntity {
-				return fmt.Errorf("failed to get manager %v/%v: %v", ns, name, err)
-			}
-			mgr = &Manager{
-				Namespace: ns,
-				Name:      name,
-			}
+		mgr, err := loadManager(c, ns, name)
+		if err != nil {
+			return err
 		}
+		mgrKey := mgr.key(c)
 		stats := new(ManagerStats)
-		statsKey := datastore.NewKey(c, "ManagerStats", "", int64(date), mgrKey)
-		if err := datastore.Get(c, statsKey, stats); err != nil {
-			if err != datastore.ErrNoSuchEntity {
+		statsKey := db.NewKey(c, "ManagerStats", "", int64(date), mgrKey)
+		if err := db.Get(c, statsKey, stats); err != nil {
+			if err != db.ErrNoSuchEntity {
 				return fmt.Errorf("failed to get stats %v/%v/%v: %v", ns, name, date, err)
 			}
 			stats = &ManagerStats{
@@ -231,29 +287,33 @@
 			}
 		}
 
-		fn(mgr, stats)
+		if err := fn(mgr, stats); err != nil {
+			return err
+		}
 
-		if _, err := datastore.Put(c, mgrKey, mgr); err != nil {
+		if _, err := db.Put(c, mgrKey, mgr); err != nil {
 			return fmt.Errorf("failed to put manager: %v", err)
 		}
-		if _, err := datastore.Put(c, statsKey, stats); err != nil {
+		if _, err := db.Put(c, statsKey, stats); err != nil {
 			return fmt.Errorf("failed to put manager stats: %v", err)
 		}
 		return nil
 	}
-	return datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{Attempts: 10})
+	return db.RunInTransaction(c, tx, &db.TransactionOptions{Attempts: 10})
 }
 
-func loadAllManagers(c context.Context) ([]*Manager, []*datastore.Key, error) {
+func loadAllManagers(c context.Context, ns string) ([]*Manager, []*db.Key, error) {
 	var managers []*Manager
-	keys, err := datastore.NewQuery("Manager").
-		GetAll(c, &managers)
+	query := db.NewQuery("Manager")
+	if ns != "" {
+		query = query.Filter("Namespace=", ns)
+	}
+	keys, err := query.GetAll(c, &managers)
 	if err != nil {
 		return nil, nil, fmt.Errorf("failed to query managers: %v", err)
 	}
 	var result []*Manager
-	var resultKeys []*datastore.Key
-
+	var resultKeys []*db.Key
 	for i, mgr := range managers {
 		if config.Namespaces[mgr.Namespace].Managers[mgr.Name].Decommissioned {
 			continue
@@ -264,18 +324,18 @@
 	return result, resultKeys, nil
 }
 
-func buildKey(c context.Context, ns, id string) *datastore.Key {
+func buildKey(c context.Context, ns, id string) *db.Key {
 	if ns == "" {
 		panic("requesting build key outside of namespace")
 	}
 	h := hash.String([]byte(fmt.Sprintf("%v-%v", ns, id)))
-	return datastore.NewKey(c, "Build", h, 0, nil)
+	return db.NewKey(c, "Build", h, 0, nil)
 }
 
 func loadBuild(c context.Context, ns, id string) (*Build, error) {
 	build := new(Build)
-	if err := datastore.Get(c, buildKey(c, ns, id), build); err != nil {
-		if err == datastore.ErrNoSuchEntity {
+	if err := db.Get(c, buildKey(c, ns, id), build); err != nil {
+		if err == db.ErrNoSuchEntity {
 			return nil, fmt.Errorf("unknown build %v/%v", ns, id)
 		}
 		return nil, fmt.Errorf("failed to get build %v/%v: %v", ns, id, err)
@@ -285,7 +345,7 @@
 
 func lastManagerBuild(c context.Context, ns, manager string) (*Build, error) {
 	var builds []*Build
-	_, err := datastore.NewQuery("Build").
+	_, err := db.NewQuery("Build").
 		Filter("Namespace=", ns).
 		Filter("Manager=", manager).
 		Filter("Type=", BuildNormal).
@@ -333,15 +393,23 @@
 			return bug, nil
 		}
 		canon := new(Bug)
-		bugKey := datastore.NewKey(c, "Bug", bug.DupOf, 0, nil)
-		if err := datastore.Get(c, bugKey, canon); err != nil {
+		bugKey := db.NewKey(c, "Bug", bug.DupOf, 0, nil)
+		if err := db.Get(c, bugKey, canon); err != nil {
 			return nil, fmt.Errorf("failed to get dup bug %q for %q: %v",
-				bug.DupOf, bugKeyHash(bug.Namespace, bug.Title, bug.Seq), err)
+				bug.DupOf, bug.keyHash(), err)
 		}
 		bug = canon
 	}
 }
 
+func (bug *Bug) key(c context.Context) *db.Key {
+	return db.NewKey(c, "Bug", bug.keyHash(), 0, nil)
+}
+
+func (bug *Bug) keyHash() string {
+	return bugKeyHash(bug.Namespace, bug.Title, bug.Seq)
+}
+
 func bugKeyHash(ns, title string, seq int64) string {
 	return hash.String([]byte(fmt.Sprintf("%v-%v-%v-%v", config.Namespaces[ns].Key, ns, title, seq)))
 }
@@ -352,18 +420,51 @@
 	return hash.String([]byte(fmt.Sprintf("%v-%v", bugHash, reporting)))[:hashLen]
 }
 
-func kernelRepoInfo(build *Build) KernelRepo {
-	return kernelRepoInfoRaw(build.KernelRepo, build.KernelBranch)
+func (bug *Bug) updateCommits(commits []string, now time.Time) {
+	bug.Commits = commits
+	bug.CommitInfo = nil
+	bug.NeedCommitInfo = true
+	bug.FixTime = now
+	bug.PatchedOn = nil
 }
 
-func kernelRepoInfoRaw(repo, branch string) KernelRepo {
-	repoID := repo
-	if branch != "" {
-		repoID += "/" + branch
+func (bug *Bug) getCommitInfo(i int) Commit {
+	if i < len(bug.CommitInfo) {
+		return bug.CommitInfo[i]
 	}
-	info := config.KernelRepos[repoID]
+	return Commit{}
+}
+
+func markCrashReported(c context.Context, crashID int64, bugKey *db.Key, now time.Time) error {
+	crash := new(Crash)
+	crashKey := db.NewKey(c, "Crash", "", crashID, bugKey)
+	if err := db.Get(c, crashKey, crash); err != nil {
+		return fmt.Errorf("failed to get reported crash %v: %v", crashID, err)
+	}
+	crash.Reported = now
+	if _, err := db.Put(c, crashKey, crash); err != nil {
+		return fmt.Errorf("failed to put reported crash %v: %v", crashID, err)
+	}
+	return nil
+}
+
+func kernelRepoInfo(build *Build) KernelRepo {
+	return kernelRepoInfoRaw(build.Namespace, build.KernelRepo, build.KernelBranch)
+}
+
+func kernelRepoInfoRaw(ns, url, branch string) KernelRepo {
+	var info KernelRepo
+	for _, repo := range config.Namespaces[ns].Repos {
+		if repo.URL == url && repo.Branch == branch {
+			info = repo
+			break
+		}
+	}
 	if info.Alias == "" {
-		info.Alias = repoID
+		info.Alias = url
+		if branch != "" {
+			info.Alias += " " + branch
+		}
 	}
 	return info
 }
diff --git a/dashboard/app/fix_test.go b/dashboard/app/fix_test.go
index 420d281..448ee73 100644
--- a/dashboard/app/fix_test.go
+++ b/dashboard/app/fix_test.go
@@ -159,9 +159,15 @@
 	builderPollResp, _ := c.client.BuilderPoll(build1.Manager)
 	c.expectEQ(len(builderPollResp.PendingCommits), 0)
 
+	c.advanceTime(time.Hour)
 	rep := c.client.pollBug()
 
+	bug, _, _ := c.loadBug(rep.ID)
+	c.expectEQ(bug.LastActivity, c.mockedTime)
+	c.expectEQ(bug.FixTime, time.Time{})
+
 	// Specify fixing commit for the bug.
+	c.advanceTime(time.Hour)
 	reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
 		ID:         rep.ID,
 		Status:     dashapi.BugStatusOpen,
@@ -169,6 +175,11 @@
 	})
 	c.expectEQ(reply.OK, true)
 
+	bug, _, _ = c.loadBug(rep.ID)
+	c.expectEQ(bug.LastActivity, c.mockedTime)
+	c.expectEQ(bug.FixTime, c.mockedTime)
+
+	c.advanceTime(time.Hour)
 	reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
 		ID:         rep.ID,
 		Status:     dashapi.BugStatusOpen,
@@ -176,6 +187,34 @@
 	})
 	c.expectEQ(reply.OK, true)
 
+	bug, _, _ = c.loadBug(rep.ID)
+	c.expectEQ(bug.LastActivity, c.mockedTime)
+	c.expectEQ(bug.FixTime, c.mockedTime)
+
+	// No updates, just check that LastActivity time is updated, FixTime preserved.
+	fixTime := c.mockedTime
+	c.advanceTime(time.Hour)
+	reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
+		ID:     rep.ID,
+		Status: dashapi.BugStatusOpen,
+	})
+	c.expectEQ(reply.OK, true)
+	bug, _, _ = c.loadBug(rep.ID)
+	c.expectEQ(bug.LastActivity, c.mockedTime)
+	c.expectEQ(bug.FixTime, fixTime)
+
+	// Send the same fixing commit, check that LastActivity time is updated, FixTime preserved.
+	c.advanceTime(time.Hour)
+	reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
+		ID:         rep.ID,
+		Status:     dashapi.BugStatusOpen,
+		FixCommits: []string{"the right one"},
+	})
+	c.expectEQ(reply.OK, true)
+	bug, _, _ = c.loadBug(rep.ID)
+	c.expectEQ(bug.LastActivity, c.mockedTime)
+	c.expectEQ(bug.FixTime, fixTime)
+
 	builderPollResp, _ = c.client.BuilderPoll(build1.Manager)
 	c.expectEQ(len(builderPollResp.PendingCommits), 1)
 	c.expectEQ(builderPollResp.PendingCommits[0], "the right one")
@@ -379,7 +418,10 @@
 	rep := c.client.pollBug()
 
 	// Upload build with 2 fixing commits for this bug.
-	build1.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep.ID}, {"fix commit 2", rep.ID}}
+	build1.FixCommits = []dashapi.Commit{
+		{Title: "fix commit 1", BugIDs: []string{rep.ID}},
+		{Title: "fix commit 2", BugIDs: []string{rep.ID}},
+	}
 	c.client.UploadBuild(build1)
 
 	// Now the commits must be associated with the bug and the second
@@ -433,7 +475,9 @@
 	c.client.updateBug(rep2.ID, dashapi.BugStatusDup, rep1.ID)
 
 	// Upload build that fixes rep2.
-	build.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep2.ID}}
+	build.FixCommits = []dashapi.Commit{
+		{Title: "fix commit 1", BugIDs: []string{rep2.ID}},
+	}
 	c.client.UploadBuild(build)
 
 	// This must fix rep1.
@@ -466,16 +510,11 @@
 	c.client.updateBug(rep2.ID, dashapi.BugStatusDup, rep1.ID)
 
 	// Upload build that fixes rep2.
-	build1.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep2.ID}}
+	build1.FixCommits = []dashapi.Commit{
+		{Title: "fix commit 1", BugIDs: []string{rep2.ID}},
+	}
 	c.client.UploadBuild(build1)
 
-	/*
-		dbBug1, _, _ := c.loadBug(rep1.ID)
-		t.Logf("BUG1: status=%v, commits: %+v, patched: %+v", dbBug1.Status, dbBug1.Commits, dbBug1.PatchedOn)
-		dbBug2, _, _ := c.loadBug(rep2.ID)
-		t.Logf("BUG2: status=%v, commits: %+v, patched: %+v", dbBug2.Status, dbBug2.Commits, dbBug2.PatchedOn)
-	*/
-
 	// Now undup the bugs. They are still unfixed as only 1 manager uploaded the commit.
 	c.client.updateBug(rep2.ID, dashapi.BugStatusOpen, "")
 
@@ -518,7 +557,10 @@
 
 	// Upload builds that fix rep1 and rep2 with different commits.
 	// This must fix rep1 eventually and we must not livelock in such scenario.
-	build1.FixCommits = []dashapi.FixCommit{{"fix commit 1", rep1.ID}, {"fix commit 2", rep2.ID}}
+	build1.FixCommits = []dashapi.Commit{
+		{Title: "fix commit 1", BugIDs: []string{rep1.ID}},
+		{Title: "fix commit 2", BugIDs: []string{rep2.ID}},
+	}
 	build2.FixCommits = build1.FixCommits
 	c.client.UploadBuild(build1)
 	c.client.UploadBuild(build2)
diff --git a/dashboard/app/fixed.html b/dashboard/app/fixed.html
new file mode 100644
index 0000000..4a51458
--- /dev/null
+++ b/dashboard/app/fixed.html
@@ -0,0 +1,19 @@
+{{/*
+Copyright 2019 syzkaller project authors. All rights reserved.
+Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+Fixed bugs page.
+*/}}
+
+<!doctype html>
+<html>
+<head>
+	{{template "head" .Header}}
+	<title>syzbot</title>
+</head>
+<body>
+	{{template "header" .Header}}
+
+	{{template "bug_list" .Bugs}}
+</body>
+</html>
diff --git a/dashboard/app/forbidden.html b/dashboard/app/forbidden.html
deleted file mode 100644
index 79849eb..0000000
--- a/dashboard/app/forbidden.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!doctype html>
-<html>
-<head>
-	{{template "head" .Header}}
-	<title>syzbot</title>
-</head>
-<body>
-	{{if .Header.LoginLink}}
-		<script>window.location.replace("{{.Header.LoginLink}}");</script>
-	{{else}}
-		403 Forbidden
-	{{end}}
-</body>
-</html>
diff --git a/dashboard/app/handler.go b/dashboard/app/handler.go
index 34a1782..bd62d26 100644
--- a/dashboard/app/handler.go
+++ b/dashboard/app/handler.go
@@ -5,12 +5,15 @@
 
 import (
 	"bytes"
+	"encoding/base64"
+	"encoding/json"
 	"fmt"
-	"html/template"
 	"net/http"
+	"sort"
+	"strings"
 	"time"
 
-	"github.com/google/syzkaller/dashboard/dashapi"
+	"github.com/google/syzkaller/pkg/html"
 	"golang.org/x/net/context"
 	"google.golang.org/appengine"
 	"google.golang.org/appengine/log"
@@ -29,19 +32,24 @@
 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		c := appengine.NewContext(r)
 		if err := fn(c, w, r); err != nil {
+			hdr := commonHeaderRaw(c, r)
 			data := &struct {
 				Header *uiHeader
 				Error  string
 			}{
-				Header: commonHeader(c, r),
+				Header: hdr,
 				Error:  err.Error(),
 			}
 			if err == ErrAccess {
-				w.WriteHeader(http.StatusForbidden)
-				err1 := templates.ExecuteTemplate(w, "forbidden.html", data)
-				if err1 != nil {
-					http.Error(w, err.Error(), http.StatusInternalServerError)
+				if hdr.LoginLink != "" {
+					http.Redirect(w, r, hdr.LoginLink, http.StatusTemporaryRedirect)
+					return
 				}
+				http.Error(w, "403 Forbidden", http.StatusForbidden)
+				return
+			}
+			if redir, ok := err.(ErrRedirect); ok {
+				http.Redirect(w, r, redir.Error(), http.StatusFound)
 				return
 			}
 			if _, dontlog := err.(ErrDontLog); !dontlog {
@@ -55,7 +63,10 @@
 	})
 }
 
-type ErrDontLog error
+type (
+	ErrDontLog  error
+	ErrRedirect error
+)
 
 func handleAuth(fn contextHandler) contextHandler {
 	return func(c context.Context, w http.ResponseWriter, r *http.Request) error {
@@ -76,12 +87,32 @@
 }
 
 type uiHeader struct {
+	Admin               bool
 	LoginLink           string
 	AnalyticsTrackingID string
+	Subpage             string
+	Namespace           string
+	Namespaces          []uiNamespace
+	Redirects           []uiRedirect
 }
 
-func commonHeader(c context.Context, r *http.Request) *uiHeader {
+type uiNamespace struct {
+	Name    string
+	Caption string
+}
+
+type uiRedirect struct {
+	From string
+	To   string
+}
+
+type cookieData struct {
+	Namespace string `json:"namespace"`
+}
+
+func commonHeaderRaw(c context.Context, r *http.Request) *uiHeader {
 	h := &uiHeader{
+		Admin:               accessLevel(c, r) == AccessAdmin,
 		AnalyticsTrackingID: config.AnalyticsTrackingID,
 	}
 	if user.Current(c) == nil {
@@ -90,75 +121,111 @@
 	return h
 }
 
-func formatTime(t time.Time) string {
-	if t.IsZero() {
-		return ""
+func commonHeader(c context.Context, r *http.Request, w http.ResponseWriter, ns string) (*uiHeader, error) {
+	accessLevel := accessLevel(c, r)
+	if ns == "" {
+		ns = strings.ToLower(r.URL.Path)
+		if ns != "" && ns[0] == '/' {
+			ns = ns[1:]
+		}
+		if pos := strings.IndexByte(ns, '/'); pos != -1 {
+			ns = ns[:pos]
+		}
 	}
-	return t.Format("2006/01/02 15:04")
+	h := commonHeaderRaw(c, r)
+	const adminPage = "admin"
+	isAdminPage := r.URL.Path == "/"+adminPage
+	isBugPage := r.URL.Path == "/bug"
+	found := false
+	for ns1, cfg := range config.Namespaces {
+		if accessLevel < cfg.AccessLevel {
+			if ns1 == ns {
+				return nil, ErrAccess
+			}
+			continue
+		}
+		if ns1 == ns {
+			found = true
+		}
+		h.Namespaces = append(h.Namespaces, uiNamespace{
+			Name:    ns1,
+			Caption: cfg.DisplayTitle,
+		})
+		// This handles redirects from old URL scheme to new scheme.
+		// This this should be removed at some point (Apr 5, 2019).
+		// Also see handling of "fixed" parameter in handleMain.
+		if isBugPage {
+			continue
+		}
+		h.Redirects = append(h.Redirects, uiRedirect{
+			From: "#" + ns1,
+			To:   "/" + ns1,
+		})
+		fragments := []string{"managers", "open", "pending"}
+		for _, reporting := range cfg.Reporting {
+			if !reporting.moderation || accessLevel < reporting.AccessLevel {
+				continue
+			}
+			fragments = append(fragments, reporting.Name)
+		}
+		for _, frag := range fragments {
+			h.Redirects = append(h.Redirects, uiRedirect{
+				From: "#" + ns1 + "-" + frag,
+				To:   "/" + ns1 + "#" + frag,
+			})
+		}
+	}
+	sort.Slice(h.Namespaces, func(i, j int) bool {
+		return h.Namespaces[i].Caption < h.Namespaces[j].Caption
+	})
+	cookie := decodeCookie(r)
+	if !found {
+		ns = config.DefaultNamespace
+		if cfg := config.Namespaces[cookie.Namespace]; cfg != nil && cfg.AccessLevel <= accessLevel {
+			ns = cookie.Namespace
+		}
+		if accessLevel == AccessAdmin {
+			ns = adminPage
+		}
+		if ns != adminPage || !isAdminPage {
+			return nil, ErrRedirect(fmt.Errorf("/%v", ns))
+		}
+	}
+	if ns != adminPage {
+		h.Namespace = ns
+		cookie.Namespace = ns
+		encodeCookie(w, cookie)
+	}
+	return h, nil
 }
 
-func formatClock(t time.Time) string {
-	if t.IsZero() {
-		return ""
+const cookieName = "syzkaller"
+
+func decodeCookie(r *http.Request) *cookieData {
+	cd := new(cookieData)
+	cookie, err := r.Cookie(cookieName)
+	if err != nil {
+		return cd
 	}
-	return t.Format("15:04")
+	decoded, err := base64.StdEncoding.DecodeString(cookie.Value)
+	if err != nil {
+		return cd
+	}
+	json.Unmarshal(decoded, cd)
+	return cd
 }
 
-func formatDuration(d time.Duration) string {
-	if d == 0 {
-		return ""
+func encodeCookie(w http.ResponseWriter, cd *cookieData) {
+	data, err := json.Marshal(cd)
+	if err != nil {
+		return
 	}
-	days := int(d / (24 * time.Hour))
-	hours := int(d / time.Hour % 24)
-	mins := int(d / time.Minute % 60)
-	if days >= 10 {
-		return fmt.Sprintf("%vd", days)
-	} else if days != 0 {
-		return fmt.Sprintf("%vd%02vh", days, hours)
-	} else if hours != 0 {
-		return fmt.Sprintf("%vh%02vm", hours, mins)
+	cookie := &http.Cookie{
+		Name:    cookieName,
+		Value:   base64.StdEncoding.EncodeToString(data),
+		Expires: time.Now().Add(time.Hour * 24 * 365),
 	}
-	return fmt.Sprintf("%vm", mins)
+	http.SetCookie(w, cookie)
 }
 
-func formatLateness(now, t time.Time) string {
-	if t.IsZero() {
-		return "never"
-	}
-	d := now.Sub(t)
-	if d < 5*time.Minute {
-		return "now"
-	}
-	return formatDuration(d)
-}
-
-func formatReproLevel(l dashapi.ReproLevel) string {
-	switch l {
-	case ReproLevelSyz:
-		return "syz"
-	case ReproLevelC:
-		return "C"
-	default:
-		return ""
-	}
-}
-
-func formatStat(v int64) string {
-	if v == 0 {
-		return ""
-	}
-	return fmt.Sprint(v)
-}
-
-var (
-	templates = template.Must(template.New("").Funcs(templateFuncs).ParseGlob("*.html"))
-
-	templateFuncs = template.FuncMap{
-		"formatTime":       formatTime,
-		"formatClock":      formatClock,
-		"formatDuration":   formatDuration,
-		"formatLateness":   formatLateness,
-		"formatReproLevel": formatReproLevel,
-		"formatStat":       formatStat,
-	}
-)
+var templates = html.CreateGlob("*.html")
diff --git a/dashboard/app/index.yaml b/dashboard/app/index.yaml
index 4adbf15..0ff9327 100644
--- a/dashboard/app/index.yaml
+++ b/dashboard/app/index.yaml
@@ -22,6 +22,19 @@
   - name: Seq
     direction: desc
 
+- kind: Bug
+  properties:
+  - name: Namespace
+  - name: NeedCommitInfo
+  - name: Commits
+
+- kind: Bug
+  properties:
+  - name: BisectCause
+  - name: ReproLevel
+  - name: FirstTime
+    direction: desc
+
 - kind: Build
   properties:
   - name: Namespace
@@ -90,3 +103,10 @@
   properties:
   - name: Reported
   - name: Finished
+
+- kind: Job
+  ancestor: yes
+  properties:
+  - name: Type
+  - name: Finished
+    direction: desc
diff --git a/dashboard/app/jobs.go b/dashboard/app/jobs.go
index bf32534..31ba04f 100644
--- a/dashboard/app/jobs.go
+++ b/dashboard/app/jobs.go
@@ -14,11 +14,12 @@
 	"github.com/google/syzkaller/pkg/email"
 	"github.com/google/syzkaller/pkg/vcs"
 	"golang.org/x/net/context"
-	"google.golang.org/appengine/datastore"
+	"google.golang.org/appengine"
+	db "google.golang.org/appengine/datastore"
 	"google.golang.org/appengine/log"
 )
 
-// handleTestRequest added new job to datastore.
+// handleTestRequest added new job to db.
 // Returns empty string if job added successfully, or reason why it wasn't added.
 func handleTestRequest(c context.Context, bugID, user, extID, link, patch, repo, branch string,
 	jobCC []string) string {
@@ -40,33 +41,33 @@
 		return fmt.Sprintf("can't find the associated bug (do you have %v in To/CC?)", myEmail)
 	}
 	bugReporting, _ := bugReportingByID(bug, bugID)
-	reply, err := addTestJob(c, bug, bugKey, bugReporting, user, extID, link, patch, repo, branch, jobCC)
+	now := timeNow(c)
+	reply, err := addTestJob(c, bug, bugKey, bugReporting, user, extID, link, patch, repo, branch, jobCC, now)
 	if err != nil {
 		log.Errorf(c, "test request failed: %v", err)
 		if reply == "" {
 			reply = internalError
 		}
 	}
-	// Update bug CC list in any case.
-	if !stringsInList(strings.Split(bugReporting.CC, "|"), jobCC) {
-		tx := func(c context.Context) error {
-			bug := new(Bug)
-			if err := datastore.Get(c, bugKey, bug); err != nil {
-				return err
-			}
-			bugReporting = bugReportingByName(bug, bugReporting.Name)
-			bugCC := strings.Split(bugReporting.CC, "|")
-			merged := email.MergeEmailLists(bugCC, jobCC)
-			bugReporting.CC = strings.Join(merged, "|")
-			if _, err := datastore.Put(c, bugKey, bug); err != nil {
-				return fmt.Errorf("failed to put bug: %v", err)
-			}
-			return nil
+	// Update bug CC and last activity time.
+	tx := func(c context.Context) error {
+		bug := new(Bug)
+		if err := db.Get(c, bugKey, bug); err != nil {
+			return err
 		}
-		if err := datastore.RunInTransaction(c, tx, nil); err != nil {
-			// We've already stored the job, so just log the error.
-			log.Errorf(c, "failed to update bug: %v", err)
+		bug.LastActivity = now
+		bugReporting = bugReportingByName(bug, bugReporting.Name)
+		bugCC := strings.Split(bugReporting.CC, "|")
+		merged := email.MergeEmailLists(bugCC, jobCC)
+		bugReporting.CC = strings.Join(merged, "|")
+		if _, err := db.Put(c, bugKey, bug); err != nil {
+			return fmt.Errorf("failed to put bug: %v", err)
 		}
+		return nil
+	}
+	if err := db.RunInTransaction(c, tx, nil); err != nil {
+		// We've already stored the job, so just log the error.
+		log.Errorf(c, "failed to update bug: %v", err)
 	}
 	if link != "" {
 		reply = "" // don't send duplicate error reply
@@ -74,8 +75,8 @@
 	return reply
 }
 
-func addTestJob(c context.Context, bug *Bug, bugKey *datastore.Key, bugReporting *BugReporting,
-	user, extID, link, patch, repo, branch string, jobCC []string) (string, error) {
+func addTestJob(c context.Context, bug *Bug, bugKey *db.Key, bugReporting *BugReporting,
+	user, extID, link, patch, repo, branch string, jobCC []string, now time.Time) (string, error) {
 	crash, crashKey, err := findCrashForBug(c, bug)
 	if err != nil {
 		return "", err
@@ -103,7 +104,8 @@
 	}
 
 	job := &Job{
-		Created:      timeNow(c),
+		Type:         JobTestPatch,
+		Created:      now,
 		User:         user,
 		CC:           jobCC,
 		Reporting:    bugReporting.Name,
@@ -124,7 +126,7 @@
 		// We can get 2 emails for the same request: one direct and one from a mailing list.
 		// Filter out such duplicates (for dup we only need link update).
 		var jobs []*Job
-		keys, err := datastore.NewQuery("Job").
+		keys, err := db.NewQuery("Job").
 			Ancestor(bugKey).
 			Filter("ExtID=", extID).
 			GetAll(c, &jobs)
@@ -139,21 +141,21 @@
 				return nil
 			}
 			existingJob.Link = link
-			if _, err := datastore.Put(c, jobKey, existingJob); err != nil {
+			if _, err := db.Put(c, jobKey, existingJob); err != nil {
 				return fmt.Errorf("failed to put job: %v", err)
 			}
 			return nil
 		}
 		// Create a new job.
-		jobKey := datastore.NewIncompleteKey(c, "Job", bugKey)
-		if _, err := datastore.Put(c, jobKey, job); err != nil {
+		jobKey := db.NewIncompleteKey(c, "Job", bugKey)
+		if _, err := db.Put(c, jobKey, job); err != nil {
 			return fmt.Errorf("failed to put job: %v", err)
 		}
-		return nil
+		return markCrashReported(c, job.CrashID, bugKey, now)
 	}
-	err = datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{XG: true, Attempts: 30})
+	err = db.RunInTransaction(c, tx, &db.TransactionOptions{XG: true, Attempts: 30})
 	if patchID != 0 && deletePatch || err != nil {
-		if err := datastore.Delete(c, datastore.NewKey(c, textPatch, "", patchID, nil)); err != nil {
+		if err := db.Delete(c, db.NewKey(c, textPatch, "", patchID, nil)); err != nil {
 			log.Errorf(c, "failed to delete patch for dup job: %v", err)
 		}
 	}
@@ -172,8 +174,6 @@
 		return fmt.Sprintf("%q does not look like a valid git repo address.", repo)
 	case !vcs.CheckBranch(branch) && !vcs.CheckCommitHash(branch):
 		return fmt.Sprintf("%q does not look like a valid git branch or commit.", branch)
-	case crash.ReproC == 0 && crash.ReproSyz == 0:
-		return "This crash does not have a reproducer. I cannot test it."
 	case bug.Status == BugStatusFixed:
 		return "This bug is already marked as fixed. No point in testing."
 	case bug.Status == BugStatusInvalid:
@@ -186,40 +186,183 @@
 }
 
 // pollPendingJobs returns the next job to execute for the provided list of managers.
-func pollPendingJobs(c context.Context, managers []string) (interface{}, error) {
-retry:
-	job, jobKey, err := loadPendingJob(c, managers)
-	if job == nil || err != nil {
-		return job, err
+func pollPendingJobs(c context.Context, testMgrs, bisectMgrs []string) (*dashapi.JobPollResp, error) {
+	testManagers := make(map[string]bool)
+	for _, mgr := range testMgrs {
+		testManagers[mgr] = true
 	}
-	jobID := extJobID(jobKey)
-	patch, _, err := getText(c, textPatch, job.Patch)
+	bisectManagers := make(map[string]bool)
+	for _, mgr := range bisectMgrs {
+		bisectManagers[mgr] = true
+	}
+retry:
+	job, jobKey, err := getNextJob(c, testManagers, bisectManagers)
+	if job == nil || err != nil {
+		return nil, err
+	}
+	resp, stale, err := createJobResp(c, job, jobKey)
 	if err != nil {
 		return nil, err
 	}
+	if stale {
+		goto retry
+	}
+	return resp, nil
+}
+
+func getNextJob(c context.Context, testManagers, bisectManagers map[string]bool) (*Job, *db.Key, error) {
+	job, jobKey, err := loadPendingJob(c, testManagers, bisectManagers)
+	if job != nil || err != nil {
+		return job, jobKey, err
+	}
+	if len(bisectManagers) == 0 {
+		return nil, nil, nil
+	}
+	// We need both C and syz repros, but the crazy datastore query restrictions
+	// do not allow to use ReproLevel>ReproLevelNone in the query.  So we do 2 separate queries.
+	// C repros tend to be of higher reliability so maybe it's not bad.
+	job, jobKey, err = createBisectJob(c, bisectManagers, ReproLevelC)
+	if job != nil || err != nil {
+		return job, jobKey, err
+	}
+	return createBisectJob(c, bisectManagers, ReproLevelSyz)
+}
+
+func createBisectJob(c context.Context, managers map[string]bool, reproLevel dashapi.ReproLevel) (
+	*Job, *db.Key, error) {
+	var bugs []*Bug
+	// Note: we could also include len(Commits)==0 but datastore does not work this way.
+	// So we would need an additional HasCommits field or something.
+	keys, err := db.NewQuery("Bug").
+		Filter("Status=", BugStatusOpen).
+		Filter("FirstTime>", time.Time{}).
+		Filter("ReproLevel=", reproLevel).
+		Filter("BisectCause=", BisectNot).
+		Order("-FirstTime").
+		Limit(300). // we only need 1 job, but we skip some because the query is not precise
+		GetAll(c, &bugs)
+	if err != nil {
+		return nil, nil, fmt.Errorf("failed to query bugs: %v", err)
+	}
+	for bi, bug := range bugs {
+		if !shouldBisectBug(bug, managers) {
+			continue
+		}
+		crash, crashKey, err := bisectCrashForBug(c, keys[bi], managers)
+		if err != nil {
+			return nil, nil, err
+		}
+		if crash == nil {
+			continue
+		}
+		return createBisectJobForBug(c, bug, crash, keys[bi], crashKey)
+	}
+	return nil, nil, nil
+}
+
+func shouldBisectBug(bug *Bug, managers map[string]bool) bool {
+	if len(bug.Commits) != 0 {
+		return false
+	}
+	for _, mgr := range bug.HappenedOn {
+		if managers[mgr] {
+			return true
+		}
+	}
+	return false
+}
+
+func bisectCrashForBug(c context.Context, bugKey *db.Key, managers map[string]bool) (
+	*Crash, *db.Key, error) {
+	crashes, crashKeys, err := queryCrashesForBug(c, bugKey, maxCrashes)
+	if err != nil {
+		return nil, nil, err
+	}
+	for ci, crash := range crashes {
+		if crash.ReproSyz == 0 || !managers[crash.Manager] {
+			continue
+		}
+		return crash, crashKeys[ci], nil
+	}
+	return nil, nil, nil
+}
+
+func createBisectJobForBug(c context.Context, bug0 *Bug, crash *Crash, bugKey, crashKey *db.Key) (
+	*Job, *db.Key, error) {
+	build, err := loadBuild(c, bug0.Namespace, crash.BuildID)
+	if err != nil {
+		return nil, nil, err
+	}
+	now := timeNow(c)
+	job := &Job{
+		Type:         JobBisectCause,
+		Created:      now,
+		Namespace:    bug0.Namespace,
+		Manager:      crash.Manager,
+		KernelRepo:   build.KernelRepo,
+		KernelBranch: build.KernelBranch,
+		BugTitle:     bug0.displayTitle(),
+		CrashID:      crashKey.IntID(),
+	}
+	var jobKey *db.Key
+	tx := func(c context.Context) error {
+		jobKey = nil
+		bug := new(Bug)
+		if err := db.Get(c, bugKey, bug); err != nil {
+			return fmt.Errorf("failed to get bug %v: %v", bugKey.StringID(), err)
+		}
+		if bug.BisectCause != BisectNot {
+			// Race, we could do a more complex retry, but we just rely on the next poll.
+			job = nil
+			return nil
+		}
+		bug.BisectCause = BisectPending
+		// Create a new job.
+		var err error
+		jobKey = db.NewIncompleteKey(c, "Job", bugKey)
+		if jobKey, err = db.Put(c, jobKey, job); err != nil {
+			return fmt.Errorf("failed to put job: %v", err)
+		}
+		if _, err := db.Put(c, bugKey, bug); err != nil {
+			return fmt.Errorf("failed to put bug: %v", err)
+		}
+		return markCrashReported(c, job.CrashID, bugKey, now)
+	}
+	if err := db.RunInTransaction(c, tx, nil); err != nil {
+		return nil, nil, fmt.Errorf("create bisect job tx failed: %v", err)
+	}
+	return job, jobKey, nil
+}
+
+func createJobResp(c context.Context, job *Job, jobKey *db.Key) (*dashapi.JobPollResp, bool, error) {
+	jobID := extJobID(jobKey)
+	patch, _, err := getText(c, textPatch, job.Patch)
+	if err != nil {
+		return nil, false, err
+	}
 	bugKey := jobKey.Parent()
-	crashKey := datastore.NewKey(c, "Crash", "", job.CrashID, bugKey)
+	crashKey := db.NewKey(c, "Crash", "", job.CrashID, bugKey)
 	crash := new(Crash)
-	if err := datastore.Get(c, crashKey, crash); err != nil {
-		return nil, fmt.Errorf("job %v: failed to get crash: %v", jobID, err)
+	if err := db.Get(c, crashKey, crash); err != nil {
+		return nil, false, fmt.Errorf("job %v: failed to get crash: %v", jobID, err)
 	}
 
 	build, err := loadBuild(c, job.Namespace, crash.BuildID)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 	kernelConfig, _, err := getText(c, textKernelConfig, build.KernelConfig)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 
 	reproC, _, err := getText(c, textReproC, crash.ReproC)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 	reproSyz, _, err := getText(c, textReproSyz, crash.ReproSyz)
 	if err != nil {
-		return nil, err
+		return nil, false, err
 	}
 
 	now := timeNow(c)
@@ -227,40 +370,53 @@
 	tx := func(c context.Context) error {
 		stale = false
 		job = new(Job)
-		if err := datastore.Get(c, jobKey, job); err != nil {
+		if err := db.Get(c, jobKey, job); err != nil {
 			return fmt.Errorf("job %v: failed to get in tx: %v", jobID, err)
 		}
 		if !job.Finished.IsZero() {
-			// This happens sometimes due to inconsistent datastore.
+			// This happens sometimes due to inconsistent db.
 			stale = true
 			return nil
 		}
 		job.Attempts++
 		job.Started = now
-		if _, err := datastore.Put(c, jobKey, job); err != nil {
+		if _, err := db.Put(c, jobKey, job); err != nil {
 			return fmt.Errorf("job %v: failed to put: %v", jobID, err)
 		}
 		return nil
 	}
-	if err := datastore.RunInTransaction(c, tx, nil); err != nil {
-		return nil, err
+	if err := db.RunInTransaction(c, tx, nil); err != nil {
+		return nil, false, err
 	}
 	if stale {
-		goto retry
+		return nil, true, nil
 	}
 	resp := &dashapi.JobPollResp{
-		ID:              jobID,
-		Manager:         job.Manager,
-		KernelRepo:      job.KernelRepo,
-		KernelBranch:    job.KernelBranch,
-		KernelConfig:    kernelConfig,
-		SyzkallerCommit: build.SyzkallerCommit,
-		Patch:           patch,
-		ReproOpts:       crash.ReproOpts,
-		ReproSyz:        reproSyz,
-		ReproC:          reproC,
+		ID:                jobID,
+		Manager:           job.Manager,
+		KernelRepo:        job.KernelRepo,
+		KernelBranch:      job.KernelBranch,
+		KernelCommit:      build.KernelCommit,
+		KernelCommitTitle: build.KernelCommitTitle,
+		KernelCommitDate:  build.KernelCommitDate,
+		KernelConfig:      kernelConfig,
+		SyzkallerCommit:   build.SyzkallerCommit,
+		Patch:             patch,
+		ReproOpts:         crash.ReproOpts,
+		ReproSyz:          reproSyz,
+		ReproC:            reproC,
 	}
-	return resp, nil
+	switch job.Type {
+	case JobTestPatch:
+		resp.Type = dashapi.JobTestPatch
+	case JobBisectCause:
+		resp.Type = dashapi.JobBisectCause
+	case JobBisectFix:
+		resp.Type = dashapi.JobBisectFix
+	default:
+		return nil, false, fmt.Errorf("bad job type %v", job.Type)
+	}
+	return resp, false, nil
 }
 
 // doneJob is called by syz-ci to mark completion of a job.
@@ -273,17 +429,22 @@
 	now := timeNow(c)
 	tx := func(c context.Context) error {
 		job := new(Job)
-		if err := datastore.Get(c, jobKey, job); err != nil {
+		if err := db.Get(c, jobKey, job); err != nil {
 			return fmt.Errorf("job %v: failed to get job: %v", jobID, err)
 		}
 		if !job.Finished.IsZero() {
 			return fmt.Errorf("job %v: already finished", jobID)
 		}
 		ns := job.Namespace
-		if isNewBuild, err := uploadBuild(c, now, ns, &req.Build, BuildJob); err != nil {
+		if req.Build.ID != "" {
+			if _, isNewBuild, err := uploadBuild(c, now, ns, &req.Build, BuildJob); err != nil {
+				return err
+			} else if !isNewBuild {
+				log.Errorf(c, "job %v: duplicate build %v", jobID, req.Build.ID)
+			}
+		}
+		if job.Log, err = putText(c, ns, textLog, req.Log, false); err != nil {
 			return err
-		} else if !isNewBuild {
-			log.Errorf(c, "job %v: duplicate build %v", jobID, req.Build.ID)
 		}
 		if job.Error, err = putText(c, ns, textError, req.Error, false); err != nil {
 			return err
@@ -294,20 +455,64 @@
 		if job.CrashReport, err = putText(c, ns, textCrashReport, req.CrashReport, false); err != nil {
 			return err
 		}
+		for _, com := range req.Commits {
+			job.Commits = append(job.Commits, Commit{
+				Hash:       com.Hash,
+				Title:      com.Title,
+				Author:     com.Author,
+				AuthorName: com.AuthorName,
+				CC:         strings.Join(sanitizeCC(c, com.CC), "|"),
+				Date:       com.Date,
+			})
+		}
+		if job.Type == JobBisectCause || job.Type == JobBisectFix {
+			// Update bug.BisectCause/Fix status and also remember current bug reporting to send results.
+			bug := new(Bug)
+			bugKey := jobKey.Parent()
+			if err := db.Get(c, bugKey, bug); err != nil {
+				return fmt.Errorf("job %v: failed to get bug: %v", jobID, err)
+			}
+			result := BisectYes
+			if len(req.Error) != 0 {
+				result = BisectError
+			}
+			if job.Type == JobBisectCause {
+				bug.BisectCause = result
+			} else {
+				bug.BisectFix = result
+			}
+			if _, err := db.Put(c, bugKey, bug); err != nil {
+				return fmt.Errorf("failed to put bug: %v", err)
+			}
+			_, bugReporting, _, _, _ := currentReporting(c, bug)
+			if bugReporting == nil || bugReporting.Reported.IsZero() {
+				// The bug is either already closed or not yet reported in the current reporting,
+				// either way we don't need to report it. If it wasn't reported, it will be reported
+				// with the bisection results.
+				job.Reported = true
+			} else {
+				job.Reporting = bugReporting.Name
+			}
+		}
+		if job.Error != 0 && job.Type != JobTestPatch {
+			// Don't report errors for non-user-initiated jobs.
+			job.Reported = true
+		}
 		job.BuildID = req.Build.ID
 		job.CrashTitle = req.CrashTitle
 		job.Finished = now
-		if _, err := datastore.Put(c, jobKey, job); err != nil {
+		if _, err := db.Put(c, jobKey, job); err != nil {
 			return fmt.Errorf("failed to put job: %v", err)
 		}
+		log.Infof(c, "DONE JOB %v: reported=%v reporting=%v", jobID, job.Reported, job.Reporting)
 		return nil
 	}
-	return datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{XG: true, Attempts: 30})
+	return db.RunInTransaction(c, tx, &db.TransactionOptions{XG: true, Attempts: 30})
 }
 
 func pollCompletedJobs(c context.Context, typ string) ([]*dashapi.BugReport, error) {
 	var jobs []*Job
-	keys, err := datastore.NewQuery("Job").
+	keys, err := db.NewQuery("Job").
 		Filter("Finished>", time.Time{}).
 		Filter("Reported=", false).
 		GetAll(c, &jobs)
@@ -316,10 +521,19 @@
 	}
 	var reports []*dashapi.BugReport
 	for i, job := range jobs {
+		if job.Reporting == "" {
+			log.Criticalf(c, "no reporting for job %v", extJobID(keys[i]))
+			continue
+		}
 		reporting := config.Namespaces[job.Namespace].ReportingByName(job.Reporting)
 		if reporting.Config.Type() != typ {
 			continue
 		}
+		// TODO: this is temporal for gradual bisection rollout.
+		// Notify only about successful bisection for now.
+		if !appengine.IsDevAppServer() && job.Type != JobTestPatch && len(job.Commits) != 1 {
+			continue
+		}
 		rep, err := createBugReportForJob(c, job, keys[i], reporting.Config)
 		if err != nil {
 			log.Errorf(c, "failed to create report for job: %v", err)
@@ -330,7 +544,7 @@
 	return reports, nil
 }
 
-func createBugReportForJob(c context.Context, job *Job, jobKey *datastore.Key, config interface{}) (
+func createBugReportForJob(c context.Context, job *Job, jobKey *db.Key, config interface{}) (
 	*dashapi.BugReport, error) {
 	reportingConfig, err := json.Marshal(config)
 	if err != nil {
@@ -354,59 +568,102 @@
 	if err != nil {
 		return nil, err
 	}
-	patch, _, err := getText(c, textPatch, job.Patch)
-	if err != nil {
-		return nil, err
-	}
 	build, err := loadBuild(c, job.Namespace, job.BuildID)
 	if err != nil {
 		return nil, err
 	}
-	kernelConfig, _, err := getText(c, textKernelConfig, build.KernelConfig)
-	if err != nil {
-		return nil, err
+	bugKey := jobKey.Parent()
+	crashKey := db.NewKey(c, "Crash", "", job.CrashID, bugKey)
+	crash := new(Crash)
+	if err := db.Get(c, crashKey, crash); err != nil {
+		return nil, fmt.Errorf("failed to get crash: %v", err)
 	}
 	bug := new(Bug)
-	if err := datastore.Get(c, jobKey.Parent(), bug); err != nil {
+	if err := db.Get(c, bugKey, bug); err != nil {
 		return nil, fmt.Errorf("failed to load job parent bug: %v", err)
 	}
 	bugReporting := bugReportingByName(bug, job.Reporting)
 	if bugReporting == nil {
 		return nil, fmt.Errorf("job bug has no reporting %q", job.Reporting)
 	}
+	var typ dashapi.ReportType
+	switch job.Type {
+	case JobTestPatch:
+		typ = dashapi.ReportTestPatch
+	case JobBisectCause:
+		typ = dashapi.ReportBisectCause
+	case JobBisectFix:
+		typ = dashapi.ReportBisectFix
+	default:
+		return nil, fmt.Errorf("unknown job type %v", job.Type)
+	}
 	rep := &dashapi.BugReport{
-		Namespace:         job.Namespace,
-		Config:            reportingConfig,
-		ID:                bugReporting.ID,
-		JobID:             extJobID(jobKey),
-		ExtID:             job.ExtID,
-		Title:             bug.displayTitle(),
-		CC:                job.CC,
-		Log:               crashLog,
-		LogLink:           externalLink(c, textCrashLog, job.CrashLog),
-		Report:            report,
-		ReportLink:        externalLink(c, textCrashReport, job.CrashReport),
-		OS:                build.OS,
-		Arch:              build.Arch,
-		VMArch:            build.VMArch,
-		CompilerID:        build.CompilerID,
-		KernelRepo:        build.KernelRepo,
-		KernelRepoAlias:   kernelRepoInfo(build).Alias,
-		KernelBranch:      build.KernelBranch,
-		KernelCommit:      build.KernelCommit,
-		KernelCommitTitle: build.KernelCommitTitle,
-		KernelCommitDate:  build.KernelCommitDate,
-		KernelConfig:      kernelConfig,
-		KernelConfigLink:  externalLink(c, textKernelConfig, build.KernelConfig),
-		CrashTitle:        job.CrashTitle,
-		Error:             jobError,
-		ErrorLink:         externalLink(c, textError, job.Error),
-		Patch:             patch,
-		PatchLink:         externalLink(c, textPatch, job.Patch),
+		Type:         typ,
+		Config:       reportingConfig,
+		JobID:        extJobID(jobKey),
+		ExtID:        job.ExtID,
+		CC:           job.CC,
+		Log:          crashLog,
+		LogLink:      externalLink(c, textCrashLog, job.CrashLog),
+		Report:       report,
+		ReportLink:   externalLink(c, textCrashReport, job.CrashReport),
+		ReproCLink:   externalLink(c, textReproC, crash.ReproC),
+		ReproSyzLink: externalLink(c, textReproSyz, crash.ReproSyz),
+		CrashTitle:   job.CrashTitle,
+		Error:        jobError,
+		ErrorLink:    externalLink(c, textError, job.Error),
+		PatchLink:    externalLink(c, textPatch, job.Patch),
+	}
+	if job.Type == JobBisectCause || job.Type == JobBisectFix {
+		kernelRepo := kernelRepoInfo(build)
+		rep.Maintainers = append(crash.Maintainers, kernelRepo.CC...)
+		rep.ExtID = bugReporting.ExtID
+		if bugReporting.CC != "" {
+			rep.CC = strings.Split(bugReporting.CC, "|")
+		}
+		switch job.Type {
+		case JobBisectCause:
+			rep.BisectCause = bisectFromJob(c, rep, job)
+		case JobBisectFix:
+			rep.BisectFix = bisectFromJob(c, rep, job)
+		}
+	}
+	// Build error output and failing VM boot log can be way too long to inline.
+	if len(rep.Error) > maxInlineError {
+		rep.Error = rep.Error[len(rep.Error)-maxInlineError:]
+		rep.ErrorTruncated = true
+	}
+	if err := fillBugReport(c, rep, bug, bugReporting, build); err != nil {
+		return nil, err
 	}
 	return rep, nil
 }
 
+func bisectFromJob(c context.Context, rep *dashapi.BugReport, job *Job) *dashapi.BisectResult {
+	bisect := &dashapi.BisectResult{
+		LogLink:         externalLink(c, textLog, job.Log),
+		CrashLogLink:    externalLink(c, textCrashLog, job.CrashLog),
+		CrashReportLink: externalLink(c, textCrashReport, job.CrashReport),
+	}
+	for _, com := range job.Commits {
+		bisect.Commits = append(bisect.Commits, &dashapi.Commit{
+			Hash:       com.Hash,
+			Title:      com.Title,
+			Author:     com.Author,
+			AuthorName: com.AuthorName,
+			Date:       com.Date,
+		})
+	}
+	if len(bisect.Commits) == 1 {
+		bisect.Commit = bisect.Commits[0]
+		bisect.Commits = nil
+		com := job.Commits[0]
+		rep.Maintainers = append(rep.Maintainers, com.Author)
+		rep.Maintainers = append(rep.Maintainers, strings.Split(com.CC, "|")...)
+	}
+	return bisect
+}
+
 func jobReported(c context.Context, jobID string) error {
 	jobKey, err := jobID2Key(c, jobID)
 	if err != nil {
@@ -414,21 +671,21 @@
 	}
 	tx := func(c context.Context) error {
 		job := new(Job)
-		if err := datastore.Get(c, jobKey, job); err != nil {
+		if err := db.Get(c, jobKey, job); err != nil {
 			return fmt.Errorf("job %v: failed to get job: %v", jobID, err)
 		}
 		job.Reported = true
-		if _, err := datastore.Put(c, jobKey, job); err != nil {
+		if _, err := db.Put(c, jobKey, job); err != nil {
 			return fmt.Errorf("failed to put job: %v", err)
 		}
 		return nil
 	}
-	return datastore.RunInTransaction(c, tx, nil)
+	return db.RunInTransaction(c, tx, nil)
 }
 
-func loadPendingJob(c context.Context, managers []string) (*Job, *datastore.Key, error) {
+func loadPendingJob(c context.Context, testManagers, bisectManagers map[string]bool) (*Job, *db.Key, error) {
 	var jobs []*Job
-	keys, err := datastore.NewQuery("Job").
+	keys, err := db.NewQuery("Job").
 		Filter("Finished=", time.Time{}).
 		Order("Attempts").
 		Order("Created").
@@ -436,24 +693,37 @@
 	if err != nil {
 		return nil, nil, fmt.Errorf("failed to query jobs: %v", err)
 	}
-	mgrs := make(map[string]bool)
-	for _, mgr := range managers {
-		mgrs[mgr] = true
-	}
 	for i, job := range jobs {
-		if !mgrs[job.Manager] {
-			continue
+		switch job.Type {
+		case JobTestPatch:
+			if !testManagers[job.Manager] {
+				continue
+			}
+		case JobBisectCause, JobBisectFix:
+			if !bisectManagers[job.Manager] {
+				continue
+			}
+			// Don't retry bisection jobs too often.
+			// This allows to have several syz-ci's doing bisection
+			// and protects from bisection job crashing syz-ci.
+			const bisectRepeat = 3 * 24 * time.Hour
+			if timeSince(c, job.Created) < bisectRepeat ||
+				timeSince(c, job.Started) < bisectRepeat {
+				continue
+			}
+		default:
+			return nil, nil, fmt.Errorf("bad job type %v", job.Type)
 		}
 		return job, keys[i], nil
 	}
 	return nil, nil, nil
 }
 
-func extJobID(jobKey *datastore.Key) string {
+func extJobID(jobKey *db.Key) string {
 	return fmt.Sprintf("%v|%v", jobKey.Parent().StringID(), jobKey.IntID())
 }
 
-func jobID2Key(c context.Context, id string) (*datastore.Key, error) {
+func jobID2Key(c context.Context, id string) (*db.Key, error) {
 	keyStr := strings.Split(id, "|")
 	if len(keyStr) != 2 {
 		return nil, fmt.Errorf("bad job id %q", id)
@@ -462,7 +732,7 @@
 	if err != nil {
 		return nil, fmt.Errorf("bad job id %q", id)
 	}
-	bugKey := datastore.NewKey(c, "Bug", keyStr[0], 0, nil)
-	jobKey := datastore.NewKey(c, "Job", "", jobKeyID, bugKey)
+	bugKey := db.NewKey(c, "Bug", keyStr[0], 0, nil)
+	jobKey := db.NewKey(c, "Job", "", jobKeyID, bugKey)
 	return jobKey, nil
 }
diff --git a/dashboard/app/jobs_test.go b/dashboard/app/jobs_test.go
index 797b4ea..b6614d3 100644
--- a/dashboard/app/jobs_test.go
+++ b/dashboard/app/jobs_test.go
@@ -33,75 +33,68 @@
 	crash.Maintainers = []string{"maintainer@kernel.org"}
 	c.client2.ReportCrash(crash)
 
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
-	sender := (<-c.emailSink).Sender
+	sender := c.pollEmailBug().Sender
 	c.incomingEmail(sender, "#syz upstream\n")
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
-	sender = (<-c.emailSink).Sender
+	sender = c.pollEmailBug().Sender
 	_, extBugID, err := email.RemoveAddrContext(sender)
-	if err != nil {
-		t.Fatal(err)
-	}
+	c.expectOK(err)
 	mailingList := config.Namespaces["test2"].Reporting[1].Config.(*EmailConfig).Email
 	c.incomingEmail(sender, "bla-bla-bla", EmailOptFrom("maintainer@kernel.org"),
 		EmailOptCC([]string{mailingList, "kernel@mailing.list"}))
 
 	c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch,
 		EmailOptFrom("test@requester.com"), EmailOptCC([]string{mailingList}))
-	c.expectEQ(len(c.emailSink), 1)
-	c.expectEQ(strings.Contains((<-c.emailSink).Body, "This crash does not have a reproducer"), true)
+	body := c.pollEmailBug().Body
+	c.expectEQ(strings.Contains(body, "This crash does not have a reproducer"), true)
 
 	// Report crash with repro.
 	crash.ReproOpts = []byte("repro opts")
 	crash.ReproSyz = []byte("repro syz")
 	crash.ReproC = []byte("repro C")
 	c.client2.ReportCrash(crash)
+	c.client2.pollAndFailBisectJob(build.Manager)
 
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
-	c.expectEQ(strings.Contains((<-c.emailSink).Body, "syzbot has found a reproducer"), true)
+	body = c.pollEmailBug().Body
+	c.expectEQ(strings.Contains(body, "syzbot has found a reproducer"), true)
 
 	c.incomingEmail(sender, "#syz test: repo",
 		EmailOptFrom("test@requester.com"), EmailOptCC([]string{mailingList}))
-	c.expectEQ(len(c.emailSink), 1)
-	c.expectEQ(strings.Contains((<-c.emailSink).Body, "want 2 args"), true)
+	body = c.pollEmailBug().Body
+	c.expectEQ(strings.Contains(body, "want 2 args"), true)
 
 	c.incomingEmail(sender, "#syz test: repo branch commit",
 		EmailOptFrom("test@requester.com"), EmailOptCC([]string{mailingList}))
-	c.expectEQ(len(c.emailSink), 1)
-	c.expectEQ(strings.Contains((<-c.emailSink).Body, "want 2 args"), true)
+	body = c.pollEmailBug().Body
+	c.expectEQ(strings.Contains(body, "want 2 args"), true)
 
 	c.incomingEmail(sender, "#syz test: repo branch",
 		EmailOptFrom("test@requester.com"), EmailOptCC([]string{mailingList}))
-	c.expectEQ(len(c.emailSink), 1)
-	c.expectEQ(strings.Contains((<-c.emailSink).Body, "does not look like a valid git repo"), true)
+	body = c.pollEmailBug().Body
+	c.expectEQ(strings.Contains(body, "does not look like a valid git repo"), true)
 
 	c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch,
 		EmailOptFrom("\"foo\" <blAcklisteD@dOmain.COM>"))
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
-	pollResp, _ := c.client2.JobPoll([]string{build.Manager})
+	c.expectNoEmail()
+	pollResp := c.client2.pollJobs(build.Manager)
 	c.expectEQ(pollResp.ID, "")
 
+	// This submits actual test request.
 	c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch,
 		EmailOptMessageID(1), EmailOptFrom("test@requester.com"),
 		EmailOptCC([]string{"somebody@else.com"}))
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.expectNoEmail()
 
 	// A dup of the same request with the same Message-ID.
 	c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch,
 		EmailOptMessageID(1), EmailOptFrom("test@requester.com"),
 		EmailOptCC([]string{"somebody@else.com"}))
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 0)
+	c.expectNoEmail()
 
-	pollResp, _ = c.client2.JobPoll([]string{"foobar"})
+	pollResp = c.client2.pollJobs("foobar")
 	c.expectEQ(pollResp.ID, "")
-	pollResp, _ = c.client2.JobPoll([]string{build.Manager})
-	c.expectEQ(pollResp.ID != "", true)
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectNE(pollResp.ID, "")
+	c.expectEQ(pollResp.Type, dashapi.JobTestPatch)
 	c.expectEQ(pollResp.Manager, build.Manager)
 	c.expectEQ(pollResp.KernelRepo, "git://git.git/git.git")
 	c.expectEQ(pollResp.KernelBranch, "kernel-branch")
@@ -112,7 +105,7 @@
 	c.expectEQ(pollResp.ReproSyz, []byte("repro syz"))
 	c.expectEQ(pollResp.ReproC, []byte("repro C"))
 
-	pollResp2, _ := c.client2.JobPoll([]string{build.Manager})
+	pollResp2 := c.client2.pollJobs(build.Manager)
 	c.expectEQ(pollResp2, pollResp)
 
 	jobDoneReq := &dashapi.JobDoneReq{
@@ -124,19 +117,17 @@
 	}
 	c.client2.JobDone(jobDoneReq)
 
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
 	{
-		dbJob, dbBuild := c.loadJob(pollResp.ID)
+		dbJob, dbBuild, _ := c.loadJob(pollResp.ID)
 		patchLink := externalLink(c.ctx, textPatch, dbJob.Patch)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
 		logLink := externalLink(c.ctx, textCrashLog, dbJob.CrashLog)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		to := email.MergeEmailLists([]string{"test@requester.com", "somebody@else.com", mailingList})
 		c.expectEQ(msg.To, to)
 		c.expectEQ(msg.Subject, "Re: "+crash.Title)
 		c.expectEQ(len(msg.Attachments), 0)
-		body := fmt.Sprintf(`Hello,
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
 
 syzbot has tested the proposed patch but the reproducer still triggered crash:
 test crash title
@@ -145,17 +136,14 @@
 
 Tested on:
 
-commit:         111111111111 kernel_commit_title1
-git tree:       repo1/branch1
+commit:         11111111 kernel_commit_title1
+git tree:       repo1 branch1
 console output: %[3]v
 kernel config:  %[2]v
 compiler:       compiler1
 patch:          %[1]v
 
-`, patchLink, kernelConfigLink, logLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+`, patchLink, kernelConfigLink, logLink))
 		c.checkURLContents(patchLink, []byte(patch))
 		c.checkURLContents(kernelConfigLink, build.KernelConfig)
 		c.checkURLContents(logLink, jobDoneReq.CrashLog)
@@ -163,22 +151,21 @@
 
 	// Testing fails with an error.
 	c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch, EmailOptMessageID(2))
-	pollResp, _ = c.client2.JobPoll([]string{build.Manager})
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectEQ(pollResp.Type, dashapi.JobTestPatch)
 	jobDoneReq = &dashapi.JobDoneReq{
 		ID:    pollResp.ID,
 		Build: *build,
 		Error: []byte("failed to apply patch"),
 	}
 	c.client2.JobDone(jobDoneReq)
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
 	{
-		dbJob, dbBuild := c.loadJob(pollResp.ID)
+		dbJob, dbBuild, _ := c.loadJob(pollResp.ID)
 		patchLink := externalLink(c.ctx, textPatch, dbJob.Patch)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(len(msg.Attachments), 0)
-		body := fmt.Sprintf(`Hello,
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
 
 syzbot tried to test the proposed patch but build/boot failed:
 
@@ -187,40 +174,36 @@
 
 Tested on:
 
-commit:         111111111111 kernel_commit_title1
-git tree:       repo1/branch1
+commit:         11111111 kernel_commit_title1
+git tree:       repo1 branch1
 kernel config:  %[2]v
 compiler:       compiler1
 patch:          %[1]v
 
-`, patchLink, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+`, patchLink, kernelConfigLink))
 		c.checkURLContents(patchLink, []byte(patch))
 		c.checkURLContents(kernelConfigLink, build.KernelConfig)
 	}
 
 	// Testing fails with a huge error that can't be inlined in email.
 	c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch, EmailOptMessageID(3))
-	pollResp, _ = c.client2.JobPoll([]string{build.Manager})
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectEQ(pollResp.Type, dashapi.JobTestPatch)
 	jobDoneReq = &dashapi.JobDoneReq{
 		ID:    pollResp.ID,
 		Build: *build,
 		Error: bytes.Repeat([]byte{'a', 'b', 'c'}, (maxInlineError+100)/3),
 	}
 	c.client2.JobDone(jobDoneReq)
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
 	{
-		dbJob, dbBuild := c.loadJob(pollResp.ID)
+		dbJob, dbBuild, _ := c.loadJob(pollResp.ID)
 		patchLink := externalLink(c.ctx, textPatch, dbJob.Patch)
 		errorLink := externalLink(c.ctx, textError, dbJob.Error)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(len(msg.Attachments), 0)
 		truncatedError := string(jobDoneReq.Error[len(jobDoneReq.Error)-maxInlineError:])
-		body := fmt.Sprintf(`Hello,
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
 
 syzbot tried to test the proposed patch but build/boot failed:
 
@@ -232,37 +215,33 @@
 
 Tested on:
 
-commit:         111111111111 kernel_commit_title1
-git tree:       repo1/branch1
+commit:         11111111 kernel_commit_title1
+git tree:       repo1 branch1
 kernel config:  %[4]v
 compiler:       compiler1
 patch:          %[3]v
 
-`, truncatedError, errorLink, patchLink, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+`, truncatedError, errorLink, patchLink, kernelConfigLink))
 		c.checkURLContents(patchLink, []byte(patch))
 		c.checkURLContents(errorLink, jobDoneReq.Error)
 		c.checkURLContents(kernelConfigLink, build.KernelConfig)
 	}
 
 	c.incomingEmail(sender, "#syz test: git://git.git/git.git kernel-branch\n"+patch, EmailOptMessageID(4))
-	pollResp, _ = c.client2.JobPoll([]string{build.Manager})
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectEQ(pollResp.Type, dashapi.JobTestPatch)
 	jobDoneReq = &dashapi.JobDoneReq{
 		ID:    pollResp.ID,
 		Build: *build,
 	}
 	c.client2.JobDone(jobDoneReq)
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
 	{
-		dbJob, dbBuild := c.loadJob(pollResp.ID)
+		dbJob, dbBuild, _ := c.loadJob(pollResp.ID)
 		patchLink := externalLink(c.ctx, textPatch, dbJob.Patch)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(len(msg.Attachments), 0)
-		body := fmt.Sprintf(`Hello,
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
 
 syzbot has tested the proposed patch and the reproducer did not trigger crash:
 
@@ -270,22 +249,19 @@
 
 Tested on:
 
-commit:         111111111111 kernel_commit_title1
-git tree:       repo1/branch1
+commit:         11111111 kernel_commit_title1
+git tree:       repo1 branch1
 kernel config:  %[3]v
 compiler:       compiler1
 patch:          %[2]v
 
 Note: testing is done by a robot and is best-effort only.
-`, extBugID, patchLink, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+`, extBugID, patchLink, kernelConfigLink))
 		c.checkURLContents(patchLink, []byte(patch))
 		c.checkURLContents(kernelConfigLink, build.KernelConfig)
 	}
 
-	pollResp, _ = c.client2.JobPoll([]string{build.Manager})
+	pollResp = c.client2.pollJobs(build.Manager)
 	c.expectEQ(pollResp.ID, "")
 }
 
@@ -301,17 +277,14 @@
 	crash.ReproOpts = []byte("repro opts")
 	crash.ReproSyz = []byte("repro syz")
 	c.client2.ReportCrash(crash)
-
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
-	sender := (<-c.emailSink).Sender
+	c.client2.pollAndFailBisectJob(build.Manager)
+	sender := c.pollEmailBug().Sender
 	_, extBugID, err := email.RemoveAddrContext(sender)
-	if err != nil {
-		t.Fatal(err)
-	}
+	c.expectOK(err)
 
-	c.incomingEmail(sender, "#syz test: git://mygit.com/git.git 5e6a2eea\n", EmailOptMessageID(1))
-	pollResp, _ := c.client2.JobPoll([]string{build.Manager})
+	c.incomingEmail(sender, "#syz test git://mygit.com/git.git 5e6a2eea\n", EmailOptMessageID(1))
+	pollResp := c.client2.pollJobs(build.Manager)
+	c.expectEQ(pollResp.Type, dashapi.JobTestPatch)
 	testBuild := testBuild(2)
 	testBuild.KernelRepo = "git://mygit.com/git.git"
 	testBuild.KernelBranch = ""
@@ -321,14 +294,12 @@
 		Build: *testBuild,
 	}
 	c.client2.JobDone(jobDoneReq)
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
 	{
-		_, dbBuild := c.loadJob(pollResp.ID)
+		_, dbBuild, _ := c.loadJob(pollResp.ID)
 		kernelConfigLink := externalLink(c.ctx, textKernelConfig, dbBuild.KernelConfig)
-		msg := <-c.emailSink
+		msg := c.pollEmailBug()
 		c.expectEQ(len(msg.Attachments), 0)
-		body := fmt.Sprintf(`Hello,
+		c.expectEQ(msg.Body, fmt.Sprintf(`Hello,
 
 syzbot has tested the proposed patch and the reproducer did not trigger crash:
 
@@ -336,20 +307,17 @@
 
 Tested on:
 
-commit:         5e6a2eea5e6a kernel_commit_title2
+commit:         5e6a2eea kernel_commit_title2
 git tree:       git://mygit.com/git.git
 kernel config:  %[2]v
 compiler:       compiler2
 
 Note: testing is done by a robot and is best-effort only.
-`, extBugID, kernelConfigLink)
-		if msg.Body != body {
-			t.Fatalf("got email body:\n%s\n\nwant:\n%s", msg.Body, body)
-		}
+`, extBugID, kernelConfigLink))
 		c.checkURLContents(kernelConfigLink, testBuild.KernelConfig)
 	}
 
-	pollResp, _ = c.client2.JobPoll([]string{build.Manager})
+	pollResp = c.client2.pollJobs(build.Manager)
 	c.expectEQ(pollResp.ID, "")
 }
 
@@ -365,21 +333,20 @@
 	crash := testCrash(build, 1)
 	crash.ReproSyz = []byte("repro syz")
 	c.client2.ReportCrash(crash)
-
-	c.expectOK(c.GET("/email_poll"))
-	c.expectEQ(len(c.emailSink), 1)
-	sender := (<-c.emailSink).Sender
+	c.client2.pollAndFailBisectJob(build.Manager)
+	sender := c.pollEmailBug().Sender
 
 	// Testing on a wrong repo must fail and no test jobs passed to manager.
 	c.incomingEmail(sender, "#syz test: git://mygit.com/git.git master\n", EmailOptMessageID(1))
 	c.expectEQ(strings.Contains((<-c.emailSink).Body, "you should test only on restricted.git"), true)
-	pollResp, _ := c.client2.JobPoll([]string{build.Manager})
+	pollResp := c.client2.pollJobs(build.Manager)
 	c.expectEQ(pollResp.ID, "")
 
 	// Testing on the right repo must succeed.
 	c.incomingEmail(sender, "#syz test: git://restricted.git/restricted.git master\n", EmailOptMessageID(2))
-	pollResp, _ = c.client2.JobPoll([]string{build.Manager})
-	c.expectEQ(pollResp.ID != "", true)
+	pollResp = c.client2.pollJobs(build.Manager)
+	c.expectNE(pollResp.ID, "")
+	c.expectEQ(pollResp.Type, dashapi.JobTestPatch)
 	c.expectEQ(pollResp.Manager, build.Manager)
 	c.expectEQ(pollResp.KernelRepo, "git://restricted.git/restricted.git")
 }
diff --git a/dashboard/app/mail_bisect_result.txt b/dashboard/app/mail_bisect_result.txt
new file mode 100644
index 0000000..0e5d927
--- /dev/null
+++ b/dashboard/app/mail_bisect_result.txt
@@ -0,0 +1,27 @@
+{{if .BisectCause.Commit}}syzbot has bisected this bug to:
+
+commit {{.BisectCause.Commit.Hash}}
+Author: {{.BisectCause.Commit.AuthorName}} <{{.BisectCause.Commit.Author}}>
+Date:   {{formatKernelTime .BisectCause.Commit.Date}}
+
+    {{.BisectCause.Commit.Title}}
+{{else if .BisectCause.Commits}}Bisection is inconclusive: the first bad commit could be any of:
+{{range $com := .BisectCause.Commits}}
+{{formatShortHash $com.Hash}} {{$com.Title}}{{end}}
+{{else}}Bisection is inconclusive: the bug happens on the oldest tested release.
+{{end}}
+bisection log:  {{.BisectCause.LogLink}}
+start commit:   {{formatShortHash .KernelCommit}} {{formatCommitTableTitle .KernelCommitTitle}}
+git tree:       {{.KernelRepoAlias}}
+{{if .BisectCause.CrashReportLink}}final crash:    {{.BisectCause.CrashReportLink}}
+{{end}}{{if .BisectCause.CrashLogLink}}console output: {{.BisectCause.CrashLogLink}}
+{{end}}{{if .KernelConfigLink}}kernel config:  {{.KernelConfigLink}}
+{{end}}dashboard link: {{.Link}}
+{{if .UserSpaceArch}}userspace arch: {{.UserSpaceArch}}
+{{end}}{{if .ReproSyzLink}}syz repro:      {{.ReproSyzLink}}
+{{end}}{{if .ReproCLink}}C reproducer:   {{.ReproCLink}}
+{{end}}{{if .BisectCause.Commit}}
+Reported-by: {{.CreditEmail}}
+Fixes: {{formatTagHash .BisectCause.Commit.Hash}} ("{{.BisectCause.Commit.Title}}")
+{{end}}
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection
diff --git a/dashboard/app/mail_bug.txt b/dashboard/app/mail_bug.txt
index df03974..7b0dde9 100644
--- a/dashboard/app/mail_bug.txt
+++ b/dashboard/app/mail_bug.txt
@@ -4,22 +4,39 @@
 {{end -}}
 syzbot {{if .First}}found{{else}}has found a reproducer for{{end}} the following crash on:
 
-HEAD commit:    {{.KernelCommit}} {{.KernelCommitTitle}}
-git tree:       {{.KernelRepo}}
+HEAD commit:    {{formatShortHash .KernelCommit}} {{formatCommitTableTitle .KernelCommitTitle}}
+git tree:       {{.KernelRepoAlias}}
 {{if .LogLink}}console output: {{.LogLink}}
 {{end}}{{if .KernelConfigLink}}kernel config:  {{.KernelConfigLink}}
 {{end}}dashboard link: {{.Link}}
-compiler:       {{.CompilerID}}
-{{if .UserSpaceArch}}userspace arch: {{.UserSpaceArch}}
-{{end}}{{if .ReproSyzLink}}syzkaller repro:{{.ReproSyzLink}}
+{{if .CompilerID}}compiler:       {{.CompilerID}}
+{{end}}{{if .UserSpaceArch}}userspace arch: {{.UserSpaceArch}}
+{{end}}{{if .ReproSyzLink}}syz repro:      {{.ReproSyzLink}}
 {{end}}{{if .ReproCLink}}C reproducer:   {{.ReproCLink}}
-{{end}}{{if .Moderation}}CC:             {{.Maintainers}}
+{{end}}{{if and .Moderation .Maintainers}}CC:             {{.Maintainers}}
 {{end}}{{if and (not .ReproCLink) (not .ReproSyzLink)}}
 Unfortunately, I don't have any reproducer for this crash yet.
 {{end}}
-IMPORTANT: if you fix the bug, please add the following tag to the commit:
-Reported-by: {{.CreditEmail}}
+{{if .BisectCause}}{{if .BisectCause.Commit}}The bug was bisected to:
 
+commit {{.BisectCause.Commit.Hash}}
+Author: {{.BisectCause.Commit.AuthorName}} <{{.BisectCause.Commit.Author}}>
+Date:   {{formatKernelTime .BisectCause.Commit.Date}}
+
+    {{.BisectCause.Commit.Title}}
+{{else if .BisectCause.Commits}}Bisection is inconclusive: the first bad commit could be any of:
+{{range $com := .BisectCause.Commits}}
+{{formatShortHash $com.Hash}} {{$com.Title}}{{end}}
+{{else}}Bisection is inconclusive: the bug happens on the oldest tested release.
+{{end}}
+bisection log:  {{.BisectCause.LogLink}}
+{{if .BisectCause.CrashReportLink}}final crash:    {{.BisectCause.CrashReportLink}}
+{{end}}{{if .BisectCause.CrashLogLink}}console output: {{.BisectCause.CrashLogLink}}
+{{end}}
+{{end}}IMPORTANT: if you fix the bug, please add the following tag to the commit:
+Reported-by: {{.CreditEmail}}
+{{if .BisectCause}}{{if .BisectCause.Commit}}Fixes: {{formatTagHash .BisectCause.Commit.Hash}} ("{{.BisectCause.Commit.Title}}")
+{{end}}{{end}}
 {{printf "%s" .Report}}
 {{if .First}}
 ---
@@ -28,7 +45,8 @@
 syzbot engineers can be reached at syzkaller@googlegroups.com.
 
 syzbot will keep track of this bug report. See:
-https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with syzbot.{{if or .ReproCLink .ReproSyzLink}}
+https://goo.gl/tpsmEJ#status for how to communicate with syzbot.{{if .BisectCause}}
+For information about bisection process see: https://goo.gl/tpsmEJ#bisection{{end}}{{if or .ReproCLink .ReproSyzLink}}
 syzbot can test patches for this bug, for details see:
 https://goo.gl/tpsmEJ#testing-patches
 {{- end -}}
diff --git a/dashboard/app/mail_test_result.txt b/dashboard/app/mail_test_result.txt
index f993824..c58328d 100644
--- a/dashboard/app/mail_test_result.txt
+++ b/dashboard/app/mail_test_result.txt
@@ -8,7 +8,7 @@
 syzbot tried to test the proposed patch but build/boot failed:
 
 {{printf "%s" .Error}}
-{{if .ErrorLink}}
+{{if .ErrorTruncated}}
 Error text is too large and was truncated, full error text is at:
 {{.ErrorLink}}
 {{end}}
@@ -19,8 +19,8 @@
 {{end}}
 Tested on:
 
-commit:         {{.KernelCommit}} {{.KernelCommitTitle}}
-git tree:       {{.KernelRepo}}
+commit:         {{formatShortHash .KernelCommit}} {{formatCommitTableTitle .KernelCommitTitle}}
+git tree:       {{.KernelRepoAlias}}
 {{if .LogLink}}console output: {{.LogLink}}
 {{end}}{{if .KernelConfigLink}}kernel config:  {{.KernelConfigLink}}
 {{end}}compiler:       {{.CompilerID}}
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index 10ed24e..aad68a0 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -14,8 +14,10 @@
 
 	"github.com/google/syzkaller/dashboard/dashapi"
 	"github.com/google/syzkaller/pkg/email"
+	"github.com/google/syzkaller/pkg/html"
+	"github.com/google/syzkaller/pkg/vcs"
 	"golang.org/x/net/context"
-	"google.golang.org/appengine/datastore"
+	db "google.golang.org/appengine/datastore"
 	"google.golang.org/appengine/log"
 )
 
@@ -25,65 +27,95 @@
 	http.Handle("/", handlerWrapper(handleMain))
 	http.Handle("/bug", handlerWrapper(handleBug))
 	http.Handle("/text", handlerWrapper(handleText))
+	http.Handle("/admin", handlerWrapper(handleAdmin))
 	http.Handle("/x/.config", handlerWrapper(handleTextX(textKernelConfig)))
 	http.Handle("/x/log.txt", handlerWrapper(handleTextX(textCrashLog)))
+	http.Handle("/x/report.txt", handlerWrapper(handleTextX(textCrashReport)))
 	http.Handle("/x/repro.syz", handlerWrapper(handleTextX(textReproSyz)))
 	http.Handle("/x/repro.c", handlerWrapper(handleTextX(textReproC)))
 	http.Handle("/x/patch.diff", handlerWrapper(handleTextX(textPatch)))
+	http.Handle("/x/bisect.txt", handlerWrapper(handleTextX(textLog)))
 	http.Handle("/x/error.txt", handlerWrapper(handleTextX(textError)))
+	for ns := range config.Namespaces {
+		http.Handle("/"+ns, handlerWrapper(handleMain))
+		http.Handle("/"+ns+"/fixed", handlerWrapper(handleFixed))
+	}
 }
 
-type uiMain struct {
-	Header        *uiHeader
-	Now           time.Time
-	Log           []byte
-	Managers      []*uiManager
-	Jobs          []*uiJob
-	BugNamespaces []*uiBugNamespace
+type uiMainPage struct {
+	Header     *uiHeader
+	Now        time.Time
+	FixedLink  string
+	FixedCount int
+	Managers   []*uiManager
+	Groups     []*uiBugGroup
+}
+
+type uiFixedPage struct {
+	Header *uiHeader
+	Now    time.Time
+	Bugs   *uiBugGroup
+}
+
+type uiAdminPage struct {
+	Header   *uiHeader
+	Log      []byte
+	Managers []*uiManager
+	Jobs     []*uiJob
 }
 
 type uiManager struct {
-	Namespace          string
-	Name               string
-	Link               string
-	CurrentBuild       *uiBuild
-	FailedBuildBugLink string
-	LastActive         time.Time
-	LastActiveBad      bool
-	CurrentUpTime      time.Duration
-	MaxCorpus          int64
-	MaxCover           int64
-	TotalFuzzingTime   time.Duration
-	TotalCrashes       int64
-	TotalExecs         int64
+	Now                   time.Time
+	Namespace             string
+	Name                  string
+	Link                  string
+	CoverLink             string
+	CurrentBuild          *uiBuild
+	FailedBuildBugLink    string
+	FailedSyzBuildBugLink string
+	LastActive            time.Time
+	LastActiveBad         bool
+	CurrentUpTime         time.Duration
+	MaxCorpus             int64
+	MaxCover              int64
+	TotalFuzzingTime      time.Duration
+	TotalCrashes          int64
+	TotalExecs            int64
 }
 
 type uiBuild struct {
-	Time             time.Time
-	SyzkallerCommit  string
-	KernelAlias      string
-	KernelCommit     string
-	KernelConfigLink string
+	Time                time.Time
+	SyzkallerCommit     string
+	SyzkallerCommitLink string
+	SyzkallerCommitDate time.Time
+	KernelAlias         string
+	KernelCommit        string
+	KernelCommitLink    string
+	KernelCommitTitle   string
+	KernelCommitDate    time.Time
+	KernelConfigLink    string
+}
+
+type uiCommit struct {
+	Hash   string
+	Title  string
+	Link   string
+	Author string
+	CC     []string
+	Date   time.Time
 }
 
 type uiBugPage struct {
-	Header       *uiHeader
-	Now          time.Time
-	Bug          *uiBug
-	DupOf        *uiBugGroup
-	Dups         *uiBugGroup
-	Similar      *uiBugGroup
-	SampleReport []byte
-	Crashes      []*uiCrash
-}
-
-type uiBugNamespace struct {
-	Name       string
-	Caption    string
-	CoverLink  string
-	FixedLink  string
-	FixedCount int
-	Groups     []*uiBugGroup
+	Header         *uiHeader
+	Now            time.Time
+	Bug            *uiBug
+	BisectCause    *uiJob
+	DupOf          *uiBugGroup
+	Dups           *uiBugGroup
+	Similar        *uiBugGroup
+	SampleReport   []byte
+	HasMaintainers bool
+	Crashes        []*uiCrash
 }
 
 type uiBugGroup struct {
@@ -104,6 +136,7 @@
 	Title          string
 	NumCrashes     int64
 	NumCrashesBad  bool
+	BisectCause    bool
 	FirstTime      time.Time
 	LastTime       time.Time
 	ReportedTime   time.Time
@@ -114,7 +147,7 @@
 	Link           string
 	ExternalLink   string
 	CreditEmail    string
-	Commits        string
+	Commits        []*uiCommit
 	PatchedOn      []string
 	MissingOn      []string
 	NumManagers    int
@@ -132,6 +165,7 @@
 }
 
 type uiJob struct {
+	Type            JobType
 	Created         time.Time
 	BugLink         string
 	ExternalLink    string
@@ -147,54 +181,103 @@
 	Attempts        int
 	Started         time.Time
 	Finished        time.Time
+	Duration        time.Duration
 	CrashTitle      string
 	CrashLogLink    string
 	CrashReportLink string
+	LogLink         string
 	ErrorLink       string
+	Commit          *uiCommit   // for conclusive bisection
+	Commits         []*uiCommit // for inconclusive bisection
+	Crash           *uiCrash
 	Reported        bool
 }
 
 // handleMain serves main page.
 func handleMain(c context.Context, w http.ResponseWriter, r *http.Request) error {
-	var errorLog []byte
-	var managers []*uiManager
-	var jobs []*uiJob
-	if accessLevel(c, r) == AccessAdmin && r.FormValue("fixed") == "" {
-		var err error
-		errorLog, err = fetchErrorLogs(c)
-		if err != nil {
-			return err
-		}
-		managers, err = loadManagers(c)
-		if err != nil {
-			return err
-		}
-		jobs, err = loadRecentJobs(c)
-		if err != nil {
-			return err
-		}
+	if ns := r.FormValue("fixed"); ns != "" {
+		http.Redirect(w, r, fmt.Sprintf("/%v/fixed", ns), http.StatusFound)
+		return nil
 	}
-	bugNamespaces, err := fetchBugs(c, r)
+	hdr, err := commonHeader(c, r, w, "")
 	if err != nil {
 		return err
 	}
-	data := &uiMain{
-		Header:        commonHeader(c, r),
-		Now:           timeNow(c),
-		Log:           errorLog,
-		Managers:      managers,
-		Jobs:          jobs,
-		BugNamespaces: bugNamespaces,
+	accessLevel := accessLevel(c, r)
+	managers, err := loadManagers(c, accessLevel, hdr.Namespace)
+	if err != nil {
+		return err
+	}
+	groups, fixedCount, err := fetchNamespaceBugs(c, accessLevel, hdr.Namespace)
+	if err != nil {
+		return err
+	}
+	data := &uiMainPage{
+		Header:     hdr,
+		Now:        timeNow(c),
+		FixedCount: fixedCount,
+		FixedLink:  fmt.Sprintf("/%v/fixed", hdr.Namespace),
+		Groups:     groups,
+		Managers:   managers,
 	}
 	return serveTemplate(w, "main.html", data)
 }
 
+func handleFixed(c context.Context, w http.ResponseWriter, r *http.Request) error {
+	accessLevel := accessLevel(c, r)
+	hdr, err := commonHeader(c, r, w, "")
+	if err != nil {
+		return err
+	}
+	hdr.Subpage = "/fixed"
+	bugs, err := fetchFixedBugs(c, accessLevel, hdr.Namespace)
+	if err != nil {
+		return err
+	}
+	data := &uiFixedPage{
+		Header: hdr,
+		Now:    timeNow(c),
+		Bugs:   bugs,
+	}
+	return serveTemplate(w, "fixed.html", data)
+}
+
+func handleAdmin(c context.Context, w http.ResponseWriter, r *http.Request) error {
+	accessLevel := accessLevel(c, r)
+	if accessLevel != AccessAdmin {
+		return ErrAccess
+	}
+	hdr, err := commonHeader(c, r, w, "")
+	if err != nil {
+		return err
+	}
+	managers, err := loadManagers(c, accessLevel, "")
+	if err != nil {
+		return err
+	}
+	errorLog, err := fetchErrorLogs(c)
+	if err != nil {
+		return err
+	}
+	jobs, err := loadRecentJobs(c)
+	if err != nil {
+		return err
+	}
+	data := &uiAdminPage{
+		Header:   hdr,
+		Log:      errorLog,
+		Managers: managers,
+		Jobs:     jobs,
+	}
+	return serveTemplate(w, "admin.html", data)
+}
+
 // handleBug serves page about a single bug (which is passed in id argument).
 func handleBug(c context.Context, w http.ResponseWriter, r *http.Request) error {
 	bug := new(Bug)
 	if id := r.FormValue("id"); id != "" {
-		bugKey := datastore.NewKey(c, "Bug", id, 0, nil)
-		if err := datastore.Get(c, bugKey, bug); err != nil {
+		bugKey := db.NewKey(c, "Bug", id, 0, nil)
+		if err := db.Get(c, bugKey, bug); err != nil {
 			return err
 		}
 	} else if extID := r.FormValue("extid"); extID != "" {
@@ -210,6 +293,10 @@
 	if err := checkAccessLevel(c, r, bug.sanitizeAccess(accessLevel)); err != nil {
 		return err
 	}
+	hdr, err := commonHeader(c, r, w, bug.Namespace)
+	if err != nil {
+		return err
+	}
 	state, err := loadReportingState(c)
 	if err != nil {
 		return err
@@ -221,7 +308,7 @@
 	var dupOf *uiBugGroup
 	if bug.DupOf != "" {
 		dup := new(Bug)
-		if err := datastore.Get(c, datastore.NewKey(c, "Bug", bug.DupOf, 0, nil), dup); err != nil {
+		if err := db.Get(c, db.NewKey(c, "Bug", bug.DupOf, 0, nil), dup); err != nil {
 			return err
 		}
 		if accessLevel >= dup.sanitizeAccess(accessLevel) {
@@ -245,15 +332,41 @@
 	if err != nil {
 		return err
 	}
+	var bisectCause *uiJob
+	if bug.BisectCause > BisectPending {
+		job, _, jobKey, _, err := loadBisectJob(c, bug)
+		if err != nil {
+			return err
+		}
+		crash := new(Crash)
+		crashKey := db.NewKey(c, "Crash", "", job.CrashID, bug.key(c))
+		if err := db.Get(c, crashKey, crash); err != nil {
+			return fmt.Errorf("failed to get crash: %v", err)
+		}
+		build, err := loadBuild(c, bug.Namespace, crash.BuildID)
+		if err != nil {
+			return err
+		}
+		bisectCause = makeUIJob(job, jobKey, crash, build)
+	}
+	hasMaintainers := false
+	for _, crash := range crashes {
+		if len(crash.Maintainers) != 0 {
+			hasMaintainers = true
+			break
+		}
+	}
 	data := &uiBugPage{
-		Header:       commonHeader(c, r),
-		Now:          timeNow(c),
-		Bug:          uiBug,
-		DupOf:        dupOf,
-		Dups:         dups,
-		Similar:      similar,
-		SampleReport: sampleReport,
-		Crashes:      crashes,
+		Header:         hdr,
+		Now:            timeNow(c),
+		Bug:            uiBug,
+		BisectCause:    bisectCause,
+		DupOf:          dupOf,
+		Dups:           dups,
+		Similar:        similar,
+		SampleReport:   sampleReport,
+		HasMaintainers: hasMaintainers,
+		Crashes:        crashes,
 	}
 	return serveTemplate(w, "bug.html", data)
 }
@@ -325,6 +438,8 @@
 		return "repro.c"
 	case textPatch:
 		return "patch.diff"
+	case textLog:
+		return "bisect.txt"
 	case textError:
 		return "error.txt"
 	default:
@@ -332,45 +447,21 @@
 	}
 }
 
-func fetchBugs(c context.Context, r *http.Request) ([]*uiBugNamespace, error) {
+func fetchNamespaceBugs(c context.Context, accessLevel AccessLevel, ns string) ([]*uiBugGroup, int, error) {
+	var bugs []*Bug
+	_, err := db.NewQuery("Bug").
+		Filter("Namespace=", ns).
+		GetAll(c, &bugs)
+	if err != nil {
+		return nil, 0, err
+	}
 	state, err := loadReportingState(c)
 	if err != nil {
-		return nil, err
-	}
-	accessLevel := accessLevel(c, r)
-	onlyFixed := r.FormValue("fixed")
-	var res []*uiBugNamespace
-	for ns, cfg := range config.Namespaces {
-		if accessLevel < cfg.AccessLevel {
-			continue
-		}
-		if onlyFixed != "" && onlyFixed != ns {
-			continue
-		}
-		uiNamespace, err := fetchNamespaceBugs(c, accessLevel, ns, state, onlyFixed != "")
-		if err != nil {
-			return nil, err
-		}
-		res = append(res, uiNamespace)
-	}
-	sort.Sort(uiBugNamespaceSorter(res))
-	return res, nil
-}
-
-func fetchNamespaceBugs(c context.Context, accessLevel AccessLevel, ns string,
-	state *ReportingState, onlyFixed bool) (*uiBugNamespace, error) {
-	query := datastore.NewQuery("Bug").Filter("Namespace=", ns)
-	if onlyFixed {
-		query = query.Filter("Status=", BugStatusFixed)
-	}
-	var bugs []*Bug
-	_, err := query.GetAll(c, &bugs)
-	if err != nil {
-		return nil, err
+		return nil, 0, err
 	}
 	managers, err := managerList(c, ns)
 	if err != nil {
-		return nil, err
+		return nil, 0, err
 	}
 	fixedCount := 0
 	groups := make(map[int][]*uiBug)
@@ -379,8 +470,9 @@
 	for _, bug := range bugs {
 		if bug.Status == BugStatusFixed {
 			fixedCount++
+			continue
 		}
-		if bug.Status == BugStatusInvalid || bug.Status == BugStatusFixed != onlyFixed {
+		if bug.Status == BugStatusInvalid {
 			continue
 		}
 		if accessLevel < bug.sanitizeAccess(accessLevel) {
@@ -391,12 +483,10 @@
 			continue
 		}
 		uiBug := createUIBug(c, bug, state, managers)
-		bugMap[bugKeyHash(bug.Namespace, bug.Title, bug.Seq)] = uiBug
+		bugMap[bug.keyHash()] = uiBug
 		id := uiBug.ReportingIndex
-		if bug.Status == BugStatusFixed {
+		if len(uiBug.Commits) != 0 {
 			id = -1
-		} else if uiBug.Commits != "" {
-			id = -2
 		}
 		groups[id] = append(groups[id], uiBug)
 	}
@@ -407,57 +497,87 @@
 		}
 		mergeUIBug(c, bug, dup)
 	}
+	cfg := config.Namespaces[ns]
 	var uiGroups []*uiBugGroup
 	for index, bugs := range groups {
-		sort.Sort(uiBugSorter(bugs))
-		caption, fragment, showPatch, showPatched := "", "", false, false
+		sort.Slice(bugs, func(i, j int) bool {
+			if bugs[i].Namespace != bugs[j].Namespace {
+				return bugs[i].Namespace < bugs[j].Namespace
+			}
+			if bugs[i].ClosedTime != bugs[j].ClosedTime {
+				return bugs[i].ClosedTime.After(bugs[j].ClosedTime)
+			}
+			return bugs[i].ReportedTime.After(bugs[j].ReportedTime)
+		})
+		caption, fragment, showPatched := "", "", false
 		switch index {
 		case -1:
-			caption, showPatch, showPatched = "fixed", true, false
-		case -2:
-			caption, showPatch, showPatched = "fix pending", false, true
-			fragment = ns + "-pending"
-		case len(config.Namespaces[ns].Reporting) - 1:
-			caption, showPatch, showPatched = "open", false, false
-			fragment = ns + "-open"
+			caption, showPatched = "fix pending", true
+			fragment = "pending"
+		case len(cfg.Reporting) - 1:
+			caption, showPatched = "open", false
+			fragment = "open"
 		default:
-			reporting := &config.Namespaces[ns].Reporting[index]
-			caption, showPatch, showPatched = reporting.DisplayTitle, false, false
-			fragment = ns + "-" + reporting.Name
+			reporting := &cfg.Reporting[index]
+			caption, showPatched = reporting.DisplayTitle, false
+			fragment = reporting.Name
 		}
 		uiGroups = append(uiGroups, &uiBugGroup{
 			Now:         timeNow(c),
-			Caption:     fmt.Sprintf("%v (%v)", caption, len(bugs)),
+			Caption:     caption,
 			Fragment:    fragment,
 			Namespace:   ns,
-			ShowPatch:   showPatch,
 			ShowPatched: showPatched,
 			ShowIndex:   index,
 			Bugs:        bugs,
 		})
 	}
-	sort.Sort(uiBugGroupSorter(uiGroups))
-	fixedLink := ""
-	if !onlyFixed {
-		fixedLink = fmt.Sprintf("?fixed=%v", ns)
+	sort.Slice(uiGroups, func(i, j int) bool {
+		return uiGroups[i].ShowIndex > uiGroups[j].ShowIndex
+	})
+	return uiGroups, fixedCount, nil
+}
+
+func fetchFixedBugs(c context.Context, accessLevel AccessLevel, ns string) (*uiBugGroup, error) {
+	var bugs []*Bug
+	_, err := db.NewQuery("Bug").
+		Filter("Namespace=", ns).
+		Filter("Status=", BugStatusFixed).
+		GetAll(c, &bugs)
+	if err != nil {
+		return nil, err
 	}
-	cfg := config.Namespaces[ns]
-	uiNamespace := &uiBugNamespace{
-		Name:       ns,
-		Caption:    cfg.DisplayTitle,
-		CoverLink:  cfg.CoverLink,
-		FixedCount: fixedCount,
-		FixedLink:  fixedLink,
-		Groups:     uiGroups,
+	state, err := loadReportingState(c)
+	if err != nil {
+		return nil, err
 	}
-	return uiNamespace, nil
+	managers, err := managerList(c, ns)
+	if err != nil {
+		return nil, err
+	}
+	res := &uiBugGroup{
+		Now:       timeNow(c),
+		Caption:   "fixed",
+		ShowPatch: true,
+		Namespace: ns,
+	}
+	for _, bug := range bugs {
+		if accessLevel < bug.sanitizeAccess(accessLevel) {
+			continue
+		}
+		res.Bugs = append(res.Bugs, createUIBug(c, bug, state, managers))
+	}
+	sort.Slice(res.Bugs, func(i, j int) bool {
+		return res.Bugs[i].ClosedTime.After(res.Bugs[j].ClosedTime)
+	})
+	return res, nil
 }
 
 func loadDupsForBug(c context.Context, r *http.Request, bug *Bug, state *ReportingState, managers []string) (
 	*uiBugGroup, error) {
-	bugHash := bugKeyHash(bug.Namespace, bug.Title, bug.Seq)
+	bugHash := bug.keyHash()
 	var dups []*Bug
-	_, err := datastore.NewQuery("Bug").
+	_, err := db.NewQuery("Bug").
 		Filter("Status=", BugStatusDup).
 		Filter("DupOf=", bugHash).
 		GetAll(c, &dups)
@@ -484,7 +604,7 @@
 
 func loadSimilarBugs(c context.Context, r *http.Request, bug *Bug, state *ReportingState) (*uiBugGroup, error) {
 	var similar []*Bug
-	_, err := datastore.NewQuery("Bug").
+	_, err := db.NewQuery("Bug").
 		Filter("Title=", bug.Title).
 		GetAll(c, &similar)
 	if err != nil {
@@ -493,6 +613,7 @@
 	managers := make(map[string][]string)
 	var results []*uiBug
 	accessLevel := accessLevel(c, r)
+	domain := config.Namespaces[bug.Namespace].SimilarityDomain
 	for _, similar := range similar {
 		if accessLevel < similar.sanitizeAccess(accessLevel) {
 			continue
@@ -500,6 +621,9 @@
 		if similar.Namespace == bug.Namespace && similar.Seq == bug.Seq {
 			continue
 		}
+		if config.Namespaces[similar.Namespace].SimilarityDomain != domain {
+			continue
+		}
 		if managers[similar.Namespace] == nil {
 			mgrs, err := managerList(c, similar.Namespace)
 			if err != nil {
@@ -547,6 +671,9 @@
 				switch bug.Status {
 				case BugStatusInvalid:
 					status = "closed as invalid"
+					if bugReporting.Auto {
+						status = "auto-" + status
+					}
 				case BugStatusFixed:
 					status = "fixed"
 				case BugStatusDup:
@@ -554,7 +681,7 @@
 				default:
 					status = fmt.Sprintf("unknown (%v)", bug.Status)
 				}
-				status = fmt.Sprintf("%v on %v", status, formatTime(bug.Closed))
+				status = fmt.Sprintf("%v on %v", status, html.FormatTime(bug.Closed))
 				break
 			}
 		}
@@ -563,10 +690,11 @@
 	if err != nil {
 		log.Errorf(c, "failed to generate credit email: %v", err)
 	}
-	id := bugKeyHash(bug.Namespace, bug.Title, bug.Seq)
+	id := bug.keyHash()
 	uiBug := &uiBug{
 		Namespace:      bug.Namespace,
 		Title:          bug.displayTitle(),
+		BisectCause:    bug.BisectCause > BisectPending,
 		NumCrashes:     bug.NumCrashes,
 		FirstTime:      bug.FirstTime,
 		LastTime:       bug.LastTime,
@@ -582,9 +710,14 @@
 	}
 	updateBugBadness(c, uiBug)
 	if len(bug.Commits) != 0 {
-		uiBug.Commits = bug.Commits[0]
-		if len(bug.Commits) > 1 {
-			uiBug.Commits = fmt.Sprintf("%q", bug.Commits)
+		for i, com := range bug.Commits {
+			cfg := config.Namespaces[bug.Namespace]
+			info := bug.getCommitInfo(i)
+			uiBug.Commits = append(uiBug.Commits, &uiCommit{
+				Hash:  info.Hash,
+				Title: com,
+				Link:  vcs.CommitLink(cfg.Repos[0].URL, info.Hash),
+			})
 		}
 		for _, mgr := range managers {
 			found := false
@@ -608,6 +741,7 @@
 
 func mergeUIBug(c context.Context, bug *uiBug, dup *Bug) {
 	bug.NumCrashes += dup.NumCrashes
+	bug.BisectCause = bug.BisectCause || dup.BisectCause > BisectPending
 	if bug.LastTime.Before(dup.LastTime) {
 		bug.LastTime = dup.LastTime
 	}
@@ -622,10 +756,9 @@
 }
 
 func loadCrashesForBug(c context.Context, bug *Bug) ([]*uiCrash, []byte, error) {
-	bugHash := bugKeyHash(bug.Namespace, bug.Title, bug.Seq)
-	bugKey := datastore.NewKey(c, "Bug", bugHash, 0, nil)
+	bugKey := bug.key(c)
 	// We can have more than maxCrashes crashes, if we have lots of reproducers.
-	crashes, _, err := queryCrashesForBug(c, bugKey, maxCrashes+200)
+	crashes, _, err := queryCrashesForBug(c, bugKey, 2*maxCrashes+200)
 	if err != nil || len(crashes) == 0 {
 		return nil, nil, err
 	}
@@ -640,17 +773,7 @@
 			}
 			builds[crash.BuildID] = build
 		}
-		ui := &uiCrash{
-			Manager:      crash.Manager,
-			Time:         crash.Time,
-			Maintainers:  fmt.Sprintf("%q", crash.Maintainers),
-			LogLink:      textLink(textCrashLog, crash.Log),
-			ReportLink:   textLink(textCrashReport, crash.Report),
-			ReproSyzLink: textLink(textReproSyz, crash.ReproSyz),
-			ReproCLink:   textLink(textReproC, crash.ReproC),
-			uiBuild:      makeUIBuild(build),
-		}
-		results = append(results, ui)
+		results = append(results, makeUICrash(crash, build))
 	}
 	sampleReport, _, err := getText(c, textCrashReport, crashes[0].Report)
 	if err != nil {
@@ -659,36 +782,68 @@
 	return results, sampleReport, nil
 }
 
+func makeUICrash(crash *Crash, build *Build) *uiCrash {
+	ui := &uiCrash{
+		Manager:      crash.Manager,
+		Time:         crash.Time,
+		Maintainers:  strings.Join(crash.Maintainers, ", "),
+		LogLink:      textLink(textCrashLog, crash.Log),
+		ReportLink:   textLink(textCrashReport, crash.Report),
+		ReproSyzLink: textLink(textReproSyz, crash.ReproSyz),
+		ReproCLink:   textLink(textReproC, crash.ReproC),
+	}
+	if build != nil {
+		ui.uiBuild = makeUIBuild(build)
+	}
+	return ui
+}
+
 func makeUIBuild(build *Build) *uiBuild {
 	return &uiBuild{
-		Time:             build.Time,
-		SyzkallerCommit:  build.SyzkallerCommit,
-		KernelAlias:      kernelRepoInfo(build).Alias,
-		KernelCommit:     build.KernelCommit,
-		KernelConfigLink: textLink(textKernelConfig, build.KernelConfig),
+		Time:                build.Time,
+		SyzkallerCommit:     build.SyzkallerCommit,
+		SyzkallerCommitLink: vcs.LogLink(vcs.SyzkallerRepo, build.SyzkallerCommit),
+		SyzkallerCommitDate: build.SyzkallerCommitDate,
+		KernelAlias:         kernelRepoInfo(build).Alias,
+		KernelCommit:        build.KernelCommit,
+		KernelCommitLink:    vcs.LogLink(build.KernelRepo, build.KernelCommit),
+		KernelCommitTitle:   build.KernelCommitTitle,
+		KernelCommitDate:    build.KernelCommitDate,
+		KernelConfigLink:    textLink(textKernelConfig, build.KernelConfig),
 	}
 }
 
-func loadManagers(c context.Context) ([]*uiManager, error) {
+func loadManagers(c context.Context, accessLevel AccessLevel, ns string) ([]*uiManager, error) {
 	now := timeNow(c)
 	date := timeDate(now)
-	managers, managerKeys, err := loadAllManagers(c)
+	managers, managerKeys, err := loadAllManagers(c, ns)
 	if err != nil {
 		return nil, err
 	}
-	var buildKeys []*datastore.Key
-	var statsKeys []*datastore.Key
+	for i := 0; i < len(managers); i++ {
+		if accessLevel >= config.Namespaces[managers[i].Namespace].AccessLevel {
+			continue
+		}
+		last := len(managers) - 1
+		managers[i] = managers[last]
+		managers = managers[:last]
+		managerKeys[i] = managerKeys[last]
+		managerKeys = managerKeys[:last]
+		i--
+	}
+	var buildKeys []*db.Key
+	var statsKeys []*db.Key
 	for i, mgr := range managers {
 		if mgr.CurrentBuild != "" {
 			buildKeys = append(buildKeys, buildKey(c, mgr.Namespace, mgr.CurrentBuild))
 		}
 		if timeDate(mgr.LastAlive) == date {
 			statsKeys = append(statsKeys,
-				datastore.NewKey(c, "ManagerStats", "", int64(date), managerKeys[i]))
+				db.NewKey(c, "ManagerStats", "", int64(date), managerKeys[i]))
 		}
 	}
 	builds := make([]*Build, len(buildKeys))
-	if err := datastore.GetMulti(c, buildKeys, builds); err != nil {
+	if err := db.GetMulti(c, buildKeys, builds); err != nil {
 		return nil, err
 	}
 	uiBuilds := make(map[string]*uiBuild)
@@ -696,7 +851,7 @@
 		uiBuilds[build.Namespace+"|"+build.ID] = makeUIBuild(build)
 	}
 	stats := make([]*ManagerStats, len(statsKeys))
-	if err := datastore.GetMulti(c, statsKeys, stats); err != nil {
+	if err := db.GetMulti(c, statsKeys, stats); err != nil {
 		return nil, err
 	}
 	var fullStats []*ManagerStats
@@ -711,61 +866,98 @@
 	var results []*uiManager
 	for i, mgr := range managers {
 		stats := fullStats[i]
+		link := mgr.Link
+		if accessLevel < AccessUser {
+			link = ""
+		}
 		results = append(results, &uiManager{
-			Namespace:          mgr.Namespace,
-			Name:               mgr.Name,
-			Link:               mgr.Link,
-			CurrentBuild:       uiBuilds[mgr.Namespace+"|"+mgr.CurrentBuild],
-			FailedBuildBugLink: bugLink(mgr.FailedBuildBug),
-			LastActive:         mgr.LastAlive,
-			LastActiveBad:      now.Sub(mgr.LastAlive) > 12*time.Hour,
-			CurrentUpTime:      mgr.CurrentUpTime,
-			MaxCorpus:          stats.MaxCorpus,
-			MaxCover:           stats.MaxCover,
-			TotalFuzzingTime:   stats.TotalFuzzingTime,
-			TotalCrashes:       stats.TotalCrashes,
-			TotalExecs:         stats.TotalExecs,
+			Now:                   timeNow(c),
+			Namespace:             mgr.Namespace,
+			Name:                  mgr.Name,
+			Link:                  link,
+			CoverLink:             config.CoverPath + mgr.Name + ".html",
+			CurrentBuild:          uiBuilds[mgr.Namespace+"|"+mgr.CurrentBuild],
+			FailedBuildBugLink:    bugLink(mgr.FailedBuildBug),
+			FailedSyzBuildBugLink: bugLink(mgr.FailedSyzBuildBug),
+			LastActive:            mgr.LastAlive,
+			LastActiveBad:         now.Sub(mgr.LastAlive) > 6*time.Hour,
+			CurrentUpTime:         mgr.CurrentUpTime,
+			MaxCorpus:             stats.MaxCorpus,
+			MaxCover:              stats.MaxCover,
+			TotalFuzzingTime:      stats.TotalFuzzingTime,
+			TotalCrashes:          stats.TotalCrashes,
+			TotalExecs:            stats.TotalExecs,
 		})
 	}
-	sort.Sort(uiManagerSorter(results))
+	sort.Slice(results, func(i, j int) bool {
+		if results[i].Namespace != results[j].Namespace {
+			return results[i].Namespace < results[j].Namespace
+		}
+		return results[i].Name < results[j].Name
+	})
 	return results, nil
 }
 
 func loadRecentJobs(c context.Context) ([]*uiJob, error) {
 	var jobs []*Job
-	keys, err := datastore.NewQuery("Job").
+	keys, err := db.NewQuery("Job").
 		Order("-Created").
-		Limit(20).
+		Limit(80).
 		GetAll(c, &jobs)
 	if err != nil {
 		return nil, err
 	}
 	var results []*uiJob
 	for i, job := range jobs {
-		ui := &uiJob{
-			Created:         job.Created,
-			BugLink:         bugLink(keys[i].Parent().StringID()),
-			ExternalLink:    job.Link,
-			User:            job.User,
-			Reporting:       job.Reporting,
-			Namespace:       job.Namespace,
-			Manager:         job.Manager,
-			BugTitle:        job.BugTitle,
-			KernelAlias:     kernelRepoInfoRaw(job.KernelRepo, job.KernelBranch).Alias,
-			PatchLink:       textLink(textPatch, job.Patch),
-			Attempts:        job.Attempts,
-			Started:         job.Started,
-			Finished:        job.Finished,
-			CrashTitle:      job.CrashTitle,
-			CrashLogLink:    textLink(textCrashLog, job.CrashLog),
-			CrashReportLink: textLink(textCrashReport, job.CrashReport),
-			ErrorLink:       textLink(textError, job.Error),
-		}
-		results = append(results, ui)
+		results = append(results, makeUIJob(job, keys[i], nil, nil))
 	}
 	return results, nil
 }
 
+func makeUIJob(job *Job, jobKey *db.Key, crash *Crash, build *Build) *uiJob {
+	ui := &uiJob{
+		Type:            job.Type,
+		Created:         job.Created,
+		BugLink:         bugLink(jobKey.Parent().StringID()),
+		ExternalLink:    job.Link,
+		User:            job.User,
+		Reporting:       job.Reporting,
+		Namespace:       job.Namespace,
+		Manager:         job.Manager,
+		BugTitle:        job.BugTitle,
+		KernelAlias:     kernelRepoInfoRaw(job.Namespace, job.KernelRepo, job.KernelBranch).Alias,
+		PatchLink:       textLink(textPatch, job.Patch),
+		Attempts:        job.Attempts,
+		Started:         job.Started,
+		Finished:        job.Finished,
+		CrashTitle:      job.CrashTitle,
+		CrashLogLink:    textLink(textCrashLog, job.CrashLog),
+		CrashReportLink: textLink(textCrashReport, job.CrashReport),
+		LogLink:         textLink(textLog, job.Log),
+		ErrorLink:       textLink(textError, job.Error),
+	}
+	if !job.Finished.IsZero() {
+		ui.Duration = job.Finished.Sub(job.Started)
+	}
+	for _, com := range job.Commits {
+		ui.Commits = append(ui.Commits, &uiCommit{
+			Hash:   com.Hash,
+			Title:  com.Title,
+			Author: fmt.Sprintf("%v <%v>", com.AuthorName, com.Author),
+			CC:     strings.Split(com.CC, "|"),
+			Date:   com.Date,
+		})
+	}
+	if len(ui.Commits) == 1 {
+		ui.Commit = ui.Commits[0]
+		ui.Commits = nil
+	}
+	if crash != nil {
+		ui.Crash = makeUICrash(crash, build)
+	}
+	return ui
+}
+
 func fetchErrorLogs(c context.Context) ([]byte, error) {
 	const (
 		minLogLevel  = 3
@@ -821,40 +1013,3 @@
 	}
 	return "/bug?id=" + id
 }
-
-type uiManagerSorter []*uiManager
-
-func (a uiManagerSorter) Len() int      { return len(a) }
-func (a uiManagerSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a uiManagerSorter) Less(i, j int) bool {
-	if a[i].Namespace != a[j].Namespace {
-		return a[i].Namespace < a[j].Namespace
-	}
-	return a[i].Name < a[j].Name
-}
-
-type uiBugSorter []*uiBug
-
-func (a uiBugSorter) Len() int      { return len(a) }
-func (a uiBugSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-func (a uiBugSorter) Less(i, j int) bool {
-	if a[i].Namespace != a[j].Namespace {
-		return a[i].Namespace < a[j].Namespace
-	}
-	if a[i].ClosedTime != a[j].ClosedTime {
-		return a[i].ClosedTime.After(a[j].ClosedTime)
-	}
-	return a[i].ReportedTime.After(a[j].ReportedTime)
-}
-
-type uiBugGroupSorter []*uiBugGroup
-
-func (a uiBugGroupSorter) Len() int           { return len(a) }
-func (a uiBugGroupSorter) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a uiBugGroupSorter) Less(i, j int) bool { return a[i].ShowIndex > a[j].ShowIndex }
-
-type uiBugNamespaceSorter []*uiBugNamespace
-
-func (a uiBugNamespaceSorter) Len() int           { return len(a) }
-func (a uiBugNamespaceSorter) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a uiBugNamespaceSorter) Less(i, j int) bool { return a[i].Caption < a[j].Caption }
diff --git a/dashboard/app/main.html b/dashboard/app/main.html
index d522444..4c1191a 100644
--- a/dashboard/app/main.html
+++ b/dashboard/app/main.html
@@ -14,114 +14,12 @@
 <body>
 	{{template "header" .Header}}
 
-	{{if .Log}}
-	<b>Error log:</b><br>
-	<textarea id="log_textarea" readonly rows="20" wrap=off>{{printf "%s" .Log}}</textarea>
-	<script>
-		var textarea = document.getElementById("log_textarea");
-		textarea.scrollTop = textarea.scrollHeight;
-	</script>
-	<br><br>
+	{{if $.FixedLink}}
+		<a href="{{$.FixedLink}}">fixed bugs ({{$.FixedCount}})</a>
 	{{end}}
-
-	{{if $.Managers}}
-	<table class="list_table" id="managers">
-		<caption>Managers:</caption>
-		<tr>
-			<th>Name</th>
-			<th>Last Active</th>
-			<th>Current Build</th>
-			<th>Current Uptime</th>
-			<th>Today: Fuzzing Time</th>
-			<th>Corpus</th>
-			<th>Coverage</th>
-			<th>Crashes</th>
-			<th>Execs</th>
-			<th>Failed Build</th>
-		</tr>
-		{{range $mgr := $.Managers}}
-			<tr>
-				<td><a href="{{$mgr.Link}}">{{$mgr.Namespace}}/{{$mgr.Name}}</a></td>
-				<td class="stat {{if $mgr.LastActiveBad}}bad{{end}}">{{formatLateness $.Now $mgr.LastActive}}</td>
-				{{if $mgr.CurrentBuild}}
-					<td class="stat" title="{{$mgr.CurrentBuild.KernelAlias}}/{{$mgr.CurrentBuild.KernelCommit}} (syzkaller {{$mgr.CurrentBuild.SyzkallerCommit}})">{{formatLateness $.Now $mgr.CurrentBuild.Time}}</td>
-				{{else}}
-					<td></td>
-				{{end}}
-				<td class="stat">{{formatDuration $mgr.CurrentUpTime}}</td>
-				<td class="stat">{{formatDuration $mgr.TotalFuzzingTime}}</td>
-				<td class="stat">{{formatStat $mgr.MaxCorpus}}</td>
-				<td class="stat">{{formatStat $mgr.MaxCover}}</td>
-				<td class="stat">{{formatStat $mgr.TotalCrashes}}</td>
-				<td class="stat">{{formatStat $mgr.TotalExecs}}</td>
-				<td class="stat">{{if $mgr.FailedBuildBugLink}}<a href="{{$mgr.FailedBuildBugLink}}" class="bad">bug</a>{{end}}</td>
-			</tr>
-		{{end}}
-	</table>
-	<br><br>
-	{{end}}
-
-	{{if $.Jobs}}
-	<table class="list_table" id="jobs">
-		<caption>Recent jobs:</caption>
-		<tr>
-			<th>Bug</th>
-			<th>Created</th>
-			<th>Started</th>
-			<th>Finished</th>
-			<th>User</th>
-			<th>Patch</th>
-			<th>Repo</th>
-			<th>Manager</th>
-			<th>Result</th>
-		</tr>
-		{{range $job := $.Jobs}}
-			<tr>
-				<td class="title"><a href="{{$job.BugLink}}">{{$job.BugTitle}}</a></td>
-				<td class="time">{{if $job.ExternalLink}}<a href="{{$job.ExternalLink}}">{{formatTime $job.Created}}</a>{{else}}{{formatTime $job.Created}}{{end}}</td>
-				<td class="time">{{formatTime $job.Started}}{{if gt $job.Attempts 1}} ({{$job.Attempts}}){{end}}</td>
-				<td class="time">{{formatTime $job.Finished}}</td>
-				<td>{{$job.User}}</td>
-				<td><a href="{{$job.PatchLink}}">patch</a></td>
-				<td class="kernel" title="{{$job.KernelAlias}}">{{$job.KernelAlias}}</td>
-				<td title="{{$job.Namespace}}/{{$job.Reporting}}">{{$job.Manager}}</td>
-				{{if $job.ErrorLink}}
-					<td class="result"><a href="{{$job.ErrorLink}}">error</a></td>
-				{{else if $job.CrashTitle}}
-					<td class="result" title="{{$job.CrashTitle}}">
-						{{if $job.CrashReportLink}}
-							<a href="{{$job.CrashReportLink}}">report</a>
-						{{end}}
-						{{if $job.CrashLogLink}}
-							 <a href="{{$job.CrashLogLink}}">log</a>
-						{{end}}
-					</td>
-				{{else if formatTime $job.Finished}}
-					<td class="result">OK</td>
-				{{else if formatTime $job.Started}}
-					<td class="result">running</td>
-				{{else}}
-					<td class="result">pending</td>
-				{{end}}
-			</tr>
-		{{end}}
-	</table>
-	<br><br>
-	{{end}}
-
-	{{range $ns := $.BugNamespaces}}
-		<br>
-		<h2 id="{{$ns.Name}}">{{$ns.Caption}}</h2>
-		{{if $ns.FixedLink}}
-			{{if $ns.CoverLink}}
-				<a href="{{$ns.CoverLink}}" target="_blank">source coverage</a> |
-			{{end}}
-			<a href="{{$ns.FixedLink}}">fixed bugs ({{$ns.FixedCount}})</a>
-		{{end}}
-		{{range $group := $ns.Groups}}
-			{{template "bug_list" $group}}
-		{{end}}
-		<br>
+	{{template "manager_list" $.Managers}}
+	{{range $group := $.Groups}}
+		{{template "bug_list" $group}}
 	{{end}}
 </body>
 </html>
diff --git a/dashboard/app/noaetest.go b/dashboard/app/noaetest.go
new file mode 100644
index 0000000..5c461b7
--- /dev/null
+++ b/dashboard/app/noaetest.go
@@ -0,0 +1,8 @@
+// Copyright 2019 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// +build !aetest
+
+package dash
+
+const isAppEngineTest = false
diff --git a/dashboard/app/notifications_test.go b/dashboard/app/notifications_test.go
new file mode 100644
index 0000000..093c6a7
--- /dev/null
+++ b/dashboard/app/notifications_test.go
@@ -0,0 +1,255 @@
+// Copyright 2019 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+// +build aetest
+
+package dash
+
+import (
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/google/syzkaller/dashboard/dashapi"
+)
+
+func TestEmailNotifUpstreamEmbargo(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+
+	crash := testCrash(build, 1)
+	c.client2.ReportCrash(crash)
+	report := c.pollEmailBug()
+	c.expectEQ(report.To, []string{"test@syzkaller.com"})
+
+	// Upstreaming happens after 14 days, so no emails yet.
+	c.advanceTime(13 * 24 * time.Hour)
+	c.expectNoEmail()
+
+	// Now we should get notification about upstreaming and upstream report:
+	c.advanceTime(2 * 24 * time.Hour)
+	notifUpstream := c.pollEmailBug()
+	upstreamReport := c.pollEmailBug()
+	c.expectEQ(notifUpstream.Sender, report.Sender)
+	c.expectEQ(notifUpstream.Body, "Sending this report upstream.")
+	c.expectNE(upstreamReport.Sender, report.Sender)
+	c.expectEQ(upstreamReport.To, []string{"bugs@syzkaller.com", "default@maintainers.com"})
+}
+
+func TestEmailNotifUpstreamSkip(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+
+	crash := testCrash(build, 1)
+	crash.Title = "skip with repro 1"
+	c.client2.ReportCrash(crash)
+	report := c.pollEmailBug()
+	c.expectEQ(report.To, []string{"test@syzkaller.com"})
+
+	// No emails yet.
+	c.expectNoEmail()
+
+	// Now upload repro and it should be auto-upstreamed.
+	crash.ReproOpts = []byte("repro opts")
+	crash.ReproSyz = []byte("getpid()")
+	c.client2.ReportCrash(crash)
+	notifUpstream := c.pollEmailBug()
+	upstreamReport := c.pollEmailBug()
+	c.expectEQ(notifUpstream.Sender, report.Sender)
+	c.expectEQ(notifUpstream.Body, "Sending this report upstream.")
+	c.expectNE(upstreamReport.Sender, report.Sender)
+	c.expectEQ(upstreamReport.To, []string{"bugs@syzkaller.com", "default@maintainers.com"})
+}
+
+func TestEmailNotifBadFix(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+
+	crash := testCrash(build, 1)
+	c.client2.ReportCrash(crash)
+	report := c.pollEmailBug()
+	c.expectEQ(report.To, []string{"test@syzkaller.com"})
+
+	c.incomingEmail(report.Sender, "#syz fix some: commit title")
+	c.expectNoEmail()
+
+	// Notification about bad fixing commit should be send after 90 days.
+	c.advanceTime(50 * 24 * time.Hour)
+	c.expectNoEmail()
+	c.advanceTime(35 * 24 * time.Hour)
+	c.expectNoEmail()
+	c.advanceTime(10 * 24 * time.Hour)
+	notif := c.pollEmailBug()
+	if !strings.Contains(notif.Body, "This bug is marked as fixed by commit:\nsome: commit title\n") {
+		t.Fatalf("bad notification text: %q", notif.Body)
+	}
+	// No notifications for another 14 days, then another one.
+	c.advanceTime(13 * 24 * time.Hour)
+	c.expectNoEmail()
+	c.advanceTime(2 * 24 * time.Hour)
+	notif = c.pollEmailBug()
+	if !strings.Contains(notif.Body, "This bug is marked as fixed by commit:\nsome: commit title\n") {
+		t.Fatalf("bad notification text: %q", notif.Body)
+	}
+}
+
+func TestEmailNotifObsoleted(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+
+	crash := testCrash(build, 1)
+	crash.Maintainers = []string{"maintainer@syzkaller.com"}
+	c.client2.ReportCrash(crash)
+	report := c.pollEmailBug()
+	// Need to upstream so that it's not auto-upstreamed before obsoleted.
+	c.incomingEmail(report.Sender, "#syz upstream")
+	report = c.pollEmailBug()
+	// Add more people to bug CC.
+	c.incomingEmail(report.Sender, "wow", EmailOptCC([]string{"somebody@else.com"}))
+
+	// Bug is open, new crashes don't create new bug.
+	c.client2.ReportCrash(crash)
+	c.expectNoEmail()
+
+	// Not yet.
+	c.advanceTime(179 * 24 * time.Hour)
+	c.expectNoEmail()
+
+	// Now!
+	c.advanceTime(2 * 24 * time.Hour)
+	notif := c.pollEmailBug()
+	if !strings.Contains(notif.Body, "Auto-closing this bug as obsolete") {
+		t.Fatalf("bad notification text: %q", notif.Body)
+	}
+	c.expectEQ(notif.To, []string{"bugs@syzkaller.com", "default@sender.com", "somebody@else.com"})
+
+	// New crash must create new bug.
+	c.client2.ReportCrash(crash)
+	report = c.pollEmailBug()
+	c.expectEQ(report.Subject, "title1 (2)")
+	// Now the same, but for the last reporting (must have smaller CC list).
+	c.incomingEmail(report.Sender, "#syz upstream")
+	report = c.pollEmailBug()
+	c.incomingEmail(report.Sender, "#syz upstream")
+	report = c.pollEmailBug()
+
+	c.advanceTime(181 * 24 * time.Hour)
+	notif = c.pollEmailBug()
+	if !strings.Contains(notif.Body, "Auto-closing this bug as obsolete") {
+		t.Fatalf("bad notification text: %q", notif.Body)
+	}
+	c.expectEQ(notif.To, []string{"bugs2@syzkaller.com"})
+}
+
+func TestEmailNotifNotObsoleted(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build := testBuild(1)
+	c.client2.UploadBuild(build)
+
+	// Crashes with repro are not auto-obsoleted.
+	crash1 := testCrash(build, 1)
+	crash1.ReproSyz = []byte("repro")
+	c.client2.ReportCrash(crash1)
+	report1 := c.pollEmailBug()
+	c.incomingEmail(report1.Sender, "#syz upstream")
+	report1 = c.pollEmailBug()
+
+	// This crash will get another crash later.
+	crash2 := testCrash(build, 2)
+	c.client2.ReportCrash(crash2)
+	report2 := c.pollEmailBug()
+	c.incomingEmail(report2.Sender, "#syz upstream")
+	report2 = c.pollEmailBug()
+
+	// This crash will get some activity later.
+	crash3 := testCrash(build, 3)
+	c.client2.ReportCrash(crash3)
+	report3 := c.pollEmailBug()
+	c.incomingEmail(report3.Sender, "#syz upstream")
+	report3 = c.pollEmailBug()
+
+	// This will be obsoleted (just to check that we have timings right).
+	c.advanceTime(24 * time.Hour)
+	crash4 := testCrash(build, 4)
+	c.client2.ReportCrash(crash4)
+	report4 := c.pollEmailBug()
+	c.incomingEmail(report4.Sender, "#syz upstream")
+	report4 = c.pollEmailBug()
+
+	c.advanceTime(179 * 24 * time.Hour)
+	c.expectNoEmail()
+
+	c.client2.ReportCrash(crash2)
+	c.incomingEmail(report3.Sender, "I am looking at it")
+
+	c.advanceTime(5 * 24 * time.Hour)
+	// Only crash 4 is obsoleted.
+	notif := c.pollEmailBug()
+	c.expectEQ(notif.Sender, report4.Sender)
+	c.expectNoEmail()
+
+	// Crash 3 also obsoleted after some time.
+	c.advanceTime(20 * 24 * time.Hour)
+	notif = c.pollEmailBug()
+	c.expectEQ(notif.Sender, report3.Sender)
+}
+
+func TestExtNotifUpstreamEmbargo(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build1 := testBuild(1)
+	c.client.UploadBuild(build1)
+
+	crash1 := testCrash(build1, 1)
+	c.client.ReportCrash(crash1)
+	rep := c.client.pollBug()
+
+	// Specify fixing commit for the bug.
+	reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
+		ID:     rep.ID,
+		Status: dashapi.BugStatusOpen,
+	})
+	c.expectEQ(reply.OK, true)
+	c.client.pollNotifs(0)
+	c.advanceTime(20 * 24 * time.Hour)
+	notif := c.client.pollNotifs(1)[0]
+	c.expectEQ(notif.ID, rep.ID)
+	c.expectEQ(notif.Type, dashapi.BugNotifUpstream)
+}
+
+func TestExtNotifUpstreamOnHold(t *testing.T) {
+	c := NewCtx(t)
+	defer c.Close()
+
+	build1 := testBuild(1)
+	c.client.UploadBuild(build1)
+
+	crash1 := testCrash(build1, 1)
+	c.client.ReportCrash(crash1)
+	rep := c.client.pollBug()
+
+	// Specify fixing commit for the bug.
+	reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
+		ID:     rep.ID,
+		Status: dashapi.BugStatusOpen,
+		OnHold: true,
+	})
+	c.expectEQ(reply.OK, true)
+	c.advanceTime(20 * 24 * time.Hour)
+	c.client.pollNotifs(0)
+}
diff --git a/dashboard/app/reporting.go b/dashboard/app/reporting.go
index 2ca8301..5020219 100644
--- a/dashboard/app/reporting.go
+++ b/dashboard/app/reporting.go
@@ -14,8 +14,9 @@
 
 	"github.com/google/syzkaller/dashboard/dashapi"
 	"github.com/google/syzkaller/pkg/email"
+	"github.com/google/syzkaller/pkg/html"
 	"golang.org/x/net/context"
-	"google.golang.org/appengine/datastore"
+	db "google.golang.org/appengine/datastore"
 	"google.golang.org/appengine/log"
 )
 
@@ -25,10 +26,13 @@
 //  - incomingCommand is called by backends to update bug statuses.
 
 const (
-	maxMailLogLen    = 1 << 20
-	maxMailReportLen = 64 << 10
-	maxInlineError   = 16 << 10
-	internalError    = "internal error"
+	maxMailLogLen              = 1 << 20
+	maxMailReportLen           = 64 << 10
+	maxInlineError             = 16 << 10
+	notifyResendPeriod         = 14 * 24 * time.Hour
+	notifyAboutBadCommitPeriod = 90 * 24 * time.Hour
+	autoObsoletePeriod         = 180 * 24 * time.Hour
+	internalError              = "internal error"
 	// This is embedded as first line of syzkaller reproducer files.
 	syzReproPrefix = "# See https://goo.gl/kgGztJ for information about syzkaller reproducers.\n"
 )
@@ -41,7 +45,7 @@
 		return nil
 	}
 	var bugs []*Bug
-	_, err = datastore.NewQuery("Bug").
+	_, err = db.NewQuery("Bug").
 		Filter("Status<", BugStatusFixed).
 		GetAll(c, &bugs)
 	if err != nil {
@@ -61,19 +65,17 @@
 			continue
 		}
 		reports = append(reports, rep)
-		if len(reports) > 50 {
-			break // temp measure during the jam
-		}
 	}
 	return reports
 }
 
-func handleReportBug(c context.Context, typ string, state *ReportingState, bug *Bug) (*dashapi.BugReport, error) {
+func handleReportBug(c context.Context, typ string, state *ReportingState, bug *Bug) (
+	*dashapi.BugReport, error) {
 	reporting, bugReporting, crash, crashKey, _, _, _, err := needReport(c, typ, state, bug)
 	if err != nil || reporting == nil {
 		return nil, err
 	}
-	rep, err := createBugReport(c, bug, crash, crashKey, bugReporting, reporting.Config)
+	rep, err := createBugReport(c, bug, crash, crashKey, bugReporting, reporting)
 	if err != nil {
 		return nil, err
 	}
@@ -83,7 +85,7 @@
 
 func needReport(c context.Context, typ string, state *ReportingState, bug *Bug) (
 	reporting *Reporting, bugReporting *BugReporting, crash *Crash,
-	crashKey *datastore.Key, reportingIdx int, status, link string, err error) {
+	crashKey *db.Key, reportingIdx int, status, link string, err error) {
 	reporting, bugReporting, reportingIdx, status, err = currentReporting(c, bug)
 	if err != nil || reporting == nil {
 		return
@@ -97,7 +99,7 @@
 	if !bugReporting.Reported.IsZero() && bugReporting.ReproLevel >= bug.ReproLevel {
 		status = fmt.Sprintf("%v: reported%v on %v",
 			reporting.DisplayTitle, reproStr(bugReporting.ReproLevel),
-			formatTime(bugReporting.Reported))
+			html.FormatTime(bugReporting.Reported))
 		reporting, bugReporting = nil, nil
 		return
 	}
@@ -125,11 +127,6 @@
 		reporting, bugReporting = nil, nil
 		return
 	}
-	if reporting.Config.NeedMaintainers() && len(crash.Maintainers) == 0 {
-		status = fmt.Sprintf("%v: no maintainers", reporting.DisplayTitle)
-		reporting, bugReporting = nil, nil
-		return
-	}
 
 	// Limit number of reports sent per day,
 	// but don't limit sending repros to already reported bugs.
@@ -149,11 +146,118 @@
 	status = fmt.Sprintf("%v: ready to report", reporting.DisplayTitle)
 	if !bugReporting.Reported.IsZero() {
 		status += fmt.Sprintf(" (reported%v on %v)",
-			reproStr(bugReporting.ReproLevel), formatTime(bugReporting.Reported))
+			reproStr(bugReporting.ReproLevel), html.FormatTime(bugReporting.Reported))
 	}
 	return
 }
 
+func reportingPollNotifications(c context.Context, typ string) []*dashapi.BugNotification {
+	var bugs []*Bug
+	_, err := db.NewQuery("Bug").
+		Filter("Status<", BugStatusFixed).
+		GetAll(c, &bugs)
+	if err != nil {
+		log.Errorf(c, "%v", err)
+		return nil
+	}
+	log.Infof(c, "fetched %v bugs", len(bugs))
+	var notifs []*dashapi.BugNotification
+	for _, bug := range bugs {
+		notif, err := handleReportNotif(c, typ, bug)
+		if err != nil {
+			log.Errorf(c, "%v: failed to create bug notif %v: %v", bug.Namespace, bug.Title, err)
+			continue
+		}
+		if notif == nil {
+			continue
+		}
+		notifs = append(notifs, notif)
+		if len(notifs) >= 10 {
+			break // don't send too many at once just in case
+		}
+	}
+	return notifs
+}
+
+func handleReportNotif(c context.Context, typ string, bug *Bug) (*dashapi.BugNotification, error) {
+	reporting, bugReporting, _, _, err := currentReporting(c, bug)
+	if err != nil || reporting == nil {
+		return nil, nil
+	}
+	if typ != "" && typ != reporting.Config.Type() {
+		return nil, nil
+	}
+	if bug.Status != BugStatusOpen || bugReporting.Reported.IsZero() {
+		return nil, nil
+	}
+
+	if reporting.moderation &&
+		reporting.Embargo != 0 &&
+		len(bug.Commits) == 0 &&
+		bugReporting.OnHold.IsZero() &&
+		timeSince(c, bugReporting.Reported) > reporting.Embargo {
+		log.Infof(c, "%v: upstreaming (embargo): %v", bug.Namespace, bug.Title)
+		return createNotification(c, dashapi.BugNotifUpstream, true, "", bug, reporting, bugReporting)
+	}
+	if reporting.moderation &&
+		len(bug.Commits) == 0 &&
+		bugReporting.OnHold.IsZero() &&
+		reporting.Filter(bug) == FilterSkip {
+		log.Infof(c, "%v: upstreaming (skip): %v", bug.Namespace, bug.Title)
+		return createNotification(c, dashapi.BugNotifUpstream, true, "", bug, reporting, bugReporting)
+	}
+	if len(bug.Commits) == 0 &&
+		bug.ReproLevel == ReproLevelNone &&
+		timeSince(c, bug.LastActivity) > notifyResendPeriod &&
+		timeSince(c, bug.LastTime) > autoObsoletePeriod {
+		log.Infof(c, "%v: obsoleting: %v", bug.Namespace, bug.Title)
+		return createNotification(c, dashapi.BugNotifObsoleted, false, "", bug, reporting, bugReporting)
+	}
+	if len(bug.Commits) > 0 &&
+		len(bug.PatchedOn) == 0 &&
+		timeSince(c, bug.LastActivity) > notifyResendPeriod &&
+		timeSince(c, bug.FixTime) > notifyAboutBadCommitPeriod {
+		log.Infof(c, "%v: bad fix commit: %v", bug.Namespace, bug.Title)
+		commits := strings.Join(bug.Commits, "\n")
+		return createNotification(c, dashapi.BugNotifBadCommit, true, commits, bug, reporting, bugReporting)
+	}
+	return nil, nil
+}
+
+func createNotification(c context.Context, typ dashapi.BugNotif, public bool, text string, bug *Bug,
+	reporting *Reporting, bugReporting *BugReporting) (*dashapi.BugNotification, error) {
+	reportingConfig, err := json.Marshal(reporting.Config)
+	if err != nil {
+		return nil, err
+	}
+	crash, _, err := findCrashForBug(c, bug)
+	if err != nil {
+		return nil, fmt.Errorf("no crashes for bug")
+	}
+	build, err := loadBuild(c, bug.Namespace, crash.BuildID)
+	if err != nil {
+		return nil, err
+	}
+	kernelRepo := kernelRepoInfo(build)
+	notif := &dashapi.BugNotification{
+		Type:      typ,
+		Namespace: bug.Namespace,
+		Config:    reportingConfig,
+		ID:        bugReporting.ID,
+		ExtID:     bugReporting.ExtID,
+		Title:     bug.displayTitle(),
+		Text:      text,
+		Public:    public,
+	}
+	if public {
+		notif.Maintainers = append(crash.Maintainers, kernelRepo.CC...)
+	}
+	if (public || reporting.moderation) && bugReporting.CC != "" {
+		notif.CC = strings.Split(bugReporting.CC, "|")
+	}
+	return notif, nil
+}
+
 func currentReporting(c context.Context, bug *Bug) (*Reporting, *BugReporting, int, string, error) {
 	for i := range bug.Reporting {
 		bugReporting := &bug.Reporting[i]
@@ -190,12 +294,26 @@
 	}
 }
 
-func createBugReport(c context.Context, bug *Bug, crash *Crash, crashKey *datastore.Key,
-	bugReporting *BugReporting, config interface{}) (*dashapi.BugReport, error) {
-	reportingConfig, err := json.Marshal(config)
+func createBugReport(c context.Context, bug *Bug, crash *Crash, crashKey *db.Key,
+	bugReporting *BugReporting, reporting *Reporting) (*dashapi.BugReport, error) {
+	reportingConfig, err := json.Marshal(reporting.Config)
 	if err != nil {
 		return nil, err
 	}
+	var job *Job
+	if bug.BisectCause == BisectYes {
+		// If we have bisection results, report the crash/repro used for bisection.
+		job1, crash1, _, crashKey1, err := loadBisectJob(c, bug)
+		if err != nil {
+			return nil, err
+		}
+		job = job1
+		if crash1.ReproC != 0 || crash.ReproC == 0 {
+			// Don't override the crash in this case,
+			// otherwise we will always think that we haven't reported the C repro.
+			crash, crashKey = crash1, crashKey1
+		}
+	}
 	crashLog, _, err := getText(c, textCrashLog, crash.Log)
 	if err != nil {
 		return nil, err
@@ -231,49 +349,104 @@
 	if err != nil {
 		return nil, err
 	}
-	kernelConfig, _, err := getText(c, textKernelConfig, build.KernelConfig)
-	if err != nil {
-		return nil, err
+	typ := dashapi.ReportNew
+	if !bugReporting.Reported.IsZero() {
+		typ = dashapi.ReportRepro
 	}
 
+	kernelRepo := kernelRepoInfo(build)
 	rep := &dashapi.BugReport{
-		Namespace:         bug.Namespace,
-		Config:            reportingConfig,
-		ID:                bugReporting.ID,
-		ExtID:             bugReporting.ExtID,
-		First:             bugReporting.Reported.IsZero(),
-		Title:             bug.displayTitle(),
-		Log:               crashLog,
-		LogLink:           externalLink(c, textCrashLog, crash.Log),
-		Report:            report,
-		ReportLink:        externalLink(c, textCrashReport, crash.Report),
-		Maintainers:       crash.Maintainers,
-		OS:                build.OS,
-		Arch:              build.Arch,
-		VMArch:            build.VMArch,
-		CompilerID:        build.CompilerID,
-		KernelRepo:        build.KernelRepo,
-		KernelRepoAlias:   kernelRepoInfo(build).Alias,
-		KernelBranch:      build.KernelBranch,
-		KernelCommit:      build.KernelCommit,
-		KernelCommitTitle: build.KernelCommitTitle,
-		KernelCommitDate:  build.KernelCommitDate,
-		KernelConfig:      kernelConfig,
-		KernelConfigLink:  externalLink(c, textKernelConfig, build.KernelConfig),
-		ReproC:            reproC,
-		ReproCLink:        externalLink(c, textReproC, crash.ReproC),
-		ReproSyz:          reproSyz,
-		ReproSyzLink:      externalLink(c, textReproSyz, crash.ReproSyz),
-		CrashID:           crashKey.IntID(),
-		NumCrashes:        bug.NumCrashes,
-		HappenedOn:        managersToRepos(c, bug.Namespace, bug.HappenedOn),
+		Type:         typ,
+		Config:       reportingConfig,
+		ExtID:        bugReporting.ExtID,
+		First:        bugReporting.Reported.IsZero(),
+		Moderation:   reporting.moderation,
+		Log:          crashLog,
+		LogLink:      externalLink(c, textCrashLog, crash.Log),
+		Report:       report,
+		ReportLink:   externalLink(c, textCrashReport, crash.Report),
+		Maintainers:  append(crash.Maintainers, kernelRepo.CC...),
+		ReproC:       reproC,
+		ReproCLink:   externalLink(c, textReproC, crash.ReproC),
+		ReproSyz:     reproSyz,
+		ReproSyzLink: externalLink(c, textReproSyz, crash.ReproSyz),
+		CrashID:      crashKey.IntID(),
+		NumCrashes:   bug.NumCrashes,
+		HappenedOn:   managersToRepos(c, bug.Namespace, bug.HappenedOn),
 	}
 	if bugReporting.CC != "" {
 		rep.CC = strings.Split(bugReporting.CC, "|")
 	}
+	if bug.BisectCause == BisectYes {
+		rep.BisectCause = bisectFromJob(c, rep, job)
+	}
+	if err := fillBugReport(c, rep, bug, bugReporting, build); err != nil {
+		return nil, err
+	}
 	return rep, nil
 }
 
+// fillBugReport fills common report fields for bug and job reports.
+func fillBugReport(c context.Context, rep *dashapi.BugReport, bug *Bug, bugReporting *BugReporting,
+	build *Build) error {
+	kernelConfig, _, err := getText(c, textKernelConfig, build.KernelConfig)
+	if err != nil {
+		return err
+	}
+	creditEmail, err := email.AddAddrContext(ownEmail(c), bugReporting.ID)
+	if err != nil {
+		return err
+	}
+	rep.Namespace = bug.Namespace
+	rep.ID = bugReporting.ID
+	rep.Title = bug.displayTitle()
+	rep.Link = fmt.Sprintf("%v/bug?extid=%v", appURL(c), bugReporting.ID)
+	rep.CreditEmail = creditEmail
+	rep.OS = build.OS
+	rep.Arch = build.Arch
+	rep.VMArch = build.VMArch
+	rep.UserSpaceArch = kernelArch(build.Arch)
+	rep.CompilerID = build.CompilerID
+	rep.KernelRepo = build.KernelRepo
+	rep.KernelRepoAlias = kernelRepoInfo(build).Alias
+	rep.KernelBranch = build.KernelBranch
+	rep.KernelCommit = build.KernelCommit
+	rep.KernelCommitTitle = build.KernelCommitTitle
+	rep.KernelCommitDate = build.KernelCommitDate
+	rep.KernelConfig = kernelConfig
+	rep.KernelConfigLink = externalLink(c, textKernelConfig, build.KernelConfig)
+	for _, addr := range bug.UNCC {
+		rep.CC = email.RemoveFromEmailList(rep.CC, addr)
+		rep.Maintainers = email.RemoveFromEmailList(rep.Maintainers, addr)
+	}
+	return nil
+}
+
+func loadBisectJob(c context.Context, bug *Bug) (*Job, *Crash, *db.Key, *db.Key, error) {
+	bugKey := bug.key(c)
+	var jobs []*Job
+	keys, err := db.NewQuery("Job").
+		Ancestor(bugKey).
+		Filter("Type=", JobBisectCause).
+		Filter("Finished>", time.Time{}).
+		Order("-Finished").
+		Limit(1).
+		GetAll(c, &jobs)
+	if err != nil {
+		return nil, nil, nil, nil, fmt.Errorf("failed to query jobs: %v", err)
+	}
+	if len(jobs) == 0 {
+		return nil, nil, nil, nil, fmt.Errorf("can't find bisect cause job for bug")
+	}
+	job := jobs[0]
+	crash := new(Crash)
+	crashKey := db.NewKey(c, "Crash", "", job.CrashID, bugKey)
+	if err := db.Get(c, crashKey, crash); err != nil {
+		return nil, nil, nil, nil, fmt.Errorf("failed to get crash: %v", err)
+	}
+	return job, crash, keys[0], crashKey, nil
+}
+
 func managersToRepos(c context.Context, ns string, managers []string) []string {
 	var repos []string
 	dedup := make(map[string]bool)
@@ -294,38 +467,55 @@
 	return repos
 }
 
+func foreachBug(c context.Context, fn func(bug *Bug) error) error {
+	const batchSize = 1000
+	for offset := 0; ; offset += batchSize {
+		var bugs []*Bug
+		_, err := db.NewQuery("Bug").
+			Offset(offset).
+			Limit(batchSize).
+			GetAll(c, &bugs)
+		if err != nil {
+			return fmt.Errorf("foreachBug: failed to query bugs: %v", err)
+		}
+		for _, bug := range bugs {
+			if err := fn(bug); err != nil {
+				return err
+			}
+		}
+		if len(bugs) < batchSize {
+			return nil
+		}
+	}
+}
+
 // reportingPollClosed is called by backends to get list of closed bugs.
 func reportingPollClosed(c context.Context, ids []string) ([]string, error) {
-	var bugs []*Bug
-	_, err := datastore.NewQuery("Bug").
-		GetAll(c, &bugs)
-	if err != nil {
-		log.Errorf(c, "%v", err)
-		return nil, nil
-	}
-	bugMap := make(map[string]*Bug)
-	for _, bug := range bugs {
-		for i := range bug.Reporting {
-			bugMap[bug.Reporting[i].ID] = bug
-		}
+	idMap := make(map[string]bool, len(ids))
+	for _, id := range ids {
+		idMap[id] = true
 	}
 	var closed []string
-	for _, id := range ids {
-		bug := bugMap[id]
-		if bug == nil {
-			continue
+	err := foreachBug(c, func(bug *Bug) error {
+		for i := range bug.Reporting {
+			bugReporting := &bug.Reporting[i]
+			if !idMap[bugReporting.ID] {
+				continue
+			}
+			var err error
+			bug, err = canonicalBug(c, bug)
+			if err != nil {
+				log.Errorf(c, "%v", err)
+				break
+			}
+			if bug.Status >= BugStatusFixed || !bugReporting.Closed.IsZero() {
+				closed = append(closed, bugReporting.ID)
+			}
+			break
 		}
-		bugReporting, _ := bugReportingByID(bug, id)
-		bug, err = canonicalBug(c, bug)
-		if err != nil {
-			log.Errorf(c, "%v", err)
-			continue
-		}
-		if bug.Status >= BugStatusFixed || !bugReporting.Closed.IsZero() {
-			closed = append(closed, id)
-		}
-	}
-	return closed, nil
+		return nil
+	})
+	return closed, err
 }
 
 // incomingCommand is entry point to bug status updates.
@@ -357,51 +547,11 @@
 	now := timeNow(c)
 	dupHash := ""
 	if cmd.Status == dashapi.BugStatusDup {
-		bugReporting, _ := bugReportingByID(bug, cmd.ID)
-		dup, dupKey, err := findBugByReportingID(c, cmd.DupOf)
-		if err != nil {
-			// Email reporting passes bug title in cmd.DupOf, try to find bug by title.
-			dup, dupKey, err = findDupByTitle(c, bug.Namespace, cmd.DupOf)
-			if err != nil {
-				return false, "can't find the dup bug", err
-			}
-			dupReporting := bugReportingByName(dup, bugReporting.Name)
-			if dupReporting == nil {
-				return false, "can't find the dup bug",
-					fmt.Errorf("dup does not have reporting %q", bugReporting.Name)
-			}
-			cmd.DupOf = dupReporting.ID
+		dupHash1, ok, reason, err := findDupBug(c, cmd, bug, bugKey)
+		if !ok || err != nil {
+			return ok, reason, err
 		}
-		dupReporting, _ := bugReportingByID(dup, cmd.DupOf)
-		if bugReporting == nil || dupReporting == nil {
-			return false, internalError, fmt.Errorf("can't find bug reporting")
-		}
-		if bugKey.StringID() == dupKey.StringID() {
-			if bugReporting.Name == dupReporting.Name {
-				return false, "Can't dup bug to itself.", nil
-			}
-			return false, fmt.Sprintf("Can't dup bug to itself in different reporting (%v->%v).\n"+
-				"Please dup syzbot bugs only onto syzbot bugs for the same kernel/reporting.",
-				bugReporting.Name, dupReporting.Name), nil
-		}
-		if bug.Namespace != dup.Namespace {
-			return false, fmt.Sprintf("Duplicate bug corresponds to a different kernel (%v->%v).\n"+
-				"Please dup syzbot bugs only onto syzbot bugs for the same kernel.",
-				bug.Namespace, dup.Namespace), nil
-		}
-		if bugReporting.Name != dupReporting.Name {
-			return false, fmt.Sprintf("Can't dup bug to a bug in different reporting (%v->%v)."+
-				"Please dup syzbot bugs only onto syzbot bugs for the same kernel/reporting.",
-				bugReporting.Name, dupReporting.Name), nil
-		}
-		dupCanon, err := canonicalBug(c, dup)
-		if err != nil {
-			return false, internalError, fmt.Errorf("failed to get canonical bug for dup: %v", err)
-		}
-		if !dupReporting.Closed.IsZero() && dupCanon.Status == BugStatusOpen {
-			return false, "Dup bug is already upstreamed.", nil
-		}
-		dupHash = bugKeyHash(dup.Namespace, dup.Title, dup.Seq)
+		dupHash = dupHash1
 	}
 
 	ok, reply := false, ""
@@ -410,7 +560,7 @@
 		ok, reply, err = incomingCommandTx(c, now, cmd, bugKey, dupHash)
 		return err
 	}
-	err = datastore.RunInTransaction(c, tx, &datastore.TransactionOptions{
+	err = db.RunInTransaction(c, tx, &db.TransactionOptions{
 		XG: true,
 		// Default is 3 which fails sometimes.
 		// We don't want incoming bug updates to fail,
@@ -423,10 +573,95 @@
 	return ok, reply, nil
 }
 
+func findDupBug(c context.Context, cmd *dashapi.BugUpdate, bug *Bug, bugKey *db.Key) (
+	string, bool, string, error) {
+	bugReporting, _ := bugReportingByID(bug, cmd.ID)
+	dup, dupKey, err := findBugByReportingID(c, cmd.DupOf)
+	if err != nil {
+		// Email reporting passes bug title in cmd.DupOf, try to find bug by title.
+		dup, dupKey, err = findDupByTitle(c, bug.Namespace, cmd.DupOf)
+		if err != nil {
+			return "", false, "can't find the dup bug", err
+		}
+		dupReporting := lastReportedReporting(dup)
+		if dupReporting == nil {
+			return "", false, "can't find the dup bug",
+				fmt.Errorf("dup does not have reporting %q", bugReporting.Name)
+		}
+		cmd.DupOf = dupReporting.ID
+	}
+	dupReporting, _ := bugReportingByID(dup, cmd.DupOf)
+	if bugReporting == nil || dupReporting == nil {
+		return "", false, internalError, fmt.Errorf("can't find bug reporting")
+	}
+	if bugKey.StringID() == dupKey.StringID() {
+		if bugReporting.Name == dupReporting.Name {
+			return "", false, "Can't dup bug to itself.", nil
+		}
+		return "", false, fmt.Sprintf("Can't dup bug to itself in different reporting (%v->%v).\n"+
+			"Please dup syzbot bugs only onto syzbot bugs for the same kernel/reporting.",
+			bugReporting.Name, dupReporting.Name), nil
+	}
+	if bug.Namespace != dup.Namespace {
+		return "", false, fmt.Sprintf("Duplicate bug corresponds to a different kernel (%v->%v).\n"+
+			"Please dup syzbot bugs only onto syzbot bugs for the same kernel.",
+			bug.Namespace, dup.Namespace), nil
+	}
+	if !allowCrossReportingDup(c, bug, dup, bugReporting, dupReporting) {
+		return "", false, fmt.Sprintf("Can't dup bug to a bug in different reporting (%v->%v)."+
+			"Please dup syzbot bugs only onto syzbot bugs for the same kernel/reporting.",
+			bugReporting.Name, dupReporting.Name), nil
+	}
+	dupCanon, err := canonicalBug(c, dup)
+	if err != nil {
+		return "", false, internalError, fmt.Errorf("failed to get canonical bug for dup: %v", err)
+	}
+	if !dupReporting.Closed.IsZero() && dupCanon.Status == BugStatusOpen {
+		return "", false, "Dup bug is already upstreamed.", nil
+	}
+	dupHash := dup.keyHash()
+	return dupHash, true, "", nil
+}
+
+func allowCrossReportingDup(c context.Context, bug, dup *Bug,
+	bugReporting, dupReporting *BugReporting) bool {
+	bugIdx := getReportingIdx(c, bug, bugReporting)
+	dupIdx := getReportingIdx(c, dup, dupReporting)
+	if bugIdx < 0 || dupIdx < 0 {
+		return false
+	}
+	if bugIdx == dupIdx {
+		return true
+	}
+	// We generally allow duping only within the same reporting.
+	// But there is one exception: we also allow duping from last but one
+	// reporting to the last one (which is stable, final destination)
+	// provided that these two reportings have the same access level and type.
+	// The rest of the combinations can lead to surprising states and
+	// information hiding, so we don't allow them.
+	cfg := config.Namespaces[bug.Namespace]
+	bugConfig := &cfg.Reporting[bugIdx]
+	dupConfig := &cfg.Reporting[dupIdx]
+	lastIdx := len(cfg.Reporting) - 1
+	return bugIdx == lastIdx-1 && dupIdx == lastIdx &&
+		bugConfig.AccessLevel == dupConfig.AccessLevel &&
+		bugConfig.Config.Type() == dupConfig.Config.Type()
+}
+
+func getReportingIdx(c context.Context, bug *Bug, bugReporting *BugReporting) int {
+	for i := range bug.Reporting {
+		if bug.Reporting[i].Name == bugReporting.Name {
+			return i
+		}
+	}
+	log.Errorf(c, "failed to find bug reporting by name: %q/%q", bug.Title, bugReporting.Name)
+	return -1
+}
+
 func incomingCommandTx(c context.Context, now time.Time, cmd *dashapi.BugUpdate,
-	bugKey *datastore.Key, dupHash string) (bool, string, error) {
+	bugKey *db.Key, dupHash string) (bool, string, error) {
 	bug := new(Bug)
-	if err := datastore.Get(c, bugKey, bug); err != nil {
+	if err := db.Get(c, bugKey, bug); err != nil {
 		return false, internalError, fmt.Errorf("can't find the corresponding bug: %v", err)
 	}
 	bugReporting, final := bugReportingByID(bug, cmd.ID)
@@ -447,22 +682,13 @@
 	if len(cmd.FixCommits) != 0 && (bug.Status == BugStatusOpen || bug.Status == BugStatusDup) {
 		sort.Strings(cmd.FixCommits)
 		if !reflect.DeepEqual(bug.Commits, cmd.FixCommits) {
-			bug.Commits = cmd.FixCommits
-			bug.PatchedOn = nil
+			bug.updateCommits(cmd.FixCommits, now)
 		}
 	}
 	if cmd.CrashID != 0 {
 		// Rememeber that we've reported this crash.
-		crash := new(Crash)
-		crashKey := datastore.NewKey(c, "Crash", "", cmd.CrashID, bugKey)
-		if err := datastore.Get(c, crashKey, crash); err != nil {
-			return false, internalError, fmt.Errorf("failed to get reported crash %v: %v",
-				cmd.CrashID, err)
-		}
-		crash.Reported = now
-		if _, err := datastore.Put(c, crashKey, crash); err != nil {
-			return false, internalError, fmt.Errorf("failed to put reported crash %v: %v",
-				cmd.CrashID, err)
+		if err := markCrashReported(c, cmd.CrashID, bugKey, now); err != nil {
+			return false, internalError, err
 		}
 		bugReporting.CrashID = cmd.CrashID
 	}
@@ -472,7 +698,7 @@
 	if bugReporting.Link == "" {
 		bugReporting.Link = cmd.Link
 	}
-	if len(cmd.CC) != 0 {
+	if len(cmd.CC) != 0 && cmd.Status != dashapi.BugStatusUnCC {
 		merged := email.MergeEmailLists(strings.Split(bugReporting.CC, "|"), cmd.CC)
 		bugReporting.CC = strings.Join(merged, "|")
 	}
@@ -482,7 +708,11 @@
 	if bug.Status != BugStatusDup {
 		bug.DupOf = ""
 	}
-	if _, err := datastore.Put(c, bugKey, bug); err != nil {
+	if cmd.Status != dashapi.BugStatusOpen || !cmd.OnHold {
+		bugReporting.OnHold = time.Time{}
+	}
+	bug.LastActivity = now
+	if _, err := db.Put(c, bugKey, bug); err != nil {
 		return false, internalError, fmt.Errorf("failed to put bug: %v", err)
 	}
 	if err := saveReportingState(c, state); err != nil {
@@ -502,6 +732,9 @@
 			bugReporting.Reported = now
 			stateEnt.Sent++ // sending repro does not count against the quota
 		}
+		if bugReporting.OnHold.IsZero() && cmd.OnHold {
+			bugReporting.OnHold = now
+		}
 		// Close all previous reporting if they are not closed yet
 		// (can happen due to Status == ReportingDisabled).
 		for i := range bug.Reporting {
@@ -529,16 +762,20 @@
 		bug.Status = BugStatusOpen
 		bug.Closed = time.Time{}
 		bugReporting.Closed = now
+		bugReporting.Auto = cmd.Notification
 	case dashapi.BugStatusInvalid:
-		bugReporting.Closed = now
 		bug.Closed = now
 		bug.Status = BugStatusInvalid
+		bugReporting.Closed = now
+		bugReporting.Auto = cmd.Notification
 	case dashapi.BugStatusDup:
 		bug.Status = BugStatusDup
 		bug.Closed = now
 		bug.DupOf = dupHash
 	case dashapi.BugStatusUpdate:
 		// Just update Link, Commits, etc below.
+	case dashapi.BugStatusUnCC:
+		bug.UNCC = email.MergeEmailLists(bug.UNCC, cmd.CC)
 	default:
 		return false, internalError, fmt.Errorf("unknown bug status %v", cmd.Status)
 	}
@@ -584,9 +821,9 @@
 	return true, "", nil
 }
 
-func findBugByReportingID(c context.Context, id string) (*Bug, *datastore.Key, error) {
+func findBugByReportingID(c context.Context, id string) (*Bug, *db.Key, error) {
 	var bugs []*Bug
-	keys, err := datastore.NewQuery("Bug").
+	keys, err := db.NewQuery("Bug").
 		Filter("Reporting.ID=", id).
 		Limit(2).
 		GetAll(c, &bugs)
@@ -602,15 +839,15 @@
 	return bugs[0], keys[0], nil
 }
 
-func findDupByTitle(c context.Context, ns, title string) (*Bug, *datastore.Key, error) {
+func findDupByTitle(c context.Context, ns, title string) (*Bug, *db.Key, error) {
 	title, seq, err := splitDisplayTitle(title)
 	if err != nil {
 		return nil, nil, err
 	}
 	bugHash := bugKeyHash(ns, title, seq)
-	bugKey := datastore.NewKey(c, "Bug", bugHash, 0, nil)
+	bugKey := db.NewKey(c, "Bug", bugHash, 0, nil)
 	bug := new(Bug)
-	if err := datastore.Get(c, bugKey, bug); err != nil {
+	if err := db.Get(c, bugKey, bug); err != nil {
 		return nil, nil, fmt.Errorf("failed to get dup: %v", err)
 	}
 	return bug, bugKey, nil
@@ -634,10 +871,19 @@
 	return nil
 }
 
-func queryCrashesForBug(c context.Context, bugKey *datastore.Key, limit int) (
-	[]*Crash, []*datastore.Key, error) {
+func lastReportedReporting(bug *Bug) *BugReporting {
+	for i := len(bug.Reporting) - 1; i >= 0; i-- {
+		if !bug.Reporting[i].Reported.IsZero() {
+			return &bug.Reporting[i]
+		}
+	}
+	return nil
+}
+
+func queryCrashesForBug(c context.Context, bugKey *db.Key, limit int) (
+	[]*Crash, []*db.Key, error) {
 	var crashes []*Crash
-	keys, err := datastore.NewQuery("Crash").
+	keys, err := db.NewQuery("Crash").
 		Ancestor(bugKey).
 		Order("-ReportLen").
 		Order("-Reported").
@@ -650,8 +896,8 @@
 	return crashes, keys, nil
 }
 
-func findCrashForBug(c context.Context, bug *Bug) (*Crash, *datastore.Key, error) {
-	bugKey := datastore.NewKey(c, "Bug", bugKeyHash(bug.Namespace, bug.Title, bug.Seq), 0, nil)
+func findCrashForBug(c context.Context, bug *Bug) (*Crash, *db.Key, error) {
+	bugKey := bug.key(c)
 	crashes, keys, err := queryCrashesForBug(c, bugKey, 1)
 	if err != nil {
 		return nil, nil, err
@@ -678,16 +924,16 @@
 
 func loadReportingState(c context.Context) (*ReportingState, error) {
 	state := new(ReportingState)
-	key := datastore.NewKey(c, "ReportingState", "", 1, nil)
-	if err := datastore.Get(c, key, state); err != nil && err != datastore.ErrNoSuchEntity {
+	key := db.NewKey(c, "ReportingState", "", 1, nil)
+	if err := db.Get(c, key, state); err != nil && err != db.ErrNoSuchEntity {
 		return nil, fmt.Errorf("failed to get reporting state: %v", err)
 	}
 	return state, nil
 }
 
 func saveReportingState(c context.Context, state *ReportingState) error {
-	key := datastore.NewKey(c, "ReportingState", "", 1, nil)
-	if _, err := datastore.Put(c, key, state); err != nil {
+	key := db.NewKey(c, "ReportingState", "", 1, nil)
+	if _, err := db.Put(c, key, state); err != nil {
 		return fmt.Errorf("failed to put reporting state: %v", err)
 	}
 	return nil
@@ -736,3 +982,16 @@
 	}
 	return a[i].FirstTime.Before(a[j].FirstTime)
 }
+
+// kernelArch returns arch as kernel developers know it (rather than Go names).
+// Currently Linux-specific.
+func kernelArch(arch string) string {
+	switch arch {
+	case "386":
+		return "i386"
+	case "amd64":
+		return "" // this is kinda the default, so we don't notify about it
+	default:
+		return arch
+	}
+}
diff --git a/dashboard/app/reporting_email.go b/dashboard/app/reporting_email.go
index 799820f..ee45a75 100644
--- a/dashboard/app/reporting_email.go
+++ b/dashboard/app/reporting_email.go
@@ -13,11 +13,11 @@
 	"regexp"
 	"strconv"
 	"strings"
-	"text/template"
 	"time"
 
 	"github.com/google/syzkaller/dashboard/dashapi"
 	"github.com/google/syzkaller/pkg/email"
+	"github.com/google/syzkaller/pkg/html"
 	"golang.org/x/net/context"
 	"google.golang.org/appengine"
 	"google.golang.org/appengine/log"
@@ -49,15 +49,20 @@
 	// entry pending for review. The prefix makes Patchwork
 	// treat it as a comment for a previous patch.
 	replySubjectPrefix = "Re: "
-	commitHashLen      = 12
-	commitTitleLen     = 47 // so that whole line fits into 78 chars
+
+	replyNoBugID = "I see the command but can't find the corresponding bug.\n" +
+		"Please resend the email to %[1]v address\n" +
+		"that is the sender of the bug report (also present in the Reported-by tag)."
+	replyBadBugID = "I see the command but can't find the corresponding bug.\n" +
+		"The email is sent to  %[1]v address\n" +
+		"but the HASH does not correspond to any known bug.\n" +
+		"Please double check the address."
 )
 
 var mailingLists map[string]bool
 
 type EmailConfig struct {
 	Email              string
-	Moderation         bool
 	MailMaintainers    bool
 	DefaultMaintainers []string
 }
@@ -66,10 +71,6 @@
 	return emailType
 }
 
-func (cfg *EmailConfig) NeedMaintainers() bool {
-	return cfg.MailMaintainers && len(cfg.DefaultMaintainers) == 0
-}
-
 func (cfg *EmailConfig) Validate() error {
 	if _, err := mail.ParseAddress(cfg.Email); err != nil {
 		return fmt.Errorf("bad email address %q: %v", cfg.Email, err)
@@ -79,8 +80,8 @@
 			return fmt.Errorf("bad email address %q: %v", email, err)
 		}
 	}
-	if cfg.Moderation && cfg.MailMaintainers {
-		return fmt.Errorf("both Moderation and MailMaintainers set")
+	if cfg.MailMaintainers && len(cfg.DefaultMaintainers) == 0 {
+		return fmt.Errorf("MailMaintainers is set but no DefaultMaintainers")
 	}
 	return nil
 }
@@ -88,13 +89,18 @@
 // handleEmailPoll is called by cron and sends emails for new bugs, if any.
 func handleEmailPoll(w http.ResponseWriter, r *http.Request) {
 	c := appengine.NewContext(r)
-	if err := emailPollBugs(c); err != nil {
-		log.Errorf(c, "bug poll failed: %v", err)
+	if err := emailPollJobs(c); err != nil {
+		log.Errorf(c, "job poll failed: %v", err)
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
-	if err := emailPollJobs(c); err != nil {
-		log.Errorf(c, "job poll failed: %v", err)
+	if err := emailPollNotifications(c); err != nil {
+		log.Errorf(c, "notif poll failed: %v", err)
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	if err := emailPollBugs(c); err != nil {
+		log.Errorf(c, "bug poll failed: %v", err)
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 		return
 	}
@@ -104,33 +110,95 @@
 func emailPollBugs(c context.Context) error {
 	reports := reportingPollBugs(c, emailType)
 	for _, rep := range reports {
-		cfg := new(EmailConfig)
-		if err := json.Unmarshal(rep.Config, cfg); err != nil {
-			log.Errorf(c, "failed to unmarshal email config: %v", err)
-			continue
+		if err := emailSendBugReport(c, rep); err != nil {
+			log.Errorf(c, "%v", err)
 		}
-		if cfg.MailMaintainers {
-			rep.CC = email.MergeEmailLists(rep.CC, rep.Maintainers, cfg.DefaultMaintainers)
+	}
+	return nil
+}
+
+func emailSendBugReport(c context.Context, rep *dashapi.BugReport) error {
+	cfg := new(EmailConfig)
+	if err := json.Unmarshal(rep.Config, cfg); err != nil {
+		return fmt.Errorf("failed to unmarshal email config: %v", err)
+	}
+	if err := emailReport(c, rep); err != nil {
+		return fmt.Errorf("failed to report bug: %v", err)
+	}
+	cmd := &dashapi.BugUpdate{
+		ID:         rep.ID,
+		Status:     dashapi.BugStatusOpen,
+		ReproLevel: dashapi.ReproLevelNone,
+		CrashID:    rep.CrashID,
+	}
+	if len(rep.ReproC) != 0 {
+		cmd.ReproLevel = dashapi.ReproLevelC
+	} else if len(rep.ReproSyz) != 0 {
+		cmd.ReproLevel = dashapi.ReproLevelSyz
+	}
+	ok, reason, err := incomingCommand(c, cmd)
+	if !ok || err != nil {
+		return fmt.Errorf("failed to update reported bug: ok=%v reason=%v err=%v", ok, reason, err)
+	}
+	return nil
+}
+
+func emailPollNotifications(c context.Context) error {
+	notifs := reportingPollNotifications(c, emailType)
+	for _, notif := range notifs {
+		if err := emailSendBugNotif(c, notif); err != nil {
+			log.Errorf(c, "%v", err)
 		}
-		if err := emailReport(c, rep, "mail_bug.txt"); err != nil {
-			log.Errorf(c, "failed to report bug: %v", err)
-			continue
-		}
-		cmd := &dashapi.BugUpdate{
-			ID:         rep.ID,
-			Status:     dashapi.BugStatusOpen,
-			ReproLevel: dashapi.ReproLevelNone,
-			CrashID:    rep.CrashID,
-		}
-		if len(rep.ReproC) != 0 {
-			cmd.ReproLevel = dashapi.ReproLevelC
-		} else if len(rep.ReproSyz) != 0 {
-			cmd.ReproLevel = dashapi.ReproLevelSyz
-		}
-		ok, reason, err := incomingCommand(c, cmd)
-		if !ok || err != nil {
-			log.Errorf(c, "failed to update reported bug: ok=%v reason=%v err=%v", ok, reason, err)
-		}
+	}
+	return nil
+}
+
+func emailSendBugNotif(c context.Context, notif *dashapi.BugNotification) error {
+	status, body := dashapi.BugStatusOpen, ""
+	switch notif.Type {
+	case dashapi.BugNotifUpstream:
+		body = "Sending this report upstream."
+		status = dashapi.BugStatusUpstream
+	case dashapi.BugNotifBadCommit:
+		days := int(notifyAboutBadCommitPeriod / time.Hour / 24)
+		body = fmt.Sprintf("This bug is marked as fixed by commit:\n%v\n"+
+			"But I can't find it in any tested tree for more than %v days.\n"+
+			"Is it a correct commit? Please update it by replying:\n"+
+			"#syz fix: exact-commit-title\n"+
+			"Until then the bug is still considered open and\n"+
+			"new crashes with the same signature are ignored.\n",
+			notif.Text, days)
+	case dashapi.BugNotifObsoleted:
+		body = "Auto-closing this bug as obsolete.\n" +
+			"Crashes did not happen for a while, no reproducer and no activity."
+		status = dashapi.BugStatusInvalid
+	default:
+		return fmt.Errorf("bad notification type %v", notif.Type)
+	}
+	cfg := new(EmailConfig)
+	if err := json.Unmarshal(notif.Config, cfg); err != nil {
+		return fmt.Errorf("failed to unmarshal email config: %v", err)
+	}
+	to := email.MergeEmailLists([]string{cfg.Email}, notif.CC)
+	if cfg.MailMaintainers && notif.Public {
+		to = email.MergeEmailLists(to, notif.Maintainers, cfg.DefaultMaintainers)
+	}
+	from, err := email.AddAddrContext(fromAddr(c), notif.ID)
+	if err != nil {
+		return err
+	}
+	log.Infof(c, "sending notif %v for %q to %q: %v", notif.Type, notif.Title, to, body)
+	if err := sendMailText(c, notif.Title, from, to, notif.ExtID, nil, body); err != nil {
+		return err
+	}
+	cmd := &dashapi.BugUpdate{
+		ID:           notif.ID,
+		Status:       status,
+		Notification: true,
+	}
+	ok, reason, err := incomingCommand(c, cmd)
+	if !ok || err != nil {
+		return fmt.Errorf("notif update failed: ok=%v reason=%v err=%v", ok, reason, err)
 	}
 	return nil
 }
@@ -141,7 +209,7 @@
 		return err
 	}
 	for _, job := range jobs {
-		if err := emailReport(c, job, "mail_test_result.txt"); err != nil {
+		if err := emailReport(c, job); err != nil {
 			log.Errorf(c, "failed to report job: %v", err)
 			continue
 		}
@@ -153,88 +221,35 @@
 	return nil
 }
 
-func emailReport(c context.Context, rep *dashapi.BugReport, templ string) error {
+func emailReport(c context.Context, rep *dashapi.BugReport) error {
+	templ, public := "", false
+	switch rep.Type {
+	case dashapi.ReportNew, dashapi.ReportRepro:
+		templ = "mail_bug.txt"
+		public = true
+	case dashapi.ReportTestPatch:
+		templ = "mail_test_result.txt"
+	case dashapi.ReportBisectCause, dashapi.ReportBisectFix:
+		templ = "mail_bisect_result.txt"
+		public = true
+	default:
+		return fmt.Errorf("unknown report type %v", rep.Type)
+	}
 	cfg := new(EmailConfig)
 	if err := json.Unmarshal(rep.Config, cfg); err != nil {
 		return fmt.Errorf("failed to unmarshal email config: %v", err)
 	}
 	to := email.MergeEmailLists([]string{cfg.Email}, rep.CC)
-	// Build error output and failing VM boot log can be way too long to inline.
-	if len(rep.Error) > maxInlineError {
-		rep.Error = rep.Error[len(rep.Error)-maxInlineError:]
-	} else {
-		rep.ErrorLink = ""
+	if cfg.MailMaintainers && public {
+		to = email.MergeEmailLists(to, rep.Maintainers, cfg.DefaultMaintainers)
 	}
 	from, err := email.AddAddrContext(fromAddr(c), rep.ID)
 	if err != nil {
 		return err
 	}
-	creditEmail, err := email.AddAddrContext(ownEmail(c), rep.ID)
-	if err != nil {
-		return err
-	}
-	userspaceArch := ""
-	if rep.Arch == "386" {
-		userspaceArch = "i386"
-	}
-	link := fmt.Sprintf("%v/bug?extid=%v", appURL(c), rep.ID)
-	// Data passed to the template.
-	type BugReportData struct {
-		First             bool
-		Link              string
-		CreditEmail       string
-		Moderation        bool
-		Maintainers       []string
-		CompilerID        string
-		KernelRepo        string
-		KernelCommit      string
-		KernelCommitTitle string
-		KernelCommitDate  string
-		UserSpaceArch     string
-		CrashTitle        string
-		Report            []byte
-		Error             []byte
-		ErrorLink         string
-		LogLink           string
-		KernelConfigLink  string
-		ReproSyzLink      string
-		ReproCLink        string
-		NumCrashes        int64
-		HappenedOn        []string
-		PatchLink         string
-	}
-	data := &BugReportData{
-		First:             rep.First,
-		Link:              link,
-		CreditEmail:       creditEmail,
-		Moderation:        cfg.Moderation,
-		Maintainers:       rep.Maintainers,
-		CompilerID:        rep.CompilerID,
-		KernelRepo:        rep.KernelRepoAlias,
-		KernelCommit:      rep.KernelCommit,
-		KernelCommitTitle: rep.KernelCommitTitle,
-		KernelCommitDate:  formatKernelTime(rep.KernelCommitDate),
-		UserSpaceArch:     userspaceArch,
-		CrashTitle:        rep.CrashTitle,
-		Report:            rep.Report,
-		Error:             rep.Error,
-		ErrorLink:         rep.ErrorLink,
-		LogLink:           rep.LogLink,
-		KernelConfigLink:  rep.KernelConfigLink,
-		ReproSyzLink:      rep.ReproSyzLink,
-		ReproCLink:        rep.ReproCLink,
-		NumCrashes:        rep.NumCrashes,
-		HappenedOn:        rep.HappenedOn,
-		PatchLink:         rep.PatchLink,
-	}
-	if len(data.KernelCommit) > commitHashLen {
-		data.KernelCommit = data.KernelCommit[:commitHashLen]
-	}
-	if len(data.KernelCommitTitle) > commitTitleLen {
-		data.KernelCommitTitle = data.KernelCommitTitle[:commitTitleLen-2] + ".."
-	}
+
 	log.Infof(c, "sending email %q to %q", rep.Title, to)
-	return sendMailTemplate(c, rep.Title, from, to, rep.ExtID, nil, templ, data)
+	return sendMailTemplate(c, rep.Title, from, to, rep.ExtID, nil, templ, rep)
 }
 
 // handleIncomingMail is the entry point for incoming emails.
@@ -248,13 +263,17 @@
 func incomingMail(c context.Context, r *http.Request) error {
 	msg, err := email.Parse(r.Body, ownEmails(c))
 	if err != nil {
-		return err
+		// Malformed emails constantly appear from spammers.
+		// But we have not seen errors parsing legit emails.
+		// These errors are annoying. Warn and ignore them.
+		log.Warningf(c, "failed to parse email: %v", err)
+		return nil
 	}
 	log.Infof(c, "received email: subject %q, from %q, cc %q, msg %q, bug %q, cmd %q, link %q",
 		msg.Subject, msg.From, msg.Cc, msg.MessageID, msg.BugID, msg.Command, msg.Link)
-	if msg.Command == "fix:" && msg.CommandArgs == "exact-commit-title" {
+	if msg.Command == email.CmdFix && msg.CommandArgs == "exact-commit-title" {
 		// Sometimes it happens that somebody sends us our own text back, ignore it.
-		msg.Command, msg.CommandArgs = "", ""
+		msg.Command, msg.CommandArgs = email.CmdNone, ""
 	}
 	bug, _, reporting := loadBugInfo(c, msg)
 	if bug == nil {
@@ -267,52 +286,39 @@
 	fromMailingList := email.CanonicalEmail(msg.From) == mailingList
 	mailingListInCC := checkMailingListInCC(c, msg, mailingList)
 	log.Infof(c, "from/cc mailing list: %v/%v", fromMailingList, mailingListInCC)
-	if msg.Command == "test:" {
-		args := strings.Split(msg.CommandArgs, " ")
-		if len(args) != 2 {
-			return replyTo(c, msg, fmt.Sprintf("want 2 args (repo, branch), got %v",
-				len(args)), nil)
-		}
-		reply := handleTestRequest(c, msg.BugID, email.CanonicalEmail(msg.From),
-			msg.MessageID, msg.Link, msg.Patch, args[0], args[1], msg.Cc)
-		if reply != "" {
-			return replyTo(c, msg, reply, nil)
-		}
-		return nil
+	if msg.Command == email.CmdTest {
+		return handleTestCommand(c, msg)
 	}
-	if fromMailingList && msg.Command != "" {
+	if fromMailingList && msg.Command != email.CmdNone {
 		log.Infof(c, "duplicate email from mailing list, ignoring")
 		return nil
 	}
 	cmd := &dashapi.BugUpdate{
-		ID:    msg.BugID,
-		ExtID: msg.MessageID,
-		Link:  msg.Link,
-		CC:    msg.Cc,
+		Status: emailCmdToStatus[msg.Command],
+		ID:     msg.BugID,
+		ExtID:  msg.MessageID,
+		Link:   msg.Link,
+		CC:     msg.Cc,
 	}
 	switch msg.Command {
-	case "":
-		cmd.Status = dashapi.BugStatusUpdate
-	case "upstream":
-		cmd.Status = dashapi.BugStatusUpstream
-	case "invalid":
-		cmd.Status = dashapi.BugStatusInvalid
-	case "undup":
-		cmd.Status = dashapi.BugStatusOpen
-	case "fix:":
+	case email.CmdNone, email.CmdUpstream, email.CmdInvalid, email.CmdUnDup:
+	case email.CmdFix:
 		if msg.CommandArgs == "" {
 			return replyTo(c, msg, fmt.Sprintf("no commit title"), nil)
 		}
-		cmd.Status = dashapi.BugStatusOpen
 		cmd.FixCommits = []string{msg.CommandArgs}
-	case "dup:":
+	case email.CmdDup:
 		if msg.CommandArgs == "" {
 			return replyTo(c, msg, fmt.Sprintf("no dup title"), nil)
 		}
-		cmd.Status = dashapi.BugStatusDup
 		cmd.DupOf = msg.CommandArgs
+	case email.CmdUnCC:
+		cmd.CC = []string{email.CanonicalEmail(msg.From)}
 	default:
-		return replyTo(c, msg, fmt.Sprintf("unknown command %q", msg.Command), nil)
+		if msg.Command != email.CmdUnknown {
+			log.Errorf(c, "unknown email command %v %q", msg.Command, msg.CommandArgs)
+		}
+		return replyTo(c, msg, fmt.Sprintf("unknown command %q", msg.CommandArgs), nil)
 	}
 	ok, reply, err := incomingCommand(c, cmd)
 	if err != nil {
@@ -321,12 +327,35 @@
 	if !ok && reply != "" {
 		return replyTo(c, msg, reply, nil)
 	}
-	if !mailingListInCC && msg.Command != "" {
+	if !mailingListInCC && msg.Command != email.CmdNone && msg.Command != email.CmdUnCC {
 		warnMailingListInCC(c, msg, mailingList)
 	}
 	return nil
 }
 
+var emailCmdToStatus = map[email.Command]dashapi.BugStatus{
+	email.CmdNone:     dashapi.BugStatusUpdate,
+	email.CmdUpstream: dashapi.BugStatusUpstream,
+	email.CmdInvalid:  dashapi.BugStatusInvalid,
+	email.CmdUnDup:    dashapi.BugStatusOpen,
+	email.CmdFix:      dashapi.BugStatusOpen,
+	email.CmdDup:      dashapi.BugStatusDup,
+	email.CmdUnCC:     dashapi.BugStatusUnCC,
+}
+
+func handleTestCommand(c context.Context, msg *email.Email) error {
+	args := strings.Split(msg.CommandArgs, " ")
+	if len(args) != 2 {
+		return replyTo(c, msg, fmt.Sprintf("want 2 args (repo, branch), got %v", len(args)), nil)
+	}
+	reply := handleTestRequest(c, msg.BugID, email.CanonicalEmail(msg.From),
+		msg.MessageID, msg.Link, msg.Patch, args[0], args[1], msg.Cc)
+	if reply != "" {
+		return replyTo(c, msg, reply, nil)
+	}
+	return nil
+}
+
 func handleEmailBounce(w http.ResponseWriter, r *http.Request) {
 	c := appengine.NewContext(r)
 	body, err := ioutil.ReadAll(r.Body)
@@ -347,12 +376,17 @@
 
 func loadBugInfo(c context.Context, msg *email.Email) (bug *Bug, bugReporting *BugReporting, reporting *Reporting) {
 	if msg.BugID == "" {
-		if msg.Command == "" {
+		if msg.Command == email.CmdNone {
 			// This happens when people CC syzbot on unrelated emails.
 			log.Infof(c, "no bug ID (%q)", msg.Subject)
 		} else {
 			log.Errorf(c, "no bug ID (%q)", msg.Subject)
-			if err := replyTo(c, msg, "Can't find the corresponding bug.", nil); err != nil {
+			from, err := email.AddAddrContext(ownEmail(c), "HASH")
+			if err != nil {
+				log.Errorf(c, "failed to format sender email address: %v", err)
+				from = "ERROR"
+			}
+			if err := replyTo(c, msg, fmt.Sprintf(replyNoBugID, from), nil); err != nil {
 				log.Errorf(c, "failed to send reply: %v", err)
 			}
 		}
@@ -361,7 +395,12 @@
 	bug, _, err := findBugByReportingID(c, msg.BugID)
 	if err != nil {
 		log.Errorf(c, "can't find bug: %v", err)
-		if err := replyTo(c, msg, "Can't find the corresponding bug.", nil); err != nil {
+		from, err := email.AddAddrContext(ownEmail(c), "HASH")
+		if err != nil {
+			log.Errorf(c, "failed to format sender email address: %v", err)
+			from = "ERROR"
+		}
+		if err := replyTo(c, msg, fmt.Sprintf(replyBadBugID, from), nil); err != nil {
 			log.Errorf(c, "failed to send reply: %v", err)
 		}
 		return nil, nil, nil
@@ -417,11 +456,16 @@
 	if err := mailTemplates.ExecuteTemplate(body, template, data); err != nil {
 		return fmt.Errorf("failed to execute %v template: %v", template, err)
 	}
+	return sendMailText(c, subject, from, to, replyTo, attachments, body.String())
+}
+
+func sendMailText(c context.Context, subject, from string, to []string, replyTo string,
+	attachments []aemail.Attachment, body string) error {
 	msg := &aemail.Message{
 		Sender:      from,
 		To:          to,
 		Subject:     subject,
-		Body:        body.String(),
+		Body:        body,
 		Attachments: attachments,
 	}
 	if replyTo != "" {
@@ -478,6 +522,21 @@
 	}
 }
 
+func sanitizeCC(c context.Context, cc []string) []string {
+	var res []string
+	for _, addr := range cc {
+		mail, err := mail.ParseAddress(addr)
+		if err != nil {
+			continue
+		}
+		if email.CanonicalEmail(mail.Address) == ownEmail(c) {
+			continue
+		}
+		res = append(res, mail.Address)
+	}
+	return res
+}
+
 func externalLink(c context.Context, tag string, id int64) string {
 	if id == 0 {
 		return ""
@@ -489,23 +548,4 @@
 	return fmt.Sprintf("https://%v.appspot.com", appengine.AppID(c))
 }
 
-func formatKernelTime(t time.Time) string {
-	if t.IsZero() {
-		return ""
-	}
-	// This is how dates appear in git log.
-	return t.Format("Mon Jan 2 15:04:05 2006 -0700")
-}
-
-func formatStringList(list []string) string {
-	return strings.Join(list, ", ")
-}
-
-var (
-	mailTemplates = template.Must(template.New("").Funcs(mailFuncs).ParseGlob("mail_*.txt"))
-
-	mailFuncs = template.FuncMap{
-		"formatTime": formatKernelTime,
-		"formatList": formatStringList,
-	}
-)
+var mailTemplates = html.CreateTextGlob("mail_*.txt")
diff --git a/dashboard/app/reporting_external.go b/dashboard/app/reporting_external.go
index 85e6b50..846f1f3 100644
--- a/dashboard/app/reporting_external.go
+++ b/dashboard/app/reporting_external.go
@@ -34,6 +34,23 @@
 	resp := &dashapi.PollBugsResponse{
 		Reports: reports,
 	}
+	jobs, err := pollCompletedJobs(c, req.Type)
+	if err != nil {
+		log.Errorf(c, "failed to poll jobs: %v", err)
+	}
+	resp.Reports = append(resp.Reports, jobs...)
+	return resp, nil
+}
+
+func apiReportingPollNotifications(c context.Context, r *http.Request, payload []byte) (interface{}, error) {
+	req := new(dashapi.PollNotificationsRequest)
+	if err := json.Unmarshal(payload, req); err != nil {
+		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
+	}
+	notifs := reportingPollNotifications(c, req.Type)
+	resp := &dashapi.PollNotificationsResponse{
+		Notifications: notifs,
+	}
 	return resp, nil
 }
 
@@ -58,6 +75,18 @@
 	if err := json.Unmarshal(payload, req); err != nil {
 		return nil, fmt.Errorf("failed to unmarshal request: %v", err)
 	}
+	if req.JobID != "" {
+		resp := &dashapi.BugUpdateReply{
+			OK:    true,
+			Error: false,
+		}
+		if err := jobReported(c, req.JobID); err != nil {
+			log.Errorf(c, "failed to mark job reported: %v", err)
+			resp.Text = err.Error()
+			resp.Error = true
+		}
+		return resp, nil
+	}
 	ok, reason, err := incomingCommand(c, req)
 	return &dashapi.BugUpdateReply{
 		OK:    ok,
diff --git a/dashboard/app/reporting_test.go b/dashboard/app/reporting_test.go
index 4d13fd0..8ae562b 100644
--- a/dashboard/app/reporting_test.go
+++ b/dashboard/app/reporting_test.go
@@ -6,6 +6,7 @@
 package dash
 
 import (
+	"fmt"
 	"testing"
 	"time"
 
@@ -36,20 +37,25 @@
 	resp, _ = c.client.ReportingPollBugs("test")
 	c.expectEQ(len(resp.Reports), 1)
 	rep := resp.Reports[0]
-	if rep.ID == "" {
-		t.Fatalf("empty report ID")
-	}
+	c.expectNE(rep.ID, "")
 	_, dbCrash, dbBuild := c.loadBug(rep.ID)
 	want := &dashapi.BugReport{
+		Type:              dashapi.ReportNew,
 		Namespace:         "test1",
 		Config:            []byte(`{"Index":1}`),
 		ID:                rep.ID,
+		OS:                "linux",
+		Arch:              "amd64",
+		VMArch:            "amd64",
 		First:             true,
+		Moderation:        true,
 		Title:             "title1",
+		Link:              fmt.Sprintf("https://testapp.appspot.com/bug?extid=%v", rep.ID),
+		CreditEmail:       fmt.Sprintf("syzbot+%v@testapp.appspotmail.com", rep.ID),
 		Maintainers:       []string{"bar@foo.com", "foo@bar.com"},
 		CompilerID:        "compiler1",
 		KernelRepo:        "repo1",
-		KernelRepoAlias:   "repo1/branch1",
+		KernelRepoAlias:   "repo1 branch1",
 		KernelBranch:      "branch1",
 		KernelCommit:      "1111111111111111111111111111111111111111",
 		KernelCommitTitle: build.KernelCommitTitle,
@@ -62,9 +68,9 @@
 		ReportLink:        externalLink(c.ctx, textCrashReport, dbCrash.Report),
 		CrashID:           rep.CrashID,
 		NumCrashes:        1,
-		HappenedOn:        []string{"repo1/branch1"},
+		HappenedOn:        []string{"repo1 branch1"},
 	}
-	c.expectEQ(rep, want)
+	c.expectEQ(want, rep)
 
 	// Since we did not update bug status yet, should get the same report again.
 	c.expectEQ(c.client.pollBug(), want)
@@ -72,20 +78,19 @@
 	// Now add syz repro and check that we get another bug report.
 	crash1.ReproOpts = []byte("some opts")
 	crash1.ReproSyz = []byte("getpid()")
+	want.Type = dashapi.ReportRepro
 	want.First = false
 	want.ReproSyz = []byte(syzReproPrefix + "#some opts\ngetpid()")
 	c.client.ReportCrash(crash1)
 	rep1 := c.client.pollBug()
-	if want.CrashID == rep1.CrashID {
-		t.Fatal("get the same CrashID for new crash")
-	}
+	c.expectNE(want.CrashID, rep1.CrashID)
 	_, dbCrash, _ = c.loadBug(rep.ID)
 	want.CrashID = rep1.CrashID
 	want.NumCrashes = 2
 	want.ReproSyzLink = externalLink(c.ctx, textReproSyz, dbCrash.ReproSyz)
 	want.LogLink = externalLink(c.ctx, textCrashLog, dbCrash.Log)
 	want.ReportLink = externalLink(c.ctx, textCrashReport, dbCrash.Report)
-	c.expectEQ(rep1, want)
+	c.expectEQ(want, rep1)
 
 	reply, _ := c.client.ReportingUpdate(&dashapi.BugUpdate{
 		ID:         rep.ID,
@@ -112,14 +117,17 @@
 
 	// Check that we get the report in the second reporting.
 	rep2 := c.client.pollBug()
-	if rep2.ID == "" || rep2.ID == rep.ID {
-		t.Fatalf("bad report ID: %q", rep2.ID)
-	}
+	c.expectNE(rep2.ID, "")
+	c.expectNE(rep2.ID, rep.ID)
+	want.Type = dashapi.ReportNew
 	want.ID = rep2.ID
+	want.Link = fmt.Sprintf("https://testapp.appspot.com/bug?extid=%v", rep2.ID)
+	want.CreditEmail = fmt.Sprintf("syzbot+%v@testapp.appspotmail.com", rep2.ID)
 	want.First = true
+	want.Moderation = false
 	want.Config = []byte(`{"Index":2}`)
 	want.NumCrashes = 3
-	c.expectEQ(rep2, want)
+	c.expectEQ(want, rep2)
 
 	// Check that that we can't upstream the bug in the final reporting.
 	reply, _ = c.client.ReportingUpdate(&dashapi.BugUpdate{
@@ -178,19 +186,24 @@
 
 	// Now it should be reported again.
 	rep = c.client.pollBug()
-	if rep.ID == "" {
-		t.Fatalf("empty report ID")
-	}
+	c.expectNE(rep.ID, "")
 	_, dbCrash, dbBuild := c.loadBug(rep.ID)
 	want := &dashapi.BugReport{
+		Type:              dashapi.ReportNew,
 		Namespace:         "test1",
 		Config:            []byte(`{"Index":1}`),
 		ID:                rep.ID,
+		OS:                "linux",
+		Arch:              "amd64",
+		VMArch:            "amd64",
 		First:             true,
+		Moderation:        true,
 		Title:             "title1 (2)",
+		Link:              fmt.Sprintf("https://testapp.appspot.com/bug?extid=%v", rep.ID),
+		CreditEmail:       fmt.Sprintf("syzbot+%v@testapp.appspotmail.com", rep.ID),
 		CompilerID:        "compiler1",
 		KernelRepo:        "repo1",
-		KernelRepoAlias:   "repo1/branch1",
+		KernelRepoAlias:   "repo1 branch1",
 		KernelBranch:      "branch1",
 		KernelCommit:      "1111111111111111111111111111111111111111",
 		KernelCommitTitle: build.KernelCommitTitle,
@@ -205,9 +218,9 @@
 		ReproCLink:        externalLink(c.ctx, textReproC, dbCrash.ReproC),
 		CrashID:           rep.CrashID,
 		NumCrashes:        1,
-		HappenedOn:        []string{"repo1/branch1"},
+		HappenedOn:        []string{"repo1 branch1"},
 	}
-	c.expectEQ(rep, want)
+	c.expectEQ(want, rep)
 	c.client.ReportFailedRepro(testCrashID(crash1))
 }
 
@@ -346,7 +359,6 @@
 	cmds := []*dashapi.BugUpdate{
 		{ID: rep1.ID, DupOf: rep1.ID},
 		{ID: rep1.ID, DupOf: rep2.ID},
-		{ID: rep1.ID, DupOf: rep3.ID},
 		{ID: rep2.ID, DupOf: rep1.ID},
 		{ID: rep2.ID, DupOf: rep2.ID},
 		{ID: rep2.ID, DupOf: rep3.ID},
@@ -360,6 +372,15 @@
 		reply, _ := c.client.ReportingUpdate(cmd)
 		c.expectEQ(reply.OK, false)
 	}
+	// Special case of cross-reporting duping:
+	cmd := &dashapi.BugUpdate{
+		Status: dashapi.BugStatusDup,
+		ID:     rep1.ID,
+		DupOf:  rep3.ID,
+	}
+	t.Logf("duping %v -> %v", cmd.ID, cmd.DupOf)
+	reply, _ := c.client.ReportingUpdate(cmd)
+	c.expectTrue(reply.OK)
 }
 
 func TestReportingFilter(t *testing.T) {
@@ -370,7 +391,7 @@
 	c.client.UploadBuild(build)
 
 	crash1 := testCrash(build, 1)
-	crash1.Title = "skip without repro 1"
+	crash1.Title = "skip with repro 1"
 	c.client.ReportCrash(crash1)
 
 	// This does not skip first reporting, because it does not have repro.
@@ -393,7 +414,7 @@
 
 	// Now report a bug that must go to the second reporting right away.
 	crash2 := testCrash(build, 2)
-	crash2.Title = "skip without repro 2"
+	crash2.Title = "skip with repro 2"
 	crash2.ReproSyz = []byte("getpid()")
 	c.client.ReportCrash(crash2)
 
diff --git a/dashboard/app/static/common.js b/dashboard/app/static/common.js
index f2c2a8c..f501d61 100644
--- a/dashboard/app/static/common.js
+++ b/dashboard/app/static/common.js
@@ -1,27 +1,24 @@
 // Copyright 2018 syzkaller project authors. All rights reserved.
 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
 
-function sortTable(item, colName, conv) {
-	table = item.parentNode.parentNode.parentNode;
-	rows = table.getElementsByTagName("tr");
+function sortTable(item, colName, conv, desc = false) {
+	table = item.parentNode.parentNode.parentNode.parentNode;
+	rows = table.rows;
 	col = findColumnByName(rows[0].getElementsByTagName("th"), colName);
-	values = new Array;
+	values = [];
 	for (i = 1; i < rows.length; i++)
-		values[i] = conv(rows[i].getElementsByTagName("td")[col].textContent);
-	desc = isSorted(values);
-	do {
-		changed = false;
-		for (i = 1; i < values.length - 1; i++) {
-			v0 = values[i];
-			v1 = values[i + 1];
-			if (desc && v0 >= v1 || !desc && v0 <= v1)
-				continue;
-			changed = true;
-			values[i] = v1;
-			values[i + 1] = v0;
-			rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
-		}
-	} while (changed);
+		values.push([conv(rows[i].getElementsByTagName("td")[col].textContent), rows[i]]);
+	if (desc)
+		desc = !isSorted(values.slice().reverse())
+	else
+		desc = isSorted(values);
+	values.sort(function(a, b) {
+		if (a[0] == b[0]) return 0;
+		if (desc && a[0] > b[0] || !desc && a[0] < b[0]) return -1;
+		return 1;
+	});
+	for (i = 0; i < values.length; i++)
+		table.tBodies[0].appendChild(values[i][1]);
 	return false;
 }
 
@@ -34,8 +31,8 @@
 }
 
 function isSorted(values) {
-	for (i = 1; i < rows.length - 1; i++) {
-		if (values[i] > values[i + 1])
+	for (i = 0; i < values.length - 1; i++) {
+		if (values[i][0] > values[i + 1][0])
 			return false;
 	}
 	return true;
@@ -43,6 +40,8 @@
 
 function textSort(v) { return v.toLowerCase(); }
 function numSort(v) { return -parseInt(v); }
+function floatSort(v) { return -parseFloat(v); }
+function yesSort(v) { return v == "yes" ? 0 : 1; }
 function reproSort(v) { return v == "C" ? 0 : v == "syz" ? 1 : 2; }
 function patchedSort(v) { return v == "" ? -1 : parseInt(v); }
 
diff --git a/dashboard/app/static/favicon.ico b/dashboard/app/static/favicon.ico
index e69de29..ae88cc0 100644
--- a/dashboard/app/static/favicon.ico
+++ b/dashboard/app/static/favicon.ico
Binary files differ
diff --git a/dashboard/app/static/style.css b/dashboard/app/static/style.css
index 2ebe32a..ee5ef5f 100644
--- a/dashboard/app/static/style.css
+++ b/dashboard/app/static/style.css
@@ -35,6 +35,12 @@
 	overflow: hidden;
 }
 
+.namespace {
+	font-weight: bold;
+	font-size: large;
+	color: #375EAB;
+}
+
 .position_table {
 	border: 0px;
 	margin: 0px;
@@ -59,7 +65,7 @@
 	background: #F4F4F4;
 }
 
-.list_table tr:nth-child(2n+1) {
+.list_table tr:nth-child(2n) {
 	background: #F4F4F4;
 }
 
@@ -77,11 +83,16 @@
 	max-width: 350pt;
 }
 
+.list_table .commit_list {
+	width: 500pt;
+	max-width: 500pt;
+}
+
 .list_table .tag {
 	font-family: monospace;
 	font-size: 8pt;
-	width: 200pt;
-	max-width: 200pt;
+	width: 40pt;
+	max-width: 40pt;
 }
 
 .list_table .opts {
@@ -101,8 +112,8 @@
 }
 
 .list_table .kernel {
-	width: 60pt;
-	max-width: 60pt;
+	width: 80pt;
+	max-width: 80pt;
 }
 
 .list_table .maintainers {
@@ -122,12 +133,43 @@
 	text-align: right;
 }
 
+.list_table .date {
+	width: 60pt;
+	max-width: 60pt;
+	font-family: monospace;
+	text-align: right;
+}
+
+.list_table .stat_name {
+	width: 150pt;
+	max-width: 150pt;
+	font-family: monospace;
+}
+
+.list_table .stat_value {
+	width: 120pt;
+	max-width: 120pt;
+	font-family: monospace;
+}
+
 .bad {
 	color: #f00;
 	font-weight: bold;
 }
 
+.inactive {
+	color: #888;
+}
+
+.plain {
+	text-decoration: none;
+}
+
 textarea {
 	width:100%;
 	font-family: monospace;
 }
+
+.mono {
+	font-family: monospace;
+}
diff --git a/dashboard/app/templates.html b/dashboard/app/templates.html
index 772135f..8c95831 100644
--- a/dashboard/app/templates.html
+++ b/dashboard/app/templates.html
@@ -6,6 +6,15 @@
 {{/* Common page head part, invoked with *uiHeader */}}
 {{define "head"}}
 	<link rel="stylesheet" href="/static/style.css"/>
+	{{if .Redirects}}
+		<script>
+			{{range $redir := .Redirects}}
+				if (window.location.hash == "{{$redir.From}}") {
+					window.location.href = "{{$redir.To}}";
+				}
+			{{end}}
+		</script>
+	{{end}}
 	<script src="/static/common.js"></script>
 	{{if .AnalyticsTrackingID}}
 		<script async src="https://www.googletagmanager.com/gtag/js?id={{.AnalyticsTrackingID}}"></script>
@@ -24,9 +33,19 @@
 		<table class="position_table">
 			<tr>
 				<td>
-					<h1><a href="/">syzbot</a></h1>
+					<h1><a href="/{{$.Namespace}}">syzbot</a></h1>
+					<select class="namespace" onchange="window.location.href = '/' + this.value + '{{.Subpage}}';">
+						{{range $ns := .Namespaces}}
+							<option value="{{$ns.Name}}" {{if eq $.Namespace $ns.Name}}selected="1"{{end}}>
+								{{$ns.Caption}}
+							</option>
+						{{end}}
+					</select>
 				</td>
 				<td class="search">
+					{{if .Admin}}
+						<a href="/admin">admin</a> |
+					{{end}}
 					{{if .LoginLink}}
 						<a href="{{.LoginLink}}">sign-in</a> |
 					{{end}}
@@ -45,13 +64,22 @@
 {{if .}}
 {{if .Bugs}}
 <table class="list_table">
-	<caption id="{{.Fragment}}">{{$.Caption}}:</caption>
+	{{if $.Fragment}}
+		<caption id="{{$.Fragment}}"><a class="plain" href="#{{$.Fragment}}">
+	{{else}}
+		<caption>
+	{{end}}
+	{{$.Caption}} ({{len $.Bugs}}):
+	{{if $.Fragment}}</a>{{end}}
+	</caption>
+	<thead>
 	<tr>
 		{{if $.ShowNamespace}}
 			<th><a onclick="return sortTable(this, 'Kernel', textSort)" href="#">Kernel</a></th>
 		{{end}}
 		<th><a onclick="return sortTable(this, 'Title', textSort)" href="#">Title</a></th>
 		<th><a onclick="return sortTable(this, 'Repro', reproSort)" href="#">Repro</a></th>
+		<th><a onclick="return sortTable(this, 'Bisected', yesSort)" href="#">Bisected</a></th>
 		<th><a onclick="return sortTable(this, 'Count', numSort)" href="#">Count</a></th>
 		<th><a onclick="return sortTable(this, 'Last', timeSort)" href="#">Last</a></th>
 		<th><a onclick="return sortTable(this, 'Reported', timeSort)" href="#">Reported</a></th>
@@ -66,11 +94,14 @@
 			<th><a onclick="return sortTable(this, 'Status', textSort)" href="#">Status</a></th>
 		{{end}}
 	</tr>
+	</thead>
+	<tbody>
 	{{range $b := .Bugs}}
 		<tr>
 			{{if $.ShowNamespace}}<td>{{$b.Namespace}}</td>{{end}}
 			<td class="title"><a href="{{$b.Link}}">{{$b.Title}}</a></td>
 			<td class="stat">{{formatReproLevel $b.ReproLevel}}</td>
+			<td class="stat">{{if $b.BisectCause}}yes{{end}}</td>
 			<td class="stat {{if $b.NumCrashesBad}}bad{{end}}">{{$b.NumCrashes}}</td>
 			<td class="stat">{{formatLateness $.Now $b.LastTime}}</td>
 			<td class="stat">
@@ -82,10 +113,10 @@
 			</td>
 			{{if $.ShowPatch}}
 				<td class="stat">{{formatLateness $.Now $b.ClosedTime}}</td>
-				<td class="title" title="{{$b.Commits}}">{{$b.Commits}}</td>
+				<td class="commit_list">{{template "fix_commits" $b.Commits}}</td>
 			{{end}}
 			{{if $.ShowPatched}}
-				<td class="patched" title="{{$b.Commits}}">{{if $b.Commits}}{{len $b.PatchedOn}}/{{$b.NumManagers}}{{end}}</td>
+				<td class="patched" {{if $b.Commits}}title="{{with $com := index $b.Commits 0}}{{$com.Title}}{{end}}"{{end}}>{{len $b.PatchedOn}}/{{$b.NumManagers}}</td>
 			{{end}}
 			{{if $.ShowStatus}}
 				<td class="status">
@@ -98,7 +129,97 @@
 			{{end}}
 		</tr>
 	{{end}}
+	</tbody>
 </table>
 {{end}}
 {{end}}
 {{end}}
+
+{{/* List of managers, invoked with []*uiManager */}}
+{{define "manager_list"}}
+{{if .}}
+<table class="list_table">
+	<caption id="managers"><a class="plain" href="managers">Instances:</a></caption>
+	<thead>
+	<tr>
+		<th>Name</th>
+		<th>Active</th>
+		<th>Uptime</th>
+		<th>Corpus</th>
+		<th>Coverage</th>
+		<th>Crashes</th>
+		<th>Execs</th>
+		<th colspan="3">Kernel build</th>
+		<th colspan="3">syzkaller build</th>
+	</tr>
+	<tr>
+		<th></th>
+		<th></th>
+		<th></th>
+		<th></th>
+		<th></th>
+		<th></th>
+		<th></th>
+		<th>Commit</th>
+		<th>Freshness</th>
+		<th>Status</th>
+		<th>Commit</th>
+		<th>Freshness</th>
+		<th>Status</th>
+	</tr>
+	</thead>
+	<tbody>
+	{{range $mgr := .}}
+		<tr>
+			<td>{{link $mgr.Link $mgr.Name}}</td>
+			<td class="stat {{if $mgr.LastActiveBad}}bad{{end}}">{{formatLateness $mgr.Now $mgr.LastActive}}</td>
+			<td class="stat">{{formatDuration $mgr.CurrentUpTime}}</td>
+			<td class="stat">{{formatStat $mgr.MaxCorpus}}</td>
+			<td class="stat">
+				{{if $mgr.CoverLink}}
+					<a href="{{$mgr.CoverLink}}" target="_blank">
+				{{end}}
+				{{formatStat $mgr.MaxCover}}
+				{{if $mgr.CoverLink}}
+					</a>
+				{{end}}
+			</td>
+			<td class="stat">{{formatStat $mgr.TotalCrashes}}</td>
+			{{if $mgr.TotalExecs}}
+				<td class="stat">{{formatStat $mgr.TotalExecs}}</td>
+			{{else}}
+				<td class="stat bad">broken</td>
+			{{end}}
+			{{with $build := $mgr.CurrentBuild}}
+				<td class="stat" title="[{{$build.KernelAlias}}] {{$build.KernelCommitTitle}}">{{link $build.KernelCommitLink (formatShortHash $build.KernelCommit)}}</td>
+				<td class="stat" title="{{formatTime $build.KernelCommitDate}}" {{if $mgr.FailedBuildBugLink}}class="bad"{{end}}>{{formatLateness $mgr.Now $build.KernelCommitDate}}</td>
+				<td class="stat">{{if $mgr.FailedBuildBugLink}}<a href="{{$mgr.FailedBuildBugLink}}" class="bad">failing</a>{{end}}</td>
+				<td class="stat">{{link $build.SyzkallerCommitLink (formatShortHash $build.SyzkallerCommit)}}</td>
+				<td class="stat" title="{{formatTime $build.SyzkallerCommitDate}}" {{if $mgr.FailedSyzBuildBugLink}}class="bad"{{end}}>{{formatLateness $mgr.Now $build.SyzkallerCommitDate}}</td>
+				<td class="stat">{{if $mgr.FailedSyzBuildBugLink}}<a href="{{$mgr.FailedSyzBuildBugLink}}" class="bad">failing</a>{{end}}</td>
+			{{else}}
+				<td></td>
+				<td></td>
+				<td></td>
+				<td></td>
+				<td></td>
+				<td></td>
+			{{end}}
+		</tr>
+	{{end}}
+	</tbody>
+</table>
+{{end}}
+{{end}}
+
+{{/* List of fixing commits, invoked with []*uiCommit */}}
+{{define "fix_commits"}}
+{{range $com := .}}
+	<span class="mono">
+		{{if $com.Hash}}
+			{{formatShortHash $com.Hash}} 
+		{{end}}
+		{{link $com.Link $com.Title}}
+	</span>
+{{end}}
+{{end}}
diff --git a/dashboard/app/util_test.go b/dashboard/app/util_test.go
index 00c7694..94b1f45 100644
--- a/dashboard/app/util_test.go
+++ b/dashboard/app/util_test.go
@@ -24,11 +24,12 @@
 	"testing"
 	"time"
 
+	"github.com/google/go-cmp/cmp"
 	"github.com/google/syzkaller/dashboard/dashapi"
 	"golang.org/x/net/context"
 	"google.golang.org/appengine"
 	"google.golang.org/appengine/aetest"
-	"google.golang.org/appengine/datastore"
+	db "google.golang.org/appengine/datastore"
 	aemail "google.golang.org/appengine/mail"
 	"google.golang.org/appengine/user"
 )
@@ -96,8 +97,14 @@
 }
 
 func (c *Ctx) expectEQ(got, want interface{}) {
-	if !reflect.DeepEqual(got, want) {
-		c.t.Fatalf("\n%v: got %#v, want %#v", caller(0), got, want)
+	if diff := cmp.Diff(got, want); diff != "" {
+		c.t.Fatalf("\n%v: %v", caller(0), diff)
+	}
+}
+
+func (c *Ctx) expectNE(got, want interface{}) {
+	if reflect.DeepEqual(got, want) {
+		c.t.Fatalf("\n%v: equal: %#v", caller(0), got)
 	}
 }
 
@@ -108,22 +115,44 @@
 }
 
 func caller(skip int) string {
-	_, file, line, _ := runtime.Caller(skip + 2)
-	return fmt.Sprintf("%v:%v", filepath.Base(file), line)
+	pcs := make([]uintptr, 10)
+	n := runtime.Callers(skip+3, pcs)
+	pcs = pcs[:n]
+	frames := runtime.CallersFrames(pcs)
+	stack := ""
+	for {
+		frame, more := frames.Next()
+		if strings.HasPrefix(frame.Function, "testing.") {
+			break
+		}
+		stack = fmt.Sprintf("%v:%v\n", filepath.Base(frame.File), frame.Line) + stack
+		if !more {
+			break
+		}
+	}
+	if stack != "" {
+		stack = stack[:len(stack)-1]
+	}
+	return stack
 }
 
 func (c *Ctx) Close() {
 	if !c.t.Failed() {
 		// Ensure that we can render main page and all bugs in the final test state.
-		c.expectOK(c.GET("/"))
+		c.expectOK(c.GET("/test1"))
+		c.expectOK(c.GET("/test2"))
+		c.expectOK(c.GET("/test1/fixed"))
+		c.expectOK(c.GET("/test2/fixed"))
+		c.expectOK(c.GET("/admin"))
 		var bugs []*Bug
-		keys, err := datastore.NewQuery("Bug").GetAll(c.ctx, &bugs)
+		keys, err := db.NewQuery("Bug").GetAll(c.ctx, &bugs)
 		if err != nil {
 			c.t.Errorf("ERROR: failed to query bugs: %v", err)
 		}
 		for _, key := range keys {
 			c.expectOK(c.GET(fmt.Sprintf("/bug?id=%v", key.StringID())))
 		}
+		// No pending emails (tests need to consume them).
 		c.expectOK(c.GET("/email_poll"))
 		for len(c.emailSink) != 0 {
 			c.t.Errorf("ERROR: leftover email: %v", (<-c.emailSink).Body)
@@ -175,14 +204,15 @@
 	http.DefaultServeMux.ServeHTTP(w, r)
 	c.t.Logf("REPLY: %v", w.Code)
 	if w.Code != http.StatusOK {
-		return nil, HttpError{w.Code, w.Body.String()}
+		return nil, HttpError{w.Code, w.Body.String(), w.HeaderMap}
 	}
 	return w.Body.Bytes(), nil
 }
 
 type HttpError struct {
-	Code int
-	Body string
+	Code    int
+	Body    string
+	Headers http.Header
 }
 
 func (err HttpError) Error() string {
@@ -194,31 +224,54 @@
 	if err != nil {
 		c.t.Fatalf("failed to load bug: %v", err)
 	}
+	return c.loadBugInfo(bug)
+}
+
+func (c *Ctx) loadBugByHash(hash string) (*Bug, *Crash, *Build) {
+	bug := new(Bug)
+	bugKey := db.NewKey(c.ctx, "Bug", hash, 0, nil)
+	c.expectOK(db.Get(c.ctx, bugKey, bug))
+	return c.loadBugInfo(bug)
+}
+
+func (c *Ctx) loadBugInfo(bug *Bug) (*Bug, *Crash, *Build) {
 	crash, _, err := findCrashForBug(c.ctx, bug)
 	if err != nil {
 		c.t.Fatalf("failed to load crash: %v", err)
 	}
-	build, err := loadBuild(c.ctx, bug.Namespace, crash.BuildID)
-	if err != nil {
-		c.t.Fatalf("failed to load build: %v", err)
-	}
+	build := c.loadBuild(bug.Namespace, crash.BuildID)
 	return bug, crash, build
 }
 
-func (c *Ctx) loadJob(extID string) (*Job, *Build) {
+func (c *Ctx) loadJob(extID string) (*Job, *Build, *Crash) {
 	jobKey, err := jobID2Key(c.ctx, extID)
 	if err != nil {
 		c.t.Fatalf("failed to create job key: %v", err)
 	}
 	job := new(Job)
-	if err := datastore.Get(c.ctx, jobKey, job); err != nil {
+	if err := db.Get(c.ctx, jobKey, job); err != nil {
 		c.t.Fatalf("failed to get job %v: %v", extID, err)
 	}
-	build, err := loadBuild(c.ctx, job.Namespace, job.BuildID)
-	if err != nil {
-		c.t.Fatalf("failed to load build: %v", err)
+	build := c.loadBuild(job.Namespace, job.BuildID)
+	crash := new(Crash)
+	crashKey := db.NewKey(c.ctx, "Crash", "", job.CrashID, jobKey.Parent())
+	if err := db.Get(c.ctx, crashKey, crash); err != nil {
+		c.t.Fatalf("failed to load crash for job: %v", err)
 	}
-	return job, build
+	return job, build, crash
+}
+
+func (c *Ctx) loadBuild(ns, id string) *Build {
+	build, err := loadBuild(c.ctx, ns, id)
+	c.expectOK(err)
+	return build
+}
+
+func (c *Ctx) loadManager(ns, name string) (*Manager, *Build) {
+	mgr, err := loadManager(c.ctx, ns, name)
+	c.expectOK(err)
+	build := c.loadBuild(ns, mgr.CurrentBuild)
+	return mgr, build
 }
 
 func (c *Ctx) checkURLContents(url string, want []byte) {
@@ -231,6 +284,22 @@
 	}
 }
 
+func (c *Ctx) pollEmailBug() *aemail.Message {
+	c.expectOK(c.GET("/email_poll"))
+	if len(c.emailSink) == 0 {
+		c.t.Fatalf("\n%v: got no emails", caller(0))
+	}
+	return <-c.emailSink
+}
+
+func (c *Ctx) expectNoEmail() {
+	c.expectOK(c.GET("/email_poll"))
+	if len(c.emailSink) != 0 {
+		msg := <-c.emailSink
+		c.t.Fatalf("\n%v: got unexpected email: %v\n%s", caller(0), msg.Subject, msg.Body)
+	}
+}
+
 type apiClient struct {
 	*Ctx
 	*dashapi.Dashboard
@@ -281,6 +350,7 @@
 		}
 		reply, _ := client.ReportingUpdate(&dashapi.BugUpdate{
 			ID:         rep.ID,
+			JobID:      rep.JobID,
 			Status:     dashapi.BugStatusOpen,
 			ReproLevel: reproLevel,
 			CrashID:    rep.CrashID,
@@ -295,6 +365,18 @@
 	return client.pollBugs(1)[0]
 }
 
+func (client *apiClient) pollNotifs(expect int) []*dashapi.BugNotification {
+	resp, _ := client.ReportingPollNotifications("test")
+	if len(resp.Notifications) != expect {
+		client.t.Fatalf("\n%v: want %v notifs, got %v", caller(0), expect, len(resp.Notifications))
+	}
+	return resp.Notifications
+}
+
+func (client *apiClient) pollNotif() *dashapi.BugNotification {
+	return client.pollNotifs(1)[0]
+}
+
 func (client *apiClient) updateBug(extID string, status dashapi.BugStatus, dup string) {
 	reply, _ := client.ReportingUpdate(&dashapi.BugUpdate{
 		ID:     extID,
@@ -304,6 +386,26 @@
 	client.expectTrue(reply.OK)
 }
 
+func (client *apiClient) pollJobs(manager string) *dashapi.JobPollResp {
+	resp, err := client.JobPoll(&dashapi.JobPollReq{
+		PatchTestManagers: []string{manager},
+		BisectManagers:    []string{manager},
+	})
+	client.expectOK(err)
+	return resp
+}
+
+func (client *apiClient) pollAndFailBisectJob(manager string) {
+	resp := client.pollJobs(manager)
+	client.expectNE(resp.ID, "")
+	client.expectEQ(resp.Type, dashapi.JobBisectCause)
+	done := &dashapi.JobDoneReq{
+		ID:    resp.ID,
+		Error: []byte("pollAndFailBisectJob"),
+	}
+	client.expectOK(client.JobDone(done))
+}
+
 type (
 	EmailOptMessageID int
 	EmailOptFrom      string
@@ -313,7 +415,7 @@
 func (c *Ctx) incomingEmail(to, body string, opts ...interface{}) {
 	id := 0
 	from := "default@sender.com"
-	cc := []string{"test@syzkaller.com", "bugs@syzkaller.com"}
+	cc := []string{"test@syzkaller.com", "bugs@syzkaller.com", "bugs2@syzkaller.com"}
 	for _, o := range opts {
 		switch opt := o.(type) {
 		case EmailOptMessageID:
diff --git a/dashboard/config/freebsd-syz-ci-service.sh b/dashboard/config/freebsd-syz-ci-service.sh
new file mode 100755
index 0000000..ace1294
--- /dev/null
+++ b/dashboard/config/freebsd-syz-ci-service.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+# To use:
+# - place this script to /usr/local/etc/rc.d/syz_ci
+# - chmod a+x /usr/local/etc/rc.d/syz_ci
+# - add the following to /etc/rc.conf (uncommented):
+#
+# syz_ci_enable="YES"
+# syz_ci_chdir="/syzkaller"
+# syz_ci_flags="-config config-freebsd.ci"
+# syz_ci_log="/syzkaller/syz-ci.log"
+# syz_ci_path="/syzkaller/syz-ci"
+#
+# Then syz-ci will start after boot, to manually start/stop:
+# service syz_ci stop
+# service syz_ci start
+
+# PROVIDE: syz_ci
+# REQUIRE: LOGIN
+
+. /etc/rc.subr
+
+command="${syz_ci_path}"
+name="syz_ci"
+pidfile="/var/run/${name}.pid"
+rcvar="syz_ci_enable"
+start_cmd="syz_ci_start"
+stop_cmd="syz_ci_stop"
+
+# syz-ci needs to be able to find the go executable.
+PATH=${PATH}:/usr/local/bin
+
+syz_ci_start()
+{
+	cd "${syz_ci_chdir}"
+	daemon -f -o "${syz_ci_log}" -p ${pidfile} "${syz_ci_path}" ${syz_ci_flags}
+}
+
+syz_ci_stop()
+{
+	local _pid
+
+	_pid=$(cat ${pidfile})
+	kill -INT $_pid
+	[ $? -eq 0 ] || return 1
+	pwait -t 120s $_pid
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/dashboard/config/kmsan-syzbot-bits.config b/dashboard/config/kmsan-syzbot-bits.config
new file mode 100644
index 0000000..cfe9079
--- /dev/null
+++ b/dashboard/config/kmsan-syzbot-bits.config
@@ -0,0 +1,44 @@
+# Additional config switches for KMSAN kernels.
+# To be used by kmsan_from_kasan_config.sh
+
+# Disable KASAN:
+# CONFIG_SLAB is not set
+# CONFIG_KASAN is not set
+
+# Enable KMSAN:
+# CONFIG_VMAP_STACK is not set
+CONFIG_KMSAN=y
+CONFIG_SLUB=y
+
+# Avoid reboot loop in instrumented kernel:
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PARAVIRT is not set
+
+# Known errors. TODO(glider): fix those and enable the configs below.
+# CONFIG_MTD is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_HARDENED_USERCOPY is not set
+
+# Disable debug configs enabled in KASAN configs:
+# CONFIG_BLK_DEBUG_FS is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
diff --git a/dashboard/config/kmsan_from_kasan_config.sh b/dashboard/config/kmsan_from_kasan_config.sh
new file mode 100755
index 0000000..2f38e19
--- /dev/null
+++ b/dashboard/config/kmsan_from_kasan_config.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# Generate upstream-kmsan.config from upstream-kasan.config.
+# Make sure $CC points to the Clang binary and $SOURCEDIR - to the kernel tree.
+
+THISDIR=`cd $(dirname $0); pwd`
+KASAN_CONFIG=${THISDIR}/upstream-kasan.config
+KMSAN_CONFIG=${THISDIR}/upstream-kmsan.config
+KMSAN_ADD=${THISDIR}/kmsan-syzbot-bits.config
+
+[ -z "${CC}" ] && echo 'Please set $CC to point to the compiler!' && exit
+[ -z "${SOURCEDIR}" ] && echo 'Please set $SOURCEDIR to point to the kernel tree!' && exit
+
+(
+cd $SOURCEDIR
+cp ${KASAN_CONFIG} .config
+scripts/kconfig/merge_config.sh .config ${KMSAN_ADD}
+make CC="${CC}" oldconfig < /dev/null
+
+echo "# The following configs are added manually, preserve them.
+# CONFIG_DEBUG_MEMORY was once added to mm tree and cause disabling of KASAN,
+# which in turn caused storm of assorted crashes after silent memory
+# corruptions. The config was reverted, but we keep it here for the case
+# it is reintroduced to kernel again.
+CONFIG_DEBUG_MEMORY=y
+# This config can be used to enable any additional temporal debugging
+# features in linux-next tree.
+CONFIG_DEBUG_AID_FOR_SYZBOT=y
+" > ${KMSAN_CONFIG}
+
+cat .config >> ${KMSAN_CONFIG}
+cp ${KMSAN_CONFIG} .config
+)
diff --git a/dashboard/config/openbsd-syzkaller.mp b/dashboard/config/openbsd-syzkaller.mp
new file mode 100644
index 0000000..9b9a2bc
--- /dev/null
+++ b/dashboard/config/openbsd-syzkaller.mp
@@ -0,0 +1,8 @@
+include "arch/amd64/conf/GENERIC.MP"
+
+pseudo-device kcov 1
+
+option LOCKF_DIAGNOSTIC
+option WITNESS
+option WITNESS_LOCKTRACE
+option WITNESS_WATCH
diff --git a/dashboard/config/openbsd-syzkaller.sp b/dashboard/config/openbsd-syzkaller.sp
new file mode 100644
index 0000000..0bc73fe
--- /dev/null
+++ b/dashboard/config/openbsd-syzkaller.sp
@@ -0,0 +1,5 @@
+include "arch/amd64/conf/GENERIC"
+
+pseudo-device kcov 1
+
+option LOCKF_DIAGNOSTIC
diff --git a/dashboard/config/overlays/README.md b/dashboard/config/overlays/README.md
new file mode 100644
index 0000000..fb2dc17
--- /dev/null
+++ b/dashboard/config/overlays/README.md
@@ -0,0 +1,7 @@
+# File hierarchies to lay on top of default images
+
+`pkg/build/openbsd.go` replaces the files in the image generated by
+`create-openbsd-vmm-worker.sh` with the contents of `ci-openbsd-multicore/`.
+A minor bit of missing connection between `userspaceDir` and this
+location is managed outside this repository by the local filesystem
+state on the `ci-openbsd` machine.
diff --git a/dashboard/config/overlays/ci-openbsd-multicore/etc/rc.conf.local b/dashboard/config/overlays/ci-openbsd-multicore/etc/rc.conf.local
new file mode 100644
index 0000000..662b2b7
--- /dev/null
+++ b/dashboard/config/overlays/ci-openbsd-multicore/etc/rc.conf.local
@@ -0,0 +1,10 @@
+# Overrides the minimal config in the image created by
+# tools/create-openbsd-vmm-worker.sh to enable PF.
+cron_flags=NO
+library_aslr=NO
+ntpd_flags=NO
+pf=YES
+pflogd_flags=YES
+slaacd_flags=NO
+smtpd_flags=NO
+sndiod_flags=NO
diff --git a/dashboard/config/upstream-apparmor.cmdline b/dashboard/config/upstream-apparmor.cmdline
new file mode 100644
index 0000000..b4c6569
--- /dev/null
+++ b/dashboard/config/upstream-apparmor.cmdline
@@ -0,0 +1,18 @@
+security=apparmor
+lsm=yama,safesetid,integrity,tomoyo,apparmor
+ima_policy=tcb
+workqueue.watchdog_thresh=140
+kvm-intel.nested=1
+nf-conntrack-ftp.ports=20000
+nf-conntrack-tftp.ports=20000
+nf-conntrack-sip.ports=20000
+nf-conntrack-irc.ports=20000
+nf-conntrack-sane.ports=20000
+vivid.n_devs=16
+vivid.multiplanar=1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
+netrom.nr_ndevs=16
+rose.rose_ndevs=16
+spec_store_bypass_disable=prctl
+numa=fake=2
+nopcid
+dummy_hcd.num=8
diff --git a/dashboard/config/upstream-kasan.config b/dashboard/config/upstream-kasan.config
index c7bf748..eefe29b 100644
--- a/dashboard/config/upstream-kasan.config
+++ b/dashboard/config/upstream-kasan.config
@@ -1,6 +1,6 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86 4.18.0-rc8 Kernel Configuration
+# Linux/x86 5.0.0-rc4 Kernel Configuration
 #
 
 # The following configs are added manually, preserve them.
@@ -14,51 +14,12 @@
 CONFIG_DEBUG_AID_FOR_SYZBOT=y
 
 #
-# Compiler: gcc (GCC) 8.0.1 20180412 (experimental)
+# Compiler: gcc (GCC) 9.0.0 20190115 (experimental)
 #
-CONFIG_64BIT=y
-CONFIG_X86_64=y
-CONFIG_X86=y
-CONFIG_INSTRUCTION_DECODER=y
-CONFIG_OUTPUT_FORMAT="elf64-x86-64"
-CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_MMU=y
-CONFIG_ARCH_MMAP_RND_BITS_MIN=28
-CONFIG_ARCH_MMAP_RND_BITS_MAX=32
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_HAS_CPU_RELAX=y
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_ARCH_HAS_FILTER_PGPROT=y
-CONFIG_HAVE_SETUP_PER_CPU_AREA=y
-CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
-CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
-CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
-CONFIG_ZONE_DMA32=y
-CONFIG_AUDIT_ARCH=y
-CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
-CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
-CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
-CONFIG_HAVE_INTEL_TXT=y
-CONFIG_X86_64_SMP=y
-CONFIG_ARCH_SUPPORTS_UPROBES=y
-CONFIG_FIX_EARLYCON_MEM=y
-CONFIG_PGTABLE_LEVELS=4
 CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=80001
+CONFIG_GCC_VERSION=90000
 CONFIG_CLANG_VERSION=0
+CONFIG_CC_HAS_ASM_GOTO=y
 CONFIG_CONSTRUCTORS=y
 CONFIG_IRQ_WORK=y
 CONFIG_BUILDTIME_EXTABLE_SORT=y
@@ -71,6 +32,7 @@
 # CONFIG_COMPILE_TEST is not set
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_BUILD_SALT=""
 CONFIG_HAVE_KERNEL_GZIP=y
 CONFIG_HAVE_KERNEL_BZIP2=y
 CONFIG_HAVE_KERNEL_LZMA=y
@@ -94,8 +56,6 @@
 CONFIG_AUDIT=y
 CONFIG_HAVE_ARCH_AUDITSYSCALL=y
 CONFIG_AUDITSYSCALL=y
-CONFIG_AUDIT_WATCH=y
-CONFIG_AUDIT_TREE=y
 
 #
 # IRQ subsystem
@@ -116,6 +76,7 @@
 # CONFIG_GENERIC_IRQ_DEBUGFS is not set
 CONFIG_CLOCKSOURCE_WATCHDOG=y
 CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
 CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
@@ -133,31 +94,41 @@
 # CONFIG_NO_HZ_FULL is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
 
 #
 # CPU/Task time and stats accounting
 #
 CONFIG_TICK_CPU_ACCOUNTING=y
 # CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
-# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_SCHED_AVG_IRQ=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_TASKSTATS=y
 CONFIG_TASK_DELAY_ACCT=y
 CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_PSI=y
+# CONFIG_PSI_DEFAULT_DISABLED is not set
 # CONFIG_CPU_ISOLATION is not set
 
 #
 # RCU Subsystem
 #
-CONFIG_TREE_RCU=y
+CONFIG_PREEMPT_RCU=y
 # CONFIG_RCU_EXPERT is not set
 CONFIG_SRCU=y
 CONFIG_TREE_SRCU=y
+CONFIG_TASKS_RCU=y
 CONFIG_RCU_STALL_COMMON=y
 CONFIG_RCU_NEED_SEGCBLIST=y
-# CONFIG_IKCONFIG is not set
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
 CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
@@ -172,8 +143,9 @@
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_MEMCG_SWAP_ENABLED=y
+CONFIG_MEMCG_KMEM=y
 CONFIG_BLK_CGROUP=y
-# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_DEBUG_BLK_CGROUP=y
 CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
@@ -197,6 +169,7 @@
 CONFIG_USER_NS=y
 CONFIG_PID_NS=y
 CONFIG_NET_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
 # CONFIG_SCHED_AUTOGROUP is not set
 # CONFIG_SYSFS_DEPRECATED is not set
 CONFIG_RELAY=y
@@ -240,7 +213,6 @@
 CONFIG_AIO=y
 CONFIG_ADVISE_SYSCALLS=y
 CONFIG_MEMBARRIER=y
-CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
@@ -270,187 +242,49 @@
 CONFIG_SYSTEM_DATA_VERIFICATION=y
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-CONFIG_CRASH_CORE=y
-CONFIG_KEXEC_CORE=y
-# CONFIG_OPROFILE is not set
-CONFIG_HAVE_OPROFILE=y
-CONFIG_OPROFILE_NMI_TIMER=y
-# CONFIG_KPROBES is not set
-CONFIG_JUMP_LABEL=y
-# CONFIG_STATIC_KEYS_SELFTEST is not set
-CONFIG_UPROBES=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_ARCH_USE_BUILTIN_BSWAP=y
-CONFIG_USER_RETURN_NOTIFIER=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_OPTPROBES=y
-CONFIG_HAVE_KPROBES_ON_FTRACE=y
-CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
-CONFIG_HAVE_NMI=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_GENERIC_SMP_IDLE_THREAD=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_HW_BREAKPOINT=y
-CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
-CONFIG_HAVE_USER_RETURN_NOTIFIER=y
-CONFIG_HAVE_PERF_EVENTS_NMI=y
-CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_RCU_TABLE_FREE=y
-CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
-CONFIG_HAVE_CMPXCHG_LOCAL=y
-CONFIG_HAVE_CMPXCHG_DOUBLE=y
-CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
-CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
-CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
-CONFIG_SECCOMP_FILTER=y
-CONFIG_PLUGIN_HOSTCC=""
-CONFIG_HAVE_GCC_PLUGINS=y
-CONFIG_HAVE_STACKPROTECTOR=y
-CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
-CONFIG_STACKPROTECTOR=y
-CONFIG_STACKPROTECTOR_STRONG=y
-CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
-CONFIG_HAVE_CONTEXT_TRACKING=y
-CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
-CONFIG_HAVE_ARCH_HUGE_VMAP=y
-CONFIG_HAVE_ARCH_SOFT_DIRTY=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_MODULES_USE_ELF_RELA=y
-CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
-CONFIG_HAVE_EXIT_THREAD=y
-CONFIG_ARCH_MMAP_RND_BITS=28
-CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
-CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
-CONFIG_HAVE_COPY_THREAD_TLS=y
-CONFIG_HAVE_STACK_VALIDATION=y
-CONFIG_HAVE_RELIABLE_STACKTRACE=y
-CONFIG_OLD_SIGSUSPEND3=y
-CONFIG_COMPAT_OLD_SIGACTION=y
-CONFIG_COMPAT_32BIT_TIME=y
-CONFIG_HAVE_ARCH_VMAP_STACK=y
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_STRICT_MODULE_RWX=y
-CONFIG_ARCH_HAS_REFCOUNT=y
-CONFIG_REFCOUNT_FULL=y
-
-#
-# GCOV-based kernel profiling
-#
-# CONFIG_GCOV_KERNEL is not set
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_MODULE_SIG is not set
-# CONFIG_MODULE_COMPRESS is not set
-# CONFIG_TRIM_UNUSED_KSYMS is not set
-CONFIG_MODULES_TREE_LOOKUP=y
-CONFIG_BLOCK=y
-CONFIG_BLK_SCSI_REQUEST=y
-CONFIG_BLK_DEV_BSG=y
-CONFIG_BLK_DEV_BSGLIB=y
-CONFIG_BLK_DEV_INTEGRITY=y
-CONFIG_BLK_DEV_ZONED=y
-CONFIG_BLK_DEV_THROTTLING=y
-# CONFIG_BLK_DEV_THROTTLING_LOW is not set
-CONFIG_BLK_CMDLINE_PARSER=y
-CONFIG_BLK_WBT=y
-# CONFIG_BLK_WBT_SQ is not set
-CONFIG_BLK_WBT_MQ=y
-# CONFIG_BLK_DEBUG_FS is not set
-# CONFIG_BLK_SED_OPAL is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_ACORN_PARTITION=y
-CONFIG_ACORN_PARTITION_CUMANA=y
-CONFIG_ACORN_PARTITION_EESOX=y
-CONFIG_ACORN_PARTITION_ICS=y
-CONFIG_ACORN_PARTITION_ADFS=y
-CONFIG_ACORN_PARTITION_POWERTEC=y
-CONFIG_ACORN_PARTITION_RISCIX=y
-CONFIG_AIX_PARTITION=y
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-CONFIG_ATARI_PARTITION=y
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_LDM_PARTITION=y
-# CONFIG_LDM_DEBUG is not set
-CONFIG_SGI_PARTITION=y
-CONFIG_ULTRIX_PARTITION=y
-CONFIG_SUN_PARTITION=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_SYSV68_PARTITION=y
-CONFIG_CMDLINE_PARTITION=y
-CONFIG_BLOCK_COMPAT=y
-CONFIG_BLK_MQ_PCI=y
-CONFIG_BLK_MQ_VIRTIO=y
-CONFIG_BLK_MQ_RDMA=y
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_CFQ_GROUP_IOSCHED=y
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_MQ_IOSCHED_DEADLINE=y
-CONFIG_MQ_IOSCHED_KYBER=y
-CONFIG_IOSCHED_BFQ=y
-CONFIG_BFQ_GROUP_IOSCHED=y
-CONFIG_PREEMPT_NOTIFIERS=y
-CONFIG_PADATA=y
-CONFIG_ASN1=y
-CONFIG_UNINLINE_SPIN_UNLOCK=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_MUTEX_SPIN_ON_OWNER=y
-CONFIG_RWSEM_SPIN_ON_OWNER=y
-CONFIG_LOCK_SPIN_ON_OWNER=y
-CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
-CONFIG_QUEUED_SPINLOCKS=y
-CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
-CONFIG_QUEUED_RWLOCKS=y
-CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
-CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_GENERIC_CMDLINE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_64BIT=y
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=28
+CONFIG_ARCH_MMAP_RND_BITS_MAX=32
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_FILTER_PGPROT=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ZONE_DMA32=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
+CONFIG_HAVE_INTEL_TXT=y
+CONFIG_X86_64_SMP=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_PGTABLE_LEVELS=4
 CONFIG_CC_HAS_SANE_STACKPROTECTOR=y
-CONFIG_FREEZER=y
 
 #
 # Processor type and features
@@ -462,7 +296,7 @@
 CONFIG_X86_MPPARSE=y
 # CONFIG_GOLDFISH is not set
 CONFIG_RETPOLINE=y
-# CONFIG_INTEL_RDT is not set
+# CONFIG_X86_RESCTRL is not set
 CONFIG_X86_EXTENDED_PLATFORM=y
 # CONFIG_X86_NUMACHIP is not set
 # CONFIG_X86_VSMP is not set
@@ -477,6 +311,7 @@
 CONFIG_SCHED_OMIT_FRAME_POINTER=y
 CONFIG_HYPERVISOR_GUEST=y
 CONFIG_PARAVIRT=y
+CONFIG_PARAVIRT_XXL=y
 CONFIG_PARAVIRT_DEBUG=y
 CONFIG_PARAVIRT_SPINLOCKS=y
 # CONFIG_QUEUED_LOCK_STAT is not set
@@ -491,26 +326,30 @@
 # CONFIG_XEN_DEBUG_FS is not set
 CONFIG_XEN_PVH=y
 CONFIG_KVM_GUEST=y
+CONFIG_PVH=y
 # CONFIG_KVM_DEBUG_FS is not set
 # CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
 CONFIG_PARAVIRT_CLOCK=y
 # CONFIG_JAILHOUSE_GUEST is not set
-CONFIG_NO_BOOTMEM=y
 # CONFIG_MK8 is not set
 # CONFIG_MPSC is not set
-# CONFIG_MCORE2 is not set
+CONFIG_MCORE2=y
 # CONFIG_MATOM is not set
-CONFIG_GENERIC_CPU=y
+# CONFIG_GENERIC_CPU is not set
 CONFIG_X86_INTERNODE_CACHE_SHIFT=6
 CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_P6_NOP=y
 CONFIG_X86_TSC=y
 CONFIG_X86_CMPXCHG64=y
 CONFIG_X86_CMOV=y
 CONFIG_X86_MINIMUM_CPU_FAMILY=64
 CONFIG_X86_DEBUGCTLMSR=y
-# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_PROCESSOR_SELECT=y
 CONFIG_CPU_SUP_INTEL=y
 CONFIG_CPU_SUP_AMD=y
+# CONFIG_CPU_SUP_HYGON is not set
 CONFIG_CPU_SUP_CENTAUR=y
 CONFIG_HPET_TIMER=y
 CONFIG_HPET_EMULATE_RTC=y
@@ -526,10 +365,6 @@
 CONFIG_SCHED_SMT=y
 CONFIG_SCHED_MC=y
 CONFIG_SCHED_MC_PRIO=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
-CONFIG_PREEMPT_COUNT=y
 CONFIG_X86_LOCAL_APIC=y
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
@@ -560,75 +395,20 @@
 CONFIG_X86_CPUID=y
 # CONFIG_X86_5LEVEL is not set
 CONFIG_X86_DIRECT_GBPAGES=y
+# CONFIG_X86_CPA_STATISTICS is not set
 CONFIG_ARCH_HAS_MEM_ENCRYPT=y
 # CONFIG_AMD_MEM_ENCRYPT is not set
 CONFIG_NUMA=y
 CONFIG_AMD_NUMA=y
 CONFIG_X86_64_ACPI_NUMA=y
 CONFIG_NODES_SPAN_OTHER_NODES=y
-# CONFIG_NUMA_EMU is not set
+CONFIG_NUMA_EMU=y
 CONFIG_NODES_SHIFT=6
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_PROC_KCORE_TEXT=y
 CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_SPARSEMEM=y
-CONFIG_NEED_MULTIPLE_NODES=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_SPARSEMEM_EXTREME=y
-CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
-CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
-CONFIG_SPARSEMEM_VMEMMAP=y
-CONFIG_HAVE_MEMBLOCK=y
-CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
-CONFIG_HAVE_GENERIC_GUP=y
-CONFIG_ARCH_DISCARD_MEMBLOCK=y
-# CONFIG_MEMORY_HOTPLUG is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
-CONFIG_MEMORY_BALLOON=y
-CONFIG_BALLOON_COMPACTION=y
-CONFIG_COMPACTION=y
-CONFIG_MIGRATION=y
-CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
-CONFIG_ARCH_ENABLE_THP_MIGRATION=y
-CONFIG_PHYS_ADDR_T_64BIT=y
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_MMU_NOTIFIER=y
-CONFIG_KSM=y
-CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
-CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
-# CONFIG_MEMORY_FAILURE is not set
-CONFIG_TRANSPARENT_HUGEPAGE=y
-CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
-# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
-CONFIG_ARCH_WANTS_THP_SWAP=y
-CONFIG_THP_SWAP=y
-CONFIG_TRANSPARENT_HUGE_PAGECACHE=y
-# CONFIG_CLEANCACHE is not set
-CONFIG_FRONTSWAP=y
-# CONFIG_CMA is not set
-# CONFIG_MEM_SOFT_DIRTY is not set
-CONFIG_ZSWAP=y
-CONFIG_ZPOOL=y
-# CONFIG_ZBUD is not set
-# CONFIG_Z3FOLD is not set
-CONFIG_ZSMALLOC=y
-# CONFIG_PGTABLE_MAPPING is not set
-# CONFIG_ZSMALLOC_STAT is not set
-CONFIG_GENERIC_EARLY_IOREMAP=y
-# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
-# CONFIG_IDLE_PAGE_TRACKING is not set
-CONFIG_ARCH_HAS_ZONE_DEVICE=y
-CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
-CONFIG_ARCH_HAS_PKEYS=y
-# CONFIG_PERCPU_STATS is not set
-# CONFIG_GUP_BENCHMARK is not set
-CONFIG_ARCH_HAS_PTE_SPECIAL=y
 # CONFIG_X86_PMEM_LEGACY is not set
 CONFIG_X86_CHECK_BIOS_CORRUPTION=y
 CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
@@ -647,11 +427,11 @@
 CONFIG_EFI=y
 # CONFIG_EFI_STUB is not set
 CONFIG_SECCOMP=y
-# CONFIG_HZ_100 is not set
+CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
 # CONFIG_HZ_300 is not set
-CONFIG_HZ_1000=y
-CONFIG_HZ=1000
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
 CONFIG_SCHED_HRTICK=y
 CONFIG_KEXEC=y
 # CONFIG_KEXEC_FILE is not set
@@ -667,12 +447,14 @@
 # CONFIG_COMPAT_VDSO is not set
 CONFIG_LEGACY_VSYSCALL_EMULATE=y
 # CONFIG_LEGACY_VSYSCALL_NONE is not set
-# CONFIG_CMDLINE_BOOL is not set
 CONFIG_MODIFY_LDT_SYSCALL=y
 CONFIG_HAVE_LIVEPATCH=y
 CONFIG_ARCH_HAS_ADD_PAGES=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_USE_PERCPU_NUMA_NODE_ID=y
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
+CONFIG_ARCH_ENABLE_THP_MIGRATION=y
 
 #
 # Power management and ACPI options
@@ -697,6 +479,8 @@
 CONFIG_PM_TRACE_RTC=y
 CONFIG_PM_CLK=y
 # CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+# CONFIG_ENERGY_MODEL is not set
+CONFIG_ARCH_SUPPORTS_ACPI=y
 CONFIG_ACPI=y
 CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
 CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
@@ -788,110 +572,25 @@
 CONFIG_CPU_IDLE=y
 # CONFIG_CPU_IDLE_GOV_LADDER is not set
 CONFIG_CPU_IDLE_GOV_MENU=y
-# CONFIG_INTEL_IDLE is not set
+# CONFIG_CPU_IDLE_GOV_TEO is not set
+CONFIG_INTEL_IDLE=y
 
 #
 # Bus options (PCI etc.)
 #
-CONFIG_PCI=y
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 CONFIG_PCI_XEN=y
-CONFIG_PCI_DOMAINS=y
 CONFIG_MMCONF_FAM10H=y
 # CONFIG_PCI_CNB20LE_QUIRK is not set
-CONFIG_PCIEPORTBUS=y
-# CONFIG_HOTPLUG_PCI_PCIE is not set
-CONFIG_PCIEAER=y
-# CONFIG_PCIEAER_INJECT is not set
-# CONFIG_PCIE_ECRC is not set
-CONFIG_PCIEASPM=y
-# CONFIG_PCIEASPM_DEBUG is not set
-CONFIG_PCIEASPM_DEFAULT=y
-# CONFIG_PCIEASPM_POWERSAVE is not set
-# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
-# CONFIG_PCIEASPM_PERFORMANCE is not set
-CONFIG_PCIE_PME=y
-# CONFIG_PCIE_DPC is not set
-# CONFIG_PCIE_PTM is not set
-CONFIG_PCI_MSI=y
-CONFIG_PCI_MSI_IRQ_DOMAIN=y
-CONFIG_PCI_QUIRKS=y
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
-# CONFIG_PCI_STUB is not set
-# CONFIG_PCI_PF_STUB is not set
-CONFIG_XEN_PCIDEV_FRONTEND=y
-CONFIG_PCI_ATS=y
-CONFIG_PCI_LOCKLESS_CONFIG=y
-CONFIG_PCI_IOV=y
-CONFIG_PCI_PRI=y
-CONFIG_PCI_PASID=y
-CONFIG_PCI_LABEL=y
-CONFIG_HOTPLUG_PCI=y
-# CONFIG_HOTPLUG_PCI_ACPI is not set
-# CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_SHPC is not set
-
-#
-# PCI controller drivers
-#
-
-#
-# Cadence PCIe controllers support
-#
-# CONFIG_VMD is not set
-
-#
-# DesignWare PCI Core Support
-#
-# CONFIG_PCIE_DW_PLAT_HOST is not set
-# CONFIG_PCIE_DW_PLAT_EP is not set
-
-#
-# PCI Endpoint
-#
-CONFIG_PCI_ENDPOINT=y
-# CONFIG_PCI_ENDPOINT_CONFIGFS is not set
-# CONFIG_PCI_EPF_TEST is not set
-
-#
-# PCI switch controller drivers
-#
-# CONFIG_PCI_SW_SWITCHTEC is not set
 # CONFIG_ISA_BUS is not set
 CONFIG_ISA_DMA_API=y
 CONFIG_AMD_NB=y
-CONFIG_PCCARD=y
-CONFIG_PCMCIA=y
-CONFIG_PCMCIA_LOAD_CIS=y
-CONFIG_CARDBUS=y
-
-#
-# PC-card bridges
-#
-CONFIG_YENTA=y
-CONFIG_YENTA_O2=y
-CONFIG_YENTA_RICOH=y
-CONFIG_YENTA_TI=y
-CONFIG_YENTA_ENE_TUNE=y
-CONFIG_YENTA_TOSHIBA=y
-# CONFIG_PD6729 is not set
-# CONFIG_I82092 is not set
-CONFIG_PCCARD_NONSTATIC=y
-# CONFIG_RAPIDIO is not set
 # CONFIG_X86_SYSFB is not set
 
 #
-# Executable file formats / Emulations
+# Binary Emulations
 #
-CONFIG_BINFMT_ELF=y
-CONFIG_COMPAT_BINFMT_ELF=y
-CONFIG_ELFCORE=y
-CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
-CONFIG_BINFMT_SCRIPT=y
-CONFIG_BINFMT_MISC=y
-CONFIG_COREDUMP=y
 CONFIG_IA32_EMULATION=y
 CONFIG_IA32_AOUT=y
 CONFIG_X86_X32=y
@@ -900,10 +599,318 @@
 CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_X86_DEV_DMA_OPS=y
+CONFIG_HAVE_GENERIC_GUP=y
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DMIID=y
+# CONFIG_DMI_SYSFS is not set
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+# CONFIG_FW_CFG_SYSFS is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# EFI (Extensible Firmware Interface) Support
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_ESRT=y
+CONFIG_EFI_RUNTIME_MAP=y
+# CONFIG_EFI_FAKE_MEMMAP is not set
+CONFIG_EFI_RUNTIME_WRAPPERS=y
+# CONFIG_EFI_BOOTLOADER_CONTROL is not set
+# CONFIG_EFI_CAPSULE_LOADER is not set
+# CONFIG_EFI_TEST is not set
+
+#
+# Tegra firmware driver
+#
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_IRQFD=y
+CONFIG_HAVE_KVM_IRQ_ROUTING=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_HAVE_KVM_MSI=y
+CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
+CONFIG_KVM_VFIO=y
+CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
+CONFIG_KVM_COMPAT=y
+CONFIG_HAVE_KVM_IRQ_BYPASS=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
+CONFIG_KVM_INTEL=y
+CONFIG_KVM_AMD=y
+# CONFIG_KVM_MMU_AUDIT is not set
+CONFIG_VHOST_NET=y
+CONFIG_VHOST_VSOCK=y
+CONFIG_VHOST=y
+CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y
+
+#
+# General architecture-dependent options
+#
+CONFIG_CRASH_CORE=y
+CONFIG_KEXEC_CORE=y
+CONFIG_HOTPLUG_SMT=y
+# CONFIG_OPROFILE is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+CONFIG_UPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
+CONFIG_HAVE_RCU_TABLE_FREE=y
+CONFIG_HAVE_RCU_TABLE_INVALIDATE=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_STACKLEAK=y
+CONFIG_HAVE_STACKPROTECTOR=y
+CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOVE_PMD=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_HAVE_ARCH_SOFT_DIRTY=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS=28
+CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
+CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
+CONFIG_HAVE_STACK_VALIDATION=y
+CONFIG_HAVE_RELIABLE_STACKTRACE=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_HAVE_ARCH_VMAP_STACK=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_STRICT_MODULE_RWX=y
+CONFIG_ARCH_HAS_REFCOUNT=y
+CONFIG_REFCOUNT_FULL=y
+CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_PLUGIN_HOSTCC="g++"
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_ZONED=y
+CONFIG_BLK_DEV_THROTTLING=y
+# CONFIG_BLK_DEV_THROTTLING_LOW is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_CGROUP_IOLATENCY=y
+CONFIG_BLK_WBT_MQ=y
+CONFIG_BLK_DEBUG_FS=y
+CONFIG_BLK_DEBUG_FS_ZONED=y
+# CONFIG_BLK_SED_OPAL is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_CUMANA=y
+CONFIG_ACORN_PARTITION_EESOX=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_ADFS=y
+CONFIG_ACORN_PARTITION_POWERTEC=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_AIX_PARTITION=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_CMDLINE_PARTITION=y
+CONFIG_BLOCK_COMPAT=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_MQ_VIRTIO=y
+CONFIG_BLK_MQ_RDMA=y
+CONFIG_BLK_PM=y
+
+#
+# IO Schedulers
+#
+CONFIG_MQ_IOSCHED_DEADLINE=y
+CONFIG_MQ_IOSCHED_KYBER=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+CONFIG_ASN1=y
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_FREEZER=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+CONFIG_BINFMT_MISC=y
+CONFIG_COREDUMP=y
+
+#
+# Memory Management options
+#
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MEMORY_BALLOON=y
+CONFIG_BALLOON_COMPACTION=y
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+# CONFIG_MEMORY_FAILURE is not set
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_THP_SWAP=y
+CONFIG_TRANSPARENT_HUGE_PAGECACHE=y
+# CONFIG_CLEANCACHE is not set
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_AREAS=7
+CONFIG_MEM_SOFT_DIRTY=y
+CONFIG_ZSWAP=y
+CONFIG_ZPOOL=y
+CONFIG_ZBUD=y
+# CONFIG_Z3FOLD is not set
+CONFIG_ZSMALLOC=y
+# CONFIG_PGTABLE_MAPPING is not set
+# CONFIG_ZSMALLOC_STAT is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
+CONFIG_IDLE_PAGE_TRACKING=y
+CONFIG_ARCH_HAS_ZONE_DEVICE=y
+CONFIG_FRAME_VECTOR=y
+CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
+CONFIG_ARCH_HAS_PKEYS=y
+CONFIG_PERCPU_STATS=y
+# CONFIG_GUP_BENCHMARK is not set
+CONFIG_ARCH_HAS_PTE_SPECIAL=y
 CONFIG_NET=y
 CONFIG_COMPAT_NETLINK_MESSAGES=y
 CONFIG_NET_INGRESS=y
 CONFIG_NET_EGRESS=y
+CONFIG_SKB_EXTENSIONS=y
 
 #
 # Networking options
@@ -918,6 +925,7 @@
 CONFIG_XFRM_OFFLOAD=y
 CONFIG_XFRM_ALGO=y
 CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
 CONFIG_XFRM_SUB_POLICY=y
 CONFIG_XFRM_MIGRATE=y
 CONFIG_XFRM_STATISTICS=y
@@ -925,12 +933,13 @@
 CONFIG_NET_KEY=y
 CONFIG_NET_KEY_MIGRATE=y
 CONFIG_SMC=y
-# CONFIG_SMC_DIAG is not set
+CONFIG_SMC_DIAG=y
 CONFIG_XDP_SOCKETS=y
+CONFIG_XDP_SOCKETS_DIAG=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
-# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_FIB_TRIE_STATS=y
 CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_MULTIPATH=y
 CONFIG_IP_ROUTE_VERBOSE=y
@@ -967,7 +976,7 @@
 CONFIG_INET_TCP_DIAG=y
 CONFIG_INET_UDP_DIAG=y
 CONFIG_INET_RAW_DIAG=y
-# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_INET_DIAG_DESTROY=y
 CONFIG_TCP_CONG_ADVANCED=y
 # CONFIG_TCP_CONG_BIC is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -1044,6 +1053,7 @@
 CONFIG_NETFILTER_NETLINK_ACCT=y
 CONFIG_NETFILTER_NETLINK_QUEUE=y
 CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NETFILTER_NETLINK_OSF=y
 CONFIG_NF_CONNTRACK=y
 CONFIG_NF_LOG_COMMON=y
 CONFIG_NF_LOG_NETDEV=y
@@ -1077,9 +1087,6 @@
 CONFIG_NETFILTER_NETLINK_GLUE_CT=y
 CONFIG_NF_NAT=y
 CONFIG_NF_NAT_NEEDED=y
-CONFIG_NF_NAT_PROTO_DCCP=y
-CONFIG_NF_NAT_PROTO_UDPLITE=y
-CONFIG_NF_NAT_PROTO_SCTP=y
 CONFIG_NF_NAT_AMANDA=y
 CONFIG_NF_NAT_FTP=y
 CONFIG_NF_NAT_IRC=y
@@ -1087,7 +1094,6 @@
 CONFIG_NF_NAT_TFTP=y
 CONFIG_NF_NAT_REDIRECT=y
 CONFIG_NETFILTER_SYNPROXY=y
-CONFIG_NF_OSF=y
 CONFIG_NF_TABLES=y
 CONFIG_NF_TABLES_SET=y
 CONFIG_NF_TABLES_INET=y
@@ -1102,6 +1108,7 @@
 CONFIG_NFT_MASQ=y
 CONFIG_NFT_REDIR=y
 CONFIG_NFT_NAT=y
+CONFIG_NFT_TUNNEL=y
 CONFIG_NFT_OBJREF=y
 CONFIG_NFT_QUEUE=y
 CONFIG_NFT_QUOTA=y
@@ -1111,7 +1118,10 @@
 CONFIG_NFT_HASH=y
 CONFIG_NFT_FIB=y
 CONFIG_NFT_FIB_INET=y
+CONFIG_NFT_XFRM=y
 CONFIG_NFT_SOCKET=y
+CONFIG_NFT_OSF=y
+CONFIG_NFT_TPROXY=y
 CONFIG_NF_DUP_NETDEV=y
 CONFIG_NFT_DUP_NETDEV=y
 CONFIG_NFT_FWD_NETDEV=y
@@ -1277,7 +1287,6 @@
 # IP: Netfilter Configuration
 #
 CONFIG_NF_DEFRAG_IPV4=y
-CONFIG_NF_CONNTRACK_IPV4=y
 CONFIG_NF_SOCKET_IPV4=y
 CONFIG_NF_TPROXY_IPV4=y
 CONFIG_NF_TABLES_IPV4=y
@@ -1292,12 +1301,11 @@
 CONFIG_NF_LOG_IPV4=y
 CONFIG_NF_REJECT_IPV4=y
 CONFIG_NF_NAT_IPV4=y
-CONFIG_NFT_CHAIN_NAT_IPV4=y
 CONFIG_NF_NAT_MASQUERADE_IPV4=y
+CONFIG_NFT_CHAIN_NAT_IPV4=y
 CONFIG_NFT_MASQ_IPV4=y
 CONFIG_NFT_REDIR_IPV4=y
 CONFIG_NF_NAT_SNMP_BASIC=y
-CONFIG_NF_NAT_PROTO_GRE=y
 CONFIG_NF_NAT_PPTP=y
 CONFIG_NF_NAT_H323=y
 CONFIG_IP_NF_IPTABLES=y
@@ -1325,8 +1333,6 @@
 #
 # IPv6: Netfilter Configuration
 #
-CONFIG_NF_DEFRAG_IPV6=y
-CONFIG_NF_CONNTRACK_IPV6=y
 CONFIG_NF_SOCKET_IPV6=y
 CONFIG_NF_TPROXY_IPV6=y
 CONFIG_NF_TABLES_IPV6=y
@@ -1364,6 +1370,7 @@
 CONFIG_IP6_NF_NAT=y
 CONFIG_IP6_NF_TARGET_MASQUERADE=y
 CONFIG_IP6_NF_TARGET_NPT=y
+CONFIG_NF_DEFRAG_IPV6=y
 CONFIG_NF_TABLES_BRIDGE=y
 CONFIG_NFT_BRIDGE_REJECT=y
 CONFIG_NF_LOG_BRIDGE=y
@@ -1388,8 +1395,7 @@
 CONFIG_BRIDGE_EBT_SNAT=y
 CONFIG_BRIDGE_EBT_LOG=y
 CONFIG_BRIDGE_EBT_NFLOG=y
-CONFIG_BPFILTER=y
-CONFIG_BPFILTER_UMH=y
+# CONFIG_BPFILTER is not set
 CONFIG_IP_DCCP=y
 CONFIG_INET_DCCP_DIAG=y
 
@@ -1430,7 +1436,9 @@
 # CONFIG_ATM_BR2684_IPFILTER is not set
 CONFIG_L2TP=y
 # CONFIG_L2TP_DEBUGFS is not set
-# CONFIG_L2TP_V3 is not set
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
 CONFIG_STP=y
 CONFIG_GARP=y
 CONFIG_MRP=y
@@ -1447,8 +1455,8 @@
 CONFIG_LLC=y
 CONFIG_LLC2=y
 # CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
+CONFIG_X25=y
+CONFIG_LAPB=y
 # CONFIG_PHONET is not set
 CONFIG_6LOWPAN=y
 # CONFIG_6LOWPAN_DEBUGFS is not set
@@ -1488,15 +1496,19 @@
 CONFIG_NET_SCH_TEQL=y
 CONFIG_NET_SCH_TBF=y
 CONFIG_NET_SCH_CBS=y
+CONFIG_NET_SCH_ETF=y
+CONFIG_NET_SCH_TAPRIO=y
 CONFIG_NET_SCH_GRED=y
 CONFIG_NET_SCH_DSMARK=y
 CONFIG_NET_SCH_NETEM=y
 CONFIG_NET_SCH_DRR=y
 CONFIG_NET_SCH_MQPRIO=y
+CONFIG_NET_SCH_SKBPRIO=y
 CONFIG_NET_SCH_CHOKE=y
 CONFIG_NET_SCH_QFQ=y
 CONFIG_NET_SCH_CODEL=y
 CONFIG_NET_SCH_FQ_CODEL=y
+CONFIG_NET_SCH_CAKE=y
 CONFIG_NET_SCH_FQ=y
 CONFIG_NET_SCH_HHF=y
 CONFIG_NET_SCH_PIE=y
@@ -1519,15 +1531,15 @@
 CONFIG_NET_CLS_ROUTE4=y
 CONFIG_NET_CLS_FW=y
 CONFIG_NET_CLS_U32=y
-# CONFIG_CLS_U32_PERF is not set
+CONFIG_CLS_U32_PERF=y
 CONFIG_CLS_U32_MARK=y
 CONFIG_NET_CLS_RSVP=y
 CONFIG_NET_CLS_RSVP6=y
 CONFIG_NET_CLS_FLOW=y
-# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_CLS_CGROUP=y
 CONFIG_NET_CLS_BPF=y
 CONFIG_NET_CLS_FLOWER=y
-# CONFIG_NET_CLS_MATCHALL is not set
+CONFIG_NET_CLS_MATCHALL=y
 CONFIG_NET_EMATCH=y
 CONFIG_NET_EMATCH_STACK=32
 CONFIG_NET_EMATCH_CMP=y
@@ -1535,12 +1547,12 @@
 CONFIG_NET_EMATCH_U32=y
 CONFIG_NET_EMATCH_META=y
 CONFIG_NET_EMATCH_TEXT=y
-# CONFIG_NET_EMATCH_CANID is not set
+CONFIG_NET_EMATCH_CANID=y
 CONFIG_NET_EMATCH_IPSET=y
 CONFIG_NET_EMATCH_IPT=y
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
-CONFIG_NET_ACT_GACT=m
+CONFIG_NET_ACT_GACT=y
 CONFIG_GACT_PROB=y
 CONFIG_NET_ACT_MIRRED=y
 CONFIG_NET_ACT_SAMPLE=y
@@ -1556,14 +1568,22 @@
 CONFIG_NET_ACT_SKBMOD=y
 CONFIG_NET_ACT_IFE=y
 CONFIG_NET_ACT_TUNNEL_KEY=y
-# CONFIG_NET_IFE_SKBMARK is not set
-# CONFIG_NET_IFE_SKBPRIO is not set
-# CONFIG_NET_IFE_SKBTCINDEX is not set
-# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_IFE_SKBMARK=y
+CONFIG_NET_IFE_SKBPRIO=y
+CONFIG_NET_IFE_SKBTCINDEX=y
+CONFIG_NET_CLS_IND=y
 CONFIG_NET_SCH_FIFO=y
 CONFIG_DCB=y
 CONFIG_DNS_RESOLVER=y
-# CONFIG_BATMAN_ADV is not set
+CONFIG_BATMAN_ADV=y
+CONFIG_BATMAN_ADV_BATMAN_V=y
+CONFIG_BATMAN_ADV_BLA=y
+CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
+# CONFIG_BATMAN_ADV_DEBUGFS is not set
+# CONFIG_BATMAN_ADV_DEBUG is not set
+# CONFIG_BATMAN_ADV_TRACING is not set
 CONFIG_OPENVSWITCH=y
 CONFIG_OPENVSWITCH_GRE=y
 CONFIG_OPENVSWITCH_VXLAN=y
@@ -1572,16 +1592,17 @@
 CONFIG_VSOCKETS_DIAG=y
 CONFIG_VIRTIO_VSOCKETS=y
 CONFIG_VIRTIO_VSOCKETS_COMMON=y
-# CONFIG_NETLINK_DIAG is not set
+CONFIG_NETLINK_DIAG=y
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=y
 CONFIG_MPLS_ROUTING=y
 CONFIG_MPLS_IPTUNNEL=y
 CONFIG_NET_NSH=y
-# CONFIG_HSR is not set
+CONFIG_HSR=y
 CONFIG_NET_SWITCHDEV=y
 CONFIG_NET_L3_MASTER_DEV=y
 CONFIG_NET_NCSI=y
+# CONFIG_NCSI_OEM_CMD_GET_MAC is not set
 CONFIG_RPS=y
 CONFIG_RFS_ACCEL=y
 CONFIG_XPS=y
@@ -1597,13 +1618,26 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_NET_DROP_MONITOR is not set
+CONFIG_NET_DROP_MONITOR=y
 CONFIG_HAMRADIO=y
 
 #
 # Packet Radio protocols
 #
-# CONFIG_AX25 is not set
+CONFIG_AX25=y
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=y
+CONFIG_ROSE=y
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=y
+CONFIG_6PACK=y
+CONFIG_BPQETHER=y
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_YAM is not set
 CONFIG_CAN=y
 CONFIG_CAN_RAW=y
 CONFIG_CAN_BCM=y
@@ -1617,7 +1651,6 @@
 CONFIG_CAN_SLCAN=y
 CONFIG_CAN_DEV=y
 CONFIG_CAN_CALC_BITTIMING=y
-# CONFIG_CAN_LEDS is not set
 # CONFIG_CAN_C_CAN is not set
 # CONFIG_CAN_CC770 is not set
 CONFIG_CAN_IFI_CANFD=y
@@ -1627,15 +1660,22 @@
 # CONFIG_CAN_SOFTING is not set
 
 #
+# CAN SPI interfaces
+#
+# CONFIG_CAN_HI311X is not set
+# CONFIG_CAN_MCP251X is not set
+
+#
 # CAN USB interfaces
 #
+# CONFIG_CAN_8DEV_USB is not set
 # CONFIG_CAN_EMS_USB is not set
 # CONFIG_CAN_ESD_USB2 is not set
 # CONFIG_CAN_GS_USB is not set
 # CONFIG_CAN_KVASER_USB is not set
-# CONFIG_CAN_PEAK_USB is not set
-# CONFIG_CAN_8DEV_USB is not set
 # CONFIG_CAN_MCBA_USB is not set
+# CONFIG_CAN_PEAK_USB is not set
+# CONFIG_CAN_UCAN is not set
 # CONFIG_CAN_DEBUG_DEVICES is not set
 CONFIG_BT=y
 CONFIG_BT_BREDR=y
@@ -1644,34 +1684,51 @@
 CONFIG_BT_BNEP=y
 CONFIG_BT_BNEP_MC_FILTER=y
 CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=y
 CONFIG_BT_HIDP=y
 CONFIG_BT_HS=y
 CONFIG_BT_LE=y
-# CONFIG_BT_6LOWPAN is not set
+CONFIG_BT_6LOWPAN=y
 CONFIG_BT_LEDS=y
 # CONFIG_BT_SELFTEST is not set
-# CONFIG_BT_DEBUGFS is not set
+CONFIG_BT_DEBUGFS=y
 
 #
 # Bluetooth device drivers
 #
 CONFIG_BT_INTEL=y
+CONFIG_BT_BCM=y
 CONFIG_BT_RTL=y
+CONFIG_BT_QCA=y
 CONFIG_BT_HCIBTUSB=y
 # CONFIG_BT_HCIBTUSB_AUTOSUSPEND is not set
-# CONFIG_BT_HCIBTUSB_BCM is not set
+CONFIG_BT_HCIBTUSB_BCM=y
 CONFIG_BT_HCIBTUSB_RTL=y
-# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_SERDEV=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_ATH3K is not set
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIUART_QCA=y
+CONFIG_BT_HCIUART_AG6XX=y
+CONFIG_BT_HCIUART_MRVL=y
 # CONFIG_BT_HCIBCM203X is not set
 # CONFIG_BT_HCIBPA10X is not set
-# CONFIG_BT_HCIBFUSB is not set
+CONFIG_BT_HCIBFUSB=y
 # CONFIG_BT_HCIDTL1 is not set
 # CONFIG_BT_HCIBT3C is not set
 # CONFIG_BT_HCIBLUECARD is not set
-# CONFIG_BT_HCIVHCI is not set
+CONFIG_BT_HCIVHCI=y
 # CONFIG_BT_MRVL is not set
 # CONFIG_BT_ATH3K is not set
-# CONFIG_AF_RXRPC is not set
+# CONFIG_BT_MTKUART is not set
+CONFIG_AF_RXRPC=y
+CONFIG_AF_RXRPC_IPV6=y
+# CONFIG_AF_RXRPC_INJECT_LOSS is not set
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=y
 CONFIG_AF_KCM=y
 CONFIG_STREAM_PARSER=y
 CONFIG_FIB_RULES=y
@@ -1685,19 +1742,17 @@
 CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y
 CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y
 CONFIG_CFG80211_DEFAULT_PS=y
-# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_CFG80211_DEBUGFS=y
 CONFIG_CFG80211_CRDA_SUPPORT=y
 CONFIG_CFG80211_WEXT=y
 CONFIG_MAC80211=y
 CONFIG_MAC80211_HAS_RC=y
 CONFIG_MAC80211_RC_MINSTREL=y
-CONFIG_MAC80211_RC_MINSTREL_HT=y
-# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
 CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
 CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
-# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_MESH=y
 CONFIG_MAC80211_LEDS=y
-# CONFIG_MAC80211_DEBUGFS is not set
+CONFIG_MAC80211_DEBUGFS=y
 # CONFIG_MAC80211_MESSAGE_TRACING is not set
 # CONFIG_MAC80211_DEBUG_MENU is not set
 CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
@@ -1711,13 +1766,17 @@
 CONFIG_NET_9P_XEN=y
 CONFIG_NET_9P_RDMA=y
 # CONFIG_NET_9P_DEBUG is not set
-# CONFIG_CAIF is not set
+CONFIG_CAIF=y
+CONFIG_CAIF_DEBUG=y
+CONFIG_CAIF_NETDEV=y
+CONFIG_CAIF_USB=y
 CONFIG_CEPH_LIB=y
 # CONFIG_CEPH_LIB_PRETTYDEBUG is not set
-# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
+CONFIG_CEPH_LIB_USE_DNS_RESOLVER=y
 CONFIG_NFC=y
 CONFIG_NFC_DIGITAL=y
 CONFIG_NFC_NCI=y
+CONFIG_NFC_NCI_SPI=y
 CONFIG_NFC_NCI_UART=y
 CONFIG_NFC_HCI=y
 CONFIG_NFC_SHDLC=y
@@ -1737,8 +1796,10 @@
 # CONFIG_NFC_MRVL_UART is not set
 # CONFIG_NFC_ST21NFCA_I2C is not set
 # CONFIG_NFC_ST_NCI_I2C is not set
+# CONFIG_NFC_ST_NCI_SPI is not set
 # CONFIG_NFC_NXP_NCI is not set
 # CONFIG_NFC_S3FWRN5_I2C is not set
+# CONFIG_NFC_ST95HF is not set
 CONFIG_PSAMPLE=y
 CONFIG_NET_IFE=y
 CONFIG_LWTUNNEL=y
@@ -1746,6 +1807,7 @@
 CONFIG_DST_CACHE=y
 CONFIG_GRO_CELLS=y
 CONFIG_SOCK_VALIDATE_XMIT=y
+CONFIG_NET_SOCK_MSG=y
 # CONFIG_NET_DEVLINK is not set
 CONFIG_MAY_USE_DEVLINK=y
 CONFIG_FAILOVER=y
@@ -1754,6 +1816,89 @@
 #
 # Device Drivers
 #
+CONFIG_HAVE_EISA=y
+# CONFIG_EISA is not set
+CONFIG_HAVE_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEAER_INJECT is not set
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
+CONFIG_PCIE_PME=y
+# CONFIG_PCIE_DPC is not set
+# CONFIG_PCIE_PTM is not set
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_PF_STUB is not set
+CONFIG_XEN_PCIDEV_FRONTEND=y
+CONFIG_PCI_ATS=y
+CONFIG_PCI_LOCKLESS_CONFIG=y
+CONFIG_PCI_IOV=y
+CONFIG_PCI_PRI=y
+CONFIG_PCI_PASID=y
+CONFIG_PCI_LABEL=y
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_ACPI is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# PCI controller drivers
+#
+
+#
+# Cadence PCIe controllers support
+#
+# CONFIG_VMD is not set
+
+#
+# DesignWare PCI Core Support
+#
+# CONFIG_PCIE_DW_PLAT_HOST is not set
+# CONFIG_PCIE_DW_PLAT_EP is not set
+# CONFIG_PCI_MESON is not set
+
+#
+# PCI Endpoint
+#
+CONFIG_PCI_ENDPOINT=y
+# CONFIG_PCI_ENDPOINT_CONFIGFS is not set
+# CONFIG_PCI_EPF_TEST is not set
+
+#
+# PCI switch controller drivers
+#
+# CONFIG_PCI_SW_SWITCHTEC is not set
+CONFIG_PCCARD=y
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=y
+# CONFIG_RAPIDIO is not set
 
 #
 # Generic Driver Options
@@ -1781,15 +1926,106 @@
 CONFIG_GENERIC_CPU_VULNERABILITIES=y
 CONFIG_REGMAP=y
 CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
 CONFIG_DMA_SHARED_BUFFER=y
 # CONFIG_DMA_FENCE_TRACE is not set
+CONFIG_DMA_CMA=y
+
+#
+# Default contiguous memory area size:
+#
+CONFIG_CMA_SIZE_MBYTES=0
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
+# CONFIG_CMA_SIZE_SEL_MIN is not set
+# CONFIG_CMA_SIZE_SEL_MAX is not set
+CONFIG_CMA_ALIGNMENT=8
 
 #
 # Bus devices
 #
 CONFIG_CONNECTOR=y
 CONFIG_PROC_EVENTS=y
-# CONFIG_MTD is not set
+# CONFIG_GNSS is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# Partition parsers
+#
+# CONFIG_MTD_REDBOOT_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_SWAP is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_MCHP23K256 is not set
+# CONFIG_MTD_SST25L is not set
+CONFIG_MTD_SLRAM=y
+CONFIG_MTD_PHRAM=y
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=128
+CONFIG_MTDRAM_ERASE_SIZE=4
+CONFIG_MTD_BLOCK2MTD=y
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_SPI_NAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_SPI_NOR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
 # CONFIG_OF is not set
 CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
 # CONFIG_PARPORT is not set
@@ -1803,11 +2039,12 @@
 CONFIG_BLK_DEV=y
 CONFIG_BLK_DEV_NULL_BLK=y
 CONFIG_BLK_DEV_NULL_BLK_FAULT_INJECTION=y
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
 CONFIG_CDROM=y
 # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
-# CONFIG_ZRAM is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_ZRAM=y
+# CONFIG_ZRAM_WRITEBACK is not set
+# CONFIG_ZRAM_MEMORY_TRACKING is not set
 # CONFIG_BLK_DEV_UMEM is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
@@ -1831,9 +2068,12 @@
 #
 # NVME Support
 #
-# CONFIG_BLK_DEV_NVME is not set
+CONFIG_NVME_CORE=y
+CONFIG_BLK_DEV_NVME=y
+# CONFIG_NVME_MULTIPATH is not set
 # CONFIG_NVME_RDMA is not set
 # CONFIG_NVME_FC is not set
+# CONFIG_NVME_TCP is not set
 # CONFIG_NVME_TARGET is not set
 
 #
@@ -1857,18 +2097,23 @@
 # CONFIG_HMC6352 is not set
 # CONFIG_DS1682 is not set
 # CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
 # CONFIG_SRAM is not set
 # CONFIG_PCI_ENDPOINT_TEST is not set
+CONFIG_PVPANIC=y
 # CONFIG_C2PORT is not set
 
 #
 # EEPROM support
 #
 # CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
 # CONFIG_EEPROM_MAX6875 is not set
-# CONFIG_EEPROM_93CX6 is not set
+CONFIG_EEPROM_93CX6=y
+# CONFIG_EEPROM_93XX46 is not set
 # CONFIG_EEPROM_IDT_89HPESX is not set
+# CONFIG_EEPROM_EE1004 is not set
 # CONFIG_CB710_CORE is not set
 
 #
@@ -1919,8 +2164,10 @@
 #
 # VOP Driver
 #
+CONFIG_VHOST_RING=y
 # CONFIG_GENWQE is not set
 # CONFIG_ECHO is not set
+# CONFIG_MISC_ALCOR_PCI is not set
 # CONFIG_MISC_RTSX_PCI is not set
 # CONFIG_MISC_RTSX_USB is not set
 CONFIG_HAVE_IDE=y
@@ -1934,22 +2181,21 @@
 CONFIG_SCSI=y
 CONFIG_SCSI_DMA=y
 CONFIG_SCSI_NETLINK=y
-# CONFIG_SCSI_MQ_DEFAULT is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
+CONFIG_CHR_DEV_ST=y
 # CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
 CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 
 #
 # SCSI Transports
@@ -1957,8 +2203,10 @@
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=y
-# CONFIG_SCSI_SAS_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_SAS_ATTRS=y
+CONFIG_SCSI_SAS_LIBSAS=y
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
 CONFIG_SCSI_SRP_ATTRS=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
@@ -1968,7 +2216,7 @@
 # CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_BE2ISCSI is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_HPSA is not set
+CONFIG_SCSI_HPSA=y
 # CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_3W_SAS is not set
 # CONFIG_SCSI_ACARD is not set
@@ -1991,6 +2239,8 @@
 # CONFIG_SCSI_UFSHCD is not set
 # CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_MYRB is not set
+# CONFIG_SCSI_MYRS is not set
 # CONFIG_VMWARE_PVSCSI is not set
 # CONFIG_XEN_SCSI_FRONTEND is not set
 # CONFIG_LIBFC is not set
@@ -2130,7 +2380,6 @@
 # CONFIG_BCACHE_CLOSURES_DEBUG is not set
 CONFIG_BLK_DEV_DM_BUILTIN=y
 CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_MQ_DEFAULT is not set
 # CONFIG_DM_DEBUG is not set
 CONFIG_DM_BUFIO=y
 # CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set
@@ -2139,7 +2388,7 @@
 # CONFIG_DM_UNSTRIPED is not set
 CONFIG_DM_CRYPT=y
 CONFIG_DM_SNAPSHOT=y
-# CONFIG_DM_THIN_PROVISIONING is not set
+CONFIG_DM_THIN_PROVISIONING=y
 CONFIG_DM_CACHE=y
 CONFIG_DM_CACHE_SMQ=y
 CONFIG_DM_WRITECACHE=y
@@ -2148,11 +2397,14 @@
 # CONFIG_DM_LOG_USERSPACE is not set
 CONFIG_DM_RAID=y
 CONFIG_DM_ZERO=y
-# CONFIG_DM_MULTIPATH is not set
+CONFIG_DM_MULTIPATH=y
+CONFIG_DM_MULTIPATH_QL=y
+CONFIG_DM_MULTIPATH_ST=y
 # CONFIG_DM_DELAY is not set
-# CONFIG_DM_UEVENT is not set
-# CONFIG_DM_FLAKEY is not set
-# CONFIG_DM_VERITY is not set
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
 # CONFIG_DM_SWITCH is not set
 # CONFIG_DM_LOG_WRITES is not set
 CONFIG_DM_INTEGRITY=y
@@ -2224,99 +2476,58 @@
 #
 # CAIF transport drivers
 #
+CONFIG_CAIF_TTY=y
+CONFIG_CAIF_SPI_SLAVE=y
+CONFIG_CAIF_SPI_SYNC=y
+CONFIG_CAIF_HSI=y
+CONFIG_CAIF_VIRTIO=y
 
 #
 # Distributed Switch Architecture drivers
 #
 # CONFIG_B53 is not set
+# CONFIG_NET_DSA_BCM_SF2 is not set
 # CONFIG_NET_DSA_LOOP is not set
+# CONFIG_NET_DSA_LANTIQ_GSWIP is not set
 # CONFIG_NET_DSA_MT7530 is not set
 # CONFIG_NET_DSA_MV88E6060 is not set
-# CONFIG_MICROCHIP_KSZ is not set
+# CONFIG_NET_DSA_MICROCHIP_KSZ9477 is not set
 # CONFIG_NET_DSA_MV88E6XXX is not set
 # CONFIG_NET_DSA_QCA8K is not set
+# CONFIG_NET_DSA_REALTEK_SMI is not set
 # CONFIG_NET_DSA_SMSC_LAN9303_I2C is not set
 # CONFIG_NET_DSA_SMSC_LAN9303_MDIO is not set
 CONFIG_ETHERNET=y
-CONFIG_NET_VENDOR_3COM=y
-# CONFIG_PCMCIA_3C574 is not set
-# CONFIG_PCMCIA_3C589 is not set
-# CONFIG_VORTEX is not set
-# CONFIG_TYPHOON is not set
-CONFIG_NET_VENDOR_ADAPTEC=y
-# CONFIG_ADAPTEC_STARFIRE is not set
-CONFIG_NET_VENDOR_AGERE=y
-# CONFIG_ET131X is not set
-CONFIG_NET_VENDOR_ALACRITECH=y
-# CONFIG_SLICOSS is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALACRITECH is not set
 CONFIG_NET_VENDOR_ALTEON=y
 # CONFIG_ACENIC is not set
 # CONFIG_ALTERA_TSE is not set
 CONFIG_NET_VENDOR_AMAZON=y
 # CONFIG_ENA_ETHERNET is not set
-CONFIG_NET_VENDOR_AMD=y
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_PCNET32 is not set
-# CONFIG_PCMCIA_NMCLAN is not set
-# CONFIG_AMD_XGBE is not set
+# CONFIG_NET_VENDOR_AMD is not set
 # CONFIG_NET_VENDOR_AQUANTIA is not set
-CONFIG_NET_VENDOR_ARC=y
-CONFIG_NET_VENDOR_ATHEROS=y
-# CONFIG_ATL2 is not set
-# CONFIG_ATL1 is not set
-# CONFIG_ATL1E is not set
-# CONFIG_ATL1C is not set
-# CONFIG_ALX is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
 # CONFIG_NET_VENDOR_AURORA is not set
-CONFIG_NET_VENDOR_BROADCOM=y
-# CONFIG_B44 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_CNIC is not set
-CONFIG_TIGON3=y
-CONFIG_TIGON3_HWMON=y
-# CONFIG_BNX2X is not set
-# CONFIG_BNXT is not set
-CONFIG_NET_VENDOR_BROCADE=y
-# CONFIG_BNA is not set
-CONFIG_NET_CADENCE=y
-# CONFIG_MACB is not set
-CONFIG_NET_VENDOR_CAVIUM=y
-# CONFIG_THUNDER_NIC_PF is not set
-# CONFIG_THUNDER_NIC_VF is not set
-# CONFIG_THUNDER_NIC_BGX is not set
-# CONFIG_THUNDER_NIC_RGX is not set
-# CONFIG_CAVIUM_PTP is not set
-# CONFIG_LIQUIDIO is not set
-# CONFIG_LIQUIDIO_VF is not set
-CONFIG_NET_VENDOR_CHELSIO=y
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_CHELSIO_T3 is not set
-# CONFIG_CHELSIO_T4 is not set
-# CONFIG_CHELSIO_T4VF is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
 CONFIG_NET_VENDOR_CISCO=y
 CONFIG_ENIC=y
 # CONFIG_NET_VENDOR_CORTINA is not set
 # CONFIG_CX_ECAT is not set
 # CONFIG_DNET is not set
-CONFIG_NET_VENDOR_DEC=y
-CONFIG_NET_TULIP=y
-# CONFIG_DE2104X is not set
-# CONFIG_TULIP is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 is not set
-# CONFIG_ULI526X is not set
-# CONFIG_PCMCIA_XIRCOM is not set
-CONFIG_NET_VENDOR_DLINK=y
-# CONFIG_DL2K is not set
-# CONFIG_SUNDANCE is not set
-CONFIG_NET_VENDOR_EMULEX=y
-# CONFIG_BE2NET is not set
-CONFIG_NET_VENDOR_EZCHIP=y
-CONFIG_NET_VENDOR_FUJITSU=y
-# CONFIG_PCMCIA_FMVJ18X is not set
-CONFIG_NET_VENDOR_HP=y
-# CONFIG_HP100 is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FUJITSU is not set
+# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 CONFIG_NET_VENDOR_I825XX=y
 CONFIG_NET_VENDOR_INTEL=y
@@ -2333,15 +2544,9 @@
 # CONFIG_I40EVF is not set
 # CONFIG_ICE is not set
 # CONFIG_FM10K is not set
-CONFIG_NET_VENDOR_EXAR=y
-# CONFIG_S2IO is not set
-# CONFIG_VXGE is not set
+# CONFIG_IGC is not set
 # CONFIG_JME is not set
-CONFIG_NET_VENDOR_MARVELL=y
-# CONFIG_MVMDIO is not set
-# CONFIG_SKGE is not set
-CONFIG_SKY2=y
-# CONFIG_SKY2_DEBUG is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_NET_VENDOR_MELLANOX=y
 CONFIG_MLX4_EN=y
 CONFIG_MLX4_EN_DCB=y
@@ -2351,90 +2556,41 @@
 # CONFIG_MLX5_CORE is not set
 # CONFIG_MLXSW_CORE is not set
 # CONFIG_MLXFW is not set
-CONFIG_NET_VENDOR_MICREL=y
-# CONFIG_KS8842 is not set
-# CONFIG_KS8851_MLL is not set
-# CONFIG_KSZ884X_PCI is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_NET_VENDOR_MICROSEMI is not set
-CONFIG_NET_VENDOR_MYRI=y
-# CONFIG_MYRI10GE is not set
+# CONFIG_NET_VENDOR_MYRI is not set
 # CONFIG_FEALNX is not set
-CONFIG_NET_VENDOR_NATSEMI=y
-# CONFIG_NATSEMI is not set
-# CONFIG_NS83820 is not set
-CONFIG_NET_VENDOR_NETRONOME=y
-# CONFIG_NFP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETERION is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
 # CONFIG_NET_VENDOR_NI is not set
-CONFIG_NET_VENDOR_8390=y
-# CONFIG_PCMCIA_AXNET is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_PCMCIA_PCNET is not set
 CONFIG_NET_VENDOR_NVIDIA=y
 CONFIG_FORCEDETH=y
-CONFIG_NET_VENDOR_OKI=y
+# CONFIG_NET_VENDOR_OKI is not set
 # CONFIG_ETHOC is not set
-CONFIG_NET_PACKET_ENGINE=y
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-CONFIG_NET_VENDOR_QLOGIC=y
-# CONFIG_QLA3XXX is not set
-# CONFIG_QLCNIC is not set
-# CONFIG_QLGE is not set
-# CONFIG_NETXEN_NIC is not set
-# CONFIG_QED is not set
-CONFIG_NET_VENDOR_QUALCOMM=y
-# CONFIG_QCOM_EMAC is not set
-# CONFIG_RMNET is not set
-CONFIG_NET_VENDOR_RDC=y
-# CONFIG_R6040 is not set
-CONFIG_NET_VENDOR_REALTEK=y
-# CONFIG_8139CP is not set
-CONFIG_8139TOO=y
-CONFIG_8139TOO_PIO=y
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_R8169 is not set
-CONFIG_NET_VENDOR_RENESAS=y
-CONFIG_NET_VENDOR_ROCKER=y
-# CONFIG_ROCKER is not set
-CONFIG_NET_VENDOR_SAMSUNG=y
-# CONFIG_SXGBE_ETH is not set
-CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_NET_VENDOR_PACKET_ENGINES is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SOLARFLARE is not set
-CONFIG_NET_VENDOR_SILAN=y
-# CONFIG_SC92031 is not set
-CONFIG_NET_VENDOR_SIS=y
-# CONFIG_SIS900 is not set
-# CONFIG_SIS190 is not set
-CONFIG_NET_VENDOR_SMSC=y
-# CONFIG_PCMCIA_SMC91C92 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SMSC911X is not set
-# CONFIG_SMSC9420 is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_SOCIONEXT is not set
-CONFIG_NET_VENDOR_STMICRO=y
-# CONFIG_STMMAC_ETH is not set
-CONFIG_NET_VENDOR_SUN=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NIU is not set
-CONFIG_NET_VENDOR_SYNOPSYS=y
-# CONFIG_DWC_XLGMAC is not set
-CONFIG_NET_VENDOR_TEHUTI=y
-# CONFIG_TEHUTI is not set
-CONFIG_NET_VENDOR_TI=y
-# CONFIG_TI_CPSW_ALE is not set
-# CONFIG_TLAN is not set
-CONFIG_NET_VENDOR_VIA=y
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
-CONFIG_NET_VENDOR_WIZNET=y
-# CONFIG_WIZNET_W5100 is not set
-# CONFIG_WIZNET_W5300 is not set
-CONFIG_NET_VENDOR_XIRCOM=y
-# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_NET_VENDOR_XIRCOM is not set
 CONFIG_FDDI=y
 # CONFIG_DEFXX is not set
 # CONFIG_SKFP is not set
@@ -2442,6 +2598,7 @@
 # CONFIG_NET_SB1000 is not set
 CONFIG_MDIO_DEVICE=y
 CONFIG_MDIO_BUS=y
+# CONFIG_MDIO_BCM_UNIMAC is not set
 # CONFIG_MDIO_BITBANG is not set
 # CONFIG_MDIO_MSCC_MIIM is not set
 # CONFIG_MDIO_THUNDER is not set
@@ -2489,26 +2646,30 @@
 # CONFIG_TERANETICS_PHY is not set
 # CONFIG_VITESSE_PHY is not set
 # CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
 CONFIG_PPP_DEFLATE=y
 CONFIG_PPP_FILTER=y
 CONFIG_PPP_MPPE=y
 CONFIG_PPP_MULTILINK=y
-# CONFIG_PPPOATM is not set
+CONFIG_PPPOATM=y
 CONFIG_PPPOE=y
 CONFIG_PPTP=y
 CONFIG_PPPOL2TP=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
-# CONFIG_SLIP is not set
+CONFIG_SLIP=y
 CONFIG_SLHC=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_USB_NET_DRIVERS=y
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_RTL8152 is not set
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_RTL8152=y
 # CONFIG_USB_LAN78XX is not set
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_AX8817X=y
@@ -2517,17 +2678,17 @@
 # CONFIG_USB_NET_CDC_EEM is not set
 CONFIG_USB_NET_CDC_NCM=y
 # CONFIG_USB_NET_HUAWEI_CDC_NCM is not set
-# CONFIG_USB_NET_CDC_MBIM is not set
-# CONFIG_USB_NET_DM9601 is not set
+CONFIG_USB_NET_CDC_MBIM=y
+CONFIG_USB_NET_DM9601=y
 # CONFIG_USB_NET_SR9700 is not set
 # CONFIG_USB_NET_SR9800 is not set
-# CONFIG_USB_NET_SMSC75XX is not set
-# CONFIG_USB_NET_SMSC95XX is not set
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
 # CONFIG_USB_NET_GL620A is not set
 CONFIG_USB_NET_NET1080=y
 # CONFIG_USB_NET_PLUSB is not set
-# CONFIG_USB_NET_MCS7830 is not set
-# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
 CONFIG_USB_NET_CDC_SUBSET_ENABLE=y
 CONFIG_USB_NET_CDC_SUBSET=y
 # CONFIG_USB_ALI_M5632 is not set
@@ -2546,8 +2707,9 @@
 # CONFIG_USB_SIERRA_NET is not set
 # CONFIG_USB_VL600 is not set
 # CONFIG_USB_NET_CH9200 is not set
+# CONFIG_USB_NET_AQC111 is not set
 CONFIG_WLAN=y
-# CONFIG_WIRELESS_WDS is not set
+CONFIG_WIRELESS_WDS=y
 CONFIG_WLAN_VENDOR_ADMTEK=y
 # CONFIG_ADM8211 is not set
 CONFIG_WLAN_VENDOR_ATH=y
@@ -2562,85 +2724,93 @@
 # CONFIG_WIL6210 is not set
 # CONFIG_ATH10K is not set
 # CONFIG_WCN36XX is not set
-CONFIG_WLAN_VENDOR_ATMEL=y
-# CONFIG_ATMEL is not set
-# CONFIG_AT76C50X_USB is not set
-CONFIG_WLAN_VENDOR_BROADCOM=y
-# CONFIG_B43 is not set
-# CONFIG_B43LEGACY is not set
-# CONFIG_BRCMSMAC is not set
-# CONFIG_BRCMFMAC is not set
-CONFIG_WLAN_VENDOR_CISCO=y
-# CONFIG_AIRO is not set
-# CONFIG_AIRO_CS is not set
-CONFIG_WLAN_VENDOR_INTEL=y
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
-# CONFIG_IWL4965 is not set
-# CONFIG_IWL3945 is not set
-# CONFIG_IWLWIFI is not set
-CONFIG_WLAN_VENDOR_INTERSIL=y
-# CONFIG_HOSTAP is not set
-# CONFIG_HERMES is not set
-# CONFIG_P54_COMMON is not set
-# CONFIG_PRISM54 is not set
-CONFIG_WLAN_VENDOR_MARVELL=y
-# CONFIG_LIBERTAS is not set
-# CONFIG_LIBERTAS_THINFIRM is not set
-# CONFIG_MWIFIEX is not set
-# CONFIG_MWL8K is not set
-CONFIG_WLAN_VENDOR_MEDIATEK=y
-# CONFIG_MT7601U is not set
-# CONFIG_MT76x2E is not set
-CONFIG_WLAN_VENDOR_RALINK=y
-# CONFIG_RT2X00 is not set
-CONFIG_WLAN_VENDOR_REALTEK=y
-# CONFIG_RTL8180 is not set
-# CONFIG_RTL8187 is not set
-CONFIG_RTL_CARDS=y
-# CONFIG_RTL8192CE is not set
-# CONFIG_RTL8192SE is not set
-# CONFIG_RTL8192DE is not set
-# CONFIG_RTL8723AE is not set
-# CONFIG_RTL8723BE is not set
-# CONFIG_RTL8188EE is not set
-# CONFIG_RTL8192EE is not set
-# CONFIG_RTL8821AE is not set
-# CONFIG_RTL8192CU is not set
-# CONFIG_RTL8XXXU is not set
-CONFIG_WLAN_VENDOR_RSI=y
-# CONFIG_RSI_91X is not set
-CONFIG_WLAN_VENDOR_ST=y
-# CONFIG_CW1200 is not set
-CONFIG_WLAN_VENDOR_TI=y
-# CONFIG_WL1251 is not set
-# CONFIG_WL12XX is not set
-# CONFIG_WL18XX is not set
-# CONFIG_WLCORE is not set
-CONFIG_WLAN_VENDOR_ZYDAS=y
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_ZD1211RW is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
 # CONFIG_WLAN_VENDOR_QUANTENNA is not set
 # CONFIG_PCMCIA_RAYCS is not set
 # CONFIG_PCMCIA_WL3501 is not set
 CONFIG_MAC80211_HWSIM=y
-# CONFIG_USB_NET_RNDIS_WLAN is not set
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_VIRT_WIFI=y
 
 #
 # WiMAX Wireless Broadband devices
 #
 # CONFIG_WIMAX_I2400M_USB is not set
-# CONFIG_WAN is not set
+CONFIG_WAN=y
+# CONFIG_LANMEDIA is not set
+CONFIG_HDLC=y
+CONFIG_HDLC_RAW=y
+CONFIG_HDLC_RAW_ETH=y
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+CONFIG_HDLC_X25=y
+# CONFIG_PCI200SYN is not set
+# CONFIG_WANXL is not set
+# CONFIG_PC300TOO is not set
+# CONFIG_FARSYNC is not set
+# CONFIG_DSCC4 is not set
+CONFIG_DLCI=y
+CONFIG_DLCI_MAX=8
+CONFIG_LAPBETHER=y
+CONFIG_X25_ASY=y
+# CONFIG_SBNI is not set
 CONFIG_IEEE802154_DRIVERS=y
 # CONFIG_IEEE802154_FAKELB is not set
+# CONFIG_IEEE802154_AT86RF230 is not set
+# CONFIG_IEEE802154_MRF24J40 is not set
+# CONFIG_IEEE802154_CC2520 is not set
 # CONFIG_IEEE802154_ATUSB is not set
+# CONFIG_IEEE802154_ADF7242 is not set
+# CONFIG_IEEE802154_CA8210 is not set
+# CONFIG_IEEE802154_MCR20A is not set
+CONFIG_IEEE802154_HWSIM=y
 CONFIG_XEN_NETDEV_FRONTEND=y
-# CONFIG_XEN_NETDEV_BACKEND is not set
-# CONFIG_VMXNET3 is not set
+CONFIG_XEN_NETDEV_BACKEND=y
+CONFIG_VMXNET3=y
 # CONFIG_FUJITSU_ES is not set
-# CONFIG_NETDEVSIM is not set
+CONFIG_NETDEVSIM=y
 CONFIG_NET_FAILOVER=y
-# CONFIG_ISDN is not set
+CONFIG_ISDN=y
+# CONFIG_ISDN_I4L is not set
+CONFIG_ISDN_CAPI=y
+CONFIG_CAPI_TRACE=y
+CONFIG_ISDN_CAPI_CAPI20=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+
+#
+# CAPI hardware drivers
+#
+# CONFIG_CAPI_AVM is not set
+# CONFIG_ISDN_DRV_GIGASET is not set
+# CONFIG_HYSDN is not set
+CONFIG_MISDN=y
+CONFIG_MISDN_DSP=y
+CONFIG_MISDN_L1OIP=y
+
+#
+# mISDN hardware drivers
+#
+# CONFIG_MISDN_HFCPCI is not set
+# CONFIG_MISDN_HFCMULTI is not set
+# CONFIG_MISDN_HFCUSB is not set
+# CONFIG_MISDN_AVMFRITZ is not set
+# CONFIG_MISDN_SPEEDFAX is not set
+# CONFIG_MISDN_INFINEON is not set
+# CONFIG_MISDN_W6692 is not set
+# CONFIG_MISDN_NETJET is not set
 # CONFIG_NVM is not set
 
 #
@@ -2736,6 +2906,7 @@
 # CONFIG_JOYSTICK_AS5011 is not set
 # CONFIG_JOYSTICK_JOYDUMP is not set
 # CONFIG_JOYSTICK_XPAD is not set
+# CONFIG_JOYSTICK_PSXPAD_SPI is not set
 # CONFIG_JOYSTICK_PXRC is not set
 CONFIG_INPUT_TABLET=y
 # CONFIG_TABLET_USB_ACECAD is not set
@@ -2747,9 +2918,12 @@
 # CONFIG_TABLET_SERIAL_WACOM4 is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_PROPERTIES=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
 # CONFIG_TOUCHSCREEN_AD7879 is not set
 # CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
 # CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_BU21029 is not set
 # CONFIG_TOUCHSCREEN_CHIPONE_ICN8505 is not set
 # CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
 # CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set
@@ -2785,10 +2959,12 @@
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
 # CONFIG_TOUCHSCREEN_TSC_SERIO is not set
 # CONFIG_TOUCHSCREEN_TSC2004 is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
 # CONFIG_TOUCHSCREEN_TSC2007 is not set
 # CONFIG_TOUCHSCREEN_SILEAD is not set
 # CONFIG_TOUCHSCREEN_ST1232 is not set
 # CONFIG_TOUCHSCREEN_STMFTS is not set
+# CONFIG_TOUCHSCREEN_SUR40 is not set
 # CONFIG_TOUCHSCREEN_SX8654 is not set
 # CONFIG_TOUCHSCREEN_TPS6507X is not set
 # CONFIG_TOUCHSCREEN_ZET6223 is not set
@@ -2816,7 +2992,19 @@
 # CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set
 # CONFIG_INPUT_DRV2665_HAPTICS is not set
 # CONFIG_INPUT_DRV2667_HAPTICS is not set
-# CONFIG_RMI4_CORE is not set
+CONFIG_RMI4_CORE=y
+# CONFIG_RMI4_I2C is not set
+# CONFIG_RMI4_SPI is not set
+# CONFIG_RMI4_SMB is not set
+CONFIG_RMI4_F03=y
+CONFIG_RMI4_F03_SERIO=y
+CONFIG_RMI4_2D_SENSOR=y
+CONFIG_RMI4_F11=y
+CONFIG_RMI4_F12=y
+CONFIG_RMI4_F30=y
+# CONFIG_RMI4_F34 is not set
+# CONFIG_RMI4_F54 is not set
+# CONFIG_RMI4_F55 is not set
 
 #
 # Hardware I/O ports
@@ -2832,6 +3020,7 @@
 # CONFIG_SERIO_ALTERA_PS2 is not set
 # CONFIG_SERIO_PS2MULT is not set
 # CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_OLPC_APSP is not set
 CONFIG_USERIO=y
 CONFIG_GAMEPORT=y
 CONFIG_GAMEPORT_NS558=y
@@ -2850,7 +3039,8 @@
 CONFIG_HW_CONSOLE=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
@@ -2861,9 +3051,10 @@
 # CONFIG_SYNCLINK_GT is not set
 # CONFIG_NOZOMI is not set
 # CONFIG_ISI is not set
-# CONFIG_N_HDLC is not set
+CONFIG_N_HDLC=y
 # CONFIG_N_GSM is not set
 # CONFIG_TRACE_SINK is not set
+CONFIG_LDISC_AUTOLOAD=y
 CONFIG_DEVMEM=y
 # CONFIG_DEVKMEM is not set
 
@@ -2896,6 +3087,8 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
 # CONFIG_SERIAL_UARTLITE is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
@@ -2909,7 +3102,8 @@
 # CONFIG_SERIAL_FSL_LPUART is not set
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
-# CONFIG_TTY_PRINTK is not set
+CONFIG_TTY_PRINTK=y
+CONFIG_TTY_PRINTK_LEVEL=6
 CONFIG_HVC_DRIVER=y
 CONFIG_HVC_IRQ=y
 CONFIG_HVC_XEN=y
@@ -2937,12 +3131,29 @@
 # CONFIG_MWAVE is not set
 # CONFIG_RAW_DRIVER is not set
 CONFIG_HPET=y
-# CONFIG_HPET_MMAP is not set
+CONFIG_HPET_MMAP=y
+CONFIG_HPET_MMAP_DEFAULT=y
 # CONFIG_HANGCHECK_TIMER is not set
-# CONFIG_TCG_TPM is not set
+CONFIG_TCG_TPM=y
+CONFIG_HW_RANDOM_TPM=y
+CONFIG_TCG_TIS_CORE=y
+CONFIG_TCG_TIS=y
+# CONFIG_TCG_TIS_SPI is not set
+# CONFIG_TCG_TIS_I2C_ATMEL is not set
+# CONFIG_TCG_TIS_I2C_INFINEON is not set
+# CONFIG_TCG_TIS_I2C_NUVOTON is not set
+# CONFIG_TCG_NSC is not set
+# CONFIG_TCG_ATMEL is not set
+# CONFIG_TCG_INFINEON is not set
+# CONFIG_TCG_XEN is not set
+CONFIG_TCG_CRB=y
+# CONFIG_TCG_VTPM_PROXY is not set
+# CONFIG_TCG_TIS_ST33ZP24_I2C is not set
+# CONFIG_TCG_TIS_ST33ZP24_SPI is not set
 # CONFIG_TELCLOCK is not set
 CONFIG_DEVPORT=y
 # CONFIG_XILLYBUS is not set
+# CONFIG_RANDOM_TRUST_CPU is not set
 
 #
 # I2C support
@@ -2984,6 +3195,7 @@
 CONFIG_I2C_PIIX4=y
 CONFIG_I2C_NFORCE2=y
 CONFIG_I2C_NFORCE2_S4985=y
+# CONFIG_I2C_NVIDIA_GPU is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -3025,7 +3237,37 @@
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_SPI is not set
+# CONFIG_I3C is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+# CONFIG_SPI_MEM is not set
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_NXP_FLEXSPI is not set
+CONFIG_SPI_PXA2XX=y
+CONFIG_SPI_PXA2XX_PCI=y
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_MXIC is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPI_SLAVE is not set
 # CONFIG_SPMI is not set
 # CONFIG_HSI is not set
 CONFIG_PPS=y
@@ -3060,6 +3302,7 @@
 # CONFIG_POWER_SUPPLY_DEBUG is not set
 # CONFIG_PDA_POWER is not set
 # CONFIG_TEST_POWER is not set
+# CONFIG_CHARGER_ADP5061 is not set
 # CONFIG_BATTERY_DS2780 is not set
 # CONFIG_BATTERY_DS2781 is not set
 # CONFIG_BATTERY_DS2782 is not set
@@ -3068,6 +3311,7 @@
 # CONFIG_BATTERY_BQ27XXX is not set
 # CONFIG_BATTERY_MAX17040 is not set
 # CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_ISP1704 is not set
 # CONFIG_CHARGER_MAX8903 is not set
 # CONFIG_CHARGER_LP8727 is not set
 # CONFIG_CHARGER_BQ2415X is not set
@@ -3081,6 +3325,7 @@
 #
 # CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7314 is not set
 # CONFIG_SENSORS_AD7414 is not set
 # CONFIG_SENSORS_AD7418 is not set
 # CONFIG_SENSORS_ADM1021 is not set
@@ -3089,6 +3334,7 @@
 # CONFIG_SENSORS_ADM1029 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7310 is not set
 # CONFIG_SENSORS_ADT7410 is not set
 # CONFIG_SENSORS_ADT7411 is not set
 # CONFIG_SENSORS_ADT7462 is not set
@@ -3130,10 +3376,12 @@
 # CONFIG_SENSORS_LTC4245 is not set
 # CONFIG_SENSORS_LTC4260 is not set
 # CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_MAX1111 is not set
 # CONFIG_SENSORS_MAX16065 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX1668 is not set
 # CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX31722 is not set
 # CONFIG_SENSORS_MAX6621 is not set
 # CONFIG_SENSORS_MAX6639 is not set
 # CONFIG_SENSORS_MAX6642 is not set
@@ -3142,7 +3390,9 @@
 # CONFIG_SENSORS_MAX31790 is not set
 # CONFIG_SENSORS_MCP3021 is not set
 # CONFIG_SENSORS_TC654 is not set
+# CONFIG_SENSORS_ADCXX is not set
 # CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
 # CONFIG_SENSORS_LM73 is not set
 # CONFIG_SENSORS_LM75 is not set
 # CONFIG_SENSORS_LM77 is not set
@@ -3164,6 +3414,8 @@
 # CONFIG_SENSORS_NCT6775 is not set
 # CONFIG_SENSORS_NCT7802 is not set
 # CONFIG_SENSORS_NCT7904 is not set
+# CONFIG_SENSORS_NPCM7XX is not set
+# CONFIG_SENSORS_OCC_P8_I2C is not set
 # CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_PMBUS is not set
 # CONFIG_SENSORS_SHT21 is not set
@@ -3184,6 +3436,7 @@
 # CONFIG_SENSORS_ADC128D818 is not set
 # CONFIG_SENSORS_ADS1015 is not set
 # CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
 # CONFIG_SENSORS_AMC6821 is not set
 # CONFIG_SENSORS_INA209 is not set
 # CONFIG_SENSORS_INA2XX is not set
@@ -3231,9 +3484,14 @@
 CONFIG_THERMAL_GOV_USER_SPACE=y
 # CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
 # CONFIG_THERMAL_EMULATION is not set
+
+#
+# Intel thermal drivers
+#
 # CONFIG_INTEL_POWERCLAMP is not set
 CONFIG_X86_PKG_TEMP_THERMAL=y
-# CONFIG_INTEL_SOC_DTS_THERMAL is not set
+CONFIG_INTEL_SOC_DTS_IOSF_CORE=y
+CONFIG_INTEL_SOC_DTS_THERMAL=y
 
 #
 # ACPI INT340X thermal drivers
@@ -3241,7 +3499,7 @@
 # CONFIG_INT340X_THERMAL is not set
 # CONFIG_INTEL_PCH_THERMAL is not set
 CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_CORE is not set
+CONFIG_WATCHDOG_CORE=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y
 # CONFIG_WATCHDOG_SYSFS is not set
@@ -3268,9 +3526,10 @@
 # CONFIG_IB700_WDT is not set
 # CONFIG_IBMASR is not set
 # CONFIG_WAFER_WDT is not set
-# CONFIG_I6300ESB_WDT is not set
+CONFIG_I6300ESB_WDT=y
 # CONFIG_IE6XX_WDT is not set
-# CONFIG_ITCO_WDT is not set
+CONFIG_ITCO_WDT=y
+CONFIG_ITCO_VENDOR_SUPPORT=y
 # CONFIG_IT8712F_WDT is not set
 # CONFIG_IT87_WDT is not set
 # CONFIG_HP_WATCHDOG is not set
@@ -3281,6 +3540,7 @@
 # CONFIG_CPU5_WDT is not set
 # CONFIG_SMSC_SCH311X_WDT is not set
 # CONFIG_SMSC37B787_WDT is not set
+# CONFIG_TQMX86_WDT is not set
 # CONFIG_VIA_WDT is not set
 # CONFIG_W83627HF_WDT is not set
 # CONFIG_W83877F_WDT is not set
@@ -3321,17 +3581,20 @@
 # CONFIG_MFD_BD9571MWV is not set
 # CONFIG_MFD_AXP20X_I2C is not set
 # CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_MADERA is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
 # CONFIG_MFD_DA9052_I2C is not set
 # CONFIG_MFD_DA9055 is not set
 # CONFIG_MFD_DA9062 is not set
 # CONFIG_MFD_DA9063 is not set
 # CONFIG_MFD_DA9150 is not set
 # CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
 # CONFIG_MFD_MC13XXX_I2C is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
-# CONFIG_LPC_ICH is not set
+CONFIG_LPC_ICH=y
 CONFIG_LPC_SCH=y
 # CONFIG_INTEL_SOC_PMIC_CHTWC is not set
 # CONFIG_MFD_INTEL_LPSS_ACPI is not set
@@ -3350,6 +3613,7 @@
 # CONFIG_MFD_MAX8998 is not set
 # CONFIG_MFD_MT6397 is not set
 # CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_MFD_VIPERBOARD is not set
 # CONFIG_MFD_RETU is not set
 # CONFIG_MFD_PCF50633 is not set
@@ -3376,6 +3640,7 @@
 # CONFIG_MFD_TI_LP873X is not set
 # CONFIG_MFD_TPS6586X is not set
 # CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
 # CONFIG_MFD_TPS80031 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_TWL6040_CORE is not set
@@ -3383,44 +3648,219 @@
 # CONFIG_MFD_LM3533 is not set
 # CONFIG_MFD_VX855 is not set
 # CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_WM8994 is not set
 # CONFIG_RAVE_SP_CORE is not set
 # CONFIG_REGULATOR is not set
-# CONFIG_RC_CORE is not set
+CONFIG_CEC_CORE=y
+CONFIG_RC_CORE=y
+CONFIG_RC_MAP=y
+# CONFIG_LIRC is not set
+CONFIG_RC_DECODERS=y
+CONFIG_IR_NEC_DECODER=y
+CONFIG_IR_RC5_DECODER=y
+CONFIG_IR_RC6_DECODER=y
+CONFIG_IR_JVC_DECODER=y
+CONFIG_IR_SONY_DECODER=y
+CONFIG_IR_SANYO_DECODER=y
+CONFIG_IR_SHARP_DECODER=y
+CONFIG_IR_MCE_KBD_DECODER=y
+CONFIG_IR_XMP_DECODER=y
+# CONFIG_IR_IMON_DECODER is not set
+# CONFIG_RC_DEVICES is not set
 CONFIG_MEDIA_SUPPORT=y
 
 #
 # Multimedia core support
 #
-# CONFIG_MEDIA_CAMERA_SUPPORT is not set
+CONFIG_MEDIA_CAMERA_SUPPORT=y
 # CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
 # CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
 # CONFIG_MEDIA_RADIO_SUPPORT is not set
 # CONFIG_MEDIA_SDR_SUPPORT is not set
-# CONFIG_MEDIA_CEC_SUPPORT is not set
+CONFIG_MEDIA_CEC_SUPPORT=y
+# CONFIG_MEDIA_CEC_RC is not set
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_V4L2=y
 # CONFIG_VIDEO_ADV_DEBUG is not set
 # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_V4L2_MEM2MEM_DEV=y
+CONFIG_V4L2_FWNODE=y
 
 #
 # Media drivers
 #
-# CONFIG_MEDIA_USB_SUPPORT is not set
-# CONFIG_MEDIA_PCI_SUPPORT is not set
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=y
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+# CONFIG_VIDEO_USBTV is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+
+#
+# USB HDMI CEC adapters
+#
+# CONFIG_USB_PULSE8_CEC is not set
+# CONFIG_USB_RAINSHADOW_CEC is not set
+CONFIG_MEDIA_PCI_SUPPORT=y
+
+#
+# Media capture support
+#
+# CONFIG_VIDEO_SOLO6X10 is not set
+# CONFIG_VIDEO_TW5864 is not set
+# CONFIG_VIDEO_TW68 is not set
+# CONFIG_VIDEO_TW686X is not set
+CONFIG_VIDEO_IPU3_CIO2=y
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+CONFIG_V4L_TEST_DRIVERS=y
+CONFIG_VIDEO_VIMC=y
+CONFIG_VIDEO_VIVID=y
+CONFIG_VIDEO_VIVID_CEC=y
+CONFIG_VIDEO_VIVID_MAX_DEVS=64
+CONFIG_VIDEO_VIM2M=y
+CONFIG_VIDEO_VICODEC=y
+CONFIG_CEC_PLATFORM_DRIVERS=y
+# CONFIG_CEC_GPIO is not set
+# CONFIG_VIDEO_SECO_CEC is not set
 
 #
 # Supported MMC/SDIO adapters
 #
 # CONFIG_CYPRESS_FIRMWARE is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_V4L2=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_DMA_CONTIG=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+CONFIG_VIDEOBUF2_DMA_SG=y
+CONFIG_VIDEO_V4L2_TPG=y
 
 #
 # Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
 #
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+CONFIG_VIDEO_IR_I2C=y
 
 #
-# Customise DVB Frontends
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# SDR tuner chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Media SPI Adapters
 #
 
 #
@@ -3440,14 +3880,17 @@
 CONFIG_VGA_ARB_MAX_GPUS=16
 # CONFIG_VGA_SWITCHEROO is not set
 CONFIG_DRM=y
-# CONFIG_DRM_DP_AUX_CHARDEV is not set
+CONFIG_DRM_MIPI_DSI=y
+CONFIG_DRM_DP_AUX_CHARDEV=y
 # CONFIG_DRM_DEBUG_MM is not set
 # CONFIG_DRM_DEBUG_SELFTEST is not set
 CONFIG_DRM_KMS_HELPER=y
 CONFIG_DRM_KMS_FB_HELPER=y
 CONFIG_DRM_FBDEV_EMULATION=y
 CONFIG_DRM_FBDEV_OVERALLOC=100
+# CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM is not set
 # CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
+# CONFIG_DRM_DP_CEC is not set
 CONFIG_DRM_TTM=y
 CONFIG_DRM_GEM_CMA_HELPER=y
 CONFIG_DRM_KMS_CMA_HELPER=y
@@ -3459,6 +3902,10 @@
 # CONFIG_DRM_I2C_SIL164 is not set
 # CONFIG_DRM_I2C_NXP_TDA998X is not set
 # CONFIG_DRM_I2C_NXP_TDA9950 is not set
+
+#
+# ARM devices
+#
 # CONFIG_DRM_RADEON is not set
 # CONFIG_DRM_AMDGPU is not set
 
@@ -3470,22 +3917,43 @@
 # AMD Library routines
 #
 # CONFIG_DRM_NOUVEAU is not set
-# CONFIG_DRM_I915 is not set
-# CONFIG_DRM_VGEM is not set
-# CONFIG_DRM_VMWGFX is not set
+CONFIG_DRM_I915=y
+# CONFIG_DRM_I915_ALPHA_SUPPORT is not set
+CONFIG_DRM_I915_CAPTURE_ERROR=y
+CONFIG_DRM_I915_COMPRESS_ERROR=y
+CONFIG_DRM_I915_USERPTR=y
+# CONFIG_DRM_I915_GVT is not set
+
+#
+# drm/i915 Debugging
+#
+# CONFIG_DRM_I915_WERROR is not set
+# CONFIG_DRM_I915_DEBUG is not set
+# CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS is not set
+# CONFIG_DRM_I915_SW_FENCE_CHECK_DAG is not set
+# CONFIG_DRM_I915_DEBUG_GUC is not set
+# CONFIG_DRM_I915_SELFTEST is not set
+# CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS is not set
+# CONFIG_DRM_I915_DEBUG_VBLANK_EVADE is not set
+# CONFIG_DRM_I915_DEBUG_RUNTIME_PM is not set
+CONFIG_DRM_VGEM=y
+CONFIG_DRM_VKMS=y
+CONFIG_DRM_VMWGFX=y
+CONFIG_DRM_VMWGFX_FBCON=y
 # CONFIG_DRM_GMA500 is not set
-# CONFIG_DRM_UDL is not set
+CONFIG_DRM_UDL=y
 # CONFIG_DRM_AST is not set
 # CONFIG_DRM_MGAG200 is not set
 CONFIG_DRM_CIRRUS_QEMU=y
 CONFIG_DRM_QXL=y
-# CONFIG_DRM_BOCHS is not set
+CONFIG_DRM_BOCHS=y
 CONFIG_DRM_VIRTIO_GPU=y
 CONFIG_DRM_PANEL=y
 
 #
 # Display Panels
 #
+# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set
 CONFIG_DRM_BRIDGE=y
 CONFIG_DRM_PANEL_BRIDGE=y
 
@@ -3493,8 +3961,16 @@
 # Display Interface Bridges
 #
 # CONFIG_DRM_ANALOGIX_ANX78XX is not set
+# CONFIG_DRM_ETNAVIV is not set
 # CONFIG_DRM_HISI_HIBMC is not set
 CONFIG_DRM_TINYDRM=y
+# CONFIG_TINYDRM_HX8357D is not set
+# CONFIG_TINYDRM_ILI9225 is not set
+# CONFIG_TINYDRM_ILI9341 is not set
+# CONFIG_TINYDRM_MI0283QT is not set
+# CONFIG_TINYDRM_REPAPER is not set
+# CONFIG_TINYDRM_ST7586 is not set
+# CONFIG_TINYDRM_ST7735R is not set
 # CONFIG_DRM_XEN is not set
 # CONFIG_DRM_LEGACY is not set
 CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
@@ -3502,10 +3978,11 @@
 #
 # Frame buffer Devices
 #
-CONFIG_FB=y
-# CONFIG_FIRMWARE_EDID is not set
 CONFIG_FB_CMDLINE=y
 CONFIG_FB_NOTIFY=y
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_BOOT_VESA_SUPPORT=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
@@ -3529,7 +4006,7 @@
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
 # CONFIG_FB_UVESA is not set
-# CONFIG_FB_VESA is not set
+CONFIG_FB_VESA=y
 CONFIG_FB_EFI=y
 # CONFIG_FB_N411 is not set
 # CONFIG_FB_HGA is not set
@@ -3539,7 +4016,6 @@
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_I740 is not set
 # CONFIG_FB_LE80578 is not set
-# CONFIG_FB_INTEL is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
@@ -3559,12 +4035,11 @@
 # CONFIG_FB_SMSCUFX is not set
 # CONFIG_FB_UDL is not set
 # CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_VIRTUAL=y
 CONFIG_XEN_FBDEV_FRONTEND=y
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
-# CONFIG_FB_BROADSHEET is not set
-# CONFIG_FB_SIMPLE is not set
+CONFIG_FB_SIMPLE=y
 # CONFIG_FB_SM712 is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
@@ -3594,6 +4069,7 @@
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER is not set
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
@@ -3717,24 +4193,29 @@
 CONFIG_SND_HDA_RECONFIG=y
 CONFIG_SND_HDA_INPUT_BEEP=y
 CONFIG_SND_HDA_INPUT_BEEP_MODE=1
-# CONFIG_SND_HDA_PATCH_LOADER is not set
+CONFIG_SND_HDA_PATCH_LOADER=y
 CONFIG_SND_HDA_CODEC_REALTEK=y
-# CONFIG_SND_HDA_CODEC_ANALOG is not set
-# CONFIG_SND_HDA_CODEC_SIGMATEL is not set
-# CONFIG_SND_HDA_CODEC_VIA is not set
-# CONFIG_SND_HDA_CODEC_HDMI is not set
-# CONFIG_SND_HDA_CODEC_CIRRUS is not set
-# CONFIG_SND_HDA_CODEC_CONEXANT is not set
-# CONFIG_SND_HDA_CODEC_CA0110 is not set
-# CONFIG_SND_HDA_CODEC_CA0132 is not set
-# CONFIG_SND_HDA_CODEC_CMEDIA is not set
-# CONFIG_SND_HDA_CODEC_SI3054 is not set
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_HDMI=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CA0132=y
+CONFIG_SND_HDA_CODEC_CA0132_DSP=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
 CONFIG_SND_HDA_GENERIC=y
 CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0
 CONFIG_SND_HDA_CORE=y
+CONFIG_SND_HDA_DSP_LOADER=y
+CONFIG_SND_HDA_COMPONENT=y
+CONFIG_SND_HDA_I915=y
 CONFIG_SND_HDA_PREALLOC_SIZE=64
+CONFIG_SND_SPI=y
 CONFIG_SND_USB=y
-# CONFIG_SND_USB_AUDIO is not set
+CONFIG_SND_USB_AUDIO=y
 # CONFIG_SND_USB_UA101 is not set
 # CONFIG_SND_USB_USX2Y is not set
 # CONFIG_SND_USB_CAIAQ is not set
@@ -3761,13 +4242,14 @@
 # CONFIG_SND_PDAUDIOCF is not set
 # CONFIG_SND_SOC is not set
 CONFIG_SND_X86=y
+# CONFIG_HDMI_LPE_AUDIO is not set
 CONFIG_SND_XEN_FRONTEND=y
 
 #
 # HID support
 #
 CONFIG_HID=y
-# CONFIG_HID_BATTERY_STRENGTH is not set
+CONFIG_HID_BATTERY_STRENGTH=y
 CONFIG_HIDRAW=y
 CONFIG_UHID=y
 CONFIG_HID_GENERIC=y
@@ -3777,89 +4259,102 @@
 #
 CONFIG_HID_A4TECH=y
 # CONFIG_HID_ACCUTOUCH is not set
-# CONFIG_HID_ACRUX is not set
+CONFIG_HID_ACRUX=y
+CONFIG_HID_ACRUX_FF=y
 CONFIG_HID_APPLE=y
 # CONFIG_HID_APPLEIR is not set
 # CONFIG_HID_ASUS is not set
 # CONFIG_HID_AUREAL is not set
 CONFIG_HID_BELKIN=y
 # CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_BIGBEN_FF is not set
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 # CONFIG_HID_CORSAIR is not set
-# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_COUGAR is not set
+CONFIG_HID_PRODIKEYS=y
 # CONFIG_HID_CMEDIA is not set
 CONFIG_HID_CYPRESS=y
-# CONFIG_HID_DRAGONRISE is not set
-# CONFIG_HID_EMS_FF is not set
+CONFIG_HID_DRAGONRISE=y
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=y
 # CONFIG_HID_ELAN is not set
-# CONFIG_HID_ELECOM is not set
+CONFIG_HID_ELECOM=y
 # CONFIG_HID_ELO is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_GEMBIRD is not set
 # CONFIG_HID_GFRM is not set
-# CONFIG_HID_HOLTEK is not set
-# CONFIG_HID_GOOGLE_HAMMER is not set
+CONFIG_HID_HOLTEK=y
+# CONFIG_HOLTEK_FF is not set
 # CONFIG_HID_GT683R is not set
-# CONFIG_HID_KEYTOUCH is not set
-# CONFIG_HID_KYE is not set
-# CONFIG_HID_UCLOGIC is not set
-# CONFIG_HID_WALTOP is not set
+CONFIG_HID_KEYTOUCH=y
+CONFIG_HID_KYE=y
+CONFIG_HID_UCLOGIC=y
+CONFIG_HID_WALTOP=y
 CONFIG_HID_GYRATION=y
 # CONFIG_HID_ICADE is not set
 CONFIG_HID_ITE=y
 # CONFIG_HID_JABRA is not set
-# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_TWINHAN=y
 CONFIG_HID_KENSINGTON=y
-# CONFIG_HID_LCPOWER is not set
-# CONFIG_HID_LED is not set
+CONFIG_HID_LCPOWER=y
+CONFIG_HID_LED=y
 # CONFIG_HID_LENOVO is not set
 CONFIG_HID_LOGITECH=y
-# CONFIG_HID_LOGITECH_DJ is not set
-# CONFIG_HID_LOGITECH_HIDPP is not set
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_HID_LOGITECH_HIDPP=y
 CONFIG_LOGITECH_FF=y
-# CONFIG_LOGIRUMBLEPAD2_FF is not set
-# CONFIG_LOGIG940_FF is not set
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
 CONFIG_LOGIWHEELS_FF=y
-# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MAGICMOUSE=y
+# CONFIG_HID_MALTRON is not set
 # CONFIG_HID_MAYFLASH is not set
 # CONFIG_HID_REDRAGON is not set
 CONFIG_HID_MICROSOFT=y
 CONFIG_HID_MONTEREY=y
-# CONFIG_HID_MULTITOUCH is not set
+CONFIG_HID_MULTITOUCH=y
 # CONFIG_HID_NTI is not set
 CONFIG_HID_NTRIG=y
-# CONFIG_HID_ORTEK is not set
+CONFIG_HID_ORTEK=y
 CONFIG_HID_PANTHERLORD=y
 CONFIG_PANTHERLORD_FF=y
 # CONFIG_HID_PENMOUNT is not set
 CONFIG_HID_PETALYNX=y
-# CONFIG_HID_PICOLCD is not set
-# CONFIG_HID_PLANTRONICS is not set
-# CONFIG_HID_PRIMAX is not set
+CONFIG_HID_PICOLCD=y
+# CONFIG_HID_PICOLCD_FB is not set
+# CONFIG_HID_PICOLCD_BACKLIGHT is not set
+# CONFIG_HID_PICOLCD_LEDS is not set
+# CONFIG_HID_PICOLCD_CIR is not set
+CONFIG_HID_PLANTRONICS=y
+CONFIG_HID_PRIMAX=y
 # CONFIG_HID_RETRODE is not set
-# CONFIG_HID_ROCCAT is not set
-# CONFIG_HID_SAITEK is not set
+CONFIG_HID_ROCCAT=y
+CONFIG_HID_SAITEK=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 # CONFIG_SONY_FF is not set
-# CONFIG_HID_SPEEDLINK is not set
+CONFIG_HID_SPEEDLINK=y
 # CONFIG_HID_STEAM is not set
 # CONFIG_HID_STEELSERIES is not set
 CONFIG_HID_SUNPLUS=y
-# CONFIG_HID_RMI is not set
-# CONFIG_HID_GREENASIA is not set
-# CONFIG_HID_SMARTJOYPLUS is not set
-# CONFIG_HID_TIVO is not set
+CONFIG_HID_RMI=y
+CONFIG_HID_GREENASIA=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=y
 CONFIG_HID_TOPSEED=y
-# CONFIG_HID_THINGM is not set
-# CONFIG_HID_THRUSTMASTER is not set
+CONFIG_HID_THINGM=y
+CONFIG_HID_THRUSTMASTER=y
+# CONFIG_THRUSTMASTER_FF is not set
 # CONFIG_HID_UDRAW_PS3 is not set
-# CONFIG_HID_WACOM is not set
-# CONFIG_HID_WIIMOTE is not set
+CONFIG_HID_WACOM=y
+CONFIG_HID_WIIMOTE=y
 # CONFIG_HID_XINMO is not set
-# CONFIG_HID_ZEROPLUS is not set
-# CONFIG_HID_ZYDACRON is not set
+CONFIG_HID_ZEROPLUS=y
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_HID_ZYDACRON=y
 # CONFIG_HID_SENSOR_HUB is not set
 # CONFIG_HID_ALPS is not set
 
@@ -3892,9 +4387,10 @@
 #
 CONFIG_USB_DEFAULT_PERSIST=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_OTG is not set
+CONFIG_USB_OTG=y
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_OTG_FSM is not set
 # CONFIG_USB_LEDS_TRIGGER_USBPORT is not set
 CONFIG_USB_MON=y
 # CONFIG_USB_WUSB_CBAF is not set
@@ -3903,15 +4399,20 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
-# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+# CONFIG_USB_XHCI_DBGCAP is not set
+CONFIG_USB_XHCI_PCI=y
+CONFIG_USB_XHCI_PLATFORM=y
 CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_EHCI_PCI=y
+# CONFIG_USB_EHCI_FSL is not set
 # CONFIG_USB_EHCI_HCD_PLATFORM is not set
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PCI=y
 # CONFIG_USB_OHCI_HCD_PLATFORM is not set
@@ -3923,9 +4424,9 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_ACM is not set
+CONFIG_USB_ACM=y
 CONFIG_USB_PRINTER=y
-# CONFIG_USB_WDM is not set
+CONFIG_USB_WDM=y
 # CONFIG_USB_TMC is not set
 
 #
@@ -3937,7 +4438,8 @@
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_REALTEK is not set
+CONFIG_USB_STORAGE_REALTEK=y
+CONFIG_REALTEK_AUTOPM=y
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -3950,24 +4452,97 @@
 # CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_STORAGE_ENE_UB6250 is not set
-# CONFIG_USB_UAS is not set
+CONFIG_USB_UAS=y
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USBIP_CORE is not set
+CONFIG_USBIP_CORE=y
+CONFIG_USBIP_VHCI_HCD=y
+CONFIG_USBIP_VHCI_HC_PORTS=8
+CONFIG_USBIP_VHCI_NR_HCS=16
+CONFIG_USBIP_HOST=y
+CONFIG_USBIP_VUDC=y
+# CONFIG_USBIP_DEBUG is not set
 # CONFIG_USB_MUSB_HDRC is not set
-# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_ULPI is not set
+# CONFIG_USB_DWC3_HOST is not set
+CONFIG_USB_DWC3_GADGET=y
+# CONFIG_USB_DWC3_DUAL_ROLE is not set
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_PCI=y
+CONFIG_USB_DWC3_HAPS=y
 # CONFIG_USB_DWC2 is not set
-# CONFIG_USB_CHIPIDEA is not set
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_PCI=y
+CONFIG_USB_CHIPIDEA_UDC=y
+# CONFIG_USB_CHIPIDEA_HOST is not set
 # CONFIG_USB_ISP1760 is not set
 
 #
 # USB port drivers
 #
-# CONFIG_USB_SERIAL is not set
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_CONSOLE is not set
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+CONFIG_USB_SERIAL_CH341=y
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP210X=y
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=y
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_F81232 is not set
+# CONFIG_USB_SERIAL_F8153X is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+CONFIG_USB_SERIAL_KEYSPAN=y
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_METRO is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MXUPORT is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=y
+CONFIG_USB_SERIAL_OTI6858=y
+# CONFIG_USB_SERIAL_QCAUX is not set
+CONFIG_USB_SERIAL_QUALCOMM=y
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+CONFIG_USB_SERIAL_SIERRAWIRELESS=y
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+CONFIG_USB_SERIAL_WWAN=y
+CONFIG_USB_SERIAL_OPTION=y
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_XSENS_MT is not set
+# CONFIG_USB_SERIAL_WISHBONE is not set
+# CONFIG_USB_SERIAL_SSU100 is not set
+# CONFIG_USB_SERIAL_QT2 is not set
+# CONFIG_USB_SERIAL_UPD78F0730 is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
 
 #
 # USB Miscellaneous drivers
@@ -3992,7 +4567,7 @@
 # CONFIG_USB_EHSET_TEST_FIXTURE is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_YUREX is not set
-# CONFIG_USB_EZUSB_FX2 is not set
+CONFIG_USB_EZUSB_FX2=y
 # CONFIG_USB_HUB_USB251XB is not set
 # CONFIG_USB_HSIC_USB3503 is not set
 # CONFIG_USB_HSIC_USB4604 is not set
@@ -4007,7 +4582,8 @@
 #
 # USB Physical Layer drivers
 #
-# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_USB_PHY=y
+CONFIG_NOP_USB_XCEIV=y
 # CONFIG_USB_ISP1301 is not set
 CONFIG_USB_GADGET=y
 # CONFIG_USB_GADGET_DEBUG is not set
@@ -4015,6 +4591,7 @@
 # CONFIG_USB_GADGET_DEBUG_FS is not set
 CONFIG_USB_GADGET_VBUS_DRAW=2
 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+# CONFIG_U_SERIAL_CONSOLE is not set
 
 #
 # USB Peripheral Controller
@@ -4033,11 +4610,57 @@
 # CONFIG_USB_GOKU is not set
 # CONFIG_USB_EG20T is not set
 # CONFIG_USB_DUMMY_HCD is not set
-# CONFIG_USB_CONFIGFS is not set
+CONFIG_USB_LIBCOMPOSITE=y
+CONFIG_USB_F_ACM=y
+CONFIG_USB_U_SERIAL=y
+CONFIG_USB_U_ETHER=y
+CONFIG_USB_F_RNDIS=y
+CONFIG_USB_F_MASS_STORAGE=y
+CONFIG_USB_F_FS=y
+CONFIG_USB_F_MIDI=y
+CONFIG_USB_CONFIGFS=y
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+# CONFIG_USB_CONFIGFS_ACM is not set
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+# CONFIG_USB_CONFIGFS_ECM is not set
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+# CONFIG_USB_CONFIGFS_RNDIS is not set
+# CONFIG_USB_CONFIGFS_EEM is not set
+# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+CONFIG_USB_CONFIGFS_F_FS=y
+# CONFIG_USB_CONFIGFS_F_UAC1 is not set
+# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
+# CONFIG_USB_CONFIGFS_F_UAC2 is not set
+CONFIG_USB_CONFIGFS_F_MIDI=y
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_G_NCM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_ACM_MS is not set
+CONFIG_USB_G_MULTI=y
+CONFIG_USB_G_MULTI_RNDIS=y
+# CONFIG_USB_G_MULTI_CDC is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
 CONFIG_TYPEC=y
 CONFIG_TYPEC_TCPM=y
+# CONFIG_TYPEC_TCPCI is not set
 # CONFIG_TYPEC_FUSB302 is not set
 CONFIG_TYPEC_UCSI=y
+# CONFIG_UCSI_CCG is not set
 CONFIG_UCSI_ACPI=y
 # CONFIG_TYPEC_TPS6598X is not set
 
@@ -4045,10 +4668,15 @@
 # USB Type-C Multiplexer/DeMultiplexer Switch support
 #
 # CONFIG_TYPEC_MUX_PI3USB30532 is not set
+
+#
+# USB Type-C Alternate Mode drivers
+#
+# CONFIG_TYPEC_DP_ALTMODE is not set
+CONFIG_USB_ROLE_SWITCH=y
 # CONFIG_USB_ROLES_INTEL_XHCI is not set
 # CONFIG_USB_LED_TRIG is not set
-# CONFIG_USB_ULPI_BUS is not set
-CONFIG_USB_ROLE_SWITCH=y
+CONFIG_USB_ULPI_BUS=y
 # CONFIG_UWB is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
@@ -4072,6 +4700,7 @@
 # CONFIG_LEDS_CLEVO_MAIL is not set
 # CONFIG_LEDS_PCA955X is not set
 # CONFIG_LEDS_PCA963X is not set
+# CONFIG_LEDS_DAC124S085 is not set
 # CONFIG_LEDS_BD2802 is not set
 # CONFIG_LEDS_INTEL_SS4200 is not set
 # CONFIG_LEDS_TCA6507 is not set
@@ -4094,6 +4723,7 @@
 # CONFIG_LEDS_TRIGGER_TIMER is not set
 # CONFIG_LEDS_TRIGGER_ONESHOT is not set
 # CONFIG_LEDS_TRIGGER_DISK is not set
+# CONFIG_LEDS_TRIGGER_MTD is not set
 # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
 # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
 # CONFIG_LEDS_TRIGGER_CPU is not set
@@ -4107,6 +4737,8 @@
 # CONFIG_LEDS_TRIGGER_CAMERA is not set
 # CONFIG_LEDS_TRIGGER_PANIC is not set
 # CONFIG_LEDS_TRIGGER_NETDEV is not set
+# CONFIG_LEDS_TRIGGER_PATTERN is not set
+# CONFIG_LEDS_TRIGGER_AUDIO is not set
 # CONFIG_ACCESSIBILITY is not set
 CONFIG_INFINIBAND=y
 CONFIG_INFINIBAND_USER_MAD=y
@@ -4118,10 +4750,15 @@
 CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS=y
 # CONFIG_INFINIBAND_MTHCA is not set
 # CONFIG_INFINIBAND_QIB is not set
-# CONFIG_MLX4_INFINIBAND is not set
+CONFIG_MLX4_INFINIBAND=y
 # CONFIG_INFINIBAND_NES is not set
 # CONFIG_INFINIBAND_OCRDMA is not set
+# CONFIG_INFINIBAND_VMWARE_PVRDMA is not set
 CONFIG_INFINIBAND_USNIC=y
+# CONFIG_INFINIBAND_BNXT_RE is not set
+# CONFIG_INFINIBAND_HFI1 is not set
+CONFIG_INFINIBAND_RDMAVT=y
+CONFIG_RDMA_RXE=y
 CONFIG_INFINIBAND_IPOIB=y
 CONFIG_INFINIBAND_IPOIB_CM=y
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
@@ -4129,10 +4766,6 @@
 CONFIG_INFINIBAND_SRP=y
 CONFIG_INFINIBAND_ISER=y
 CONFIG_INFINIBAND_OPA_VNIC=y
-CONFIG_INFINIBAND_RDMAVT=y
-CONFIG_RDMA_RXE=y
-# CONFIG_INFINIBAND_HFI1 is not set
-# CONFIG_INFINIBAND_BNXT_RE is not set
 CONFIG_EDAC_ATOMIC_SCRUB=y
 CONFIG_EDAC_SUPPORT=y
 CONFIG_EDAC=y
@@ -4199,10 +4832,26 @@
 # CONFIG_RTC_DRV_RX8025 is not set
 # CONFIG_RTC_DRV_EM3027 is not set
 # CONFIG_RTC_DRV_RV8803 is not set
+# CONFIG_RTC_DRV_SD3078 is not set
 
 #
 # SPI RTC drivers
 #
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
 CONFIG_RTC_I2C_AND_SPI=y
 
 #
@@ -4250,8 +4899,8 @@
 CONFIG_DMA_VIRTUAL_CHANNELS=y
 CONFIG_DMA_ACPI=y
 # CONFIG_ALTERA_MSGDMA is not set
-# CONFIG_INTEL_IDMA64 is not set
-# CONFIG_INTEL_IOATDMA is not set
+CONFIG_INTEL_IDMA64=y
+CONFIG_INTEL_IOATDMA=y
 # CONFIG_QCOM_HIDMA_MGMT is not set
 # CONFIG_QCOM_HIDMA is not set
 CONFIG_DW_DMAC_CORE=y
@@ -4262,17 +4911,29 @@
 #
 # DMA Clients
 #
-# CONFIG_ASYNC_TX_DMA is not set
+CONFIG_ASYNC_TX_DMA=y
 # CONFIG_DMATEST is not set
+CONFIG_DMA_ENGINE_RAID=y
 
 #
 # DMABUF options
 #
 CONFIG_SYNC_FILE=y
-# CONFIG_SW_SYNC is not set
+CONFIG_SW_SYNC=y
+CONFIG_UDMABUF=y
+CONFIG_DCA=y
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
-# CONFIG_VFIO is not set
+CONFIG_VFIO_IOMMU_TYPE1=y
+CONFIG_VFIO_VIRQFD=y
+CONFIG_VFIO=y
+# CONFIG_VFIO_NOIOMMU is not set
+CONFIG_VFIO_PCI=y
+# CONFIG_VFIO_PCI_VGA is not set
+CONFIG_VFIO_PCI_MMAP=y
+CONFIG_VFIO_PCI_INTX=y
+CONFIG_VFIO_PCI_IGD=y
+# CONFIG_VFIO_MDEV is not set
 CONFIG_IRQ_BYPASS_MANAGER=y
 # CONFIG_VIRT_DRIVERS is not set
 CONFIG_VIRTIO=y
@@ -4293,7 +4954,7 @@
 # Xen driver support
 #
 CONFIG_XEN_BALLOON=y
-CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_SCRUB_PAGES_DEFAULT=y
 CONFIG_XEN_DEV_EVTCHN=y
 CONFIG_XEN_BACKEND=y
 CONFIG_XENFS=y
@@ -4302,6 +4963,7 @@
 CONFIG_XEN_XENBUS_FRONTEND=y
 CONFIG_XEN_GNTDEV=y
 CONFIG_XEN_GRANT_DEV_ALLOC=y
+# CONFIG_XEN_GRANT_DMA_ALLOC is not set
 CONFIG_SWIOTLB_XEN=y
 CONFIG_XEN_TMEM=m
 CONFIG_XEN_PCIDEV_BACKEND=y
@@ -4316,6 +4978,7 @@
 CONFIG_XEN_ACPI=y
 CONFIG_XEN_SYMS=y
 CONFIG_XEN_HAVE_VPMU=y
+CONFIG_XEN_FRONT_PGDIR_SHBUF=y
 CONFIG_STAGING=y
 # CONFIG_PRISM2_USB is not set
 # CONFIG_COMEDI is not set
@@ -4328,7 +4991,6 @@
 # CONFIG_VT6655 is not set
 # CONFIG_VT6656 is not set
 # CONFIG_FB_SM750 is not set
-# CONFIG_FB_XGI is not set
 
 #
 # Speakup console speech
@@ -4345,28 +5007,44 @@
 CONFIG_ION_SYSTEM_HEAP=y
 CONFIG_ION_CARVEOUT_HEAP=y
 CONFIG_ION_CHUNK_HEAP=y
+CONFIG_ION_CMA_HEAP=y
 # CONFIG_LTE_GDM724X is not set
 # CONFIG_FIREWIRE_SERIAL is not set
-# CONFIG_DGNC is not set
 # CONFIG_GS_FPGABOOT is not set
-# CONFIG_CRYPTO_SKEIN is not set
 # CONFIG_UNISYSSPAR is not set
+# CONFIG_WILC1000_SPI is not set
 # CONFIG_MOST is not set
 # CONFIG_GREYBUS is not set
+# CONFIG_DRM_VBOXVIDEO is not set
+# CONFIG_PI433 is not set
 
 #
-# USB Power Delivery and Type-C drivers
+# Gasket devices
 #
-# CONFIG_TYPEC_TCPCI is not set
-# CONFIG_TYPEC_RT1711H is not set
-# CONFIG_DRM_VBOXVIDEO is not set
+# CONFIG_STAGING_GASKET_FRAMEWORK is not set
+# CONFIG_XIL_AXIS_FIFO is not set
+CONFIG_EROFS_FS=y
+CONFIG_EROFS_FS_DEBUG=y
+CONFIG_EROFS_FS_XATTR=y
+CONFIG_EROFS_FS_POSIX_ACL=y
+CONFIG_EROFS_FS_SECURITY=y
+CONFIG_EROFS_FS_USE_VM_MAP_RAM=y
+CONFIG_EROFS_FAULT_INJECTION=y
+CONFIG_EROFS_FS_IO_MAX_RETRIES=5
+CONFIG_EROFS_FS_ZIP=y
+CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT=2
+# CONFIG_EROFS_FS_ZIP_NO_CACHE is not set
+# CONFIG_EROFS_FS_ZIP_CACHE_UNIPOLAR is not set
+CONFIG_EROFS_FS_ZIP_CACHE_BIPOLAR=y
 CONFIG_X86_PLATFORM_DEVICES=y
 # CONFIG_ACER_WIRELESS is not set
 # CONFIG_ACERHDF is not set
 # CONFIG_ASUS_LAPTOP is not set
+# CONFIG_DCDBAS is not set
 # CONFIG_DELL_SMBIOS is not set
 # CONFIG_DELL_SMO8800 is not set
 # CONFIG_DELL_RBTN is not set
+# CONFIG_DELL_RBU is not set
 # CONFIG_FUJITSU_LAPTOP is not set
 # CONFIG_FUJITSU_TABLET is not set
 # CONFIG_AMILO_RFKILL is not set
@@ -4380,7 +5058,7 @@
 # CONFIG_IDEAPAD_LAPTOP is not set
 # CONFIG_THINKPAD_ACPI is not set
 # CONFIG_SENSORS_HDAPS is not set
-# CONFIG_INTEL_MENLOW is not set
+CONFIG_INTEL_MENLOW=y
 CONFIG_EEEPC_LAPTOP=y
 # CONFIG_ASUS_WIRELESS is not set
 # CONFIG_ACPI_WMI is not set
@@ -4399,14 +5077,19 @@
 # CONFIG_APPLE_GMUX is not set
 # CONFIG_INTEL_RST is not set
 # CONFIG_INTEL_SMARTCONNECT is not set
-# CONFIG_PVPANIC is not set
 # CONFIG_INTEL_PMC_IPC is not set
 # CONFIG_SURFACE_PRO3_BUTTON is not set
 # CONFIG_INTEL_PUNIT_IPC is not set
 # CONFIG_MLX_PLATFORM is not set
 # CONFIG_INTEL_TURBO_MAX_3 is not set
+CONFIG_I2C_MULTI_INSTANTIATE=y
+# CONFIG_INTEL_ATOMISP2_PM is not set
 CONFIG_PMC_ATOM=y
-# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CHROME_PLATFORMS=y
+CONFIG_CHROMEOS_LAPTOP=y
+CONFIG_CHROMEOS_PSTORE=y
+CONFIG_CHROMEOS_TBMC=y
+CONFIG_CROS_KBD_LED_BACKLIGHT=y
 # CONFIG_MELLANOX_PLATFORM is not set
 CONFIG_CLKDEV_LOOKUP=y
 CONFIG_HAVE_CLK_PREPARE=y
@@ -4415,6 +5098,7 @@
 #
 # Common Clock Framework
 #
+# CONFIG_COMMON_CLK_MAX9485 is not set
 # CONFIG_COMMON_CLK_SI5351 is not set
 # CONFIG_COMMON_CLK_SI544 is not set
 # CONFIG_COMMON_CLK_CDCE706 is not set
@@ -4430,21 +5114,23 @@
 CONFIG_MAILBOX=y
 CONFIG_PCC=y
 # CONFIG_ALTERA_MBOX is not set
+CONFIG_IOMMU_IOVA=y
 CONFIG_IOMMU_API=y
 CONFIG_IOMMU_SUPPORT=y
 
 #
 # Generic IOMMU Pagetable Support
 #
-CONFIG_IOMMU_IOVA=y
+# CONFIG_IOMMU_DEBUGFS is not set
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
 CONFIG_AMD_IOMMU=y
 # CONFIG_AMD_IOMMU_V2 is not set
 CONFIG_DMAR_TABLE=y
 CONFIG_INTEL_IOMMU=y
 # CONFIG_INTEL_IOMMU_SVM is not set
-# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU_DEFAULT_ON=y
 CONFIG_INTEL_IOMMU_FLOPPY_WA=y
-# CONFIG_IRQ_REMAP is not set
+CONFIG_IRQ_REMAP=y
 
 #
 # Remoteproc drivers
@@ -4471,6 +5157,10 @@
 #
 
 #
+# NXP/Freescale QorIQ SoC drivers
+#
+
+#
 # i.MX SoC drivers
 #
 
@@ -4484,7 +5174,13 @@
 #
 # CONFIG_XILINX_VCU is not set
 # CONFIG_PM_DEVFREQ is not set
-# CONFIG_EXTCON is not set
+CONFIG_EXTCON=y
+
+#
+# Extcon Device Drivers
+#
+# CONFIG_EXTCON_RT8973A is not set
+# CONFIG_EXTCON_SM5502 is not set
 # CONFIG_MEMORY is not set
 # CONFIG_IIO is not set
 # CONFIG_NTB is not set
@@ -4496,16 +5192,20 @@
 #
 CONFIG_ARM_GIC_MAX_NR=1
 # CONFIG_IPACK_BUS is not set
-# CONFIG_RESET_CONTROLLER is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_TI_SYSCON is not set
 # CONFIG_FMC is not set
 
 #
 # PHY Subsystem
 #
-# CONFIG_GENERIC_PHY is not set
+CONFIG_GENERIC_PHY=y
 # CONFIG_BCM_KONA_USB2_PHY is not set
 # CONFIG_PHY_PXA_28NM_HSIC is not set
 # CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_PHY_QCOM_USB_HS is not set
+# CONFIG_PHY_QCOM_USB_HSIC is not set
+# CONFIG_PHY_TUSB1210 is not set
 # CONFIG_POWERCAP is not set
 # CONFIG_MCB is not set
 
@@ -4520,6 +5220,7 @@
 #
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+# CONFIG_ANDROID_BINDERFS is not set
 CONFIG_ANDROID_BINDER_DEVICES="binder0,binder1,binder2,binder3,binder4,binder5,binder6,binder7,binder8,binder9,binder10,binder11,binder12,binder13,binder14,binder15,binder16,binder17,binder18,binder19,binder20,binder21,binder22,binder23,binder24,binder25,binder26,binder27,binder28,binder29,binder30,binder31"
 # CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set
 # CONFIG_LIBNVDIMM is not set
@@ -4536,41 +5237,13 @@
 # CONFIG_UNISYS_VISORBUS is not set
 # CONFIG_SIOX is not set
 # CONFIG_SLIMBUS is not set
-
-#
-# Firmware Drivers
-#
-# CONFIG_EDD is not set
-CONFIG_FIRMWARE_MEMMAP=y
-# CONFIG_DELL_RBU is not set
-# CONFIG_DCDBAS is not set
-CONFIG_DMIID=y
-# CONFIG_DMI_SYSFS is not set
-CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
-# CONFIG_ISCSI_IBFT_FIND is not set
-# CONFIG_FW_CFG_SYSFS is not set
-# CONFIG_GOOGLE_FIRMWARE is not set
-
-#
-# EFI (Extensible Firmware Interface) Support
-#
-CONFIG_EFI_VARS=y
-CONFIG_EFI_ESRT=y
-CONFIG_EFI_RUNTIME_MAP=y
-# CONFIG_EFI_FAKE_MEMMAP is not set
-CONFIG_EFI_RUNTIME_WRAPPERS=y
-# CONFIG_EFI_BOOTLOADER_CONTROL is not set
-# CONFIG_EFI_CAPSULE_LOADER is not set
-# CONFIG_EFI_TEST is not set
-
-#
-# Tegra firmware driver
-#
+# CONFIG_INTERCONNECT is not set
 
 #
 # File systems
 #
 CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_VALIDATE_FS_PARSER=y
 CONFIG_FS_IOMAP=y
 # CONFIG_EXT2_FS is not set
 CONFIG_EXT3_FS=y
@@ -4580,8 +5253,6 @@
 CONFIG_EXT4_USE_FOR_EXT2=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
-CONFIG_EXT4_ENCRYPTION=y
-CONFIG_EXT4_FS_ENCRYPTION=y
 # CONFIG_EXT4_DEBUG is not set
 CONFIG_JBD2=y
 # CONFIG_JBD2_DEBUG is not set
@@ -4621,7 +5292,6 @@
 CONFIG_F2FS_FS_POSIX_ACL=y
 CONFIG_F2FS_FS_SECURITY=y
 CONFIG_F2FS_CHECK_FS=y
-CONFIG_F2FS_FS_ENCRYPTION=y
 CONFIG_F2FS_FAULT_INJECTION=y
 CONFIG_FS_DAX=y
 CONFIG_FS_POSIX_ACL=y
@@ -4654,6 +5324,7 @@
 CONFIG_OVERLAY_FS_INDEX=y
 # CONFIG_OVERLAY_FS_NFS_EXPORT is not set
 # CONFIG_OVERLAY_FS_XINO_AUTO is not set
+# CONFIG_OVERLAY_FS_METACOPY is not set
 
 #
 # Caches
@@ -4673,7 +5344,7 @@
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
-# CONFIG_UDF_FS is not set
+CONFIG_UDF_FS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -4706,21 +5377,45 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_MEMFD_CREATE=y
+CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_EFIVAR_FS=y
 CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ORANGEFS_FS is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
+CONFIG_ECRYPT_FS=y
+# CONFIG_ECRYPT_FS_MESSAGING is not set
 CONFIG_HFS_FS=y
 CONFIG_HFSPLUS_FS=y
-CONFIG_HFSPLUS_FS_POSIX_ACL=y
 # CONFIG_BEFS_FS is not set
 CONFIG_BFS_FS=y
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_SECURITY=y
+# CONFIG_UBIFS_FS_AUTHENTICATION is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_SQUASHFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_FILE_CACHE is not set
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_SINGLE=y
+# CONFIG_SQUASHFS_DECOMP_MULTI is not set
+# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_ZLIB=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
 # CONFIG_VXFS_FS is not set
 CONFIG_MINIX_FS=y
 # CONFIG_OMFS_FS is not set
@@ -4739,14 +5434,15 @@
 CONFIG_NFS_V4=y
 # CONFIG_NFS_SWAP is not set
 CONFIG_NFS_V4_1=y
-# CONFIG_NFS_V4_2 is not set
+CONFIG_NFS_V4_2=y
 CONFIG_PNFS_FILE_LAYOUT=y
 CONFIG_PNFS_BLOCK=y
 CONFIG_PNFS_FLEXFILE_LAYOUT=m
 CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
 # CONFIG_NFS_V4_1_MIGRATION is not set
+CONFIG_NFS_V4_SECURITY_LABEL=y
 CONFIG_ROOT_NFS=y
-# CONFIG_NFS_FSCACHE is not set
+CONFIG_NFS_FSCACHE=y
 # CONFIG_NFS_USE_LEGACY_DNS is not set
 CONFIG_NFS_USE_KERNEL_DNS=y
 CONFIG_NFSD=y
@@ -4836,256 +5532,13 @@
 # CONFIG_DLM_DEBUG is not set
 
 #
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-
-#
-# printk and dmesg options
-#
-CONFIG_PRINTK_TIME=y
-CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
-CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_DYNAMIC_DEBUG is not set
-
-#
-# Compile-time checks and compiler options
-#
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_INFO_REDUCED is not set
-# CONFIG_DEBUG_INFO_SPLIT is not set
-# CONFIG_DEBUG_INFO_DWARF4 is not set
-# CONFIG_GDB_SCRIPTS is not set
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=2048
-# CONFIG_STRIP_ASM_SYMS is not set
-# CONFIG_READABLE_ASM is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_PAGE_OWNER is not set
-CONFIG_DEBUG_FS=y
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_SECTION_MISMATCH is not set
-CONFIG_SECTION_MISMATCH_WARN_ONLY=y
-CONFIG_FRAME_POINTER=y
-CONFIG_STACK_VALIDATION=y
-# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
-CONFIG_MAGIC_SYSRQ_SERIAL=y
-CONFIG_DEBUG_KERNEL=y
-
-#
-# Memory Debugging
-#
-CONFIG_PAGE_EXTENSION=y
-# CONFIG_DEBUG_PAGEALLOC is not set
-CONFIG_PAGE_POISONING=y
-CONFIG_PAGE_POISONING_NO_SANITY=y
-# CONFIG_PAGE_POISONING_ZERO is not set
-# CONFIG_DEBUG_PAGE_REF is not set
-# CONFIG_DEBUG_RODATA_TEST is not set
-CONFIG_DEBUG_OBJECTS=y
-# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
-CONFIG_DEBUG_OBJECTS_FREE=y
-CONFIG_DEBUG_OBJECTS_TIMERS=y
-CONFIG_DEBUG_OBJECTS_WORK=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_HAVE_DEBUG_KMEMLEAK=y
-# CONFIG_DEBUG_KMEMLEAK is not set
-CONFIG_DEBUG_STACK_USAGE=y
-CONFIG_DEBUG_VM=y
-CONFIG_DEBUG_VM_VMACACHE=y
-# CONFIG_DEBUG_VM_RB is not set
-# CONFIG_DEBUG_VM_PGFLAGS is not set
-CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
-# CONFIG_DEBUG_VIRTUAL is not set
-CONFIG_DEBUG_MEMORY_INIT=y
-# CONFIG_DEBUG_PER_CPU_MAPS is not set
-CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
-CONFIG_DEBUG_STACKOVERFLOW=y
-CONFIG_HAVE_ARCH_KASAN=y
-CONFIG_KASAN=y
-CONFIG_KASAN_EXTRA=y
-# CONFIG_KASAN_OUTLINE is not set
-CONFIG_KASAN_INLINE=y
-# CONFIG_TEST_KASAN is not set
-CONFIG_ARCH_HAS_KCOV=y
-CONFIG_CC_HAS_SANCOV_TRACE_PC=y
-CONFIG_KCOV=y
-CONFIG_KCOV_ENABLE_COMPARISONS=y
-CONFIG_KCOV_INSTRUMENT_ALL=y
-# CONFIG_DEBUG_SHIRQ is not set
-
-#
-# Debug Lockups and Hangs
-#
-CONFIG_LOCKUP_DETECTOR=y
-CONFIG_SOFTLOCKUP_DETECTOR=y
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
-CONFIG_HARDLOCKUP_DETECTOR_PERF=y
-CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y
-CONFIG_HARDLOCKUP_DETECTOR=y
-CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
-CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=140
-CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
-CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
-CONFIG_WQ_WATCHDOG=y
-CONFIG_PANIC_ON_OOPS=y
-CONFIG_PANIC_ON_OOPS_VALUE=1
-CONFIG_PANIC_TIMEOUT=86400
-# CONFIG_SCHED_DEBUG is not set
-CONFIG_SCHED_INFO=y
-CONFIG_SCHEDSTATS=y
-CONFIG_SCHED_STACK_END_CHECK=y
-# CONFIG_DEBUG_TIMEKEEPING is not set
-
-#
-# Lock Debugging (spinlocks, mutexes, etc...)
-#
-CONFIG_LOCK_DEBUGGING_SUPPORT=y
-CONFIG_PROVE_LOCKING=y
-# CONFIG_LOCK_STAT is not set
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
-CONFIG_DEBUG_RWSEMS=y
-CONFIG_DEBUG_LOCK_ALLOC=y
-CONFIG_LOCKDEP=y
-# CONFIG_DEBUG_LOCKDEP is not set
-CONFIG_DEBUG_ATOMIC_SLEEP=y
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_LOCK_TORTURE_TEST is not set
-# CONFIG_WW_MUTEX_SELFTEST is not set
-CONFIG_TRACE_IRQFLAGS=y
-CONFIG_STACKTRACE=y
-# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_KOBJECT_RELEASE is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_LIST=y
-CONFIG_DEBUG_PI_LIST=y
-# CONFIG_DEBUG_SG is not set
-CONFIG_DEBUG_NOTIFIERS=y
-# CONFIG_DEBUG_CREDENTIALS is not set
-
-#
-# RCU Debugging
-#
-CONFIG_PROVE_RCU=y
-# CONFIG_RCU_PERF_TEST is not set
-# CONFIG_RCU_TORTURE_TEST is not set
-CONFIG_RCU_CPU_STALL_TIMEOUT=100
-# CONFIG_RCU_TRACE is not set
-# CONFIG_RCU_EQS_DEBUG is not set
-# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
-# CONFIG_NOTIFIER_ERROR_INJECTION is not set
-CONFIG_FAULT_INJECTION=y
-CONFIG_FAILSLAB=y
-CONFIG_FAIL_PAGE_ALLOC=y
-CONFIG_FAIL_MAKE_REQUEST=y
-CONFIG_FAIL_IO_TIMEOUT=y
-CONFIG_FAIL_FUTEX=y
-CONFIG_FAULT_INJECTION_DEBUG_FS=y
-# CONFIG_LATENCYTOP is not set
-CONFIG_USER_STACKTRACE_SUPPORT=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
-CONFIG_HAVE_FENTRY=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_TRACE_CLOCK=y
-CONFIG_RING_BUFFER=y
-CONFIG_EVENT_TRACING=y
-CONFIG_CONTEXT_SWITCH_TRACER=y
-CONFIG_TRACING=y
-CONFIG_GENERIC_TRACER=y
-CONFIG_TRACING_SUPPORT=y
-CONFIG_FTRACE=y
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_HWLAT_TRACER is not set
-# CONFIG_FTRACE_SYSCALLS is not set
-# CONFIG_TRACER_SNAPSHOT is not set
-CONFIG_BRANCH_PROFILE_NONE=y
-# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
-# CONFIG_STACK_TRACER is not set
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_UPROBE_EVENTS=y
-CONFIG_BPF_EVENTS=y
-CONFIG_PROBE_EVENTS=y
-# CONFIG_FTRACE_STARTUP_TEST is not set
-# CONFIG_MMIOTRACE is not set
-# CONFIG_HIST_TRIGGERS is not set
-# CONFIG_TRACEPOINT_BENCHMARK is not set
-# CONFIG_RING_BUFFER_BENCHMARK is not set
-# CONFIG_RING_BUFFER_STARTUP_TEST is not set
-# CONFIG_TRACE_EVAL_MAP_FILE is not set
-CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
-# CONFIG_DMA_API_DEBUG is not set
-# CONFIG_RUNTIME_TESTING_MENU is not set
-# CONFIG_MEMTEST is not set
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
-# CONFIG_UBSAN is not set
-CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
-# CONFIG_STRICT_DEVMEM is not set
-CONFIG_EARLY_PRINTK_USB=y
-CONFIG_X86_VERBOSE_BOOTUP=y
-CONFIG_EARLY_PRINTK=y
-CONFIG_EARLY_PRINTK_DBGP=y
-# CONFIG_EARLY_PRINTK_EFI is not set
-# CONFIG_EARLY_PRINTK_USB_XDBC is not set
-# CONFIG_X86_PTDUMP is not set
-# CONFIG_EFI_PGT_DUMP is not set
-# CONFIG_DEBUG_WX is not set
-CONFIG_DOUBLEFAULT=y
-# CONFIG_DEBUG_TLBFLUSH is not set
-CONFIG_HAVE_MMIOTRACE_SUPPORT=y
-CONFIG_IO_DELAY_TYPE_0X80=0
-CONFIG_IO_DELAY_TYPE_0XED=1
-CONFIG_IO_DELAY_TYPE_UDELAY=2
-CONFIG_IO_DELAY_TYPE_NONE=3
-CONFIG_IO_DELAY_0X80=y
-# CONFIG_IO_DELAY_0XED is not set
-# CONFIG_IO_DELAY_UDELAY is not set
-# CONFIG_IO_DELAY_NONE is not set
-CONFIG_DEFAULT_IO_DELAY_TYPE=0
-CONFIG_DEBUG_BOOT_PARAMS=y
-# CONFIG_CPA_DEBUG is not set
-CONFIG_OPTIMIZE_INLINING=y
-# CONFIG_DEBUG_ENTRY is not set
-# CONFIG_DEBUG_NMI_SELFTEST is not set
-CONFIG_X86_DEBUG_FPU=y
-# CONFIG_PUNIT_ATOM_DEBUG is not set
-# CONFIG_UNWINDER_ORC is not set
-CONFIG_UNWINDER_FRAME_POINTER=y
-
-#
 # Security options
 #
 CONFIG_KEYS=y
 CONFIG_KEYS_COMPAT=y
 CONFIG_PERSISTENT_KEYRINGS=y
 CONFIG_BIG_KEYS=y
+CONFIG_TRUSTED_KEYS=y
 CONFIG_ENCRYPTED_KEYS=y
 CONFIG_KEY_DH_OPERATIONS=y
 # CONFIG_SECURITY_DMESG_RESTRICT is not set
@@ -5107,29 +5560,60 @@
 # CONFIG_STATIC_USERMODEHELPER is not set
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
 CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_SECURITY_SELINUX_DEVELOP=y
 CONFIG_SECURITY_SELINUX_AVC_STATS=y
 CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0
-# CONFIG_SECURITY_SMACK is not set
-# CONFIG_SECURITY_TOMOYO is not set
+CONFIG_SECURITY_SMACK=y
+# CONFIG_SECURITY_SMACK_BRINGUP is not set
+CONFIG_SECURITY_SMACK_NETFILTER=y
+# CONFIG_SECURITY_SMACK_APPEND_SIGNALS is not set
+CONFIG_SECURITY_TOMOYO=y
+CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY=1024
+CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG=32
+# CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER is not set
+CONFIG_SECURITY_TOMOYO_POLICY_LOADER="/sbin/tomoyo-init"
+CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER="/sbin/init"
 CONFIG_SECURITY_APPARMOR=y
-CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
 CONFIG_SECURITY_APPARMOR_HASH=y
 CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y
-# CONFIG_SECURITY_APPARMOR_DEBUG is not set
+CONFIG_SECURITY_APPARMOR_DEBUG=y
+CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS=y
+# CONFIG_SECURITY_APPARMOR_DEBUG_MESSAGES is not set
 # CONFIG_SECURITY_LOADPIN is not set
 CONFIG_SECURITY_YAMA=y
+CONFIG_SECURITY_SAFESETID=y
 CONFIG_INTEGRITY=y
-# CONFIG_INTEGRITY_SIGNATURE is not set
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_INTEGRITY_TRUSTED_KEYRING=y
 CONFIG_INTEGRITY_AUDIT=y
-# CONFIG_IMA is not set
-# CONFIG_EVM is not set
-CONFIG_DEFAULT_SECURITY_SELINUX=y
-# CONFIG_DEFAULT_SECURITY_APPARMOR is not set
-# CONFIG_DEFAULT_SECURITY_DAC is not set
-CONFIG_DEFAULT_SECURITY="selinux"
+CONFIG_IMA=y
+CONFIG_IMA_MEASURE_PCR_IDX=10
+CONFIG_IMA_LSM_RULES=y
+# CONFIG_IMA_TEMPLATE is not set
+CONFIG_IMA_NG_TEMPLATE=y
+# CONFIG_IMA_SIG_TEMPLATE is not set
+CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng"
+# CONFIG_IMA_DEFAULT_HASH_SHA1 is not set
+CONFIG_IMA_DEFAULT_HASH_SHA256=y
+# CONFIG_IMA_DEFAULT_HASH_SHA512 is not set
+# CONFIG_IMA_DEFAULT_HASH_WP512 is not set
+CONFIG_IMA_DEFAULT_HASH="sha256"
+CONFIG_IMA_WRITE_POLICY=y
+CONFIG_IMA_READ_POLICY=y
+CONFIG_IMA_APPRAISE=y
+# CONFIG_IMA_ARCH_POLICY is not set
+# CONFIG_IMA_APPRAISE_BUILD_POLICY is not set
+CONFIG_IMA_APPRAISE_BOOTPARAM=y
+# CONFIG_IMA_TRUSTED_KEYRING is not set
+# CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY is not set
+CONFIG_EVM=y
+CONFIG_EVM_ATTR_FSUUID=y
+CONFIG_EVM_EXTRA_SMACK_XATTRS=y
+CONFIG_EVM_ADD_XATTRS=y
+# CONFIG_EVM_LOAD_X509 is not set
+CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
 CONFIG_XOR_BLOCKS=y
 CONFIG_ASYNC_CORE=y
 CONFIG_ASYNC_MEMCPY=y
@@ -5170,7 +5654,6 @@
 CONFIG_CRYPTO_PCRYPT=y
 CONFIG_CRYPTO_WORKQUEUE=y
 CONFIG_CRYPTO_CRYPTD=y
-CONFIG_CRYPTO_MCRYPTD=y
 CONFIG_CRYPTO_AUTHENC=y
 # CONFIG_CRYPTO_TEST is not set
 CONFIG_CRYPTO_SIMD=y
@@ -5208,9 +5691,14 @@
 CONFIG_CRYPTO_CTS=y
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_OFB=y
 CONFIG_CRYPTO_PCBC=y
 CONFIG_CRYPTO_XTS=y
 CONFIG_CRYPTO_KEYWRAP=y
+CONFIG_CRYPTO_NHPOLY1305=y
+CONFIG_CRYPTO_NHPOLY1305_SSE2=y
+CONFIG_CRYPTO_NHPOLY1305_AVX2=y
+CONFIG_CRYPTO_ADIANTUM=y
 
 #
 # Hash modes
@@ -5243,13 +5731,11 @@
 CONFIG_CRYPTO_SHA1_SSSE3=y
 CONFIG_CRYPTO_SHA256_SSSE3=y
 CONFIG_CRYPTO_SHA512_SSSE3=y
-CONFIG_CRYPTO_SHA1_MB=y
-CONFIG_CRYPTO_SHA256_MB=y
-CONFIG_CRYPTO_SHA512_MB=y
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_SHA3=y
 CONFIG_CRYPTO_SM3=y
+CONFIG_CRYPTO_STREEBOG=y
 CONFIG_CRYPTO_TGR192=y
 CONFIG_CRYPTO_WP512=y
 CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=y
@@ -5288,7 +5774,6 @@
 CONFIG_CRYPTO_SERPENT_AVX_X86_64=y
 CONFIG_CRYPTO_SERPENT_AVX2_X86_64=y
 CONFIG_CRYPTO_SM4=y
-CONFIG_CRYPTO_SPECK=y
 CONFIG_CRYPTO_TEA=y
 CONFIG_CRYPTO_TWOFISH=y
 CONFIG_CRYPTO_TWOFISH_COMMON=y
@@ -5321,6 +5806,7 @@
 CONFIG_CRYPTO_USER_API_SKCIPHER=y
 CONFIG_CRYPTO_USER_API_RNG=y
 CONFIG_CRYPTO_USER_API_AEAD=y
+# CONFIG_CRYPTO_STATS is not set
 CONFIG_CRYPTO_HASH_INFO=y
 CONFIG_CRYPTO_HW=y
 CONFIG_CRYPTO_DEV_PADLOCK=y
@@ -5341,7 +5827,10 @@
 CONFIG_CRYPTO_DEV_VIRTIO=y
 CONFIG_ASYMMETRIC_KEY_TYPE=y
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE=y
 CONFIG_X509_CERTIFICATE_PARSER=y
+CONFIG_PKCS8_PRIVATE_KEY_PARSER=y
+CONFIG_TPM_KEY_PARSER=y
 CONFIG_PKCS7_MESSAGE_PARSER=y
 CONFIG_PKCS7_TEST_KEY=y
 CONFIG_SIGNED_PE_FILE_VERIFICATION=y
@@ -5354,34 +5843,13 @@
 # CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set
 CONFIG_SECONDARY_TRUSTED_KEYRING=y
 # CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
-CONFIG_HAVE_KVM=y
-CONFIG_HAVE_KVM_IRQCHIP=y
-CONFIG_HAVE_KVM_IRQFD=y
-CONFIG_HAVE_KVM_IRQ_ROUTING=y
-CONFIG_HAVE_KVM_EVENTFD=y
-CONFIG_KVM_MMIO=y
-CONFIG_KVM_ASYNC_PF=y
-CONFIG_HAVE_KVM_MSI=y
-CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
-CONFIG_KVM_VFIO=y
-CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
-CONFIG_KVM_COMPAT=y
-CONFIG_HAVE_KVM_IRQ_BYPASS=y
-CONFIG_VIRTUALIZATION=y
-CONFIG_KVM=y
-CONFIG_KVM_INTEL=y
-CONFIG_KVM_AMD=y
-# CONFIG_KVM_MMU_AUDIT is not set
-CONFIG_VHOST_NET=y
-CONFIG_VHOST_VSOCK=y
-CONFIG_VHOST=y
-CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y
 CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
 #
 CONFIG_RAID6_PQ=y
+CONFIG_RAID6_PQ_BENCHMARK=y
 CONFIG_BITREVERSE=y
 CONFIG_RATIONAL=y
 CONFIG_GENERIC_STRNCPY_FROM_USER=y
@@ -5402,8 +5870,9 @@
 # CONFIG_CRC32_SLICEBY4 is not set
 # CONFIG_CRC32_SARWATE is not set
 # CONFIG_CRC32_BIT is not set
+CONFIG_CRC64=y
 CONFIG_CRC4=y
-# CONFIG_CRC7 is not set
+CONFIG_CRC7=y
 CONFIG_LIBCRC32C=y
 # CONFIG_CRC8 is not set
 CONFIG_XXHASH=y
@@ -5435,11 +5904,14 @@
 CONFIG_DECOMPRESS_LZO=y
 CONFIG_DECOMPRESS_LZ4=y
 CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=y
+CONFIG_REED_SOLOMON_DEC8=y
 CONFIG_TEXTSEARCH=y
 CONFIG_TEXTSEARCH_KMP=y
 CONFIG_TEXTSEARCH_BM=y
 CONFIG_TEXTSEARCH_FSM=y
-CONFIG_RADIX_TREE_MULTIORDER=y
+CONFIG_INTERVAL_TREE=y
+CONFIG_XARRAY_MULTI=y
 CONFIG_ASSOCIATIVE_ARRAY=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT_MAP=y
@@ -5447,12 +5919,12 @@
 CONFIG_NEED_SG_DMA_LENGTH=y
 CONFIG_NEED_DMA_MAP_STATE=y
 CONFIG_ARCH_DMA_ADDR_T_64BIT=y
-CONFIG_DMA_DIRECT_OPS=y
 CONFIG_DMA_VIRT_OPS=y
 CONFIG_SWIOTLB=y
 CONFIG_SGL_ALLOC=y
 CONFIG_IOMMU_HELPER=y
 CONFIG_CHECK_SIGNATURE=y
+# CONFIG_CPUMASK_OFFSTACK is not set
 CONFIG_CPU_RMAP=y
 CONFIG_DQL=y
 CONFIG_GLOB=y
@@ -5463,6 +5935,7 @@
 # CONFIG_DDR is not set
 CONFIG_IRQ_POLL=y
 CONFIG_MPILIB=y
+CONFIG_SIGNATURE=y
 CONFIG_OID_REGISTRY=y
 CONFIG_UCS2_STRING=y
 CONFIG_FONT_SUPPORT=y
@@ -5470,10 +5943,265 @@
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 CONFIG_SG_POOL=y
-CONFIG_ARCH_HAS_SG_CHAIN=y
 CONFIG_ARCH_HAS_PMEM_API=y
 CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE=y
 CONFIG_ARCH_HAS_UACCESS_MCSAFE=y
 CONFIG_STACKDEPOT=y
 CONFIG_SBITMAP=y
 # CONFIG_STRING_SELFTEST is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_PRINTK_CALLER=y
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
+CONFIG_CONSOLE_LOGLEVEL_QUIET=4
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+# CONFIG_DEBUG_INFO_SPLIT is not set
+# CONFIG_DEBUG_INFO_DWARF4 is not set
+# CONFIG_GDB_SCRIPTS is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+CONFIG_STACK_VALIDATION=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+CONFIG_MAGIC_SYSRQ_SERIAL=y
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+CONFIG_PAGE_EXTENSION=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_OWNER is not set
+CONFIG_PAGE_POISONING=y
+CONFIG_PAGE_POISONING_NO_SANITY=y
+# CONFIG_PAGE_POISONING_ZERO is not set
+# CONFIG_DEBUG_PAGE_REF is not set
+# CONFIG_DEBUG_RODATA_TEST is not set
+CONFIG_DEBUG_OBJECTS=y
+# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_VM_VMACACHE=y
+CONFIG_DEBUG_VM_RB=y
+CONFIG_DEBUG_VM_PGFLAGS=y
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
+CONFIG_DEBUG_VIRTUAL=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_PER_CPU_MAPS=y
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_HAVE_ARCH_KASAN=y
+CONFIG_CC_HAS_KASAN_GENERIC=y
+CONFIG_KASAN=y
+CONFIG_KASAN_GENERIC=y
+# CONFIG_KASAN_OUTLINE is not set
+CONFIG_KASAN_INLINE=y
+# CONFIG_TEST_KASAN is not set
+CONFIG_ARCH_HAS_KCOV=y
+CONFIG_CC_HAS_SANCOV_TRACE_PC=y
+CONFIG_KCOV=y
+CONFIG_KCOV_ENABLE_COMPARISONS=y
+CONFIG_KCOV_INSTRUMENT_ALL=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+CONFIG_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HARDLOCKUP_CHECK_TIMESTAMP=y
+CONFIG_HARDLOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=140
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
+CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_ON_OOPS_VALUE=1
+CONFIG_PANIC_TIMEOUT=86400
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHED_INFO=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_TIMEKEEPING is not set
+CONFIG_DEBUG_PREEMPT=y
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_PROVE_LOCKING=y
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+CONFIG_DEBUG_RWSEMS=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_LOCKDEP=y
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_WW_MUTEX_SELFTEST is not set
+CONFIG_TRACE_IRQFLAGS=y
+CONFIG_STACKTRACE=y
+# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set
+CONFIG_DEBUG_KOBJECT=y
+# CONFIG_DEBUG_KOBJECT_RELEASE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PI_LIST=y
+CONFIG_DEBUG_SG=y
+CONFIG_DEBUG_NOTIFIERS=y
+CONFIG_DEBUG_CREDENTIALS=y
+
+#
+# RCU Debugging
+#
+CONFIG_PROVE_RCU=y
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=100
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAILSLAB=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAIL_MAKE_REQUEST=y
+CONFIG_FAIL_IO_TIMEOUT=y
+CONFIG_FAIL_FUTEX=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+# CONFIG_LATENCYTOP is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_FENTRY=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_PREEMPTIRQ_TRACEPOINTS=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_PREEMPTIRQ_EVENTS is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_UPROBE_EVENTS=y
+CONFIG_BPF_EVENTS=y
+CONFIG_DYNAMIC_EVENTS=y
+CONFIG_PROBE_EVENTS=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+CONFIG_MMIOTRACE=y
+# CONFIG_HIST_TRIGGERS is not set
+# CONFIG_MMIOTRACE_TEST is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_RING_BUFFER_STARTUP_TEST is not set
+# CONFIG_PREEMPTIRQ_DELAY_TEST is not set
+# CONFIG_TRACE_EVAL_MAP_FILE is not set
+CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+# CONFIG_MEMTEST is not set
+CONFIG_BUG_ON_DATA_CORRUPTION=y
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
+# CONFIG_UBSAN is not set
+CONFIG_UBSAN_ALIGNMENT=y
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+CONFIG_DEBUG_AID_FOR_SYZBOT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_EARLY_PRINTK_USB=y
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_EARLY_PRINTK_DBGP=y
+# CONFIG_EARLY_PRINTK_EFI is not set
+# CONFIG_EARLY_PRINTK_USB_XDBC is not set
+# CONFIG_X86_PTDUMP is not set
+# CONFIG_EFI_PGT_DUMP is not set
+# CONFIG_DEBUG_WX is not set
+CONFIG_DOUBLEFAULT=y
+# CONFIG_DEBUG_TLBFLUSH is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+CONFIG_DEBUG_BOOT_PARAMS=y
+# CONFIG_CPA_DEBUG is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_ENTRY is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+CONFIG_X86_DEBUG_FPU=y
+# CONFIG_PUNIT_ATOM_DEBUG is not set
+# CONFIG_UNWINDER_ORC is not set
+CONFIG_UNWINDER_FRAME_POINTER=y
diff --git a/dashboard/config/upstream-kmsan.config b/dashboard/config/upstream-kmsan.config
index f3e78dc..aa9ae51 100644
--- a/dashboard/config/upstream-kmsan.config
+++ b/dashboard/config/upstream-kmsan.config
@@ -1,58 +1,24 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# Linux/x86 4.18.0-rc8 Kernel Configuration
-#
-
 # The following configs are added manually, preserve them.
-# See comments in upstream-kasan.config.
+# CONFIG_DEBUG_MEMORY was once added to mm tree and cause disabling of KASAN,
+# which in turn caused storm of assorted crashes after silent memory
+# corruptions. The config was reverted, but we keep it here for the case
+# it is reintroduced to kernel again.
 CONFIG_DEBUG_MEMORY=y
+# This config can be used to enable any additional temporal debugging
+# features in linux-next tree.
 CONFIG_DEBUG_AID_FOR_SYZBOT=y
 
 #
-# Compiler: gcc (GCC) 8.0.1 20180412 (experimental)
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86 4.20.0-rc7 Kernel Configuration
 #
-CONFIG_64BIT=y
-CONFIG_X86_64=y
-CONFIG_X86=y
-CONFIG_INSTRUCTION_DECODER=y
-CONFIG_OUTPUT_FORMAT="elf64-x86-64"
-CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_MMU=y
-CONFIG_ARCH_MMAP_RND_BITS_MIN=28
-CONFIG_ARCH_MMAP_RND_BITS_MAX=32
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_GENERIC_BUG=y
-CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_HAS_CPU_RELAX=y
-CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
-CONFIG_ARCH_HAS_FILTER_PGPROT=y
-CONFIG_HAVE_SETUP_PER_CPU_AREA=y
-CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
-CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
-CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
-CONFIG_ZONE_DMA32=y
-CONFIG_AUDIT_ARCH=y
-CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
-CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
-CONFIG_HAVE_INTEL_TXT=y
-CONFIG_X86_64_SMP=y
-CONFIG_ARCH_SUPPORTS_UPROBES=y
-CONFIG_FIX_EARLYCON_MEM=y
-CONFIG_PGTABLE_LEVELS=4
-CONFIG_CC_IS_GCC=y
-CONFIG_GCC_VERSION=80001
-CONFIG_CLANG_VERSION=0
+
+#
+# Compiler: clang version 8.0.0 (trunk 339414)
+#
+CONFIG_GCC_VERSION=0
+CONFIG_CC_IS_CLANG=y
+CONFIG_CLANG_VERSION=80000
 CONFIG_IRQ_WORK=y
 CONFIG_BUILDTIME_EXTABLE_SORT=y
 CONFIG_THREAD_INFO_IN_TASK=y
@@ -64,6 +30,7 @@
 # CONFIG_COMPILE_TEST is not set
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_BUILD_SALT=""
 CONFIG_HAVE_KERNEL_GZIP=y
 CONFIG_HAVE_KERNEL_BZIP2=y
 CONFIG_HAVE_KERNEL_LZMA=y
@@ -109,6 +76,7 @@
 # CONFIG_GENERIC_IRQ_DEBUGFS is not set
 CONFIG_CLOCKSOURCE_WATCHDOG=y
 CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
 CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
@@ -126,20 +94,26 @@
 # CONFIG_NO_HZ_FULL is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
 
 #
 # CPU/Task time and stats accounting
 #
 CONFIG_TICK_CPU_ACCOUNTING=y
 # CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
-# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_SCHED_AVG_IRQ=y
 CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_TASKSTATS=y
 CONFIG_TASK_DELAY_ACCT=y
 CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
-CONFIG_CPU_ISOLATION=y
+CONFIG_PSI=y
+# CONFIG_PSI_DEFAULT_DISABLED is not set
+# CONFIG_CPU_ISOLATION is not set
 
 #
 # RCU Subsystem
@@ -150,7 +124,9 @@
 CONFIG_TREE_SRCU=y
 CONFIG_RCU_STALL_COMMON=y
 CONFIG_RCU_NEED_SEGCBLIST=y
-# CONFIG_IKCONFIG is not set
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
 CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
@@ -158,18 +134,20 @@
 CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
 CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
 CONFIG_ARCH_SUPPORTS_INT128=y
-# CONFIG_NUMA_BALANCING is not set
+CONFIG_NUMA_BALANCING=y
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
 CONFIG_CGROUPS=y
 CONFIG_PAGE_COUNTER=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_MEMCG_SWAP_ENABLED=y
+CONFIG_MEMCG_KMEM=y
 CONFIG_BLK_CGROUP=y
-# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_DEBUG_BLK_CGROUP=y
 CONFIG_CGROUP_WRITEBACK=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_CFS_BANDWIDTH is not set
+CONFIG_CFS_BANDWIDTH=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
@@ -189,6 +167,7 @@
 CONFIG_USER_NS=y
 CONFIG_PID_NS=y
 CONFIG_NET_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
 # CONFIG_SCHED_AUTOGROUP is not set
 # CONFIG_SYSFS_DEPRECATED is not set
 CONFIG_RELAY=y
@@ -232,7 +211,6 @@
 CONFIG_AIO=y
 CONFIG_ADVISE_SYSCALLS=y
 CONFIG_MEMBARRIER=y
-CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
@@ -266,189 +244,47 @@
 CONFIG_SYSTEM_DATA_VERIFICATION=y
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-CONFIG_CRASH_CORE=y
-CONFIG_KEXEC_CORE=y
-# CONFIG_OPROFILE is not set
-CONFIG_HAVE_OPROFILE=y
-CONFIG_OPROFILE_NMI_TIMER=y
-# CONFIG_KPROBES is not set
-CONFIG_JUMP_LABEL=y
-# CONFIG_STATIC_KEYS_SELFTEST is not set
-CONFIG_UPROBES=y
-CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
-CONFIG_ARCH_USE_BUILTIN_BSWAP=y
-CONFIG_HAVE_IOREMAP_PROT=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_OPTPROBES=y
-CONFIG_HAVE_KPROBES_ON_FTRACE=y
-CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
-CONFIG_HAVE_NMI=y
-CONFIG_HAVE_ARCH_TRACEHOOK=y
-CONFIG_HAVE_DMA_CONTIGUOUS=y
-CONFIG_GENERIC_SMP_IDLE_THREAD=y
-CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
-CONFIG_ARCH_HAS_SET_MEMORY=y
-CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
-CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_RSEQ=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_HW_BREAKPOINT=y
-CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
-CONFIG_HAVE_USER_RETURN_NOTIFIER=y
-CONFIG_HAVE_PERF_EVENTS_NMI=y
-CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
-CONFIG_HAVE_PERF_REGS=y
-CONFIG_HAVE_PERF_USER_STACK_DUMP=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_RCU_TABLE_FREE=y
-CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
-CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
-CONFIG_HAVE_CMPXCHG_LOCAL=y
-CONFIG_HAVE_CMPXCHG_DOUBLE=y
-CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
-CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
-CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
-CONFIG_SECCOMP_FILTER=y
-CONFIG_PLUGIN_HOSTCC=""
-CONFIG_HAVE_GCC_PLUGINS=y
-CONFIG_HAVE_STACKPROTECTOR=y
-CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
-# CONFIG_STACKPROTECTOR is not set
-CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
-CONFIG_HAVE_CONTEXT_TRACKING=y
-CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
-CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
-CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
-CONFIG_HAVE_ARCH_HUGE_VMAP=y
-CONFIG_HAVE_ARCH_SOFT_DIRTY=y
-CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
-CONFIG_MODULES_USE_ELF_RELA=y
-CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
-CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
-CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
-CONFIG_HAVE_EXIT_THREAD=y
-CONFIG_ARCH_MMAP_RND_BITS=28
-CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
-CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
-CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
-CONFIG_HAVE_COPY_THREAD_TLS=y
-CONFIG_HAVE_STACK_VALIDATION=y
-CONFIG_HAVE_RELIABLE_STACKTRACE=y
-CONFIG_OLD_SIGSUSPEND3=y
-CONFIG_COMPAT_OLD_SIGACTION=y
-CONFIG_COMPAT_32BIT_TIME=y
-CONFIG_HAVE_ARCH_VMAP_STACK=y
-# CONFIG_VMAP_STACK is not set
-CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
-CONFIG_STRICT_MODULE_RWX=y
-CONFIG_ARCH_HAS_REFCOUNT=y
-# CONFIG_REFCOUNT_FULL is not set
-
-#
-# GCOV-based kernel profiling
-#
-# CONFIG_GCOV_KERNEL is not set
-CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_MODULE_SIG is not set
-# CONFIG_MODULE_COMPRESS is not set
-# CONFIG_TRIM_UNUSED_KSYMS is not set
-CONFIG_MODULES_TREE_LOOKUP=y
-CONFIG_BLOCK=y
-CONFIG_BLK_SCSI_REQUEST=y
-CONFIG_BLK_DEV_BSG=y
-CONFIG_BLK_DEV_BSGLIB=y
-CONFIG_BLK_DEV_INTEGRITY=y
-CONFIG_BLK_DEV_ZONED=y
-CONFIG_BLK_DEV_THROTTLING=y
-# CONFIG_BLK_DEV_THROTTLING_LOW is not set
-CONFIG_BLK_CMDLINE_PARSER=y
-CONFIG_BLK_WBT=y
-# CONFIG_BLK_WBT_SQ is not set
-CONFIG_BLK_WBT_MQ=y
-# CONFIG_BLK_DEBUG_FS is not set
-# CONFIG_BLK_SED_OPAL is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_ACORN_PARTITION=y
-CONFIG_ACORN_PARTITION_CUMANA=y
-CONFIG_ACORN_PARTITION_EESOX=y
-CONFIG_ACORN_PARTITION_ICS=y
-CONFIG_ACORN_PARTITION_ADFS=y
-CONFIG_ACORN_PARTITION_POWERTEC=y
-CONFIG_ACORN_PARTITION_RISCIX=y
-CONFIG_AIX_PARTITION=y
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-CONFIG_ATARI_PARTITION=y
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_LDM_PARTITION=y
-# CONFIG_LDM_DEBUG is not set
-CONFIG_SGI_PARTITION=y
-CONFIG_ULTRIX_PARTITION=y
-CONFIG_SUN_PARTITION=y
-CONFIG_KARMA_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_SYSV68_PARTITION=y
-CONFIG_CMDLINE_PARTITION=y
-CONFIG_BLOCK_COMPAT=y
-CONFIG_BLK_MQ_PCI=y
-CONFIG_BLK_MQ_VIRTIO=y
-CONFIG_BLK_MQ_RDMA=y
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_CFQ_GROUP_IOSCHED=y
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_MQ_IOSCHED_DEADLINE=y
-CONFIG_MQ_IOSCHED_KYBER=y
-CONFIG_IOSCHED_BFQ=y
-CONFIG_BFQ_GROUP_IOSCHED=y
-CONFIG_ASN1=y
-CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
-CONFIG_INLINE_READ_UNLOCK=y
-CONFIG_INLINE_READ_UNLOCK_IRQ=y
-CONFIG_INLINE_WRITE_UNLOCK=y
-CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
-CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
-CONFIG_MUTEX_SPIN_ON_OWNER=y
-CONFIG_RWSEM_SPIN_ON_OWNER=y
-CONFIG_LOCK_SPIN_ON_OWNER=y
-CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
-CONFIG_QUEUED_SPINLOCKS=y
-CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
-CONFIG_QUEUED_RWLOCKS=y
-CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
-CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_64BIT=y
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=28
+CONFIG_ARCH_MMAP_RND_BITS_MAX=32
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_FILTER_PGPROT=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ZONE_DMA32=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_HAVE_INTEL_TXT=y
+CONFIG_X86_64_SMP=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_PGTABLE_LEVELS=4
 CONFIG_CC_HAS_SANE_STACKPROTECTOR=y
-CONFIG_FREEZER=y
 
 #
 # Processor type and features
@@ -477,22 +313,25 @@
 CONFIG_HYPERVISOR_GUEST=y
 # CONFIG_PARAVIRT is not set
 # CONFIG_JAILHOUSE_GUEST is not set
-CONFIG_NO_BOOTMEM=y
 # CONFIG_MK8 is not set
 # CONFIG_MPSC is not set
-# CONFIG_MCORE2 is not set
+CONFIG_MCORE2=y
 # CONFIG_MATOM is not set
-CONFIG_GENERIC_CPU=y
+# CONFIG_GENERIC_CPU is not set
 CONFIG_X86_INTERNODE_CACHE_SHIFT=6
 CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_P6_NOP=y
 CONFIG_X86_TSC=y
 CONFIG_X86_CMPXCHG64=y
 CONFIG_X86_CMOV=y
 CONFIG_X86_MINIMUM_CPU_FAMILY=64
 CONFIG_X86_DEBUGCTLMSR=y
-# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_PROCESSOR_SELECT=y
 CONFIG_CPU_SUP_INTEL=y
 CONFIG_CPU_SUP_AMD=y
+# CONFIG_CPU_SUP_HYGON is not set
 CONFIG_CPU_SUP_CENTAUR=y
 CONFIG_HPET_TIMER=y
 CONFIG_HPET_EMULATE_RTC=y
@@ -508,9 +347,6 @@
 CONFIG_SCHED_SMT=y
 CONFIG_SCHED_MC=y
 CONFIG_SCHED_MC_PRIO=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
 CONFIG_X86_LOCAL_APIC=y
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
@@ -519,7 +355,7 @@
 CONFIG_X86_MCE_INTEL=y
 CONFIG_X86_MCE_AMD=y
 CONFIG_X86_MCE_THRESHOLD=y
-# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_MCE_INJECT=y
 CONFIG_X86_THERMAL_VECTOR=y
 
 #
@@ -541,69 +377,20 @@
 CONFIG_X86_CPUID=y
 # CONFIG_X86_5LEVEL is not set
 CONFIG_X86_DIRECT_GBPAGES=y
+# CONFIG_X86_CPA_STATISTICS is not set
 CONFIG_ARCH_HAS_MEM_ENCRYPT=y
 # CONFIG_AMD_MEM_ENCRYPT is not set
 CONFIG_NUMA=y
 CONFIG_AMD_NUMA=y
 CONFIG_X86_64_ACPI_NUMA=y
 CONFIG_NODES_SPAN_OTHER_NODES=y
-# CONFIG_NUMA_EMU is not set
+CONFIG_NUMA_EMU=y
 CONFIG_NODES_SHIFT=6
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_PROC_KCORE_TEXT=y
 CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_SPARSEMEM_MANUAL=y
-CONFIG_SPARSEMEM=y
-CONFIG_NEED_MULTIPLE_NODES=y
-CONFIG_HAVE_MEMORY_PRESENT=y
-CONFIG_SPARSEMEM_EXTREME=y
-CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
-CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
-CONFIG_SPARSEMEM_VMEMMAP=y
-CONFIG_HAVE_MEMBLOCK=y
-CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
-CONFIG_HAVE_GENERIC_GUP=y
-CONFIG_ARCH_DISCARD_MEMBLOCK=y
-# CONFIG_MEMORY_HOTPLUG is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
-CONFIG_COMPACTION=y
-CONFIG_MIGRATION=y
-CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
-CONFIG_ARCH_ENABLE_THP_MIGRATION=y
-CONFIG_PHYS_ADDR_T_64BIT=y
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_MMU_NOTIFIER=y
-CONFIG_KSM=y
-CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
-CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
-# CONFIG_MEMORY_FAILURE is not set
-CONFIG_TRANSPARENT_HUGEPAGE=y
-CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
-# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
-CONFIG_ARCH_WANTS_THP_SWAP=y
-CONFIG_THP_SWAP=y
-CONFIG_TRANSPARENT_HUGE_PAGECACHE=y
-# CONFIG_CLEANCACHE is not set
-# CONFIG_FRONTSWAP is not set
-# CONFIG_CMA is not set
-# CONFIG_MEM_SOFT_DIRTY is not set
-# CONFIG_ZPOOL is not set
-# CONFIG_ZBUD is not set
-# CONFIG_ZSMALLOC is not set
-CONFIG_GENERIC_EARLY_IOREMAP=y
-# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
-# CONFIG_IDLE_PAGE_TRACKING is not set
-CONFIG_ARCH_HAS_ZONE_DEVICE=y
-CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
-CONFIG_ARCH_HAS_PKEYS=y
-# CONFIG_PERCPU_STATS is not set
-# CONFIG_GUP_BENCHMARK is not set
-CONFIG_ARCH_HAS_PTE_SPECIAL=y
 # CONFIG_X86_PMEM_LEGACY is not set
 CONFIG_X86_CHECK_BIOS_CORRUPTION=y
 CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
@@ -616,17 +403,17 @@
 CONFIG_ARCH_USES_PG_UNCACHED=y
 CONFIG_ARCH_RANDOM=y
 CONFIG_X86_SMAP=y
-CONFIG_X86_INTEL_UMIP=y
-CONFIG_X86_INTEL_MPX=y
+# CONFIG_X86_INTEL_UMIP is not set
+# CONFIG_X86_INTEL_MPX is not set
 CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y
 CONFIG_EFI=y
 # CONFIG_EFI_STUB is not set
 CONFIG_SECCOMP=y
-# CONFIG_HZ_100 is not set
+CONFIG_HZ_100=y
 # CONFIG_HZ_250 is not set
 # CONFIG_HZ_300 is not set
-CONFIG_HZ_1000=y
-CONFIG_HZ=1000
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
 CONFIG_SCHED_HRTICK=y
 CONFIG_KEXEC=y
 # CONFIG_KEXEC_FILE is not set
@@ -634,7 +421,6 @@
 # CONFIG_KEXEC_JUMP is not set
 CONFIG_PHYSICAL_START=0x1000000
 CONFIG_RELOCATABLE=y
-# CONFIG_RANDOMIZE_BASE is not set
 CONFIG_PHYSICAL_ALIGN=0x200000
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set
@@ -648,6 +434,9 @@
 CONFIG_ARCH_HAS_ADD_PAGES=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_USE_PERCPU_NUMA_NODE_ID=y
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION=y
+CONFIG_ARCH_ENABLE_THP_MIGRATION=y
 
 #
 # Power management and ACPI options
@@ -664,15 +453,21 @@
 # CONFIG_PM_AUTOSLEEP is not set
 # CONFIG_PM_WAKELOCKS is not set
 CONFIG_PM=y
-# CONFIG_PM_DEBUG is not set
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_PM_SLEEP_DEBUG=y
+CONFIG_PM_TRACE=y
+CONFIG_PM_TRACE_RTC=y
 CONFIG_PM_CLK=y
 # CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_ARCH_SUPPORTS_ACPI=y
 CONFIG_ACPI=y
 CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
 CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
 CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
 # CONFIG_ACPI_DEBUGGER is not set
-# CONFIG_ACPI_SPCR_TABLE is not set
+CONFIG_ACPI_SPCR_TABLE=y
 CONFIG_ACPI_LPIT=y
 CONFIG_ACPI_SLEEP=y
 # CONFIG_ACPI_PROCFS_POWER is not set
@@ -758,7 +553,7 @@
 CONFIG_CPU_IDLE=y
 # CONFIG_CPU_IDLE_GOV_LADDER is not set
 CONFIG_CPU_IDLE_GOV_MENU=y
-# CONFIG_INTEL_IDLE is not set
+CONFIG_INTEL_IDLE=y
 
 #
 # Bus options (PCI etc.)
@@ -770,7 +565,7 @@
 CONFIG_MMCONF_FAM10H=y
 # CONFIG_PCI_CNB20LE_QUIRK is not set
 CONFIG_PCIEPORTBUS=y
-# CONFIG_HOTPLUG_PCI_PCIE is not set
+CONFIG_HOTPLUG_PCI_PCIE=y
 CONFIG_PCIEAER=y
 # CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIE_ECRC is not set
@@ -851,7 +646,264 @@
 # CONFIG_X86_SYSFB is not set
 
 #
-# Executable file formats / Emulations
+# Binary Emulations
+#
+CONFIG_IA32_EMULATION=y
+CONFIG_IA32_AOUT=y
+CONFIG_X86_X32=y
+CONFIG_COMPAT_32=y
+CONFIG_COMPAT=y
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_X86_DEV_DMA_OPS=y
+CONFIG_HAVE_GENERIC_GUP=y
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_DMIID=y
+# CONFIG_DMI_SYSFS is not set
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+# CONFIG_FW_CFG_SYSFS is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# EFI (Extensible Firmware Interface) Support
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_ESRT=y
+CONFIG_EFI_RUNTIME_MAP=y
+# CONFIG_EFI_FAKE_MEMMAP is not set
+CONFIG_EFI_RUNTIME_WRAPPERS=y
+# CONFIG_EFI_BOOTLOADER_CONTROL is not set
+# CONFIG_EFI_CAPSULE_LOADER is not set
+# CONFIG_EFI_TEST is not set
+
+#
+# Tegra firmware driver
+#
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_KVM_IRQCHIP=y
+CONFIG_HAVE_KVM_IRQFD=y
+CONFIG_HAVE_KVM_IRQ_ROUTING=y
+CONFIG_HAVE_KVM_EVENTFD=y
+CONFIG_KVM_MMIO=y
+CONFIG_KVM_ASYNC_PF=y
+CONFIG_HAVE_KVM_MSI=y
+CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
+CONFIG_KVM_VFIO=y
+CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
+CONFIG_KVM_COMPAT=y
+CONFIG_HAVE_KVM_IRQ_BYPASS=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
+CONFIG_KVM_INTEL=y
+CONFIG_KVM_AMD=y
+# CONFIG_KVM_MMU_AUDIT is not set
+CONFIG_VHOST_NET=y
+CONFIG_VHOST_VSOCK=y
+CONFIG_VHOST=y
+CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y
+
+#
+# General architecture-dependent options
+#
+CONFIG_CRASH_CORE=y
+CONFIG_KEXEC_CORE=y
+CONFIG_HOTPLUG_SMT=y
+# CONFIG_OPROFILE is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+CONFIG_UPROBES=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
+CONFIG_ARCH_HAS_SET_MEMORY=y
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_RSEQ=y
+CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_ARCH_STACKLEAK=y
+CONFIG_HAVE_STACKPROTECTOR=y
+CONFIG_CC_HAS_STACKPROTECTOR_NONE=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD=y
+CONFIG_HAVE_ARCH_HUGE_VMAP=y
+CONFIG_HAVE_ARCH_SOFT_DIRTY=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS=28
+CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=8
+CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES=y
+CONFIG_HAVE_COPY_THREAD_TLS=y
+CONFIG_HAVE_STACK_VALIDATION=y
+CONFIG_HAVE_RELIABLE_STACKTRACE=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_COMPAT_OLD_SIGACTION=y
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_HAVE_ARCH_VMAP_STACK=y
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
+CONFIG_STRICT_KERNEL_RWX=y
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
+CONFIG_STRICT_MODULE_RWX=y
+CONFIG_ARCH_HAS_REFCOUNT=y
+CONFIG_REFCOUNT_FULL=y
+CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GCC_PLUGINS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_BLOCK=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_ZONED=y
+CONFIG_BLK_DEV_THROTTLING=y
+# CONFIG_BLK_DEV_THROTTLING_LOW is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_CGROUP_IOLATENCY=y
+# CONFIG_BLK_WBT_SQ is not set
+CONFIG_BLK_WBT_MQ=y
+# CONFIG_BLK_DEBUG_FS is not set
+# CONFIG_BLK_SED_OPAL is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_CUMANA=y
+CONFIG_ACORN_PARTITION_EESOX=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_ADFS=y
+CONFIG_ACORN_PARTITION_POWERTEC=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_AIX_PARTITION=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_CMDLINE_PARTITION=y
+CONFIG_BLOCK_COMPAT=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_MQ_VIRTIO=y
+CONFIG_BLK_MQ_RDMA=y
+CONFIG_BLK_PM=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CFQ_GROUP_IOSCHED is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_MQ_IOSCHED_DEADLINE=y
+CONFIG_MQ_IOSCHED_KYBER=y
+CONFIG_IOSCHED_BFQ=y
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_PADATA=y
+CONFIG_ASN1=y
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y
+CONFIG_FREEZER=y
+
+#
+# Executable file formats
 #
 CONFIG_BINFMT_ELF=y
 CONFIG_COMPAT_BINFMT_ELF=y
@@ -860,14 +912,65 @@
 CONFIG_BINFMT_SCRIPT=y
 CONFIG_BINFMT_MISC=y
 CONFIG_COREDUMP=y
-CONFIG_IA32_EMULATION=y
-CONFIG_IA32_AOUT=y
-# CONFIG_X86_X32 is not set
-CONFIG_COMPAT_32=y
-CONFIG_COMPAT=y
-CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
-CONFIG_SYSVIPC_COMPAT=y
-CONFIG_X86_DEV_DMA_OPS=y
+
+#
+# Memory Management options
+#
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_MEMORY_ISOLATION=y
+# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MEMORY_BALLOON=y
+CONFIG_BALLOON_COMPACTION=y
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+# CONFIG_MEMORY_FAILURE is not set
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
+# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_THP_SWAP=y
+CONFIG_TRANSPARENT_HUGE_PAGECACHE=y
+# CONFIG_CLEANCACHE is not set
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+CONFIG_CMA_AREAS=7
+CONFIG_MEM_SOFT_DIRTY=y
+CONFIG_ZSWAP=y
+CONFIG_ZPOOL=y
+CONFIG_ZBUD=y
+# CONFIG_Z3FOLD is not set
+CONFIG_ZSMALLOC=y
+# CONFIG_PGTABLE_MAPPING is not set
+# CONFIG_ZSMALLOC_STAT is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set
+CONFIG_IDLE_PAGE_TRACKING=y
+CONFIG_ARCH_HAS_ZONE_DEVICE=y
+CONFIG_FRAME_VECTOR=y
+CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y
+CONFIG_ARCH_HAS_PKEYS=y
+CONFIG_PERCPU_STATS=y
+# CONFIG_GUP_BENCHMARK is not set
+CONFIG_ARCH_HAS_PTE_SPECIAL=y
 CONFIG_NET=y
 CONFIG_COMPAT_NETLINK_MESSAGES=y
 CONFIG_NET_INGRESS=y
@@ -886,6 +989,7 @@
 CONFIG_XFRM_OFFLOAD=y
 CONFIG_XFRM_ALGO=y
 CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
 CONFIG_XFRM_SUB_POLICY=y
 CONFIG_XFRM_MIGRATE=y
 CONFIG_XFRM_STATISTICS=y
@@ -893,12 +997,12 @@
 CONFIG_NET_KEY=y
 CONFIG_NET_KEY_MIGRATE=y
 CONFIG_SMC=y
-# CONFIG_SMC_DIAG is not set
+CONFIG_SMC_DIAG=y
 CONFIG_XDP_SOCKETS=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
-# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_FIB_TRIE_STATS=y
 CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_MULTIPATH=y
 CONFIG_IP_ROUTE_VERBOSE=y
@@ -935,7 +1039,7 @@
 CONFIG_INET_TCP_DIAG=y
 CONFIG_INET_UDP_DIAG=y
 CONFIG_INET_RAW_DIAG=y
-# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_INET_DIAG_DESTROY=y
 CONFIG_TCP_CONG_ADVANCED=y
 # CONFIG_TCP_CONG_BIC is not set
 CONFIG_TCP_CONG_CUBIC=y
@@ -1012,6 +1116,7 @@
 CONFIG_NETFILTER_NETLINK_ACCT=y
 CONFIG_NETFILTER_NETLINK_QUEUE=y
 CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NETFILTER_NETLINK_OSF=y
 CONFIG_NF_CONNTRACK=y
 CONFIG_NF_LOG_COMMON=y
 CONFIG_NF_LOG_NETDEV=y
@@ -1055,7 +1160,6 @@
 CONFIG_NF_NAT_TFTP=y
 CONFIG_NF_NAT_REDIRECT=y
 CONFIG_NETFILTER_SYNPROXY=y
-CONFIG_NF_OSF=y
 CONFIG_NF_TABLES=y
 CONFIG_NF_TABLES_SET=y
 CONFIG_NF_TABLES_INET=y
@@ -1070,6 +1174,7 @@
 CONFIG_NFT_MASQ=y
 CONFIG_NFT_REDIR=y
 CONFIG_NFT_NAT=y
+CONFIG_NFT_TUNNEL=y
 CONFIG_NFT_OBJREF=y
 CONFIG_NFT_QUEUE=y
 CONFIG_NFT_QUOTA=y
@@ -1079,7 +1184,10 @@
 CONFIG_NFT_HASH=y
 CONFIG_NFT_FIB=y
 CONFIG_NFT_FIB_INET=y
+CONFIG_NFT_XFRM=y
 CONFIG_NFT_SOCKET=y
+CONFIG_NFT_OSF=y
+CONFIG_NFT_TPROXY=y
 CONFIG_NF_DUP_NETDEV=y
 CONFIG_NFT_DUP_NETDEV=y
 CONFIG_NFT_FWD_NETDEV=y
@@ -1245,7 +1353,6 @@
 # IP: Netfilter Configuration
 #
 CONFIG_NF_DEFRAG_IPV4=y
-CONFIG_NF_CONNTRACK_IPV4=y
 CONFIG_NF_SOCKET_IPV4=y
 CONFIG_NF_TPROXY_IPV4=y
 CONFIG_NF_TABLES_IPV4=y
@@ -1260,8 +1367,8 @@
 CONFIG_NF_LOG_IPV4=y
 CONFIG_NF_REJECT_IPV4=y
 CONFIG_NF_NAT_IPV4=y
-CONFIG_NFT_CHAIN_NAT_IPV4=y
 CONFIG_NF_NAT_MASQUERADE_IPV4=y
+CONFIG_NFT_CHAIN_NAT_IPV4=y
 CONFIG_NFT_MASQ_IPV4=y
 CONFIG_NFT_REDIR_IPV4=y
 CONFIG_NF_NAT_SNMP_BASIC=y
@@ -1293,8 +1400,6 @@
 #
 # IPv6: Netfilter Configuration
 #
-CONFIG_NF_DEFRAG_IPV6=y
-CONFIG_NF_CONNTRACK_IPV6=y
 CONFIG_NF_SOCKET_IPV6=y
 CONFIG_NF_TPROXY_IPV6=y
 CONFIG_NF_TABLES_IPV6=y
@@ -1332,6 +1437,7 @@
 CONFIG_IP6_NF_NAT=y
 CONFIG_IP6_NF_TARGET_MASQUERADE=y
 CONFIG_IP6_NF_TARGET_NPT=y
+CONFIG_NF_DEFRAG_IPV6=y
 CONFIG_NF_TABLES_BRIDGE=y
 CONFIG_NFT_BRIDGE_REJECT=y
 CONFIG_NF_LOG_BRIDGE=y
@@ -1356,8 +1462,7 @@
 CONFIG_BRIDGE_EBT_SNAT=y
 CONFIG_BRIDGE_EBT_LOG=y
 CONFIG_BRIDGE_EBT_NFLOG=y
-CONFIG_BPFILTER=y
-CONFIG_BPFILTER_UMH=y
+# CONFIG_BPFILTER is not set
 CONFIG_IP_DCCP=y
 CONFIG_INET_DCCP_DIAG=y
 
@@ -1398,7 +1503,9 @@
 # CONFIG_ATM_BR2684_IPFILTER is not set
 CONFIG_L2TP=y
 # CONFIG_L2TP_DEBUGFS is not set
-# CONFIG_L2TP_V3 is not set
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
 CONFIG_STP=y
 CONFIG_GARP=y
 CONFIG_MRP=y
@@ -1415,8 +1522,8 @@
 CONFIG_LLC=y
 CONFIG_LLC2=y
 # CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
+CONFIG_X25=y
+CONFIG_LAPB=y
 # CONFIG_PHONET is not set
 CONFIG_6LOWPAN=y
 # CONFIG_6LOWPAN_DEBUGFS is not set
@@ -1456,15 +1563,19 @@
 CONFIG_NET_SCH_TEQL=y
 CONFIG_NET_SCH_TBF=y
 CONFIG_NET_SCH_CBS=y
+CONFIG_NET_SCH_ETF=y
+CONFIG_NET_SCH_TAPRIO=y
 CONFIG_NET_SCH_GRED=y
 CONFIG_NET_SCH_DSMARK=y
 CONFIG_NET_SCH_NETEM=y
 CONFIG_NET_SCH_DRR=y
 CONFIG_NET_SCH_MQPRIO=y
+CONFIG_NET_SCH_SKBPRIO=y
 CONFIG_NET_SCH_CHOKE=y
 CONFIG_NET_SCH_QFQ=y
 CONFIG_NET_SCH_CODEL=y
 CONFIG_NET_SCH_FQ_CODEL=y
+CONFIG_NET_SCH_CAKE=y
 CONFIG_NET_SCH_FQ=y
 CONFIG_NET_SCH_HHF=y
 CONFIG_NET_SCH_PIE=y
@@ -1487,15 +1598,15 @@
 CONFIG_NET_CLS_ROUTE4=y
 CONFIG_NET_CLS_FW=y
 CONFIG_NET_CLS_U32=y
-# CONFIG_CLS_U32_PERF is not set
+CONFIG_CLS_U32_PERF=y
 CONFIG_CLS_U32_MARK=y
 CONFIG_NET_CLS_RSVP=y
 CONFIG_NET_CLS_RSVP6=y
 CONFIG_NET_CLS_FLOW=y
-# CONFIG_NET_CLS_CGROUP is not set
+CONFIG_NET_CLS_CGROUP=y
 CONFIG_NET_CLS_BPF=y
 CONFIG_NET_CLS_FLOWER=y
-# CONFIG_NET_CLS_MATCHALL is not set
+CONFIG_NET_CLS_MATCHALL=y
 CONFIG_NET_EMATCH=y
 CONFIG_NET_EMATCH_STACK=32
 CONFIG_NET_EMATCH_CMP=y
@@ -1503,12 +1614,13 @@
 CONFIG_NET_EMATCH_U32=y
 CONFIG_NET_EMATCH_META=y
 CONFIG_NET_EMATCH_TEXT=y
-# CONFIG_NET_EMATCH_CANID is not set
+CONFIG_NET_EMATCH_CANID=y
 CONFIG_NET_EMATCH_IPSET=y
 CONFIG_NET_EMATCH_IPT=y
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
-# CONFIG_NET_ACT_GACT is not set
+CONFIG_NET_ACT_GACT=y
+CONFIG_GACT_PROB=y
 CONFIG_NET_ACT_MIRRED=y
 CONFIG_NET_ACT_SAMPLE=y
 CONFIG_NET_ACT_IPT=y
@@ -1523,14 +1635,21 @@
 CONFIG_NET_ACT_SKBMOD=y
 CONFIG_NET_ACT_IFE=y
 CONFIG_NET_ACT_TUNNEL_KEY=y
-# CONFIG_NET_IFE_SKBMARK is not set
-# CONFIG_NET_IFE_SKBPRIO is not set
-# CONFIG_NET_IFE_SKBTCINDEX is not set
-# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_IFE_SKBMARK=y
+CONFIG_NET_IFE_SKBPRIO=y
+CONFIG_NET_IFE_SKBTCINDEX=y
+CONFIG_NET_CLS_IND=y
 CONFIG_NET_SCH_FIFO=y
 CONFIG_DCB=y
 CONFIG_DNS_RESOLVER=y
-# CONFIG_BATMAN_ADV is not set
+CONFIG_BATMAN_ADV=y
+CONFIG_BATMAN_ADV_BATMAN_V=y
+CONFIG_BATMAN_ADV_BLA=y
+CONFIG_BATMAN_ADV_DAT=y
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_BATMAN_ADV_MCAST=y
+# CONFIG_BATMAN_ADV_DEBUGFS is not set
+# CONFIG_BATMAN_ADV_TRACING is not set
 CONFIG_OPENVSWITCH=y
 CONFIG_OPENVSWITCH_GRE=y
 CONFIG_OPENVSWITCH_VXLAN=y
@@ -1539,16 +1658,17 @@
 CONFIG_VSOCKETS_DIAG=y
 CONFIG_VIRTIO_VSOCKETS=y
 CONFIG_VIRTIO_VSOCKETS_COMMON=y
-# CONFIG_NETLINK_DIAG is not set
+CONFIG_NETLINK_DIAG=y
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=y
 CONFIG_MPLS_ROUTING=y
 CONFIG_MPLS_IPTUNNEL=y
 CONFIG_NET_NSH=y
-# CONFIG_HSR is not set
+CONFIG_HSR=y
 CONFIG_NET_SWITCHDEV=y
 CONFIG_NET_L3_MASTER_DEV=y
 CONFIG_NET_NCSI=y
+# CONFIG_NCSI_OEM_CMD_GET_MAC is not set
 CONFIG_RPS=y
 CONFIG_RFS_ACCEL=y
 CONFIG_XPS=y
@@ -1564,13 +1684,26 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_NET_DROP_MONITOR is not set
+CONFIG_NET_DROP_MONITOR=y
 CONFIG_HAMRADIO=y
 
 #
 # Packet Radio protocols
 #
-# CONFIG_AX25 is not set
+CONFIG_AX25=y
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=y
+CONFIG_ROSE=y
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=y
+CONFIG_6PACK=y
+CONFIG_BPQETHER=y
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_YAM is not set
 CONFIG_CAN=y
 CONFIG_CAN_RAW=y
 CONFIG_CAN_BCM=y
@@ -1584,7 +1717,6 @@
 CONFIG_CAN_SLCAN=y
 CONFIG_CAN_DEV=y
 CONFIG_CAN_CALC_BITTIMING=y
-# CONFIG_CAN_LEDS is not set
 # CONFIG_CAN_C_CAN is not set
 # CONFIG_CAN_CC770 is not set
 CONFIG_CAN_IFI_CANFD=y
@@ -1594,15 +1726,22 @@
 # CONFIG_CAN_SOFTING is not set
 
 #
+# CAN SPI interfaces
+#
+# CONFIG_CAN_HI311X is not set
+# CONFIG_CAN_MCP251X is not set
+