From 179b683cf16f41a2b4c8e2aa0a0f7dd343e43454 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 16:49:07 -0500 Subject: [PATCH 01/15] kmeta: define linux config fragments for xen Create kernel configuration fragment for common Xen configurations applied to kernels built to run in Xen VM. This should cover dom0, pv, pvh and hvm guests and most if not all paravirtualized backend/frontend modules. Signed-off-by: Eric Chanudet --- .../openxt-kmeta/features/xen/xen-balloon.cfg | 2 ++ .../openxt-kmeta/features/xen/xen-balloon.scc | 5 +++++ .../openxt-kmeta/features/xen/xen-blk-be.cfg | 2 ++ .../openxt-kmeta/features/xen/xen-blk-be.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-blk-fe.cfg | 1 + .../openxt-kmeta/features/xen/xen-blk-fe.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-debugfs.cfg | 1 + .../openxt-kmeta/features/xen/xen-debugfs.scc | 4 ++++ .../files/openxt-kmeta/features/xen/xen-dom0.cfg | 3 +++ .../files/openxt-kmeta/features/xen/xen-dom0.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-net-be.cfg | 2 ++ .../openxt-kmeta/features/xen/xen-net-be.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-net-fe.cfg | 2 ++ .../openxt-kmeta/features/xen/xen-net-fe.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-pci-be.cfg | 3 +++ .../openxt-kmeta/features/xen/xen-pci-be.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-pci-fe.cfg | 2 ++ .../openxt-kmeta/features/xen/xen-pci-fe.scc | 5 +++++ .../files/openxt-kmeta/features/xen/xen-pv.cfg | 4 ++++ .../files/openxt-kmeta/features/xen/xen-pv.scc | 4 ++++ .../files/openxt-kmeta/features/xen/xen-pvh.cfg | 15 +++++++++++++++ .../files/openxt-kmeta/features/xen/xen-pvh.scc | 4 ++++ .../files/openxt-kmeta/features/xen/xen-pvhvm.cfg | 5 +++++ .../files/openxt-kmeta/features/xen/xen-pvhvm.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-vfb-fe.cfg | 1 + .../openxt-kmeta/features/xen/xen-vfb-fe.scc | 4 ++++ .../openxt-kmeta/features/xen/xen-vkbd-fe.cfg | 2 ++ .../openxt-kmeta/features/xen/xen-vkbd-fe.scc | 4 ++++ 28 files changed, 103 insertions(+) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.cfg new file mode 100644 index 0000000000..31dee6891b --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.cfg @@ -0,0 +1,2 @@ +CONFIG_XEN_BALLOON=y +CONFIG_XEN_SCRUB_PAGES_DEFAULT=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.scc new file mode 100644 index 0000000000..601b78cb4b --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-balloon.scc @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Enable Xen memory balloon module" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-balloon.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.cfg new file mode 100644 index 0000000000..7ce3de2e59 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.cfg @@ -0,0 +1,2 @@ +CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.scc new file mode 100644 index 0000000000..59cb0a0983 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-be.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen block device backend driver" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-blk-be.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.cfg new file mode 100644 index 0000000000..2473142aaa --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.cfg @@ -0,0 +1 @@ +CONFIG_XEN_BLKDEV_FRONTEND=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.scc new file mode 100644 index 0000000000..ddc924ba6f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-blk-fe.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen paravirtualized block device driver." +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-blk-fe.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.cfg new file mode 100644 index 0000000000..f250e987f2 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.cfg @@ -0,0 +1 @@ +CONFIG_XEN_DEBUG_FS=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.scc new file mode 100644 index 0000000000..5be56e4d08 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-debugfs.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen debug file-system" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-debugfs.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.cfg new file mode 100644 index 0000000000..e588eb647c --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.cfg @@ -0,0 +1,3 @@ +CONFIG_HYPERVISOR_GUEST=y +CONFIG_PARAVIRT=y +CONFIG_XEN=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.scc new file mode 100644 index 0000000000..9116808058 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-dom0.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen dom0 kernel support" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-dom0.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.cfg new file mode 100644 index 0000000000..86c293f54c --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.cfg @@ -0,0 +1,2 @@ +CONFIG_XEN_BACKEND=y +CONFIG_XEN_NETDEV_BACKEND=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.scc new file mode 100644 index 0000000000..f92e122879 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-be.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen backend network device" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-net-be.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.cfg new file mode 100644 index 0000000000..726a687a65 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.cfg @@ -0,0 +1,2 @@ +CONFIG_NETDEVICES=y +CONFIG_XEN_NETDEV_FRONTEND=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.scc new file mode 100644 index 0000000000..e73683e153 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-net-fe.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen network device frontend driver" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-net-fe.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.cfg new file mode 100644 index 0000000000..fb4bac7977 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.cfg @@ -0,0 +1,3 @@ +CONFIG_XEN_BACKEND=y +CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_PCI_STUB=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.scc new file mode 100644 index 0000000000..4dc6a0324f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-be.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen PCI-device backend driver" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-pci-be.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.cfg new file mode 100644 index 0000000000..66a6c16e0a --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.cfg @@ -0,0 +1,2 @@ +CONFIG_PCI=y +CONFIG_XEN_PCIDEV_FRONTEND=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.scc new file mode 100644 index 0000000000..bf56bf2a71 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pci-fe.scc @@ -0,0 +1,5 @@ +define KFEATURE_DESCRIPTION "Enable Xen paravirtualized PCI driver." +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-pci-fe.cfg + diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.cfg new file mode 100644 index 0000000000..59c537751c --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.cfg @@ -0,0 +1,4 @@ +CONFIG_HYPERVISOR_GUEST=y +CONFIG_PARAVIRT=y +CONFIG_XEN=y +CONFIG_XEN_PV=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.scc new file mode 100644 index 0000000000..d3847454e8 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pv.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen PV guest kernel support" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-pv.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.cfg new file mode 100644 index 0000000000..3a94f365c8 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.cfg @@ -0,0 +1,15 @@ +# +# Processor type and features +# +CONFIG_HYPERVISOR_GUEST=y +CONFIG_PARAVIRT=y +CONFIG_XEN=y +CONFIG_XEN_PV=y +CONFIG_PARAVIRT_TIME_ACCOUNTING=y +CONFIG_XEN_PVH=y +# CONFIG_SCHED_MC is not set + +# +# Device drivers +# +CONFIG_PCI=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.scc new file mode 100644 index 0000000000..347f57c139 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvh.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen PVH guest kernel support" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-pvh.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.cfg new file mode 100644 index 0000000000..cf1352cb84 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.cfg @@ -0,0 +1,5 @@ +CONFIG_PARAVIRT=y +CONFIG_HYPERVISOR_GUEST=y +CONFIG_XEN=y +# CONFIG_XEN_DOM0 is not set +CONFIG_PCI=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.scc new file mode 100644 index 0000000000..4b3c49f173 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-pvhvm.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen PV on HVM (Xen platform device) in guest support" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-pvhvm.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.cfg new file mode 100644 index 0000000000..9a7fa19cd6 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.cfg @@ -0,0 +1 @@ +CONFIG_XEN_FBDEV_FRONTEND=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.scc new file mode 100644 index 0000000000..5ca930c8f4 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vfb-fe.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen virtual framebuffer frontend driver" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-vfb-fe.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.cfg new file mode 100644 index 0000000000..6d78d799bd --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.cfg @@ -0,0 +1,2 @@ +CONFIG_INPUT_MISC=y +CONFIG_INPUT_XEN_KBDDEV_FRONTEND=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.scc b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.scc new file mode 100644 index 0000000000..796da9d5c3 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/xen/xen-vkbd-fe.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable Xen virtual keyboard frontend driver" +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware xen-vkbd-fe.cfg From 4c1f30cf14af6cad7d4cb065ce8ce60806618a3f Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 16:55:55 -0500 Subject: [PATCH 02/15] kmeta: define ktypes for generic Xen domain types Define ktypes to handle configuration of different kinds of Xen guest kernels: dom0, pv, pvh, hvm. All inherit a common base to avoid redundancies. Signed-off-by: Eric Chanudet --- .../files/openxt-kmeta/ktypes/xen/base.cfg | 44 +++++++++++++++++++ .../files/openxt-kmeta/ktypes/xen/base.scc | 28 ++++++++++++ .../files/openxt-kmeta/ktypes/xen/dom0.cfg | 16 +++++++ .../files/openxt-kmeta/ktypes/xen/dom0.scc | 13 ++++++ .../files/openxt-kmeta/ktypes/xen/hvm.cfg | 9 ++++ .../files/openxt-kmeta/ktypes/xen/hvm.scc | 13 ++++++ .../files/openxt-kmeta/ktypes/xen/pv.cfg | 38 ++++++++++++++++ .../files/openxt-kmeta/ktypes/xen/pv.scc | 6 +++ .../files/openxt-kmeta/ktypes/xen/pvh.cfg | 27 ++++++++++++ .../files/openxt-kmeta/ktypes/xen/pvh.scc | 6 +++ 10 files changed, 200 insertions(+) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.cfg new file mode 100644 index 0000000000..985895a64f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.cfg @@ -0,0 +1,44 @@ +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y + +# +# General architecture-dependent options +# +# CONFIG_VIRTUALIZATION is not set + +# +# Security options +# +CONFIG_SECURITY=y + +# +# Networking support +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set + +# +# Device Drivers +# +# CONFIG_VIRTIO_MENU is not set + +CONFIG_BLK_DEV_LOOP=y + +# CONFIG_IOMMU_SUPPORT is not set + +# CONFIG_LEGACY_PTYS is not set + +# CONFIG_XEN_BALLOON is not set + +# +# Processor type and features +# +# CONFIG_KVM_GUEST is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.scc new file mode 100644 index 0000000000..2761d32b5e --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/base.scc @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: MIT +define KERNEL_VERSION 5.4 +branch v5.4 + +force kconf non-hardware base.cfg + +include features/lttng/lttng.scc + +include features/blktrace/blktrace.scc + +include features/utrace/utrace.scc + +include features/seccomp/seccomp.scc + +include features/ftrace/ftrace.scc + +# Initramfs gen_initramfs_list.sh hook +include features/initramfs/initramfs.scc + +include features/tmpfs/tmpfs-posix-acl.scc + +include features/edac/edac.scc + +# individual cfg block section +include cfg/fs/devtmpfs.scc +include cfg/fs/debugfs.scc + +include cfg/systemd.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.cfg new file mode 100644 index 0000000000..936c05e97a --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.cfg @@ -0,0 +1,16 @@ +# +# Processor type and features +# +# CONFIG_XEN_PVHVM is not set + +# +# Device drivers +# +# CONFIG_XEN_PCIDEV_FRONTEND is not set +# CONFIG_XEN_BLKDEV_FRONTEND is not set +# CONFIG_XEN_FBDEV_FRONTEND is not set + +# CONFIG_WIRELESS is not set +# CONFIG_ETHERNET is not set +# CONFIG_WLAN is not set +# CONFIG_BLK_DEV_MD is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.scc new file mode 100644 index 0000000000..650f064dfb --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/dom0.scc @@ -0,0 +1,13 @@ +include ktypes/xen/base.scc + +# Firmware loading support. +include features/firmware/firmware.scc + +# PCI support (PCI backend support). +include features/pci/pci.scc +include features/pci-iov/pci-iov.scc + +# Xen dom0 support. +include features/xen/xen-dom0.scc + +kconf non-hardware ktypes/xen/dom0.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.cfg new file mode 100644 index 0000000000..9ba566f4a8 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.cfg @@ -0,0 +1,9 @@ +# +# Processor type and features +# +CONFIG_XEN_PVHVM=y + +# +# SPI support +# +# CONFIG_SPI is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.scc new file mode 100644 index 0000000000..c1792b0532 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/hvm.scc @@ -0,0 +1,13 @@ +include ktypes/xen/base.scc + +# Firmware loading support. +include features/firmware/firmware.scc + +# PCI support (PCI backend support). +include features/pci/pci.scc +include features/pci-iov/pci-iov.scc + +# Xen PV on HVM support. +include features/xen/xen-pvhvm.scc + +kconf non-hardware ktypes/xen/hvm.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.cfg new file mode 100644 index 0000000000..7de165c7cc --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.cfg @@ -0,0 +1,38 @@ +# +# Processor type and features +# +# CONFIG_XEN_PVHVM is not set + +# +# Power management and ACPI options +# +# CONFIG_ACPI is not set + +# +# Device drivers +# +# CONFIG_XEN_BALLOON is not set +# CONFIG_XEN_PCIDEV_FRONTEND is not set +# CONFIG_XEN_FBDEV_FRONTEND is not set +# CONFIG_XEN_BLKDEV_FRONTEND is not set + +# CONFIG_WIRELESS is not set +# CONFIG_ETHERNET is not set +# CONFIG_WLAN is not set +# CONFIG_PPP is not set +# CONFIG_NET_CORE is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_DEVPORT is not set +# CONFIG_HWMON is not set +# CONFIG_SERIO is not set +# CONFIG_USB_SUPPORT is not set + +# +# Cryptographic API +# +# CONFIG_CRYPTO_HW is not set + +# +# SPI support +# +# CONFIG_SPI is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.scc new file mode 100644 index 0000000000..e46a1f3f06 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pv.scc @@ -0,0 +1,6 @@ +include ktypes/xen/base.scc + +# Xen PV support. +include features/xen/xen-pv.scc + +kconf non-hardware ktypes/xen/pv.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.cfg new file mode 100644 index 0000000000..4da8f5b9ff --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.cfg @@ -0,0 +1,27 @@ +# +# SPI support +# +# CONFIG_SPI is not set + +# +# Device drivers +# +# CONFIG_XEN_BALLOON is not set +# CONFIG_XEN_PCIDEV_FRONTEND is not set +# CONFIG_XEN_FBDEV_FRONTEND is not set +# CONFIG_XEN_BLKDEV_FRONTEND is not set + +# CONFIG_WIRELESS is not set +# CONFIG_ETHERNET is not set +# CONFIG_WLAN is not set +# CONFIG_PPP is not set +# CONFIG_NET_CORE is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_DEVPORT is not set +# CONFIG_HWMON is not set +# CONFIG_SERIO is not set +# CONFIG_USB_SUPPORT is not set + +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_HID is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.scc new file mode 100644 index 0000000000..827cf4036f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/pvh.scc @@ -0,0 +1,6 @@ +include ktypes/xen/base.scc + +# Xen PVH support. +include features/xen/xen-pvh.scc + +kconf non-hardware ktypes/xen/pvh.cfg From 6c8f529647dcb4fb736f0c9ee60b7c3c054fc6d7 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 17:13:07 -0500 Subject: [PATCH 03/15] kmeta: define ktypes for common service VMs OpenXT relies on service VMs to isolate different components for each others. Define abstract ktypes with the minimal configuration to support the following use-cases: - stubdom - uivm - ndvm These can then be configured for a targeted BSP. Signed-off-by: Eric Chanudet --- .../files/openxt-kmeta/ktypes/xen/ndvm.cfg | 13 ++++++++++++ .../files/openxt-kmeta/ktypes/xen/ndvm.scc | 14 +++++++++++++ .../files/openxt-kmeta/ktypes/xen/stubdom.cfg | 16 +++++++++++++++ .../files/openxt-kmeta/ktypes/xen/stubdom.scc | 3 +++ .../files/openxt-kmeta/ktypes/xen/uivm.cfg | 20 +++++++++++++++++++ .../files/openxt-kmeta/ktypes/xen/uivm.scc | 3 +++ 6 files changed, 69 insertions(+) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.cfg new file mode 100644 index 0000000000..921c5ce26a --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.cfg @@ -0,0 +1,13 @@ +# +# Networking +# +CONFIG_BRIDGE=y + +# +# Device drivers +# +# CONFIG_CDROM is not set +# CONFIG_SCSI is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_HID is not set +# CONFIG_USB_SUPPORT is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.scc new file mode 100644 index 0000000000..1d629487dd --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/ndvm.scc @@ -0,0 +1,14 @@ +include ktypes/xen/hvm.scc + +# +# Xen PV on HVM support +# +include features/xen/xen-pvhvm.scc + +# +# Xen paravirtualized backends +# +include features/xen/xen-net-be.scc +include features/xen/xen-blk-fe.scc + +kconf non-hardware ndvm.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.cfg new file mode 100644 index 0000000000..e4b07a193d --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.cfg @@ -0,0 +1,16 @@ +# +# Device drivers +# +# CONFIG_INPUT is not set +# CONFIG_VT is not set + +# +# Network device support +# +CONFIG_NET_CORE=y +CONFIG_TUN=y + +# +# Networking options +# +CONFIG_BRIDGE=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.scc new file mode 100644 index 0000000000..15b0f58cba --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/stubdom.scc @@ -0,0 +1,3 @@ +include ktypes/xen/pv.scc + +kconf non-hardware stubdom.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.cfg new file mode 100644 index 0000000000..72b1e802ab --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.cfg @@ -0,0 +1,20 @@ +# +# Processor type and features +# +# CONFIG_XEN_DOM0 is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_EVDEV=y + +# +# Device drivers +# +CONFIG_FB=y + +# +# Character devices +# +CONFIG_VT_HW_CONSOLE_BINDING=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.scc new file mode 100644 index 0000000000..3acf2fc153 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/xen/uivm.scc @@ -0,0 +1,3 @@ +include ktypes/xen/pvh.scc + +kconf non-hardware uivm.cfg From f2baf6e0f0330f0c162c56bf05aaf5cc178d233c Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 17:19:59 -0500 Subject: [PATCH 04/15] kmeta: define config fragments for openxt patches With the exception of backports, most patche series are independent of each others with little to no risk of conflicts. Attempt to isolate each on per features/goal and provide a configuration fragment to add in KERNEL_FEATURES. Signed-off-by: Eric Chanudet --- ...tdev-switch-from-kcalloc-to-kvcalloc.patch | 77 + .../patches/backports/backports.scc | 6 + ...gister-bug-in-STMicroelectronics-TPM.patch | 38 + .../openxt-kmeta/patches/blktap2/blktap2.cfg | 1 + .../patches/blktap2/blktap2.patch | 3070 ++++++++++++ .../openxt-kmeta/patches/blktap2/blktap2.scc | 7 + .../bridge-carrier-follow-prio0.patch | 114 + .../openxt-bridge-quirks.scc | 10 + .../skb-forward-copy-bridge-param.patch | 84 + .../extra-mt-input-devices.patch | 59 + .../openxt-input-quirks.scc | 6 + .../openxt-pci-quirks/konrad-ioperm.patch | 251 + .../openxt-pci-quirks/openxt-pci-quirks.scc | 20 + .../openxt-pci-quirks/pci-pt-flr.patch | 105 + .../pci-pt-move-unaligned-resources.patch | 78 + .../pciback-restrictive-attr.patch | 98 + ...h-reset-interface-to-pciback-s-sysfs.patch | 513 ++ .../openxt-pv-video-quirks.scc | 7 + .../xenkbd-tablet-resolution.patch | 59 + .../dont-suspend-xen-serial-port.patch | 53 + .../openxt-serial-quirks/hvc-kgdb-fix.patch | 91 + .../intel-amt-support.patch | 45 + .../openxt-serial-quirks.scc | 12 + .../disable-csum-xennet.patch | 67 + ...k-skip-frontend-wait-during-shutdown.patch | 87 + .../netfront-support-backend-relocate.patch | 70 + .../openxt-service-vms/openxt-service-vms.scc | 18 + ...us-move-otherend-watches-on-relocate.patch | 110 + .../xenpv-no-tty0-as-default-console.patch | 54 + .../patches/openxt-tpm/openxt-tpm.scc | 10 + .../patches/openxt-tpm/tpm-log-didvid.patch | 51 + .../openxt-tpm/tpm-tis-force-ioremap.patch | 25 + .../patches/openxt-usbback/openxt-usbback.scc | 5 + .../patches/openxt-usbback/usbback-base.patch | 4440 +++++++++++++++++ .../acpi-video-delay-init.patch | 92 + .../openxt-video-quirks.scc | 11 + .../openxt-video-quirks/realmem-mmap.patch | 57 + .../openxt-vwif/netback-vwif-support.patch | 10 + .../patches/openxt-vwif/openxt-vwif.scc | 6 + .../xen-txt-add-xen-txt-eventlog-module.patch | 303 ++ .../patches/xen-txt-evtlog/xen-txt-evtlog.cfg | 1 + .../patches/xen-txt-evtlog/xen-txt-evtlog.scc | 8 + ...a-155-qsb-023-add-RING_COPY_RESPONSE.patch | 52 + ...e-local-copy-of-response-before-usin.patch | 122 + ...pare-request-locally-only-then-put-i.patch | 136 + ...t-add-range-check-for-Tx-response-id.patch | 29 + ...y-response-out-of-shared-buffer-befo.patch | 174 + ...not-use-data-already-exposed-to-back.patch | 59 + .../openxt-kmeta/patches/xsa-155/xsa-155.scc | 10 + 49 files changed, 10811 insertions(+) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/backports/0001-xen-gntdev-switch-from-kcalloc-to-kvcalloc.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/backports/backports.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/backports/tpm_tis-work-around-status-register-bug-in-STMicroelectronics-TPM.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/bridge-carrier-follow-prio0.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/openxt-bridge-quirks.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/skb-forward-copy-bridge-param.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/extra-mt-input-devices.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/openxt-input-quirks.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/konrad-ioperm.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/openxt-pci-quirks.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-flr.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-move-unaligned-resources.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pciback-restrictive-attr.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/thorough-reset-interface-to-pciback-s-sysfs.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/openxt-pv-video-quirks.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/xenkbd-tablet-resolution.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/dont-suspend-xen-serial-port.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/hvc-kgdb-fix.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/intel-amt-support.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/openxt-serial-quirks.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/disable-csum-xennet.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netback-skip-frontend-wait-during-shutdown.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netfront-support-backend-relocate.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/openxt-service-vms.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenbus-move-otherend-watches-on-relocate.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenpv-no-tty0-as-default-console.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/openxt-tpm.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-log-didvid.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-tis-force-ioremap.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/openxt-usbback.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/usbback-base.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/acpi-video-delay-init.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/openxt-video-quirks.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/realmem-mmap.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/netback-vwif-support.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/openxt-vwif.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-add-xen-txt-eventlog-module.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-add-RING_COPY_RESPONSE.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-make-local-copy-of-response-before-usin.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-prepare-request-locally-only-then-put-i.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-add-range-check-for-Tx-response-id.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-copy-response-out-of-shared-buffer-befo.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-do-not-use-data-already-exposed-to-back.patch create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/backports/0001-xen-gntdev-switch-from-kcalloc-to-kvcalloc.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/backports/0001-xen-gntdev-switch-from-kcalloc-to-kvcalloc.patch new file mode 100644 index 0000000000..73ccdb2c47 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/backports/0001-xen-gntdev-switch-from-kcalloc-to-kvcalloc.patch @@ -0,0 +1,77 @@ +From b3f7931f5c61ba39e81a5c958bf5d65ebb1838af Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 7 Nov 2019 12:15:46 +0100 +Subject: [PATCH] xen/gntdev: switch from kcalloc() to kvcalloc() + +With sufficient many pages to map gntdev can reach order 9 allocation +sizes. As there is no need to have physically contiguous buffers switch +to kvcalloc() in order to avoid failing allocations. + +Signed-off-by: Juergen Gross +Reviewed-by: Oleksandr Andrushchenko +Reviewed-by: Boris Ostrovsky +Signed-off-by: Juergen Gross +--- + drivers/xen/gntdev.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c +index ad621ec1912c..4fc83e3f5ad3 100644 +--- a/drivers/xen/gntdev.c ++++ b/drivers/xen/gntdev.c +@@ -112,14 +112,14 @@ static void gntdev_free_map(struct gntdev_grant_map *map) + gnttab_free_pages(map->count, map->pages); + + #ifdef CONFIG_XEN_GRANT_DMA_ALLOC +- kfree(map->frames); ++ kvfree(map->frames); + #endif +- kfree(map->pages); +- kfree(map->grants); +- kfree(map->map_ops); +- kfree(map->unmap_ops); +- kfree(map->kmap_ops); +- kfree(map->kunmap_ops); ++ kvfree(map->pages); ++ kvfree(map->grants); ++ kvfree(map->map_ops); ++ kvfree(map->unmap_ops); ++ kvfree(map->kmap_ops); ++ kvfree(map->kunmap_ops); + kfree(map); + } + +@@ -133,12 +133,13 @@ struct gntdev_grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, + if (NULL == add) + return NULL; + +- add->grants = kcalloc(count, sizeof(add->grants[0]), GFP_KERNEL); +- add->map_ops = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL); +- add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL); +- add->kmap_ops = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL); +- add->kunmap_ops = kcalloc(count, sizeof(add->kunmap_ops[0]), GFP_KERNEL); +- add->pages = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL); ++ add->grants = kvcalloc(count, sizeof(add->grants[0]), GFP_KERNEL); ++ add->map_ops = kvcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL); ++ add->unmap_ops = kvcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL); ++ add->kmap_ops = kvcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL); ++ add->kunmap_ops = kvcalloc(count, ++ sizeof(add->kunmap_ops[0]), GFP_KERNEL); ++ add->pages = kvcalloc(count, sizeof(add->pages[0]), GFP_KERNEL); + if (NULL == add->grants || + NULL == add->map_ops || + NULL == add->unmap_ops || +@@ -157,8 +158,8 @@ struct gntdev_grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, + if (dma_flags & (GNTDEV_DMA_FLAG_WC | GNTDEV_DMA_FLAG_COHERENT)) { + struct gnttab_dma_alloc_args args; + +- add->frames = kcalloc(count, sizeof(add->frames[0]), +- GFP_KERNEL); ++ add->frames = kvcalloc(count, sizeof(add->frames[0]), ++ GFP_KERNEL); + if (!add->frames) + goto err; + +-- +2.28.0 + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/backports/backports.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/backports/backports.scc new file mode 100644 index 0000000000..cc762cbe65 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/backports/backports.scc @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply backported patches" +define KFEATURE_COMPATIBILITY all + +patch tpm_tis-work-around-status-register-bug-in-STMicroelectronics-TPM.patch +patch 0001-xen-gntdev-switch-from-kcalloc-to-kvcalloc.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/backports/tpm_tis-work-around-status-register-bug-in-STMicroelectronics-TPM.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/backports/tpm_tis-work-around-status-register-bug-in-STMicroelectronics-TPM.patch new file mode 100644 index 0000000000..37a85cd173 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/backports/tpm_tis-work-around-status-register-bug-in-STMicroelectronics-TPM.patch @@ -0,0 +1,38 @@ +From: Omar Sandoval +Subject: [PATCH] tpm_tis: work around status register bug in STMicroelectronics TPM +Date: Wed, 15 Apr 2020 15:45:22 -0700 +Message-Id: <6c55d7c1fb84e5bf2ace9f05ec816ef67bd873e1.1586990595.git.osandov@fb.com> + +We've encountered a particular model of STMicroelectronics TPM that +transiently returns a bad value in the status register. This causes the +kernel to believe that the TPM is ready to receive a command when it +actually isn't, which in turn causes the send to time out in +get_burstcount(). In testing, reading the status register one extra time +convinces the TPM to return a valid value. + +Signed-off-by: Omar Sandoval +--- + drivers/char/tpm/tpm_tis_core.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/char/tpm/tpm_tis_core.c ++++ b/drivers/char/tpm/tpm_tis_core.c +@@ -238,6 +238,18 @@ static u8 tpm_tis_status(struct tpm_chip + rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status); + if (rc < 0) + return 0; ++ /* ++ * Some STMicroelectronics TPMs have a bug where the status register is ++ * sometimes bogus (all 1s) if read immediately after the access ++ * register is written to. Bits 0, 1, and 5 are always supposed to read ++ * as 0, so this is clearly invalid. Reading the register a second time ++ * returns a valid value. ++ */ ++ if (unlikely(status == 0xff)) { ++ rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status); ++ if (rc < 0) ++ return 0; ++ } + + return status; + } diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.cfg b/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.cfg new file mode 100644 index 0000000000..76e1996bca --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.cfg @@ -0,0 +1 @@ +CONFIG_BLK_DEV_TAP=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.patch new file mode 100644 index 0000000000..30404b9205 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.patch @@ -0,0 +1,3070 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +blktap2 driver. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +The block tap driver allows block device requests to be redirected to +processes, through a device interface. Doing so allows user-space development +of high-performance block storage backends, where disk images may be +implemented as files, in memory, or on other hosts across the network. + +See http://xenbits.xensource.com/hg/xen-unstable.hg/file/tip/tools/blktap2/README. + +################################################################################ +CHANGELOG +################################################################################ +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner +Port to 5.4 blk-mq: Jason Andryuk +Restore 4.14 spinlock order + +###############################################################################i +REMOVAL +################################################################################ +This is required for guest block devices support. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +Guest block devices handling. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/block/Kconfig ++++ b/drivers/block/Kconfig +@@ -469,4 +469,13 @@ config BLK_DEV_RSXX + To compile this driver as a module, choose M here: the + module will be called rsxx. + ++config BLK_DEV_TAP ++ tristate "Blktap userspace devices" ++ help ++ The block tap driver allows block device requests to be ++ redirected to processes, through a device interface. ++ Doing so allows user-space development of high-performance ++ block storage backends, where disk images may be implemented ++ as files, in memory, or on other hosts across the network. ++ + endif # BLK_DEV +--- a/drivers/block/Makefile ++++ b/drivers/block/Makefile +@@ -25,6 +25,7 @@ obj-$(CONFIG_BLK_DEV_UMEM) += umem.o + obj-$(CONFIG_BLK_DEV_NBD) += nbd.o + obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o + obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o ++obj-$(CONFIG_BLK_DEV_TAP) += blktap/ + + obj-$(CONFIG_BLK_DEV_SX8) += sx8.o + +--- /dev/null ++++ b/drivers/block/blktap/Makefile +@@ -0,0 +1,3 @@ ++obj-$(CONFIG_BLK_DEV_TAP) := blktap.o ++ ++blktap-objs := control.o ring.o device.o request.o sysfs.o +--- /dev/null ++++ b/drivers/block/blktap/blktap.h +@@ -0,0 +1,185 @@ ++#ifndef _BLKTAP_H_ ++#define _BLKTAP_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern int blktap_debug_level; ++extern int blktap_ring_major; ++extern int blktap_device_major; ++ ++#define BTPRINTK(level, tag, force, _f, _a...) \ ++ do { \ ++ if (blktap_debug_level > level && \ ++ (force || printk_ratelimit())) \ ++ printk(tag "%s: " _f, __func__, ##_a); \ ++ } while (0) ++ ++#define BTDBG(_f, _a...) BTPRINTK(8, KERN_DEBUG, 1, _f, ##_a) ++#define BTINFO(_f, _a...) BTPRINTK(0, KERN_INFO, 0, _f, ##_a) ++#define BTWARN(_f, _a...) BTPRINTK(0, KERN_WARNING, 0, _f, ##_a) ++#define BTERR(_f, _a...) BTPRINTK(0, KERN_ERR, 0, _f, ##_a) ++ ++#define MAX_BLKTAP_DEVICE 1024 ++ ++#define BLKTAP_DEVICE 4 ++#define BLKTAP_DEVICE_CLOSED 5 ++#define BLKTAP_PAUSE_REQUESTED 6 ++#define BLKTAP_PAUSED 7 ++#define BLKTAP_SHUTDOWN_REQUESTED 8 ++ ++#define BLKTAP_REQUEST_FREE 0 ++#define BLKTAP_REQUEST_PENDING 1 ++ ++#define BLKTAP2_RING_MESSAGE_PAUSE 1 ++#define BLKTAP2_RING_MESSAGE_RESUME 2 ++ ++struct blktap_device { ++ struct mutex lock; ++ struct gendisk *gd; ++ struct request_queue *rq; ++ struct blk_mq_tag_set tag_set; ++}; ++ ++struct blktap_request; ++ ++struct blktap_ring { ++ struct task_struct *task; ++ ++ struct vm_area_struct *vma; ++ struct blktap_front_ring ring; ++ unsigned long ring_vstart; ++ unsigned long user_vstart; ++ ++ int response; ++ ++ /* pending doesn't have any locking, but that is okay. Insertions ++ * happen under blktap_device->lock, so that is serialized. Removal ++ * uses the blktap_request->usr_idx, so they aren't iterating the ++ * array. As long as pointer assignments are atomic, then you don't ++ * have to worry about Insertion and Removal racing. In practice, ++ * there are simultaneous operations, so n_pending needs to be ++ * atomic_t to keep those in sync. */ ++ atomic_t n_pending; ++ struct blktap_request *pending[BLKTAP_RING_SIZE]; ++ ++ wait_queue_head_t poll_wait; ++ ++ dev_t devno; ++ struct device *dev; ++}; ++ ++struct blktap_statistics { ++ unsigned long st_print; ++ int st_rd_req; ++ int st_wr_req; ++ int st_tr_req; ++ int st_oo_req; ++ int st_fl_req; ++ int st_rd_sect; ++ int st_wr_sect; ++ int st_tr_sect; ++ s64 st_rd_cnt; ++ s64 st_rd_sum_usecs; ++ s64 st_rd_max_usecs; ++ s64 st_wr_cnt; ++ s64 st_wr_sum_usecs; ++ s64 st_wr_max_usecs; ++}; ++ ++struct blktap_request { ++ struct blktap *tap; ++ struct request *rq; ++ int usr_idx; ++ ++ int operation; ++ ++ struct scatterlist sg_table[BLKTAP_SEGMENT_MAX]; ++ struct page *pages[BLKTAP_SEGMENT_MAX]; ++ int nr_pages; ++}; ++ ++#define blktap_for_each_sg(_sg, _req, _i) \ ++ for (_sg = (_req)->sg_table, _i = 0; \ ++ _i < (_req)->nr_pages; \ ++ (_sg)++, (_i)++) ++ ++struct blktap { ++ int minor; ++ unsigned long dev_inuse; ++ ++ struct blktap_ring ring; ++ struct blktap_device device; ++ struct blktap_page_pool *pool; ++ ++ wait_queue_head_t remove_wait; ++ struct work_struct remove_work; ++ struct delayed_work destroy_work; ++ char name[BLKTAP_NAME_MAX]; ++ ++ struct blktap_statistics stats; ++}; ++ ++struct blktap_page_pool { ++ struct mempool_s *bufs; ++ spinlock_t lock; ++ struct kobject kobj; ++ wait_queue_head_t wait; ++}; ++ ++extern struct mutex blktap_lock; ++extern struct blktap **blktaps; ++extern int blktap_max_minor; ++ ++int blktap_control_destroy_tap(struct blktap *); ++size_t blktap_control_debug(struct blktap *, char *, size_t); ++ ++int blktap_ring_init(void); ++void blktap_ring_exit(void); ++size_t blktap_ring_debug(struct blktap *, char *, size_t); ++int blktap_ring_create(struct blktap *); ++int blktap_ring_destroy(struct blktap *); ++int blktap_ring_pause(struct blktap *); ++int blktap_ring_resume(struct blktap *); ++struct blktap_request *blktap_ring_make_request(struct blktap *); ++void blktap_ring_free_request(struct blktap *,struct blktap_request *); ++void blktap_ring_submit_request(struct blktap *, struct blktap_request *); ++int blktap_ring_map_request_segment(struct blktap *, struct blktap_request *, int); ++int blktap_ring_map_request(struct blktap *, struct blktap_request *); ++void blktap_ring_unmap_request(struct blktap *, struct blktap_request *); ++void blktap_ring_kick_user(struct blktap *); ++ ++int blktap_sysfs_init(void); ++void blktap_sysfs_exit(void); ++int blktap_sysfs_create(struct blktap *); ++void blktap_sysfs_destroy(struct blktap *); ++ ++int blktap_device_init(void); ++void blktap_device_exit(void); ++size_t blktap_device_debug(struct blktap *, char *, size_t); ++int blktap_device_create(struct blktap *, struct blktap_device_info *); ++void blktap_device_configure(struct blktap *tap, struct blktap_device_info *info); ++int blktap_device_destroy(struct blktap *); ++int blktap_device_try_destroy(struct blktap *tap); ++int blktap_device_pause(struct blktap *); ++int blktap_device_resume(struct blktap *tap); ++void blktap_device_run_queues(struct blktap *); ++void blktap_device_end_request(struct blktap *, struct blktap_request *, blk_status_t); ++ ++int blktap_page_pool_init(struct kobject *); ++void blktap_page_pool_exit(void); ++struct blktap_page_pool *blktap_page_pool_get(const char *); ++ ++size_t blktap_request_debug(struct blktap *, char *, size_t); ++struct blktap_request *blktap_request_alloc(struct blktap *); ++int blktap_request_get_pages(struct blktap *, struct blktap_request *, int); ++void blktap_request_free(struct blktap *, struct blktap_request *); ++void blktap_request_bounce(struct blktap *, struct blktap_request *, int, int); ++ ++ ++#endif +--- /dev/null ++++ b/drivers/block/blktap/control.c +@@ -0,0 +1,360 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "blktap.h" ++ ++DEFINE_MUTEX(blktap_lock); ++ ++struct blktap **blktaps; ++int blktap_max_minor; ++static struct blktap_page_pool *default_pool; ++ ++static struct blktap * ++blktap_control_get_minor(void) ++{ ++ int minor; ++ struct blktap *tap; ++ ++ tap = kzalloc(sizeof(*tap), GFP_KERNEL); ++ if (unlikely(!tap)) ++ return NULL; ++ ++ mutex_lock(&blktap_lock); ++ ++ for (minor = 0; minor < blktap_max_minor; minor++) ++ if (!blktaps[minor]) ++ break; ++ ++ if (minor == MAX_BLKTAP_DEVICE) ++ goto fail; ++ ++ if (minor == blktap_max_minor) { ++ void *p; ++ int n; ++ ++ n = min(2 * blktap_max_minor, MAX_BLKTAP_DEVICE); ++ p = krealloc(blktaps, n * sizeof(blktaps[0]), GFP_KERNEL); ++ if (!p) ++ goto fail; ++ ++ blktaps = p; ++ minor = blktap_max_minor; ++ blktap_max_minor = n; ++ ++ memset(&blktaps[minor], 0, (n - minor) * sizeof(blktaps[0])); ++ } ++ ++ tap->minor = minor; ++ blktaps[minor] = tap; ++ ++ __module_get(THIS_MODULE); ++out: ++ mutex_unlock(&blktap_lock); ++ return tap; ++ ++fail: ++ mutex_unlock(&blktap_lock); ++ kfree(tap); ++ tap = NULL; ++ goto out; ++} ++ ++static void ++blktap_control_put_minor(struct blktap* tap) ++{ ++ blktaps[tap->minor] = NULL; ++ kfree(tap); ++ ++ module_put(THIS_MODULE); ++} ++ ++static struct blktap* ++blktap_control_create_tap(void) ++{ ++ struct blktap *tap; ++ int err; ++ ++ tap = blktap_control_get_minor(); ++ if (!tap) ++ return NULL; ++ ++ kobject_get(&default_pool->kobj); ++ tap->pool = default_pool; ++ mutex_init(&tap->device.lock); ++ ++ err = blktap_ring_create(tap); ++ if (err) ++ goto fail_tap; ++ ++ err = blktap_sysfs_create(tap); ++ if (err) ++ goto fail_ring; ++ ++ return tap; ++ ++fail_ring: ++ blktap_ring_destroy(tap); ++fail_tap: ++ blktap_control_put_minor(tap); ++ ++ return NULL; ++} ++ ++int ++blktap_control_destroy_tap(struct blktap *tap) ++{ ++ int err; ++ ++ err = blktap_ring_destroy(tap); ++ if (err) ++ return err; ++ ++ kobject_put(&tap->pool->kobj); ++ ++ blktap_sysfs_destroy(tap); ++ ++ blktap_control_put_minor(tap); ++ return err; ++} ++ ++static void ++blktap_control_remove_work(struct work_struct *work) ++{ ++ struct blktap *tap ++ = container_of(work, struct blktap, remove_work); ++ blktap_control_destroy_tap(tap); ++} ++ ++static int ++blktap_control_destroy_tap_ioctl(int minor) ++{ ++ struct blktap *tap; ++ struct blktap_ring *ring; ++ int r; ++ ++ tap = blktaps[minor]; ++ if (!tap) ++ return -ENODEV; ++ ++ ring = &tap->ring; ++ ++ if (ring->vma == NULL && atomic_read(&ring->n_pending)) ++ printk(KERN_WARNING ++ "blktap%d ring not mapped and n_pending %d\n", ++ minor, atomic_read(&ring->n_pending)); ++ ++ r = wait_event_interruptible(tap->remove_wait, ++ atomic_read(&ring->n_pending) == 0 || ++ ring->vma == NULL); ++ if (r == -ERESTARTSYS) ++ return -EAGAIN; ++ ++ if (test_and_set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) ++ return 0; ++ ++ if (tap->ring.vma) { ++ struct blktap_sring *sring = ring->ring.sring; ++ ++ *BLKTAP_RING_MESSAGE(sring) = BLKTAP_RING_MESSAGE_CLOSE; ++ blktap_ring_kick_user(tap); ++ } else { ++ INIT_WORK(&tap->remove_work, blktap_control_remove_work); ++ schedule_work(&tap->remove_work); ++ } ++ ++ return 0; ++} ++ ++static long ++blktap_control_ioctl(struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct blktap *tap; ++ ++ switch (cmd) { ++ case BLKTAP_IOCTL_ALLOC_TAP: { ++ struct blktap_info info; ++ void __user *ptr = (void __user*)arg; ++ ++ tap = blktap_control_create_tap(); ++ if (!tap) ++ return -ENOMEM; ++ ++ info.ring_major = blktap_ring_major; ++ info.bdev_major = blktap_device_major; ++ info.ring_minor = tap->minor; ++ ++ if (copy_to_user(ptr, &info, sizeof(info))) { ++ blktap_control_destroy_tap(tap); ++ return -EFAULT; ++ } ++ ++ return 0; ++ } ++ ++ case BLKTAP_IOCTL_FREE_TAP: { ++ int minor = arg; ++ ++ if (minor > MAX_BLKTAP_DEVICE) ++ return -EINVAL; ++ ++ return blktap_control_destroy_tap_ioctl(minor); ++ } ++ } ++ ++ return -ENOIOCTLCMD; ++} ++ ++static struct file_operations blktap_control_file_operations = { ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = blktap_control_ioctl, ++}; ++ ++static struct miscdevice blktap_control = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "blktap-control", ++ .fops = &blktap_control_file_operations, ++}; ++ ++static struct device *control_device; ++ ++static ssize_t ++blktap_control_show_default_pool(struct device *device, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%s", kobject_name(&default_pool->kobj)); ++} ++ ++static ssize_t ++blktap_control_store_default_pool(struct device *device, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct blktap_page_pool *pool, *tmp = default_pool; ++ ++ pool = blktap_page_pool_get(buf); ++ if (IS_ERR(pool)) ++ return PTR_ERR(pool); ++ ++ default_pool = pool; ++ kobject_put(&tmp->kobj); ++ ++ return size; ++} ++ ++static DEVICE_ATTR(default_pool, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, ++ blktap_control_show_default_pool, ++ blktap_control_store_default_pool); ++ ++size_t ++blktap_control_debug(struct blktap *tap, char *buf, size_t size) ++{ ++ char *s = buf, *end = buf + size; ++ ++ s += snprintf(s, end - s, ++ "tap %u:%u name:'%s' flags:%#08lx\n", ++ MAJOR(tap->ring.devno), MINOR(tap->ring.devno), ++ tap->name, tap->dev_inuse); ++ ++ return s - buf; ++} ++ ++static int __init ++blktap_control_init(void) ++{ ++ int err; ++ ++ err = misc_register(&blktap_control); ++ if (err) ++ return err; ++ ++ control_device = blktap_control.this_device; ++ ++ blktap_max_minor = min(64, MAX_BLKTAP_DEVICE); ++ blktaps = kzalloc(blktap_max_minor * sizeof(blktaps[0]), GFP_KERNEL); ++ if (!blktaps) { ++ BTERR("failed to allocate blktap minor map"); ++ return -ENOMEM; ++ } ++ ++ err = blktap_page_pool_init(&control_device->kobj); ++ if (err) ++ return err; ++ ++ default_pool = blktap_page_pool_get("default"); ++ if (!default_pool) ++ return -ENOMEM; ++ ++ err = device_create_file(control_device, &dev_attr_default_pool); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static void ++blktap_control_exit(void) ++{ ++ if (default_pool) { ++ kobject_put(&default_pool->kobj); ++ default_pool = NULL; ++ } ++ ++ blktap_page_pool_exit(); ++ ++ if (blktaps) { ++ kfree(blktaps); ++ blktaps = NULL; ++ } ++ ++ if (control_device) { ++ misc_deregister(&blktap_control); ++ control_device = NULL; ++ } ++} ++ ++static void ++blktap_exit(void) ++{ ++ blktap_control_exit(); ++ blktap_ring_exit(); ++ blktap_sysfs_exit(); ++ blktap_device_exit(); ++} ++ ++static int __init ++blktap_init(void) ++{ ++ int err; ++ ++ err = blktap_device_init(); ++ if (err) ++ goto fail; ++ ++ err = blktap_ring_init(); ++ if (err) ++ goto fail; ++ ++ err = blktap_sysfs_init(); ++ if (err) ++ goto fail; ++ ++ err = blktap_control_init(); ++ if (err) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ blktap_exit(); ++ return err; ++} ++ ++module_init(blktap_init); ++module_exit(blktap_exit); ++MODULE_LICENSE("Dual BSD/GPL"); +--- /dev/null ++++ b/drivers/block/blktap/device.c +@@ -0,0 +1,710 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "blktap.h" ++ ++int blktap_device_major; ++ ++#define dev_to_blktap(_dev) container_of(_dev, struct blktap, device) ++ ++struct blktap_req { ++ blk_status_t error; ++}; ++ ++static inline struct blktap_req *blktap_req(struct request *rq) ++{ ++ return blk_mq_rq_to_pdu(rq); ++} ++ ++static int ++blktap_device_open(struct block_device *bdev, fmode_t mode) ++{ ++ struct gendisk *disk = bdev->bd_disk; ++ struct blktap_device *tapdev = disk->private_data; ++ ++ if (!tapdev) ++ return -ENXIO; ++ ++ /* NB. we might have bounced a bd trylock by tapdisk. when ++ * failing for reasons not !tapdev, make sure to kick tapdisk ++ * out of destroy wait state again. */ ++ ++ return 0; ++} ++ ++static void ++blktap_device_release(struct gendisk *disk, fmode_t mode) ++{ ++ struct blktap_device *tapdev = disk->private_data; ++ struct block_device *bdev = bdget_disk(disk, 0); ++ struct blktap *tap = dev_to_blktap(tapdev); ++ ++ bdput(bdev); ++ ++ if (!bdev->bd_openers) { ++ set_bit(BLKTAP_DEVICE_CLOSED, &tap->dev_inuse); ++ blktap_ring_kick_user(tap); ++ } ++} ++ ++static int ++blktap_device_getgeo(struct block_device *bd, struct hd_geometry *hg) ++{ ++ /* We don't have real geometry info, but let's at least return ++ values consistent with the size of the device */ ++ sector_t nsect = get_capacity(bd->bd_disk); ++ sector_t cylinders = nsect; ++ ++ hg->heads = 0xff; ++ hg->sectors = 0x3f; ++ sector_div(cylinders, hg->heads * hg->sectors); ++ hg->cylinders = cylinders; ++ if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect) ++ hg->cylinders = 0xffff; ++ return 0; ++} ++ ++static int ++blktap_device_ioctl(struct block_device *bd, fmode_t mode, ++ unsigned command, unsigned long argument) ++{ ++ int i; ++ ++ switch (command) { ++ case CDROMMULTISESSION: ++ BTDBG("FIXME: support multisession CDs later\n"); ++ for (i = 0; i < sizeof(struct cdrom_multisession); i++) ++ if (put_user(0, (char __user *)(argument + i))) ++ return -EFAULT; ++ return 0; ++ ++ case SCSI_IOCTL_GET_IDLUN: ++ if (!access_ok(argument, sizeof(struct scsi_idlun))) ++ return -EFAULT; ++ ++ /* return 0 for now. */ ++ __put_user(0, &((struct scsi_idlun __user *)argument)->dev_id); ++ __put_user(0, ++ &((struct scsi_idlun __user *)argument)->host_unique_id); ++ return 0; ++ ++ default: ++ /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", ++ command);*/ ++ return -EINVAL; /* same return as native Linux */ ++ } ++ ++ return 0; ++} ++ ++static struct block_device_operations blktap_device_file_operations = { ++ .owner = THIS_MODULE, ++ .open = blktap_device_open, ++ .release = blktap_device_release, ++ .ioctl = blktap_device_ioctl, ++ .getgeo = blktap_device_getgeo ++}; ++ ++void ++blktap_device_end_request(struct blktap *tap, ++ struct blktap_request *request, ++ blk_status_t error) ++{ ++ struct blktap_device *tapdev = &tap->device; ++ struct request *rq = request->rq; ++ ++ blktap_ring_unmap_request(tap, request); ++ ++ blktap_ring_free_request(tap, request); ++ ++ dev_dbg(disk_to_dev(tapdev->gd), ++ "end_request: op=%d error=%d bytes=%d\n", ++ rq_data_dir(rq), error, blk_rq_bytes(rq)); ++ ++ blk_mq_end_request(rq, error); ++} ++ ++int ++blktap_device_make_request(struct blktap *tap, struct request *rq) ++{ ++ struct blktap_device *tapdev = &tap->device; ++ struct blktap_request *request; ++ int nsegs; ++ int err; ++ ++ request = blktap_ring_make_request(tap); ++ if (IS_ERR(request)) { ++ err = PTR_ERR(request); ++ request = NULL; ++ ++ if (err == -ENOSPC || err == -ENOMEM) ++ goto stop; ++ ++ goto fail; ++ } ++ ++ if (blk_rq_is_passthrough(rq)) { ++ err = -EOPNOTSUPP; ++ goto fail; ++ } ++ ++ switch (req_op(rq)) { ++ case REQ_OP_DISCARD: ++ request->operation = BLKTAP_OP_TRIM; ++ request->nr_pages = 0; ++ goto submit; ++ case REQ_OP_FLUSH: ++ request->operation = BLKTAP_OP_FLUSH; ++ request->nr_pages = 0; ++ goto submit; ++ case REQ_OP_READ: ++ request->operation = BLKTAP_OP_READ; ++ break; ++ case REQ_OP_WRITE: ++ request->operation = BLKTAP_OP_WRITE; ++ break; ++ default: ++ err = -EOPNOTSUPP; ++ goto fail; ++ } ++ ++ nsegs = blk_rq_map_sg(rq->q, rq, request->sg_table); ++ ++ err = blktap_request_get_pages(tap, request, nsegs); ++ if (err) ++ goto stop; ++ ++ err = blktap_ring_map_request(tap, request); ++ if (err) ++ goto fail; ++ ++submit: ++ request->rq = rq; ++ blktap_ring_submit_request(tap, request); ++ ++ return 0; ++ ++stop: ++ tap->stats.st_oo_req++; ++ err = -EBUSY; ++ ++_out: ++ if (request) ++ blktap_ring_free_request(tap, request); ++ ++ return err; ++fail: ++ if (printk_ratelimit()) ++ dev_warn(disk_to_dev(tapdev->gd), ++ "make request: %d, failing\n", err); ++ goto _out; ++} ++ ++static void cleanup_queue(struct request_queue *rq) ++{ ++ struct blktap *tap = rq->queuedata; ++ struct blktap_device *tapdev = &tap->device; ++ ++ blk_cleanup_queue(rq); ++ blk_mq_free_tag_set(&tapdev->tag_set); ++} ++ ++void blktap_device_run_queues(struct blktap *tap) ++{ ++ struct blktap_device *tapdev = &tap->device; ++ ++ if (!tapdev->gd) ++ return; ++ ++ if (!RING_FULL(&tap->ring.ring)) ++ blk_mq_start_stopped_hw_queues(tapdev->gd->queue, true); ++} ++ ++static void ++blktap_device_restart(struct blktap *tap) ++{ ++ struct blktap_device *dev; ++ ++ dev = &tap->device; ++ ++ mutex_lock(&dev->lock); ++ ++ /* Re-enable calldowns. */ ++ if (dev->gd) { ++ struct request_queue *rq = dev->gd->queue; ++ ++ if (blk_queue_stopped(rq)) ++ blk_mq_start_hw_queues(rq); ++ ++ /* Kick things off immediately. */ ++ blktap_ring_kick_user(tap); ++ } ++ ++ mutex_unlock(&dev->lock); ++} ++ ++void ++blktap_device_configure(struct blktap *tap, ++ struct blktap_device_info *info) ++{ ++ struct blktap_device *tapdev = &tap->device; ++ struct gendisk *gd = tapdev->gd; ++ struct request_queue *rq = gd->queue; ++ struct queue_limits *limits = &rq->limits; ++ ++ set_capacity(gd, info->capacity); ++ set_disk_ro(gd, !!(info->flags & BLKTAP_DEVICE_FLAG_RO)); ++ ++ blk_queue_flag_set(QUEUE_FLAG_VIRT, rq); ++ blk_queue_logical_block_size(rq, info->sector_size); ++ ++ /* Hard sector size and alignment in hardware */ ++ blk_queue_physical_block_size(rq, info->phys_block_size); ++ blk_queue_alignment_offset(rq, info->phys_block_offset); ++ ++ /* Each segment in a request is up to an aligned page in size. */ ++ blk_queue_segment_boundary(rq, PAGE_SIZE - 1); ++ blk_queue_max_segment_size(rq, PAGE_SIZE); ++ ++ /* Ensure a merged request will fit in a single I/O ring slot. */ ++ blk_queue_max_segments(rq, BLKTAP_SEGMENT_MAX); ++ blk_queue_max_segment_size(rq, PAGE_SIZE); ++ ++ /* Make sure buffer addresses are sector-aligned. */ ++ blk_queue_dma_alignment(rq, 511); ++ ++ /* Make sure there is buffer control on high memory pages */ ++ blk_queue_bounce_limit(rq, BLK_BOUNCE_HIGH); ++ ++ /* Enable cache control */ ++ if (info->flags & BLKTAP_DEVICE_FLAG_FLUSH) ++ blk_queue_write_cache(rq, true, false); ++ ++ /* Block discards */ ++ if (info->flags & BLKTAP_DEVICE_FLAG_TRIM) { ++ blk_queue_max_discard_sectors(rq, UINT_MAX); ++ ++ limits->discard_granularity = info->trim_block_size; ++ limits->discard_alignment = info->trim_block_offset; ++ ++ blk_queue_flag_set(QUEUE_FLAG_DISCARD, rq); ++ } ++} ++ ++static int ++blktap_device_validate_info(struct blktap *tap, ++ struct blktap_device_info *info) ++{ ++ struct device *dev = tap->ring.dev; ++ ++ /* sector size is is 2^(n >= 9) */ ++ if (info->sector_size < 512 || ++ !is_power_of_2(info->sector_size)) ++ goto fail; ++ ++ /* make sure capacity won't overflow */ ++ if (!info->capacity || ++ info->capacity > ULLONG_MAX >> ilog2(info->sector_size)) ++ goto fail; ++ ++ /* physical blocks default to logical ones */ ++ if (!(info->flags & BLKTAP_DEVICE_FLAG_PSZ)) { ++ info->phys_block_size = info->sector_size; ++ info->phys_block_offset = 0; ++ } ++ ++ /* phys block size is 2^n and >= logical */ ++ if (info->phys_block_size < info->sector_size || ++ !is_power_of_2(info->phys_block_size)) ++ goto fail; ++ ++ /* alignment offset < physical/logical */ ++ if (info->phys_block_offset % info->sector_size || ++ info->phys_block_offset >= info->phys_block_size) ++ goto fail; ++ ++ /* trim info vs logical addressing */ ++ if (info->flags & BLKTAP_DEVICE_FLAG_TRIM) { ++ ++ if (info->trim_block_size < info->sector_size || ++ !is_power_of_2(info->trim_block_size)) ++ goto fail; ++ ++ if (info->trim_block_offset % info->sector_size || ++ info->trim_block_offset >= info->trim_block_size) ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ dev_err(dev, ++ "capacity: %llu, sector-size: %u/%u+%u, " ++ "trim: %u+%u flags: %#lx\n", ++ info->capacity, info->sector_size, ++ info->phys_block_size, info->phys_block_offset, ++ info->trim_block_size, info->trim_block_offset, ++ info->flags); ++ return -EINVAL; ++} ++ ++int ++blktap_device_resume(struct blktap *tap) ++{ ++ int err; ++ ++ if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse)) ++ return -ENODEV; ++ ++ if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return 0; ++ ++ err = blktap_ring_resume(tap); ++ if (err) ++ return err; ++ ++ BTDBG("restarting device\n"); ++ blktap_device_restart(tap); ++ ++ return 0; ++} ++ ++int ++blktap_device_pause(struct blktap *tap) ++{ ++ struct blktap_device *dev = &tap->device; ++ ++ if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse)) ++ return -ENODEV; ++ ++ if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return 0; ++ ++ mutex_lock(&dev->lock); ++ ++ blk_mq_stop_hw_queues(dev->gd->queue); ++ set_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse); ++ ++ mutex_unlock(&dev->lock); ++ ++ return blktap_ring_pause(tap); ++} ++ ++int ++blktap_device_destroy(struct blktap *tap) ++{ ++ struct blktap_device *tapdev = &tap->device; ++ struct block_device *bdev; ++ struct gendisk *gd; ++ int err; ++ ++ gd = tapdev->gd; ++ if (!gd) ++ return 0; ++ ++ bdev = bdget_disk(gd, 0); ++ ++ err = !mutex_trylock(&bdev->bd_mutex); ++ if (err) { ++ /* NB. avoid a deadlock. the last opener syncs the ++ * bdev holding bd_mutex. */ ++ err = -EBUSY; ++ goto out_nolock; ++ } ++ ++ if (bdev->bd_openers) { ++ err = -EBUSY; ++ goto out; ++ } ++ ++ blk_mq_stop_hw_queues(tapdev->rq); ++ ++ del_gendisk(gd); ++ gd->private_data = NULL; ++ ++ cleanup_queue(gd->queue); ++ ++ put_disk(gd); ++ tapdev->gd = NULL; ++ ++ clear_bit(BLKTAP_DEVICE, &tap->dev_inuse); ++ ++ if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) ++ blktap_control_destroy_tap(tap); ++ ++ err = 0; ++out: ++ mutex_unlock(&bdev->bd_mutex); ++out_nolock: ++ bdput(bdev); ++ ++ return err; ++} ++ ++static void ++blktap_device_fail_queue(struct blktap *tap) ++{ ++ struct blktap_device *tapdev = &tap->device; ++ struct request_queue *q = tapdev->gd->queue; ++ ++ mutex_lock(&tapdev->lock); ++ // Moved inside lock like it was in 4.14 ++ blk_queue_flag_clear(QUEUE_FLAG_STOPPED, q); ++ cleanup_queue(tapdev->gd->queue); ++ ++ mutex_unlock(&tapdev->lock); ++} ++ ++int ++blktap_device_try_destroy(struct blktap *tap) ++{ ++ int err; ++ ++ err = blktap_device_destroy(tap); ++ if (err) ++ blktap_device_fail_queue(tap); ++ ++ return err; ++} ++ ++static inline void flush_requests(struct blktap *tap) ++{ ++ struct blktap_ring *rinfo = &tap->ring; ++ ++ RING_PUSH_REQUESTS(&rinfo->ring); ++ ++ blktap_ring_kick_user(tap); ++} ++ ++static blk_status_t blktap_queue_rq(struct blk_mq_hw_ctx *hctx, ++ const struct blk_mq_queue_data *qd) ++{ ++ struct blktap *tap = hctx->queue->queuedata; ++ struct blktap_device *tapdev = &tap->device; ++ struct blktap_ring *rinfo = &tap->ring; ++ ++ blk_mq_start_request(qd->rq); ++ mutex_lock(&tapdev->lock); ++ if (RING_FULL(&rinfo->ring)) ++ goto out_busy; ++ ++ switch (blktap_device_make_request(tap, qd->rq)) { ++ case -EBUSY: ++ goto out_busy; ++ break; ++ case -EOPNOTSUPP: ++ goto out_err; ++ break; ++ case 0: ++ break; ++ } ++ ++ if (qd->last) ++ flush_requests(tap); ++ ++ mutex_unlock(&tapdev->lock); ++ return BLK_STS_OK; ++ ++// EOPNOTSUPP ++out_err: ++ mutex_unlock(&tapdev->lock); ++ return BLK_STS_IOERR; ++ ++out_busy: ++ blk_mq_stop_hw_queue(hctx); ++ mutex_unlock(&tapdev->lock); ++ return BLK_STS_DEV_RESOURCE; ++} ++ ++static void blktap_complete_rq(struct request *rq) ++{ ++ blk_mq_end_request(rq, blktap_req(rq)->error); ++} ++ ++static void blktap_commit_rqs(struct blk_mq_hw_ctx *hctx) ++{ ++ struct blktap *tap = hctx->queue->queuedata; ++ ++ flush_requests(tap); ++} ++ ++static const struct blk_mq_ops blktap_mq_ops = { ++ .queue_rq = blktap_queue_rq, ++ .complete = blktap_complete_rq, ++ .commit_rqs = blktap_commit_rqs, ++}; ++ ++static struct request_queue *init_queue(struct blktap *tap) ++{ ++ struct blktap_device *tapdev = &tap->device; ++ struct request_queue *rq; ++ ++ memset(&tapdev->tag_set, 0, sizeof(tapdev->tag_set)); ++ tapdev->tag_set.ops = &blktap_mq_ops; ++ tapdev->tag_set.nr_hw_queues = 1; ++ tapdev->tag_set.queue_depth = BLKTAP_RING_SIZE / 2; ++ tapdev->tag_set.numa_node = NUMA_NO_NODE; ++ tapdev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; ++ tapdev->tag_set.cmd_size = 0; ++ tapdev->tag_set.driver_data = tap; ++ ++ if (blk_mq_alloc_tag_set(&tapdev->tag_set)) ++ return NULL; ++ ++ rq = blk_mq_init_queue(&tapdev->tag_set); ++ if (IS_ERR(rq)) { ++ blk_mq_free_tag_set(&tapdev->tag_set); ++ return rq; ++ } ++ ++ rq->queuedata = tap; ++ ++ tapdev->rq = rq; ++ ++ return rq; ++} ++ ++int ++blktap_device_create(struct blktap *tap, struct blktap_device_info *info) ++{ ++ int minor, err; ++ struct gendisk *gd; ++ struct request_queue *rq; ++ struct blktap_device *tapdev; ++ ++ gd = NULL; ++ rq = NULL; ++ tapdev = &tap->device; ++ minor = tap->minor; ++ ++ if (test_bit(BLKTAP_DEVICE, &tap->dev_inuse)) ++ return -EEXIST; ++ ++ if (blktap_device_validate_info(tap, info)) ++ return -EINVAL; ++ ++ gd = alloc_disk(1); ++ if (!gd) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ ++ if (minor < 26) { ++ sprintf(gd->disk_name, "td%c", 'a' + minor % 26); ++ } else if (minor < (26 + 1) * 26) { ++ sprintf(gd->disk_name, "td%c%c", ++ 'a' + minor / 26 - 1,'a' + minor % 26); ++ } else { ++ const unsigned int m1 = (minor / 26 - 1) / 26 - 1; ++ const unsigned int m2 = (minor / 26 - 1) % 26; ++ const unsigned int m3 = minor % 26; ++ sprintf(gd->disk_name, "td%c%c%c", ++ 'a' + m1, 'a' + m2, 'a' + m3); ++ } ++ ++ gd->major = blktap_device_major; ++ gd->first_minor = minor; ++ gd->fops = &blktap_device_file_operations; ++ gd->private_data = tapdev; ++ ++ rq = init_queue(tap); ++ if (!rq) { ++ err = -ENOMEM; ++ goto fail; ++ } ++ ++ gd->queue = rq; ++ tapdev->gd = gd; ++ ++ blktap_device_configure(tap, info); ++ add_disk(gd); ++ ++ set_bit(BLKTAP_DEVICE, &tap->dev_inuse); ++ ++ dev_info(disk_to_dev(gd), ++ "sector-size: %u/%u+%u capacity: %llu" ++ " discard: %u+%u flush: %#lx\n", ++ queue_logical_block_size(rq), ++ queue_physical_block_size(rq), ++ queue_alignment_offset(rq), ++ (unsigned long long)get_capacity(gd), ++ rq->limits.discard_granularity, ++ queue_discard_alignment(rq), ++ rq->queue_flags); ++ ++ return 0; ++ ++fail: ++ if (gd) ++ del_gendisk(gd); ++ if (rq) ++ cleanup_queue(rq); ++ ++ return err; ++} ++ ++size_t ++blktap_device_debug(struct blktap *tap, char *buf, size_t size) ++{ ++ struct gendisk *disk = tap->device.gd; ++ struct request_queue *q; ++ struct block_device *bdev; ++ char *s = buf, *end = buf + size; ++ ++ if (!disk) ++ return 0; ++ ++ q = disk->queue; ++ ++ s += snprintf(s, end - s, ++ "disk capacity:%llu sector size:%u\n", ++ (unsigned long long)get_capacity(disk), ++ queue_logical_block_size(q)); ++ ++ s += snprintf(s, end - s, ++ "queue flags:%#lx stopped:%d\n", ++ q->queue_flags, blk_queue_stopped(q)); ++ ++ bdev = bdget_disk(disk, 0); ++ if (bdev) { ++ s += snprintf(s, end - s, ++ "bdev openers:%d closed:%d\n", ++ bdev->bd_openers, ++ test_bit(BLKTAP_DEVICE_CLOSED, &tap->dev_inuse)); ++ bdput(bdev); ++ } ++ ++ return s - buf; ++} ++ ++int __init ++blktap_device_init() ++{ ++ int major; ++ ++ /* Dynamically allocate a major for this device */ ++ major = register_blkdev(0, "tapdev"); ++ if (major < 0) { ++ BTERR("Couldn't register blktap device\n"); ++ return -ENOMEM; ++ } ++ ++ blktap_device_major = major; ++ BTINFO("blktap device major %d\n", major); ++ ++ return 0; ++} ++ ++void ++blktap_device_exit(void) ++{ ++ if (blktap_device_major) ++ unregister_blkdev(blktap_device_major, "tapdev"); ++} +--- /dev/null ++++ b/drivers/block/blktap/request.c +@@ -0,0 +1,427 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "blktap.h" ++ ++/* max pages per shared pool. just to prevent accidental dos. */ ++#define POOL_MAX_PAGES (256*BLKTAP_SEGMENT_MAX) ++ ++/* default page pool size. when considering to shrink a shared pool, ++ * note that paused tapdisks may grab a whole lot of pages for a long ++ * time. */ ++#define POOL_DEFAULT_PAGES (2 * BLKTAP_RING_SIZE * BLKTAP_SEGMENT_MAX) ++ ++/* max number of pages allocatable per request. */ ++#define POOL_MAX_REQUEST_PAGES BLKTAP_SEGMENT_MAX ++ ++/* min request structs per pool. These grow dynamically. */ ++#define POOL_MIN_REQS BLKTAP_RING_SIZE ++ ++static struct kset *pool_set; ++ ++#define kobj_to_pool(_kobj) \ ++ container_of(_kobj, struct blktap_page_pool, kobj) ++ ++static struct kmem_cache *request_cache; ++static mempool_t *request_pool; ++ ++static void ++__page_pool_wake(struct blktap_page_pool *pool) ++{ ++ mempool_t *mem = pool->bufs; ++ ++ /* ++ NB. slightly wasteful to always wait for a full segment ++ set. but this ensures the next disk makes ++ progress. presently, the repeated request struct ++ alloc/release cycles would otherwise keep everyone spinning. ++ */ ++ ++ if (mem->curr_nr >= POOL_MAX_REQUEST_PAGES) ++ wake_up(&pool->wait); ++} ++ ++int ++blktap_request_get_pages(struct blktap *tap, ++ struct blktap_request *request, int nr_pages) ++{ ++ struct blktap_page_pool *pool = tap->pool; ++ mempool_t *mem = pool->bufs; ++ struct page *page; ++ ++ BUG_ON(request->nr_pages != 0); ++ BUG_ON(nr_pages > POOL_MAX_REQUEST_PAGES); ++ ++ if (mem->curr_nr < nr_pages) ++ return -ENOMEM; ++ ++ /* NB. avoid thundering herds of tapdisks colliding. */ ++ spin_lock(&pool->lock); ++ ++ if (mem->curr_nr < nr_pages) { ++ spin_unlock(&pool->lock); ++ return -ENOMEM; ++ } ++ ++ while (request->nr_pages < nr_pages) { ++ page = mempool_alloc(mem, GFP_NOWAIT); ++ BUG_ON(!page); ++ request->pages[request->nr_pages++] = page; ++ } ++ ++ spin_unlock(&pool->lock); ++ ++ return 0; ++} ++ ++static void ++blktap_request_put_pages(struct blktap *tap, ++ struct blktap_request *request) ++{ ++ struct blktap_page_pool *pool = tap->pool; ++ struct page *page; ++ ++ while (request->nr_pages) { ++ page = request->pages[--request->nr_pages]; ++ mempool_free(page, pool->bufs); ++ } ++} ++ ++size_t ++blktap_request_debug(struct blktap *tap, char *buf, size_t size) ++{ ++ struct blktap_page_pool *pool = tap->pool; ++ mempool_t *mem = pool->bufs; ++ char *s = buf, *end = buf + size; ++ ++ s += snprintf(buf, end - s, ++ "pool:%s pages:%d free:%d\n", ++ kobject_name(&pool->kobj), ++ mem->min_nr, mem->curr_nr); ++ ++ return s - buf; ++} ++ ++static void ++blktap_request_ctor(void *obj) ++{ ++ struct blktap_request *request = obj; ++ ++ memset(request, 0, sizeof(*request)); ++ sg_init_table(request->sg_table, ARRAY_SIZE(request->sg_table)); ++} ++ ++struct blktap_request* ++blktap_request_alloc(struct blktap *tap) ++{ ++ struct blktap_request *request; ++ ++ request = mempool_alloc(request_pool, GFP_NOWAIT); ++ if (request) { ++ blktap_request_ctor(request); ++ request->tap = tap; ++ } ++ ++ return request; ++} ++ ++void ++blktap_request_free(struct blktap *tap, ++ struct blktap_request *request) ++{ ++ blktap_request_put_pages(tap, request); ++ ++ mempool_free(request, request_pool); ++ ++ __page_pool_wake(tap->pool); ++} ++ ++void ++blktap_request_bounce(struct blktap *tap, ++ struct blktap_request *request, ++ int seg, int write) ++{ ++ struct scatterlist *sg = &request->sg_table[seg]; ++ void *s, *p; ++ ++ if (!sg || !request) ++ return; ++ ++ BUG_ON(seg >= request->nr_pages); ++ ++ s = sg_virt(sg); ++ p = page_address(request->pages[seg]); ++ if (!s || !p) ++ return; ++ ++ p = (uint8_t*)p + sg->offset; ++ if (write) ++ memcpy(p, s, sg->length); ++ else ++ memcpy(s, p, sg->length); ++} ++ ++static int ++blktap_page_pool_resize(struct blktap_page_pool *pool, int target) ++{ ++ mempool_t *bufs = pool->bufs; ++ int err; ++ ++ /* NB. mempool asserts min_nr >= 1 */ ++ target = max(1, target); ++ ++ err = mempool_resize(bufs, target); ++ if (err) ++ return err; ++ ++ __page_pool_wake(pool); ++ ++ return 0; ++} ++ ++struct pool_attribute { ++ struct attribute attr; ++ ++ ssize_t (*show)(struct blktap_page_pool *pool, ++ char *buf); ++ ++ ssize_t (*store)(struct blktap_page_pool *pool, ++ const char *buf, size_t count); ++}; ++ ++#define kattr_to_pool_attr(_kattr) \ ++ container_of(_kattr, struct pool_attribute, attr) ++ ++static ssize_t ++blktap_page_pool_show_size(struct blktap_page_pool *pool, ++ char *buf) ++{ ++ mempool_t *mem = pool->bufs; ++ return sprintf(buf, "%d", mem->min_nr); ++} ++ ++static ssize_t ++blktap_page_pool_store_size(struct blktap_page_pool *pool, ++ const char *buf, size_t size) ++{ ++ int target; ++ ++ /* ++ * NB. target fixup to avoid undesired results. less than a ++ * full segment set can wedge the disk. much more than a ++ * couple times the physical queue depth is rarely useful. ++ */ ++ ++ target = simple_strtoul(buf, NULL, 0); ++ target = max(POOL_MAX_REQUEST_PAGES, target); ++ target = min(target, POOL_MAX_PAGES); ++ ++ return blktap_page_pool_resize(pool, target) ? : size; ++} ++ ++static struct pool_attribute blktap_page_pool_attr_size = ++ __ATTR(size, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, ++ blktap_page_pool_show_size, ++ blktap_page_pool_store_size); ++ ++static ssize_t ++blktap_page_pool_show_free(struct blktap_page_pool *pool, ++ char *buf) ++{ ++ mempool_t *mem = pool->bufs; ++ return sprintf(buf, "%d", mem->curr_nr); ++} ++ ++static struct pool_attribute blktap_page_pool_attr_free = ++ __ATTR(free, S_IRUSR|S_IRGRP|S_IROTH, ++ blktap_page_pool_show_free, ++ NULL); ++ ++static struct attribute *blktap_page_pool_attrs[] = { ++ &blktap_page_pool_attr_size.attr, ++ &blktap_page_pool_attr_free.attr, ++ NULL, ++}; ++ ++static inline struct kobject* ++__blktap_kset_find_obj(struct kset *kset, const char *name) ++{ ++ struct kobject *k; ++ struct kobject *ret = NULL; ++ ++ spin_lock(&kset->list_lock); ++ list_for_each_entry(k, &kset->list, entry) { ++ if (kobject_name(k) && !strcmp(kobject_name(k), name)) { ++ ret = kobject_get(k); ++ break; ++ } ++ } ++ spin_unlock(&kset->list_lock); ++ return ret; ++} ++ ++static ssize_t ++blktap_page_pool_show_attr(struct kobject *kobj, struct attribute *kattr, ++ char *buf) ++{ ++ struct blktap_page_pool *pool = kobj_to_pool(kobj); ++ struct pool_attribute *attr = kattr_to_pool_attr(kattr); ++ ++ if (attr->show) ++ return attr->show(pool, buf); ++ ++ return -EIO; ++} ++ ++static ssize_t ++blktap_page_pool_store_attr(struct kobject *kobj, struct attribute *kattr, ++ const char *buf, size_t size) ++{ ++ struct blktap_page_pool *pool = kobj_to_pool(kobj); ++ struct pool_attribute *attr = kattr_to_pool_attr(kattr); ++ ++ if (attr->show) ++ return attr->store(pool, buf, size); ++ ++ return -EIO; ++} ++ ++static struct sysfs_ops blktap_page_pool_sysfs_ops = { ++ .show = blktap_page_pool_show_attr, ++ .store = blktap_page_pool_store_attr, ++}; ++ ++static void ++blktap_page_pool_release(struct kobject *kobj) ++{ ++ struct blktap_page_pool *pool = kobj_to_pool(kobj); ++ mempool_destroy(pool->bufs); ++ kfree(pool); ++} ++ ++struct kobj_type blktap_page_pool_ktype = { ++ .release = blktap_page_pool_release, ++ .sysfs_ops = &blktap_page_pool_sysfs_ops, ++ .default_attrs = blktap_page_pool_attrs, ++}; ++ ++static void* ++__mempool_page_alloc(gfp_t gfp_mask, void *pool_data) ++{ ++ struct page *page; ++ ++ if (!gfpflags_allow_blocking(gfp_mask)) ++ return NULL; ++ ++ page = alloc_page(gfp_mask); ++ if (page) ++ SetPageReserved(page); ++ ++ return page; ++} ++ ++static void ++__mempool_page_free(void *element, void *pool_data) ++{ ++ struct page *page = element; ++ ++ ClearPageReserved(page); ++ put_page(page); ++} ++ ++static struct kobject* ++blktap_page_pool_create(const char *name, int nr_pages) ++{ ++ struct blktap_page_pool *pool; ++ int err; ++ ++ pool = kzalloc(sizeof(*pool), GFP_KERNEL); ++ if (!pool) ++ goto fail; ++ ++ spin_lock_init(&pool->lock); ++ init_waitqueue_head(&pool->wait); ++ ++ pool->bufs = mempool_create(nr_pages, ++ __mempool_page_alloc, __mempool_page_free, ++ pool); ++ if (!pool->bufs) ++ goto fail_pool; ++ ++ kobject_init(&pool->kobj, &blktap_page_pool_ktype); ++ pool->kobj.kset = pool_set; ++ err = kobject_add(&pool->kobj, &pool_set->kobj, "%s", name); ++ if (err) ++ goto fail_bufs; ++ ++ return &pool->kobj; ++ ++ kobject_del(&pool->kobj); ++fail_bufs: ++ mempool_destroy(pool->bufs); ++fail_pool: ++ kfree(pool); ++fail: ++ return NULL; ++} ++ ++struct blktap_page_pool* ++blktap_page_pool_get(const char *name) ++{ ++ struct kobject *kobj; ++ ++ kobj = __blktap_kset_find_obj(pool_set, name); ++ if (!kobj) ++ kobj = blktap_page_pool_create(name, ++ POOL_DEFAULT_PAGES); ++ if (!kobj) ++ return ERR_PTR(-ENOMEM); ++ ++ return kobj_to_pool(kobj); ++} ++ ++int __init ++blktap_page_pool_init(struct kobject *parent) ++{ ++ request_cache = ++ kmem_cache_create("blktap-request", ++ sizeof(struct blktap_request), 0, ++ 0, NULL); ++ if (!request_cache) ++ return -ENOMEM; ++ ++ request_pool = ++ mempool_create_slab_pool(POOL_MIN_REQS, request_cache); ++ if (!request_pool) ++ return -ENOMEM; ++ ++ pool_set = kset_create_and_add("pools", NULL, parent); ++ if (!pool_set) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++void ++blktap_page_pool_exit(void) ++{ ++ if (pool_set) { ++ BUG_ON(!list_empty(&pool_set->list)); ++ kset_unregister(pool_set); ++ pool_set = NULL; ++ } ++ ++ if (request_pool) { ++ mempool_destroy(request_pool); ++ request_pool = NULL; ++ } ++ ++ if (request_cache) { ++ kmem_cache_destroy(request_cache); ++ request_cache = NULL; ++ } ++} +--- /dev/null ++++ b/drivers/block/blktap/ring.c +@@ -0,0 +1,814 @@ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "blktap.h" ++ ++#define BLKTAP_DESTROY_RETRY_PERIOD (HZ/10) /*100 msec*/ ++ ++int blktap_ring_major; ++static struct cdev blktap_ring_cdev; ++ ++ /* ++ * BLKTAP - immediately before the mmap area, ++ * we have a bunch of pages reserved for shared memory rings. ++ */ ++#define RING_PAGES 1 ++ ++#define BLKTAP_INFO_SIZE_AT(_memb) \ ++ offsetof(struct blktap_device_info, _memb) + \ ++ sizeof(((struct blktap_device_info*)0)->_memb) ++ ++static void ++blktap_ring_read_response(struct blktap *tap, ++ const struct blktap_ring_response *rsp) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ struct blktap_request *request; ++ int usr_idx, err; ++ ++ request = NULL; ++ ++ usr_idx = rsp->id; ++ if (usr_idx < 0 || usr_idx >= BLKTAP_RING_SIZE) { ++ err = -ERANGE; ++ goto invalid; ++ } ++ ++ request = ring->pending[usr_idx]; ++ ++ if (!request) { ++ err = -ESRCH; ++ goto invalid; ++ } ++ ++ if (rsp->operation != request->operation) { ++ err = -EINVAL; ++ goto invalid; ++ } ++ ++ dev_dbg(ring->dev, ++ "request %d [%p] response: %d\n", ++ request->usr_idx, request, rsp->status); ++ ++ err = rsp->status == BLKTAP_RSP_OKAY ? BLK_STS_OK : BLK_STS_IOERR; ++end_request: ++ blktap_device_end_request(tap, request, err); ++ return; ++ ++invalid: ++ dev_warn(ring->dev, ++ "invalid response, idx:%d status:%d op:%d/%d: err %d\n", ++ usr_idx, rsp->status, ++ rsp->operation, request->operation, ++ err); ++ if (request) ++ goto end_request; ++} ++ ++static void ++blktap_read_ring(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ struct blktap_ring_response rsp; ++ RING_IDX rc, rp; ++ ++ if (!ring->vma) { ++ return; ++ } ++ ++ /* for each outstanding message on the ring */ ++ rp = ring->ring.sring->rsp_prod; ++ rmb(); ++ ++ for (rc = ring->ring.rsp_cons; rc != rp; rc++) { ++ memcpy(&rsp, RING_GET_RESPONSE(&ring->ring, rc), sizeof(rsp)); ++ blktap_ring_read_response(tap, &rsp); ++ } ++ ++ ring->ring.rsp_cons = rc; ++ ++ blktap_device_run_queues(tap); ++} ++ ++#define MMAP_VADDR(_start, _req, _seg) \ ++ ((_start) + \ ++ ((_req) * BLKTAP_SEGMENT_MAX * BLKTAP_PAGE_SIZE) + \ ++ ((_seg) * BLKTAP_PAGE_SIZE)) ++ ++static vm_fault_t blktap_ring_fault(struct vm_fault *vmf) ++{ ++ return VM_FAULT_SIGBUS; ++} ++ ++static void ++blktap_ring_fail_pending(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ struct blktap_request *request; ++ int usr_idx; ++ ++ for (usr_idx = 0; usr_idx < BLKTAP_RING_SIZE; usr_idx++) { ++ request = ring->pending[usr_idx]; ++ if (!request) ++ continue; ++ ++ request->rq->cmd_flags |= RQF_QUIET; ++ blktap_device_end_request(tap, request, BLK_STS_IOERR); ++ } ++} ++ ++static void ++blktap_ring_vm_close(struct vm_area_struct *vma) ++{ ++ struct blktap *tap = vma->vm_private_data; ++ struct blktap_ring *ring = &tap->ring; ++ struct page *page = virt_to_page(ring->ring.sring); ++ ++ blktap_ring_fail_pending(tap); ++ ++ zap_page_range(vma, vma->vm_start, PAGE_SIZE); ++ ClearPageReserved(page); ++ __free_page(page); ++ ++ ring->vma = NULL; ++ wake_up_interruptible(&tap->remove_wait); ++ ++ if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) ++ blktap_control_destroy_tap(tap); ++} ++ ++static struct vm_operations_struct blktap_ring_vm_operations = { ++ .close = blktap_ring_vm_close, ++ .fault = blktap_ring_fault, ++}; ++ ++int ++blktap_ring_map_segment(struct blktap *tap, ++ struct blktap_request *request, ++ int seg) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ unsigned long uaddr; ++ int ret; ++ ++ down_write(&ring->vma->vm_mm->mmap_sem); ++ ++ uaddr = MMAP_VADDR(ring->user_vstart, request->usr_idx, seg); ++ ret = vm_insert_page(ring->vma, uaddr, request->pages[seg]); ++ ++ up_write(&ring->vma->vm_mm->mmap_sem); ++ ++ return ret; ++} ++ ++int ++blktap_ring_map_request(struct blktap *tap, ++ struct blktap_request *request) ++{ ++ int seg, err = 0; ++ int write; ++ ++ write = request->operation == BLKTAP_OP_WRITE; ++ ++ for (seg = 0; seg < request->nr_pages; seg++) { ++ if (write) ++ blktap_request_bounce(tap, request, seg, write); ++ ++ err = blktap_ring_map_segment(tap, request, seg); ++ if (err) ++ break; ++ } ++ ++ if (err) ++ blktap_ring_unmap_request(tap, request); ++ ++ return err; ++} ++ ++void ++blktap_ring_unmap_request(struct blktap *tap, ++ struct blktap_request *request) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ unsigned long uaddr; ++ unsigned size; ++ int seg, read; ++ ++ uaddr = MMAP_VADDR(ring->user_vstart, request->usr_idx, 0); ++ size = request->nr_pages << PAGE_SHIFT; ++ read = request->operation == BLKTAP_OP_READ; ++ ++ if (read) ++ for (seg = 0; seg < request->nr_pages; seg++) ++ blktap_request_bounce(tap, request, seg, !read); ++ ++ zap_page_range(ring->vma, uaddr, size); ++} ++ ++void ++blktap_ring_free_request(struct blktap *tap, ++ struct blktap_request *request) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ ++ ring->pending[request->usr_idx] = NULL; ++ atomic_dec(&ring->n_pending); ++ wake_up_interruptible(&tap->remove_wait); ++ ++ blktap_request_free(tap, request); ++} ++ ++struct blktap_request* ++blktap_ring_make_request(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ struct blktap_request *request; ++ int usr_idx; ++ ++ if (RING_FULL(&ring->ring)) ++ return ERR_PTR(-ENOSPC); ++ ++ request = blktap_request_alloc(tap); ++ if (!request) ++ return ERR_PTR(-ENOMEM); ++ ++ for (usr_idx = 0; usr_idx < BLKTAP_RING_SIZE; usr_idx++) ++ if (!ring->pending[usr_idx]) ++ break; ++ ++ BUG_ON(usr_idx >= BLKTAP_RING_SIZE); ++ ++ request->tap = tap; ++ request->usr_idx = usr_idx; ++ ++ ring->pending[usr_idx] = request; ++ atomic_inc(&ring->n_pending); ++ wake_up_interruptible(&tap->remove_wait); ++ ++ return request; ++} ++ ++static int ++blktap_ring_make_rw_request(struct blktap *tap, ++ struct blktap_request *request, ++ struct blktap_ring_request *breq) ++{ ++ struct scatterlist *sg; ++ unsigned int i, nsecs = 0; ++ ++ blktap_for_each_sg(sg, request, i) { ++ struct blktap_segment *seg = &breq->u.rw.seg[i]; ++ int first, count; ++ ++ count = sg->length >> 9; ++ first = sg->offset >> 9; ++ ++ seg->first_sect = first; ++ seg->last_sect = first + count - 1; ++ ++ nsecs += count; ++ } ++ ++ breq->u.rw.sector_number = blk_rq_pos(request->rq); ++ ++ return nsecs; ++} ++ ++static int ++blktap_ring_make_tr_request(struct blktap *tap, ++ struct blktap_request *request, ++ struct blktap_ring_request *breq) ++{ ++ struct bio *bio = request->rq->bio; ++ unsigned int nsecs; ++ ++ breq->u.tr.nr_sectors = nsecs = bio_sectors(bio); ++ breq->u.tr.sector_number = bio->bi_iter.bi_sector; ++ ++ return nsecs; ++} ++ ++void ++blktap_ring_submit_request(struct blktap *tap, ++ struct blktap_request *request) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ struct blktap_ring_request *breq; ++ int nsecs; ++ ++ dev_dbg(ring->dev, ++ "request %d [%p] submit\n", request->usr_idx, request); ++ ++ breq = RING_GET_REQUEST(&ring->ring, ring->ring.req_prod_pvt); ++ ++ breq->id = request->usr_idx; ++ breq->__pad = 0; ++ breq->operation = request->operation; ++ breq->nr_segments = request->nr_pages; ++ ++ switch (breq->operation) { ++ case BLKTAP_OP_READ: ++ nsecs = blktap_ring_make_rw_request(tap, request, breq); ++ ++ tap->stats.st_rd_sect += nsecs; ++ tap->stats.st_rd_req++; ++ break; ++ ++ case BLKTAP_OP_WRITE: ++ nsecs = blktap_ring_make_rw_request(tap, request, breq); ++ ++ tap->stats.st_wr_sect += nsecs; ++ tap->stats.st_wr_req++; ++ break; ++ ++ case BLKTAP_OP_FLUSH: ++ breq->u.rw.sector_number = 0; ++ tap->stats.st_fl_req++; ++ break; ++ ++ case BLKTAP_OP_TRIM: ++ nsecs = blktap_ring_make_tr_request(tap, request, breq); ++ ++ tap->stats.st_tr_sect += nsecs; ++ tap->stats.st_tr_req++; ++ break; ++ default: ++ BUG(); ++ } ++ ++ ring->ring.req_prod_pvt++; ++} ++ ++static int ++blktap_ring_open(struct inode *inode, struct file *filp) ++{ ++ struct blktap *tap = NULL; ++ int minor; ++ ++ minor = iminor(inode); ++ ++ if (minor < blktap_max_minor) ++ tap = blktaps[minor]; ++ ++ if (!tap) ++ return -ENXIO; ++ ++ if (test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) ++ return -ENXIO; ++ ++ if (tap->ring.task) ++ return -EBUSY; ++ ++ filp->private_data = tap; ++ tap->ring.task = current; ++ ++ return 0; ++} ++ ++static void ++blktap_destroy_work(struct work_struct *work) ++{ ++ struct blktap *tap ++ = container_of(work, struct blktap, destroy_work.work); ++ ++ if (blktap_device_try_destroy(tap)) { ++ schedule_delayed_work(&tap->destroy_work, BLKTAP_DESTROY_RETRY_PERIOD); ++ } ++} ++ ++static int ++blktap_ring_release(struct inode *inode, struct file *filp) ++{ ++ struct blktap *tap = filp->private_data; ++ ++ tap->ring.task = NULL; ++ ++ if (blktap_device_try_destroy(tap)) { ++ INIT_DELAYED_WORK(&tap->destroy_work, blktap_destroy_work); ++ schedule_delayed_work(&tap->destroy_work, BLKTAP_DESTROY_RETRY_PERIOD); ++ } ++ ++ return 0; ++} ++ ++static int ++blktap_ring_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ struct blktap *tap = filp->private_data; ++ struct blktap_ring *ring = &tap->ring; ++ struct blktap_sring *sring; ++ struct page *page = NULL; ++ int err; ++ ++ if (ring->vma) ++ return -EBUSY; ++ ++ page = alloc_page(GFP_KERNEL|__GFP_ZERO); ++ if (!page) ++ return -ENOMEM; ++ ++ SetPageReserved(page); ++ ++ err = vm_insert_page(vma, vma->vm_start, page); ++ if (err) ++ goto fail; ++ ++ sring = page_address(page); ++ SHARED_RING_INIT(sring); ++ FRONT_RING_INIT(&ring->ring, sring, PAGE_SIZE); ++ ++ ring->ring_vstart = vma->vm_start; ++ ring->user_vstart = ring->ring_vstart + PAGE_SIZE; ++ ++ vma->vm_private_data = tap; ++ ++ vma->vm_flags |= VM_DONTCOPY; ++ vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; ++ ++ vma->vm_ops = &blktap_ring_vm_operations; ++ ++ ring->vma = vma; ++ wake_up_interruptible(&tap->remove_wait); ++ ++ return 0; ++ ++fail: ++ if (page) { ++ zap_page_range(vma, vma->vm_start, PAGE_SIZE); ++ ClearPageReserved(page); ++ __free_page(page); ++ } ++ ++ return err; ++} ++ ++static inline void ++blktap_ring_set_message(struct blktap *tap, int msg) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ ++ if (ring->ring.sring) ++ ring->ring.sring->pad[0] = msg; ++} ++ ++static long ++blktap_ring_ioctl(struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct blktap *tap = filp->private_data; ++ struct blktap_ring *ring = &tap->ring; ++ void __user *ptr = (void *)arg; ++ int err; ++ ++ BTDBG("%d: cmd: %u, arg: %lu\n", tap->minor, cmd, arg); ++ ++ if (!ring->vma || ring->vma->vm_mm != current->mm) ++ return -EACCES; ++ ++ switch(cmd) { ++ case BLKTAP_IOCTL_RESPOND: ++ ++ blktap_read_ring(tap); ++ return 0; ++ ++ case BLKTAP_IOCTL_CREATE_DEVICE_COMPAT: { ++ struct blktap_device_info info; ++ struct blktap2_params params; ++ ++ if (copy_from_user(¶ms, ptr, sizeof(params))) ++ return -EFAULT; ++ ++ info.capacity = params.capacity; ++ info.sector_size = params.sector_size; ++ info.flags = 0; ++ ++ err = blktap_device_create(tap, &info); ++ if (err) ++ return err; ++ ++ if (params.name[0]) { ++ strncpy(tap->name, params.name, sizeof(params.name)); ++ tap->name[sizeof(tap->name)-1] = 0; ++ } ++ ++ return 0; ++ } ++ ++ case BLKTAP_IOCTL_CREATE_DEVICE: { ++ struct blktap_device_info __user *ptr = (void *)arg; ++ struct blktap_device_info info; ++ unsigned long mask; ++ size_t base_sz, sz; ++ ++ mask = BLKTAP_DEVICE_FLAG_RO; ++ mask |= BLKTAP_DEVICE_FLAG_PSZ; ++ mask |= BLKTAP_DEVICE_FLAG_FLUSH; ++ mask |= BLKTAP_DEVICE_FLAG_TRIM; ++ ++ memset(&info, 0, sizeof(info)); ++ sz = base_sz = BLKTAP_INFO_SIZE_AT(flags); ++ ++ if (copy_from_user(&info, ptr, sz)) ++ return -EFAULT; ++ ++ if ((info.flags & BLKTAP_DEVICE_FLAG_PSZ) != 0) ++ sz = BLKTAP_INFO_SIZE_AT(phys_block_offset); ++ ++ if (info.flags & BLKTAP_DEVICE_FLAG_TRIM) ++ sz = BLKTAP_INFO_SIZE_AT(trim_block_offset); ++ ++ if (sz > base_sz) ++ if (copy_from_user(&info, ptr, sz)) ++ return -EFAULT; ++ ++ if (put_user(info.flags & mask, &ptr->flags)) ++ return -EFAULT; ++ ++ return blktap_device_create(tap, &info); ++ } ++ ++ case BLKTAP_IOCTL_REMOVE_DEVICE: ++ ++ return blktap_device_destroy(tap); ++ ++ case BLKTAP2_IOCTL_SET_PARAMS: { ++ struct blktap2_params params; ++ struct blktap_device_info info; ++ ++ if (!arg) ++ return -EINVAL; ++ ++ if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return -EINVAL; ++ ++ if (copy_from_user(¶ms, (struct blktap_params __user *)arg, ++ sizeof(params))) { ++ BTERR("failed to get params\n"); ++ return -EFAULT; ++ } ++ ++ info.capacity = params.capacity; ++ info.sector_size = params.sector_size; ++ info.flags = 0; ++ ++ blktap_device_configure(tap, &info); ++ ++ if (params.name[0]) { ++ strncpy(tap->name, params.name, sizeof(params.name)); ++ tap->name[sizeof(tap->name)-1] = 0; ++ } ++ ++ return 0; ++ } ++ ++ case BLKTAP2_IOCTL_PAUSE: ++ if (!test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) ++ return -EINVAL; ++ ++ set_bit(BLKTAP_PAUSED, &tap->dev_inuse); ++ clear_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse); ++ ++ blktap_ring_set_message(tap, 0); ++ wake_up_interruptible(&tap->remove_wait); ++ ++ return 0; ++ ++ case BLKTAP2_IOCTL_REOPEN: ++ if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return -EINVAL; ++ ++ if (!arg) ++ return -EINVAL; ++ ++ if (copy_to_user((char __user *)arg, ++ tap->name, ++ strlen(tap->name) + 1)) ++ return -EFAULT; ++ ++ blktap_ring_set_message(tap, 0); ++ wake_up_interruptible(&tap->remove_wait); ++ ++ return 0; ++ ++ case BLKTAP2_IOCTL_RESUME: ++ if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return -EINVAL; ++ ++ tap->ring.response = (int)arg; ++ if (!tap->ring.response) ++ clear_bit(BLKTAP_PAUSED, &tap->dev_inuse); ++ ++ blktap_ring_set_message(tap, 0); ++ wake_up_interruptible(&tap->remove_wait); ++ ++ return 0; ++ } ++ ++ return -ENOTTY; ++} ++ ++static unsigned int blktap_ring_poll(struct file *filp, poll_table *wait) ++{ ++ struct blktap *tap = filp->private_data; ++ struct blktap_ring *ring = &tap->ring; ++ struct blktap_device *tapdev = &tap->device; ++ int work; ++ ++ poll_wait(filp, &tap->pool->wait, wait); ++ poll_wait(filp, &ring->poll_wait, wait); ++ ++ mutex_lock(&tapdev->lock); ++ if (ring->vma) ++ blktap_device_run_queues(tap); ++ ++ work = ring->ring.sring->rsp_prod != ring->ring.sring->req_prod; ++ mutex_unlock(&tapdev->lock); ++ ++ if (work || ++ *BLKTAP_RING_MESSAGE(ring->ring.sring) || ++ test_and_clear_bit(BLKTAP_DEVICE_CLOSED, &tap->dev_inuse)) ++ return POLLIN | POLLRDNORM; ++ ++ return 0; ++} ++ ++static struct file_operations blktap_ring_file_operations = { ++ .owner = THIS_MODULE, ++ .open = blktap_ring_open, ++ .release = blktap_ring_release, ++ .unlocked_ioctl = blktap_ring_ioctl, ++ .mmap = blktap_ring_mmap, ++ .poll = blktap_ring_poll, ++}; ++ ++void ++blktap_ring_kick_user(struct blktap *tap) ++{ ++ wake_up(&tap->ring.poll_wait); ++} ++ ++int ++blktap_ring_resume(struct blktap *tap) ++{ ++ int err; ++ struct blktap_ring *ring = &tap->ring; ++ ++ if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return -EINVAL; ++ ++ /* set shared flag for resume */ ++ ring->response = 0; ++ ++ blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_RESUME); ++ blktap_ring_kick_user(tap); ++ ++ wait_event_interruptible(tap->remove_wait, ring->response || ++ !test_bit(BLKTAP_PAUSED, &tap->dev_inuse)); ++ ++ err = ring->response; ++ ring->response = 0; ++ ++ BTDBG("err: %d\n", err); ++ ++ if (err) ++ return err; ++ ++ if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++int ++blktap_ring_pause(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ ++ if (!test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) ++ return -EINVAL; ++ ++ BTDBG("draining queue\n"); ++ for (;;) { ++ int r; ++ ++ r = wait_event_interruptible_timeout(tap->remove_wait, ++ atomic_read(&ring->n_pending) == 0, ++ HZ / 10); ++ if (r == -ERESTARTSYS) ++ return -EAGAIN; ++ if (r > 0) ++ break; ++ } ++ ++ blktap_ring_set_message(tap, BLKTAP2_RING_MESSAGE_PAUSE); ++ blktap_ring_kick_user(tap); ++ ++ BTDBG("waiting for tapdisk response\n"); ++ wait_event_interruptible(tap->remove_wait, test_bit(BLKTAP_PAUSED, &tap->dev_inuse)); ++ if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) ++ return -EAGAIN; ++ ++ return 0; ++} ++ ++int ++blktap_ring_destroy(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ ++ if (ring->task || ring->vma || test_bit(BLKTAP_DEVICE, &tap->dev_inuse)) ++ return -EBUSY; ++ ++ return 0; ++} ++ ++int ++blktap_ring_create(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ ++ init_waitqueue_head(&ring->poll_wait); ++ ring->devno = MKDEV(blktap_ring_major, tap->minor); ++ ++ return 0; ++} ++ ++size_t ++blktap_ring_debug(struct blktap *tap, char *buf, size_t size) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ char *s = buf, *end = buf + size; ++ int usr_idx; ++ ++ s += snprintf(s, end - s, ++ "begin pending:%d\n", atomic_read(&ring->n_pending)); ++ ++ for (usr_idx = 0; usr_idx < BLKTAP_RING_SIZE; usr_idx++) { ++ struct blktap_request *request; ++ struct timeval t; ++ ++ request = ring->pending[usr_idx]; ++ if (!request) ++ continue; ++ ++ jiffies_to_timeval(jiffies, &t); ++ ++ s += snprintf(s, end - s, ++ "%02d: usr_idx:%02d " ++ "op:%x nr_pages:%02d time:%lu.%09lu\n", ++ usr_idx, request->usr_idx, ++ request->operation, request->nr_pages, ++ t.tv_sec, t.tv_usec); ++ } ++ ++ s += snprintf(s, end - s, "end pending\n"); ++ ++ return s - buf; ++} ++ ++ ++int __init ++blktap_ring_init(void) ++{ ++ dev_t dev = 0; ++ int err; ++ ++ cdev_init(&blktap_ring_cdev, &blktap_ring_file_operations); ++ blktap_ring_cdev.owner = THIS_MODULE; ++ ++ err = alloc_chrdev_region(&dev, 0, MAX_BLKTAP_DEVICE, "blktap2"); ++ if (err < 0) { ++ BTERR("error registering ring devices: %d\n", err); ++ return err; ++ } ++ ++ err = cdev_add(&blktap_ring_cdev, dev, MAX_BLKTAP_DEVICE); ++ if (err) { ++ BTERR("error adding ring device: %d\n", err); ++ unregister_chrdev_region(dev, MAX_BLKTAP_DEVICE); ++ return err; ++ } ++ ++ blktap_ring_major = MAJOR(dev); ++ BTINFO("blktap ring major: %d\n", blktap_ring_major); ++ ++ return 0; ++} ++ ++void ++blktap_ring_exit(void) ++{ ++ if (!blktap_ring_major) ++ return; ++ ++ cdev_del(&blktap_ring_cdev); ++ unregister_chrdev_region(MKDEV(blktap_ring_major, 0), ++ MAX_BLKTAP_DEVICE); ++ ++ blktap_ring_major = 0; ++} +--- /dev/null ++++ b/drivers/block/blktap/sysfs.c +@@ -0,0 +1,359 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "blktap.h" ++ ++int blktap_debug_level = 1; ++ ++static struct class *class; ++ ++static ssize_t ++blktap_sysfs_set_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct blktap *tap; ++ ++ tap = dev_get_drvdata(dev); ++ if (!tap) ++ return 0; ++ ++ if (size >= BLKTAP_NAME_MAX) ++ return -ENAMETOOLONG; ++ ++ if (strnlen(buf, size) != size) ++ return -EINVAL; ++ ++ strcpy(tap->name, buf); ++ ++ return size; ++} ++ ++static ssize_t ++blktap_sysfs_get_name(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct blktap *tap; ++ ssize_t size; ++ ++ tap = dev_get_drvdata(dev); ++ if (!tap) ++ return 0; ++ ++ if (tap->name[0]) ++ size = sprintf(buf, "%s\n", tap->name); ++ else ++ size = sprintf(buf, "%d\n", tap->minor); ++ ++ return size; ++} ++static DEVICE_ATTR(name, S_IRUGO|S_IWUSR, ++ blktap_sysfs_get_name, blktap_sysfs_set_name); ++ ++static void ++blktap_sysfs_remove_work(struct work_struct *work) ++{ ++ struct blktap *tap ++ = container_of(work, struct blktap, remove_work); ++ blktap_control_destroy_tap(tap); ++} ++ ++static ssize_t ++blktap_sysfs_remove_device(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct blktap *tap; ++ int err; ++ ++ tap = dev_get_drvdata(dev); ++ if (!tap) ++ return size; ++ ++ if (test_and_set_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) ++ goto wait; ++ ++ if (tap->ring.vma) { ++ struct blktap_sring *sring = tap->ring.ring.sring; ++ *BLKTAP_RING_MESSAGE(sring) = BLKTAP_RING_MESSAGE_CLOSE; ++ blktap_ring_kick_user(tap); ++ } else { ++ INIT_WORK(&tap->remove_work, blktap_sysfs_remove_work); ++ schedule_work(&tap->remove_work); ++ } ++wait: ++ err = wait_event_interruptible(tap->remove_wait, ++ !dev_get_drvdata(dev)); ++ if (err) ++ return err; ++ ++ return size; ++} ++static DEVICE_ATTR(remove, S_IWUSR, NULL, blktap_sysfs_remove_device); ++ ++static ssize_t ++blktap_sysfs_pause_device(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int err; ++ struct blktap *tap = dev_get_drvdata(dev); ++ ++ BTDBG("pausing %u:%u: dev_inuse: %lu\n", ++ MAJOR(tap->ring.devno), MINOR(tap->ring.devno), tap->dev_inuse); ++ ++ if (!tap->ring.dev || ++ test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) { ++ err = -ENODEV; ++ goto out; ++ } ++ ++ if (test_bit(BLKTAP_PAUSE_REQUESTED, &tap->dev_inuse)) { ++ err = -EBUSY; ++ goto out; ++ } ++ ++ if (test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) { ++ err = 0; ++ goto out; ++ } ++ ++ err = blktap_device_pause(tap); ++ ++out: ++ ++ return (err ? err : size); ++} ++static DEVICE_ATTR(pause, S_IWUSR, NULL, blktap_sysfs_pause_device); ++ ++static ssize_t ++blktap_sysfs_resume_device(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int err; ++ struct blktap *tap = dev_get_drvdata(dev); ++ ++ if (!tap->ring.dev || ++ test_bit(BLKTAP_SHUTDOWN_REQUESTED, &tap->dev_inuse)) { ++ err = -ENODEV; ++ goto out; ++ } ++ ++ if (!test_bit(BLKTAP_PAUSED, &tap->dev_inuse)) { ++ err = -EINVAL; ++ goto out; ++ } ++ ++ err = blktap_device_resume(tap); ++ ++out: ++ ++ BTDBG("returning %d\n", (err ? err : (int)size)); ++ return (err ? err : size); ++} ++static DEVICE_ATTR(resume, S_IWUSR, NULL, blktap_sysfs_resume_device); ++ ++static ssize_t ++blktap_sysfs_debug_device(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct blktap *tap; ++ char *s = buf, *end = buf + PAGE_SIZE; ++ ++ tap = dev_get_drvdata(dev); ++ if (!tap) ++ return 0; ++ ++ s += blktap_control_debug(tap, s, end - s); ++ ++ s += blktap_request_debug(tap, s, end - s); ++ ++ s += blktap_device_debug(tap, s, end - s); ++ ++ s += blktap_ring_debug(tap, s, end - s); ++ ++ return s - buf; ++} ++static DEVICE_ATTR(debug, S_IRUGO, blktap_sysfs_debug_device, NULL); ++ ++static ssize_t ++blktap_sysfs_show_task(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct blktap *tap; ++ ssize_t rv = 0; ++ ++ tap = dev_get_drvdata(dev); ++ if (!tap) ++ return 0; ++ ++ if (tap->ring.task) ++ rv = sprintf(buf, "%d\n", tap->ring.task->pid); ++ ++ return rv; ++} ++static DEVICE_ATTR(task, S_IRUGO, blktap_sysfs_show_task, NULL); ++ ++static ssize_t ++blktap_sysfs_show_pool(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct blktap *tap = dev_get_drvdata(dev); ++ return sprintf(buf, "%s", kobject_name(&tap->pool->kobj)); ++} ++ ++static ssize_t ++blktap_sysfs_store_pool(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct blktap *tap = dev_get_drvdata(dev); ++ struct blktap_page_pool *pool, *tmp = tap->pool; ++ ++ if (tap->device.gd) ++ return -EBUSY; ++ ++ pool = blktap_page_pool_get(buf); ++ if (IS_ERR(pool)) ++ return PTR_ERR(pool); ++ ++ tap->pool = pool; ++ kobject_put(&tmp->kobj); ++ ++ return size; ++} ++DEVICE_ATTR(pool, S_IRUSR|S_IWUSR, ++ blktap_sysfs_show_pool, blktap_sysfs_store_pool); ++ ++int ++blktap_sysfs_create(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ struct device *dev; ++ int err = 0; ++ ++ init_waitqueue_head(&tap->remove_wait); ++ ++ dev = device_create(class, NULL, ring->devno, ++ tap, "blktap%d", tap->minor); ++ if (IS_ERR(dev)) ++ err = PTR_ERR(dev); ++ if (!err) ++ err = device_create_file(dev, &dev_attr_name); ++ if (!err) ++ err = device_create_file(dev, &dev_attr_remove); ++ if (!err) ++ err = device_create_file(dev, &dev_attr_pause); ++ if (!err) ++ err = device_create_file(dev, &dev_attr_resume); ++ if (!err) ++ err = device_create_file(dev, &dev_attr_debug); ++ if (!err) ++ err = device_create_file(dev, &dev_attr_task); ++ if (!err) ++ err = device_create_file(dev, &dev_attr_pool); ++ if (!err) ++ ring->dev = dev; ++ else ++ device_unregister(dev); ++ ++ return err; ++} ++ ++void ++blktap_sysfs_destroy(struct blktap *tap) ++{ ++ struct blktap_ring *ring = &tap->ring; ++ struct device *dev; ++ ++ dev = ring->dev; ++ ++ if (!dev) ++ return; ++ ++ dev_set_drvdata(dev, NULL); ++ wake_up(&tap->remove_wait); ++ ++ device_unregister(dev); ++ ring->dev = NULL; ++} ++ ++static ssize_t ++verbosity_show(struct class *class, ++ struct class_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", blktap_debug_level); ++} ++ ++static ssize_t ++verbosity_store(struct class *class, ++ struct class_attribute *attr, ++ const char *buf, size_t size) ++{ ++ int level; ++ ++ if (sscanf(buf, "%d", &level) == 1) { ++ blktap_debug_level = level; ++ return size; ++ } ++ ++ return -EINVAL; ++} ++static CLASS_ATTR_RW(verbosity); ++ ++ ++static ssize_t ++devices_show(struct class *class, ++ struct class_attribute *attr, ++ char *buf) ++{ ++ int i, ret; ++ struct blktap *tap; ++ ++ mutex_lock(&blktap_lock); ++ ++ ret = 0; ++ for (i = 0; i < blktap_max_minor; i++) { ++ tap = blktaps[i]; ++ if (!tap) ++ continue; ++ ++ if (!test_bit(BLKTAP_DEVICE, &tap->dev_inuse)) ++ continue; ++ ++ ret += sprintf(buf + ret, "%d %s\n", tap->minor, tap->name); ++ } ++ ++ mutex_unlock(&blktap_lock); ++ ++ return ret; ++} ++static CLASS_ATTR_RO(devices); ++ ++void ++blktap_sysfs_exit(void) ++{ ++ if (class) ++ class_destroy(class); ++} ++ ++int __init ++blktap_sysfs_init(void) ++{ ++ struct class *cls; ++ int err = 0; ++ ++ cls = class_create(THIS_MODULE, "blktap2"); ++ if (IS_ERR(cls)) ++ err = PTR_ERR(cls); ++ if (!err) ++ err = class_create_file(cls, &class_attr_verbosity); ++ if (!err) ++ err = class_create_file(cls, &class_attr_devices); ++ if (!err) ++ class = cls; ++ else ++ class_destroy(cls); ++ ++ return err; ++} +--- /dev/null ++++ b/include/linux/blktap.h +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (c) 2011, XenSource Inc. ++ * All rights reserved. ++ */ ++ ++#ifndef _LINUX_BLKTAP_H ++#define _LINUX_BLKTAP_H ++ ++/* ++ * Control ++ */ ++ ++#define BLKTAP_IOCTL_RESPOND 1 ++#define BLKTAP_IOCTL_ALLOC_TAP 200 ++#define BLKTAP_IOCTL_FREE_TAP 201 ++#define BLKTAP2_IOCTL_SET_PARAMS 203 ++#define BLKTAP2_IOCTL_PAUSE 204 ++#define BLKTAP2_IOCTL_REOPEN 205 ++#define BLKTAP2_IOCTL_RESUME 206 ++#define BLKTAP_IOCTL_CREATE_DEVICE 208 ++#define BLKTAP_IOCTL_REMOVE_DEVICE 207 ++ ++#define BLKTAP_DEVICE_FLAG_RO 0x00000001UL /* disk is R/O */ ++#define BLKTAP_DEVICE_FLAG_PSZ 0x00000002UL /* physical sector size */ ++#define BLKTAP_DEVICE_FLAG_FLUSH 0x00000004UL /* supports FLUSH */ ++#define BLKTAP_DEVICE_FLAG_TRIM 0x00000008UL /* supports TRIM */ ++ ++struct blktap_info { ++ unsigned int ring_major; ++ unsigned int bdev_major; ++ unsigned int ring_minor; ++}; ++ ++struct blktap_device_info { ++ unsigned long long capacity; ++ unsigned int sector_size; ++ unsigned long flags; ++ unsigned int phys_block_size; ++ unsigned int phys_block_offset; ++ unsigned int trim_block_size; ++ unsigned int trim_block_offset; ++}; ++ ++/* ++ * I/O ring ++ */ ++ ++#ifdef __KERNEL__ ++#define BLKTAP_PAGE_SIZE PAGE_SIZE ++#endif ++ ++#include ++ ++struct blktap_segment { ++ uint32_t __pad; ++ uint8_t first_sect; ++ uint8_t last_sect; ++}; ++ ++#define BLKTAP_OP_READ 0 ++#define BLKTAP_OP_WRITE 1 ++#define BLKTAP_OP_FLUSH 2 ++#define BLKTAP_OP_TRIM 3 ++ ++#define BLKTAP_SEGMENT_MAX 11 ++ ++struct blktap_ring_rw_request { ++ uint64_t sector_number; ++ struct blktap_segment seg[BLKTAP_SEGMENT_MAX]; ++}; ++ ++struct blktap_ring_tr_request { ++ uint64_t sector_number; ++ uint64_t nr_sectors; ++}; ++ ++struct blktap_ring_request { ++ uint8_t operation; ++ uint8_t nr_segments; ++ uint16_t __pad; ++ uint64_t id; ++ union { ++ struct blktap_ring_rw_request rw; ++ struct blktap_ring_tr_request tr; ++ } u; ++}; ++ ++#define BLKTAP_RSP_EOPNOTSUPP -2 ++#define BLKTAP_RSP_ERROR -1 ++#define BLKTAP_RSP_OKAY 0 ++ ++struct blktap_ring_response { ++ uint64_t id; ++ uint8_t operation; ++ int16_t status; ++}; ++ ++DEFINE_RING_TYPES(blktap, ++ struct blktap_ring_request, ++ struct blktap_ring_response); ++ ++#define BLKTAP_RING_SIZE __CONST_RING_SIZE(blktap, BLKTAP_PAGE_SIZE) ++ ++/* ++ * Ring messages + old ioctls (DEPRECATED) ++ */ ++ ++#define BLKTAP_RING_MESSAGE(_sring) \ ++ ((uint8_t*)(&(_sring)->rsp_event + 1)) ++#define BLKTAP_RING_MESSAGE_CLOSE 3 ++#define BLKTAP_IOCTL_CREATE_DEVICE_COMPAT 202 ++#define BLKTAP_NAME_MAX 256 ++ ++struct blktap2_params { ++ char name[BLKTAP_NAME_MAX]; ++ unsigned long long capacity; ++ unsigned long sector_size; ++}; ++ ++#endif /* _LINUX_BLKTAP_H */ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.scc new file mode 100644 index 0000000000..f4ef12ec99 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/blktap2/blktap2.scc @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Add blktap2 driver." +define KFEATURE_COMPATIBILITY all + +patch blktap2.patch + +kconf non-hardware blktap2.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/bridge-carrier-follow-prio0.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/bridge-carrier-follow-prio0.patch new file mode 100644 index 0000000000..b509103de9 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/bridge-carrier-follow-prio0.patch @@ -0,0 +1,114 @@ +--- a/net/bridge/br_if.c ++++ b/net/bridge/br_if.c +@@ -86,6 +86,7 @@ void br_port_carrier_check(struct net_br + *notified = true; + } + } ++ br_maybe_copy_iface_carrier(p); + spin_unlock_bh(&br->lock); + } + +@@ -746,6 +747,31 @@ void br_port_flags_change(struct net_bri + br_recalculate_neigh_suppress_enabled(br); + } + ++/* if p->priority == 0 either copy carier if p is forwarding ++ * or set carrier to off if p is is not forwarding ++ * */ ++int br_maybe_copy_iface_carrier(struct net_bridge_port *p) ++{ ++ int carrier; ++ if (p->priority == 0) { ++ if (p->state == BR_STATE_FORWARDING) ++ carrier = netif_carrier_ok(p->dev); ++ else ++ carrier = 0; ++ if (carrier != netif_carrier_ok(p->br->dev)) { ++ printk("prio 0 port %s carrier %s, update bridge %s state\n", ++ p->dev->name, carrier ? "on" : "off", ++ p->br->dev->name); ++ if (carrier) ++ netif_carrier_on(p->br->dev); ++ else ++ netif_carrier_off(p->br->dev); ++ } ++ return 1; ++ } ++ return 0; ++} ++ + bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag) + { + struct net_bridge_port *p; +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -623,6 +623,7 @@ netdev_features_t br_features_recompute( + void br_port_flags_change(struct net_bridge_port *port, unsigned long mask); + void br_manage_promisc(struct net_bridge *br); + int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev); ++extern int br_maybe_copy_iface_carrier(struct net_bridge_port *p); + + /* br_input.c */ + int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); +--- a/net/bridge/br_stp.c ++++ b/net/bridge/br_stp.c +@@ -466,8 +466,13 @@ void br_port_state_selection(struct net_ + + if (liveports == 0) + netif_carrier_off(br->dev); +- else +- netif_carrier_on(br->dev); ++ else { ++ int carrier_copied = 0; ++ list_for_each_entry(p, &br->port_list, list) ++ carrier_copied |= br_maybe_copy_iface_carrier(p); ++ if (!carrier_copied) ++ netif_carrier_on(br->dev); ++ } + } + + /* called under bridge lock */ +--- a/net/bridge/br_stp_if.c ++++ b/net/bridge/br_stp_if.c +@@ -316,6 +316,7 @@ int br_stp_set_port_priority(struct net_ + br_port_state_selection(p->br); + } + ++ br_maybe_copy_iface_carrier(p); + return 0; + } + +--- a/net/bridge/br_sysfs_br.c ++++ b/net/bridge/br_sysfs_br.c +@@ -345,6 +345,23 @@ static ssize_t no_linklocal_learn_store( + } + static DEVICE_ATTR_RW(no_linklocal_learn); + ++static int set_link_state(struct net_bridge *br, unsigned long val) ++{ ++ if (val) ++ netif_carrier_on(br->dev); ++ else ++ netif_carrier_off(br->dev); ++ return 0; ++} ++ ++static ssize_t store_link_state(struct device *d, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ return store_bridge_parm(d, buf, len, set_link_state); ++} ++static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state); ++ + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + static ssize_t multicast_router_show(struct device *d, + struct device_attribute *attr, char *buf) +@@ -864,6 +881,7 @@ static struct attribute *bridge_attrs[] + &dev_attr_gc_timer.attr, + &dev_attr_group_addr.attr, + &dev_attr_flush.attr, ++ &dev_attr_link_state.attr, + &dev_attr_no_linklocal_learn.attr, + #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + &dev_attr_multicast_router.attr, diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/openxt-bridge-quirks.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/openxt-bridge-quirks.scc new file mode 100644 index 0000000000..cb094bf7a6 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/openxt-bridge-quirks.scc @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT bridge quirks." +define KFEATURE_COMPATIBILITY all + +# Change the bridge carrier state according to the priority 0 forwarding port. +patch bridge-carrier-follow-prio0.patch + +# Cmdline option to have the bridge pass copy of the skb and release the initial one. +## TODO: determine if this is necessary (not enabled by default in any vm) +patch skb-forward-copy-bridge-param.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/skb-forward-copy-bridge-param.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/skb-forward-copy-bridge-param.patch new file mode 100644 index 0000000000..b7999820fc --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-bridge-quirks/skb-forward-copy-bridge-param.patch @@ -0,0 +1,84 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Add a module parameter to enable skb forward copy. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +When the parameter is enabled, the bridge will pass copy of the skb and release +the initial one. + +################################################################################ +CHANGELOG +################################################################################ +Original author: Ross Phillipson +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +? + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None. + +################################################################################ +PATCHES +################################################################################ +--- a/net/bridge/br_forward.c ++++ b/net/bridge/br_forward.c +@@ -7,6 +7,7 @@ + * Lennert Buytenhek + */ + ++#include + #include + #include + #include +@@ -17,6 +18,10 @@ + #include + #include "br_private.h" + ++static int br_skb_forward_copy = 0; ++module_param_named(skb_forward_copy, br_skb_forward_copy, uint, S_IRUGO); ++MODULE_PARM_DESC(skb_forward_copy, "Enable or disable SKB copying on forward path"); ++ + /* Don't forward packets to originating port or forwarding disabled */ + static inline int should_deliver(const struct net_bridge_port *p, + const struct sk_buff *skb) +@@ -32,6 +37,8 @@ static inline int should_deliver(const s + + int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) + { ++ struct sk_buff *new_skb; ++ + skb_push(skb, ETH_HLEN); + if (!is_skb_forwardable(skb->dev, skb)) + goto drop; +@@ -49,7 +56,15 @@ int br_dev_queue_push_xmit(struct net *n + skb_set_network_header(skb, depth); + } + +- dev_queue_xmit(skb); ++ if (!br_skb_forward_copy) ++ dev_queue_xmit(skb); ++ else { ++ new_skb = skb_copy(skb, GFP_ATOMIC); ++ if (new_skb) { ++ dev_queue_xmit(new_skb); ++ kfree_skb(skb); ++ } ++ } + + return 0; + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/extra-mt-input-devices.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/extra-mt-input-devices.patch new file mode 100644 index 0000000000..df973de7ea --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/extra-mt-input-devices.patch @@ -0,0 +1,59 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Add the Mosart 7105 MT multitouch input device (Panasonic CF-C1 systems). + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Add the Mosart 7105 MT multitouch input device to support Panasonic CF-C1 +systems in hid-ids.h list. + +################################################################################ +CHANGELOG +################################################################################ +Original Author: Ross Philipson +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Depending on the HCL, MOsart 7105 MT multitouch input device is supported or +not. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -1177,6 +1177,7 @@ + #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 + #define USB_DEVICE_ID_ASUS_MD_5110 0x5110 + #define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100 ++#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART5 0x7105 + + #define USB_VENDOR_ID_TWINHAN 0x6253 + #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -2025,6 +2025,9 @@ static const struct hid_device_id mt_dev + { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, + MT_USB_DEVICE(USB_VENDOR_ID_TURBOX, + USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, ++ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, ++ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, ++ USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART5) }, + + /* Novatek Panel */ + { .driver_data = MT_CLS_NSMU, diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/openxt-input-quirks.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/openxt-input-quirks.scc new file mode 100644 index 0000000000..71b016bba7 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-input-quirks/openxt-input-quirks.scc @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT input quirks." +define KFEATURE_COMPATIBILITY all + +# TODO: determine if this is necessary (device still relevant?) +patch extra-mt-input-devices.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/konrad-ioperm.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/konrad-ioperm.patch new file mode 100644 index 0000000000..e01e5eafc8 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/konrad-ioperm.patch @@ -0,0 +1,251 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Paravirtualize IO permission bitmap. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +See: +http://old-list-archives.xen.org/archives/html/xen-devel/2009-05/msg01139.html + +A PV Xen guest kernel has no TSS of its own, so the IO permission +bitmap must be paravirtualized. This patch adds set_io_bitmap +as a paravirt op, and defines a native version which updates the tss, +and a Xen version which uses a hypercall. + +This is much easier now that 32 and 64-bit use the same code to +manage the IO bitmap. + +################################################################################ +CHANGELOG +################################################################################ +Original author: Konrad Rzeszutek Wilk +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Until fixed upstream or for non-pv service VM pass-through. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +PIO passthrough in PV guests. + +################################################################################ +PATCHES +################################################################################ +--- a/arch/x86/include/asm/paravirt.h ++++ b/arch/x86/include/asm/paravirt.h +@@ -299,6 +299,12 @@ static inline void set_iopl_mask(unsigne + PVOP_VCALL1(cpu.set_iopl_mask, mask); + } + ++static inline void set_io_bitmap(struct thread_struct *thread, ++ unsigned long bytes_updated) ++{ ++ PVOP_VCALL2(cpu.set_io_bitmap, thread, bytes_updated); ++} ++ + static inline void paravirt_activate_mm(struct mm_struct *prev, + struct mm_struct *next) + { +--- a/arch/x86/include/asm/paravirt_types.h ++++ b/arch/x86/include/asm/paravirt_types.h +@@ -141,6 +141,8 @@ struct pv_cpu_ops { + void (*load_sp0)(unsigned long sp0); + + void (*set_iopl_mask)(unsigned mask); ++ void (*set_io_bitmap)(struct thread_struct *thread, ++ unsigned long bytes_updated); + + void (*wbinvd)(void); + +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -534,6 +534,9 @@ static inline void native_set_iopl_mask( + #endif + } + ++extern void native_set_io_bitmap(struct thread_struct *thread, ++ unsigned long updated_bytes); ++ + static inline void + native_load_sp0(unsigned long sp0) + { +@@ -574,6 +577,12 @@ static inline void load_sp0(unsigned lon + } + + #define set_iopl_mask native_set_iopl_mask ++ ++static inline void set_io_bitmap(struct thread_struct *thread, ++ unsigned long updated_bytes) ++{ ++ native_set_io_bitmap(thread, updated_bytes); ++} + #endif /* CONFIG_PARAVIRT_XXL */ + + /* Free all resources held by a thread. */ +--- a/arch/x86/kernel/ioport.c ++++ b/arch/x86/kernel/ioport.c +@@ -21,13 +21,29 @@ + #include + #include + ++void native_set_io_bitmap(struct thread_struct *t, ++ unsigned long bytes_updated) ++{ ++ struct tss_struct *tss; ++ ++ if (!bytes_updated) ++ return; ++ ++ tss = &per_cpu(cpu_tss_rw, get_cpu()); ++ ++ /* Update the TSS: */ ++ if (t->io_bitmap_ptr) ++ memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); ++ else ++ memset(tss->io_bitmap, 0xff, bytes_updated); ++} ++ + /* + * this changes the io permissions bitmap in the current task. + */ + long ksys_ioperm(unsigned long from, unsigned long num, int turn_on) + { + struct thread_struct *t = ¤t->thread; +- struct tss_struct *tss; + unsigned int i, max_long, bytes, bytes_updated; + + if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) +@@ -63,13 +79,13 @@ long ksys_ioperm(unsigned long from, uns + } + + /* +- * do it in the per-thread copy and in the TSS ... ++ * do it in the per-thread copy + * +- * Disable preemption via get_cpu() - we must not switch away ++ * Disable preemption - we must not switch away + * because the ->io_bitmap_max value must match the bitmap + * contents: + */ +- tss = &per_cpu(cpu_tss_rw, get_cpu()); ++ preempt_disable(); + + if (turn_on) + bitmap_clear(t->io_bitmap_ptr, from, num); +@@ -90,10 +106,9 @@ long ksys_ioperm(unsigned long from, uns + + t->io_bitmap_max = bytes; + +- /* Update the TSS: */ +- memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); ++ set_io_bitmap(t, bytes_updated); + +- put_cpu(); ++ preempt_enable(); + + return 0; + } +--- a/arch/x86/kernel/paravirt.c ++++ b/arch/x86/kernel/paravirt.c +@@ -342,6 +342,7 @@ struct paravirt_patch_template pv_ops = + .cpu.swapgs = native_swapgs, + + .cpu.set_iopl_mask = native_set_iopl_mask, ++ .cpu.set_io_bitmap = native_set_io_bitmap, + + .cpu.start_context_switch = paravirt_nop, + .cpu.end_context_switch = paravirt_nop, +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -114,16 +114,12 @@ void exit_thread(struct task_struct *tsk + struct fpu *fpu = &t->fpu; + + if (bp) { +- struct tss_struct *tss = &per_cpu(cpu_tss_rw, get_cpu()); +- ++ preempt_disable(); + t->io_bitmap_ptr = NULL; + clear_thread_flag(TIF_IO_BITMAP); +- /* +- * Careful, clear this in the TSS too: +- */ +- memset(tss->io_bitmap, 0xff, t->io_bitmap_max); ++ set_io_bitmap(t, t->io_bitmap_max); + t->io_bitmap_max = 0; +- put_cpu(); ++ preempt_enable(); + kfree(bp); + } + +@@ -273,26 +269,10 @@ static inline void switch_to_bitmap(stru + struct thread_struct *next, + unsigned long tifp, unsigned long tifn) + { +- struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw); +- +- if (tifn & _TIF_IO_BITMAP) { +- /* +- * Copy the relevant range of the IO bitmap. +- * Normally this is 128 bytes or less: +- */ +- memcpy(tss->io_bitmap, next->io_bitmap_ptr, +- max(prev->io_bitmap_max, next->io_bitmap_max)); +- /* +- * Make sure that the TSS limit is correct for the CPU +- * to notice the IO bitmap. +- */ +- refresh_tss_limit(); +- } else if (tifp & _TIF_IO_BITMAP) { +- /* +- * Clear any possible leftover bits: +- */ +- memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); +- } ++ if ((tifn & _TIF_IO_BITMAP) || ++ (tifp & _TIF_IO_BITMAP)) ++ set_io_bitmap(next, ++ max(prev->io_bitmap_max, next->io_bitmap_max)); + } + + #ifdef CONFIG_SMP +--- a/arch/x86/xen/enlighten_pv.c ++++ b/arch/x86/xen/enlighten_pv.c +@@ -846,6 +846,18 @@ void xen_set_iopl_mask(unsigned mask) + HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); + } + ++static void xen_set_io_bitmap(struct thread_struct *thread, ++ unsigned long bytes_updated) ++{ ++ struct physdev_set_iobitmap set_iobitmap; ++ ++ set_xen_guest_handle(set_iobitmap.bitmap, ++ (char *)thread->io_bitmap_ptr); ++ set_iobitmap.nr_ports = thread->io_bitmap_ptr ? IO_BITMAP_BITS : 0; ++ WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, ++ &set_iobitmap)); ++} ++ + static void xen_io_delay(void) + { + } +@@ -1057,6 +1069,7 @@ static const struct pv_cpu_ops xen_cpu_o + .load_sp0 = xen_load_sp0, + + .set_iopl_mask = xen_set_iopl_mask, ++ .set_io_bitmap = xen_set_io_bitmap, + .io_delay = xen_io_delay, + + /* Xen takes care of %gs when switching to usermode for us */ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/openxt-pci-quirks.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/openxt-pci-quirks.scc new file mode 100644 index 0000000000..4ccd0c2311 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/openxt-pci-quirks.scc @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT PCI quirks." +define KFEATURE_COMPATIBILITY all + +# Align start address of PCI resources passed-through. +# TODO: determine if this is necessary +patch pci-pt-move-unaligned-resources.patch + +# FLR quirks for VGA devices +# TODO: determine if this is necessary. Half of the patch relates to IGD, which is not supported for pass-through. +patch pci-pt-flr.patch + +# Paravirtualize IO permission bitmap. +patch konrad-ioperm.patch + +# handle reverting setting the policy to permissive for a pci device passed-through via pciback/pcifront. +patch pciback-restrictive-attr.patch + +# Exhaust all PCI device reset options after being passed through. +patch thorough-reset-interface-to-pciback-s-sysfs.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-flr.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-flr.patch new file mode 100644 index 0000000000..4eadaf0ecd --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-flr.patch @@ -0,0 +1,105 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +PCI pass-through quirks for FLR. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Couple of quirks for FLR: +_ Wait 500ms (instead of 200ms defined in specs?) for VGA/Display video + controllers FLR. + +_ Ivy Bridge Intel Graphic Device: + * Force enable response in memory before FLR. + * Restore command register and return ENOTTY so generic reset logic can be + run after the quirk. + +################################################################################ +CHANGELOG +################################################################################ +Original author: James McKenzie +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +This patch is related to Intel Graphic Devices only. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -5055,7 +5055,12 @@ int pci_probe_reset_function(struct pci_ + if (rc != -ENOTTY) + return rc; + +- return pci_parent_bus_reset(dev, 1); ++ rc = pci_parent_bus_reset(dev, 1); ++ /* larger delay for gpus */ ++ if (dev->class == 0x30000 || dev->class == 0x38000) ++ msleep(500); ++ return rc; ++ + } + + /** +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -3764,10 +3764,15 @@ static int reset_ivb_igd(struct pci_dev + void __iomem *mmio_base; + unsigned long timeout; + u32 val; ++ u16 cmd; + + if (probe) + return 0; + ++ /* enable response in memory space */ ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY); ++ + mmio_base = pci_iomap(dev, 0, 0); + if (!mmio_base) + return -ENOMEM; +@@ -3798,7 +3803,10 @@ reset_complete: + iowrite32(0x00000002, mmio_base + NSDE_PWR_STATE); + + pci_iounmap(dev, mmio_base); +- return 0; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ /* follow with regular flr, returning ENOTTY causes rest of the FLR non-device specific code ++ to execute. Alternatively we could execute it here explicitly and mby that would be cleaner */ ++ return -ENOTTY; + } + + /* Device-specific reset method for Chelsio T4-based adapters */ +--- a/drivers/xen/xen-pciback/pci_stub.c ++++ b/drivers/xen/xen-pciback/pci_stub.c +@@ -417,10 +417,13 @@ static int pcistub_init_device(struct pc + if (!dev_data->pci_saved_state) + dev_err(&dev->dev, "Could not store PCI conf saved state!\n"); + else { ++#if 0 + dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n"); + __pci_reset_function_locked(dev); + pci_restore_state(dev); ++#endif + } ++ + /* Now disable the device (this also ensures some private device + * data is setup before we export) + */ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-move-unaligned-resources.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-move-unaligned-resources.patch new file mode 100644 index 0000000000..c349341652 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pci-pt-move-unaligned-resources.patch @@ -0,0 +1,78 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Align start address of PCI resources passed through. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +In some cases, the resource's start address is not page-aligned at this point. +Pass-through to the guest will then fail. This patch makes sure this odd +behaviour does not happen. + +################################################################################ +CHANGELOG +################################################################################ +Original author: Tomasz Wroblewski +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +This is a work-around for a corner case, more testing should be done to figure +out if it still happens and why. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None, this is an OpenXT work-around. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +PCI pass-through, depending on the device. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/pci/pci.c ++++ b/drivers/pci/pci.c +@@ -6111,6 +6111,27 @@ void __weak pci_resource_to_user(const s + static char *resource_alignment_param; + static DEFINE_SPINLOCK(resource_alignment_lock); + ++static ++resource_size_t pci_auto_resource_alignment(struct pci_dev *dev) ++{ ++ int i; ++ struct resource *r; ++ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || ++ (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && ++ (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)) ++ return 0; ++ ++ /* move resources only if they are not page aligned */ ++ for (i = 0; i < PCI_BRIDGE_RESOURCES; ++i) { ++ r = &dev->resource[i]; ++ if (!(r->flags & IORESOURCE_MEM)) ++ continue; ++ if (r->start & (PAGE_SIZE-1)) ++ return PAGE_SIZE; ++ } ++ return 0; ++} ++ + /** + * pci_specified_resource_alignment - get resource alignment specified by user. + * @dev: the PCI device to get +@@ -6168,6 +6189,8 @@ static resource_size_t pci_specified_res + } + p++; + } ++ if (align < PAGE_SIZE) ++ align = pci_auto_resource_alignment(dev); + out: + spin_unlock(&resource_alignment_lock); + return align; diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pciback-restrictive-attr.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pciback-restrictive-attr.patch new file mode 100644 index 0000000000..dd807a8854 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/pciback-restrictive-attr.patch @@ -0,0 +1,98 @@ +--- a/drivers/xen/xen-pciback/pci_stub.c ++++ b/drivers/xen/xen-pciback/pci_stub.c +@@ -1370,15 +1370,14 @@ out: + } + static DRIVER_ATTR_RW(quirks); + +-static ssize_t permissive_store(struct device_driver *drv, const char *buf, +- size_t count) ++static int set_confspace_policy(const char *dev_str, bool permissive) + { + int domain, bus, slot, func; + int err; + struct pcistub_device *psdev; + struct xen_pcibk_dev_data *dev_data; + +- err = str_to_slot(buf, &domain, &bus, &slot, &func); ++ err = str_to_slot(dev_str, &domain, &bus, &slot, &func); + if (err) + goto out; + +@@ -1394,22 +1393,33 @@ static ssize_t permissive_store(struct d + err = -ENXIO; + goto release; + } +- if (!dev_data->permissive) { +- dev_data->permissive = 1; ++ ++ if (!dev_data->permissive && permissive) { + /* Let user know that what they're doing could be unsafe */ + dev_warn(&psdev->dev->dev, "enabling permissive mode " + "configuration space accesses!\n"); + dev_warn(&psdev->dev->dev, + "permissive mode is potentially unsafe!\n"); + } ++ dev_data->permissive = permissive; + release: + pcistub_device_put(psdev); + out: +- if (!err) +- err = count; + return err; + } + ++static ssize_t permissive_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ int err; ++ ++ err = set_confspace_policy(buf, true); ++ if (err) { ++ return err; ++ } ++ return count; ++} ++ + static ssize_t permissive_show(struct device_driver *drv, char *buf) + { + struct pcistub_device *psdev; +@@ -1434,6 +1444,20 @@ static ssize_t permissive_show(struct de + } + static DRIVER_ATTR_RW(permissive); + ++static ssize_t restrictive_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ int err; ++ ++ err = set_confspace_policy(buf, false); ++ if (err) { ++ return err; ++ } ++ return count; ++} ++static DRIVER_ATTR_WO(restrictive); ++ ++ + static void pcistub_exit(void) + { + driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_new_slot); +@@ -1442,6 +1466,8 @@ static void pcistub_exit(void) + driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_slots); + driver_remove_file(&xen_pcibk_pci_driver.driver, &driver_attr_quirks); + driver_remove_file(&xen_pcibk_pci_driver.driver, ++ &driver_attr_restrictive); ++ driver_remove_file(&xen_pcibk_pci_driver.driver, + &driver_attr_permissive); + driver_remove_file(&xen_pcibk_pci_driver.driver, + &driver_attr_irq_handlers); +@@ -1533,6 +1559,9 @@ static int __init pcistub_init(void) + if (!err) + err = driver_create_file(&xen_pcibk_pci_driver.driver, + &driver_attr_permissive); ++ if (!err) ++ err = driver_create_file(&xen_pcibk_pci_driver.driver, ++ &driver_attr_restrictive); + + if (!err) + err = driver_create_file(&xen_pcibk_pci_driver.driver, diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/thorough-reset-interface-to-pciback-s-sysfs.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/thorough-reset-interface-to-pciback-s-sysfs.patch new file mode 100644 index 0000000000..9b8ae3fc3b --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pci-quirks/thorough-reset-interface-to-pciback-s-sysfs.patch @@ -0,0 +1,513 @@ +From d686351d8ea4a1ea1d755d0a10f6f14d1c870911 Mon Sep 17 00:00:00 2001 +From: Kate Temkin +Date: Wed, 8 Apr 2015 00:58:24 -0400 +Subject: [PATCH] Add thorough reset interface to pciback's sysfs. + +-------------------------------------------------------------------------------- +SHORT DESCRIPTION: +-------------------------------------------------------------------------------- +Adds an interface that allows "more thorough" resets to be performed +on devices which don't support Function Level Resets (FLRs). This +interface should allow the toolstack to ensure that a PCI device is in a +known state prior to passing it through to a VM. + +-------------------------------------------------------------------------------- +LONG DESCRIPTION: +-------------------------------------------------------------------------------- + +From Konrad Rzeszutek Wilk's original post to xen-devel and the LKML: + + The life-cycle of a PCI device in Xen pciback is complex + and is constrained by the PCI generic locking mechanism. + + It starts with the device being binded to us - for which + we do a device function reset (and done via SysFS + so the PCI lock is held) + + If the device is unbinded from us - we also do a function + reset (also done via SysFS so the PCI lock is held). + + If the device is un-assigned from a guest - we do a function + reset (no PCI lock). + + All on the individual PCI function level (so bus:device:function). + + Unfortunatly a function reset is not adequate for certain + PCIe devices. The reset for an individual PCI function "means + device must support FLR (PCIe or AF), PM reset on D3hot->D0 + device specific reset, or be a singleton device on a bus + a secondary bus reset. FLR does not have widespread support, + reset is not very reliable, and bus topology is dictated by the + and device design. We need to provide a means for a user to + a bus reset in cases where the existing mechanisms are not + or not reliable. " (Adam Williamson, 'vfio-pci: PCI hot reset + interface' commit 8b27ee60bfd6bbb84d2df28fa706c5c5081066ca). + + As such to do a slot or a bus reset is we need another mechanism. + This is not exposed SysFS as there is no good way of exposing + a bus topology there. + + This is due to the complexity - we MUST know that the different + functions off a PCIe device are not in use by other drivers, or + if they are in use (say one of them is assigned to a guest + and the other is idle) - it is still OK to reset the slot + (assuming both of them are owned by Xen pciback). + + This patch does that by doing an slot or bus reset (if + slot not supported) if all of the functions of a PCIe + device belong to Xen PCIback. We do not care if the device is + in-use as we depend on the toolstack to be aware of this - + however if it is we will WARN the user. + + Due to the complexity with the PCI lock we cannot do + the reset when a device is binded ('echo $BDF > bind') + or when unbinded ('echo $BDF > unbind') as the pci_[slot|bus]_reset + also take the same lock resulting in a dead-lock. + + Putting the reset function in a workqueue or thread + won't work either - as we have to do the reset function + outside the 'unbind' context (it holds the PCI lock). + But once you 'unbind' a device the device is no longer + under the ownership of Xen pciback and the pci_set_drvdata + has been reset so we cannot use a thread for this. + + Instead of doing all this complex dance, we depend on the toolstack + doing the right thing. As such implement [... a SysFS attribute] + which [... the toolstack] uses when a device is detached or attached + from/to a guest. It bypasses the need to worry about the PCI lock. + + To not inadvertly do a bus reset that would affect devices that + are in use by other drivers (other than Xen pciback) prior + to the reset we check that all of the devices under the bridge + are owned by Xen pciback. If they are not we do not do + the bus (or slot) reset. + + We also warn the user if the device is in use - but still + continue with the reset. This should not happen as the toolstack + also does the check. + +-- + +Our version of the patch has been modified to use a less confusing +sysfs name. The original name ('do_flr') is inappropriate, as it +implies a function level reset; it is entirely possible that the patch +code will use a bus-level reset when appropriate. + +The new sysfs entry is located at: + + /sys/bus/pci/drivers/pciback/reset_device + +and can be activated by writing a domain:bus:device:function device +identifier into the sysfs file. As an example: + + echo "0000:01:00.0" > /sys/bus/pci/drivers/pciback/reset_device + +would reset the device matching the D:BDF descriptor above. + +-------------------------------------------------------------------------------- +CHANGELOG: +-------------------------------------------------------------------------------- +This is a port of a patch that likely had many authors, including: + -Konrad Rzeszutek Wilk + -Alex Williamson + -Ross Phillipson +Ported to OpenXT by: Kyle J. Temkin , 4/8/15 +Rewrite by: Kyle J. Temkin , 4/10/15 + +-------------------------------------------------------------------------------- +DEPENDENCIES +-------------------------------------------------------------------------------- +This patch requires ONE of the following: + -A relatively modern linux kernel (3.18+) as a base; which provides + the PCI functions used; or + -Our PCI reset backports patch (backport-pci-reset-functionality.patch), + which backports the relevant functionality to 3.11. + +To take advantage of this patch, the utilized toolstack should be +changed to: + -Use the provided "reset_device" property, rather than the PCI + device's sysfs "reset" entry. This enables resets beyond a FLR to be + used. + -Ensure that all functions of a given device are passed through + together. This allows us to use some of the more thorugh resetting + techniques, when possible. + +-------------------------------------------------------------------------------- +REMOVAL +-------------------------------------------------------------------------------- +This patch provides a service which is necessary for proper passthrough +of many PCI cards: a generalized ability to reset PCI devices, without +requiring that the device support FLR or power-management based resets. + +This patch will be necessary until either the Linux PCI subsystem or Xen +PCIback drivers are modified to provide this support; or until cards +without proper FLR support are no longer supported. + +-------------------------------------------------------------------------------- +UPSTREAM PLAN +-------------------------------------------------------------------------------- + +This code is taken from a patch which was originally proposed and +rejected from upstream on the LKML and xen-devel. An upstream +implementation of the functionality of this patch is still necessary; +and can and should be implemented. + +This patch will hopefully be replaced with an upstream version when +community concensus has produced a single "blessed" method of +accomplishing its functionality. + +-------------------------------------------------------------------------------- +PATCHES +-------------------------------------------------------------------------------- +--- + drivers/xen/xen-pciback/pci_stub.c | 338 ++++++++++++++++++++++++++++++++++--- + 1 file changed, 312 insertions(+), 26 deletions(-) + +--- a/drivers/xen/xen-pciback/pci_stub.c ++++ b/drivers/xen/xen-pciback/pci_stub.c +@@ -102,10 +102,8 @@ static void pcistub_device_release(struc + + xen_unregister_device_domain_owner(dev); + +- /* Call the reset function which does not take lock as this +- * is called from "unbind" which takes a device_lock mutex. +- */ +- __pci_reset_function_locked(dev); ++ /* Reset is done by the toolstack by using 'reset_device' on the ++ * SysFS. */ + if (dev_data && + pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state)) + dev_info(&dev->dev, "Could not reload PCI state\n"); +@@ -126,9 +124,6 @@ static void pcistub_device_release(struc + err); + } + +- /* Disable the device */ +- xen_pcibk_reset_device(dev); +- + kfree(dev_data); + pci_set_drvdata(dev, NULL); + +@@ -225,6 +220,243 @@ struct pci_dev *pcistub_get_pci_dev_by_s + return found_dev; + } + ++ ++/** ++ * Returns true iff the given device supports PCIe FLRs. ++ */ ++static bool __device_supports_pcie_flr(struct pci_dev *dev) ++{ ++ u32 cap; ++ ++ /* ++ * Read the device's capabilities. Note that this can be used even on legacy ++ * PCI devices (and not just on PCIe devices)-- it indicates that no capabilities ++ * are supported if the device is legacy PCI by setting cap to 0. ++ */ ++ pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); ++ ++ /* Return true iff the device advertises supporting an FLR. */ ++ return (cap & PCI_EXP_DEVCAP_FLR); ++} ++ ++ ++/** ++ * Returns true iff the given device supports PCI Advanced Functionality (AF) FLRs. ++ */ ++static bool __device_supports_pci_af_flr(struct pci_dev *dev) ++{ ++ int pos; ++ u8 capability_flags; ++ ++ /* First, try to find the location of the PCI Advanced Functionality capability byte. */ ++ pos = pci_find_capability(dev, PCI_CAP_ID_AF); ++ ++ /* ++ * If we weren't able to find the capability byte, this device doesn't support ++ * the Advanced Functionality extensions, and thus won't support AF FLR. ++ */ ++ if (!pos) ++ return false; ++ ++ /* Read the capabilities advertised in the AF capability byte. */ ++ pci_read_config_byte(dev, pos + PCI_AF_CAP, &capability_flags); ++ ++ /* ++ * If the device does support AF, it will advertise FLR support via the ++ * PCI_AF_CAP_FLR bit. We'll also check for the Transactions Pending (TP) ++ * mechanism, as the kernel requires this extension to issue an AF FLR. ++ * (Internally, the PCI reset code needs to be able to wait for all ++ * pending transactions to complete prior to issuing the AF FLR.) ++ */ ++ return (capability_flags & PCI_AF_CAP_TP) && (capability_flags & PCI_AF_CAP_FLR); ++} ++ ++ ++/** ++ * Returns true iff the given device adverstises supporting function- ++ * level-reset (FLR). ++ */ ++static bool device_supports_flr(struct pci_dev *dev) ++{ ++ return __device_supports_pci_af_flr(dev) || __device_supports_pcie_flr(dev); ++} ++ ++ ++/** ++ * Out argument for the __safe_to_sbr_device_callback function. ++ */ ++struct safe_to_sbr_arguments { ++ ++ //Stores the most recently encountered PCI device that does ++ //not belong to pciback. As used below, this is the result of a ++ //search for a non-pciback device on a bus; we stop upon finding ++ //the first non-pciback device. ++ struct pci_dev *last_non_pciback_device; ++ ++ //Stores the number of pciback devices that appear to be in use ++ //on the bus in question. ++ int use_count; ++ ++}; ++ ++ ++/** ++ * A callback function which determines if a given PCI device is owned by pciback, ++ * and whether the given device is in use. Used by safe_to_sbr_device. ++ * ++ * @param dev The PCI device to be checked. ++ * @param data An out argument of type struct safe_to_sbr_device_callback_arguments. ++ * Updated to indicate the result of the search. See the struct's definition ++ * for more details. ++ * ++ */ ++static int __safe_to_sbr_device_callback(struct pci_dev *dev, void *data) ++{ ++ ++ struct pcistub_device *psdev; ++ ++ bool device_owned_by_pciback = false; ++ struct safe_to_sbr_arguments *arg = data; ++ ++ unsigned long flags; ++ ++ //Ensure that we have exclusive access to the list of PCI devices, ++ //so we can traverse it. ++ spin_lock_irqsave(&pcistub_devices_lock, flags); ++ ++ //Iterate over all PCI devices owned by the pci stub. ++ list_for_each_entry(psdev, &pcistub_devices, dev_list) { ++ ++ //If the given device is owned by pciback... ++ if (psdev->dev == dev) { ++ ++ //mark it as a pciback device. ++ device_owned_by_pciback = true; ++ ++ //If we have a physical device associated with the pciback device, ++ //mark this device as in-use. ++ if (psdev->pdev) ++ arg->use_count++; ++ ++ //Stop searching; we've found a the PCIback device associated with this one. ++ break; ++ } ++ } ++ ++ //Release the PCI device lock... ++ spin_unlock_irqrestore(&pcistub_devices_lock, flags); ++ ++ //... and report if we've found a device that's not owned by pciback. ++ dev_dbg(&dev->dev, "%s\n", device_owned_by_pciback ? "is owned by pciback, and can be reset if not in use." ++ : "not owned by pciback, and thus cannot be reset."); ++ ++ //If we've found a device that's not owned by pciback, update our data ++ //argument so it points to the most recent unowned device. (We check ++ //this like a flag, later: if it's never set, no one owns the device!) ++ if (!device_owned_by_pciback) ++ arg->last_non_pciback_device = dev; ++ ++ //If we've found a device that's not owned by pciback, return false-- ++ //this indicates that pci_walk_bus should cease its walk. ++ return !device_owned_by_pciback; ++} ++ ++ ++/** ++ * Returns true iff it should be safe to issue a secondary bus reset ++ * to the device; that is, if an SBR can be issued without disrupting ++ * other devices. ++ */ ++static bool safe_to_sbr_device(struct pci_dev *dev) ++{ ++ struct safe_to_sbr_arguments walk_result = { .last_non_pciback_device = NULL, .use_count = 0 }; ++ ++ //Walk the PCI bus, attempting to find if any of the given devices ++ pci_walk_bus(dev->bus, __safe_to_sbr_device_callback, &walk_result); ++ ++ //If the device is in use, emit a warning error. ++ if(walk_result.use_count > 0) ++ dev_dbg(&dev->dev, "is in use; currently not safe to SBR device.\n"); ++ ++ //Return true iff we did not pick up any other devices ++ //that were either in use, or not owned by pciback. ++ return (walk_result.last_non_pciback_device == NULL) && (walk_result.use_count == 0); ++} ++ ++ ++/** ++ * Attempt a raw reset of the provided PCI device-- via any ++ * method available to us. This method prefers the gentlest ++ * possible reset method-- currently an FLR, which many ++ * PCIe devices should support. ++ * ++ * @param dev The pci device to be reset. ++ * @return Zero on success, or the error code generated by the reset method on failure. ++ */ ++static int __pcistub_raw_device_reset(struct pci_dev *dev) ++{ ++ //Determine if bus resetting techniques (SBR, slot resets) ++ //are safe, and thus should be allowed. ++ int allow_bus_reset = safe_to_sbr_device(dev); ++ ++ //If FLRs are supported; we'll try to let the linux kernel ++ //manually reset the device. ++ if(device_supports_flr(dev)) { ++ dev_dbg(&dev->dev, "Resetting device using an FLR."); ++ return pci_reset_function(dev); ++ } ++ ++ //pci_reset_bus will first attempt by slot, if unable, ++ //will attempt to reset the entire PCI bus ++ if(allow_bus_reset) { ++ dev_dbg(&dev->dev, "Resetting device using a slot or SBR"); ++ return pci_reset_bus(dev); ++ } ++ ++ //If we weren't able to reset the device by any of our known-good methods, ++ //fall back to the linux kernel's reset function. Unfortunately, this considers a ++ //power management reset to be a valid reset; though this doesn't work for many devices-- ++ //especially GPUs. ++ dev_err(&dev->dev, "No reset methods available for %s. Falling back to kernel reset.", pci_name(dev)); ++ pci_reset_function(dev); ++ ++ //Return an error code, indicating that we likely did not reset the device correctly. ++ return -ENOTTY; ++} ++ ++ ++/** ++ * Resets the target (pciback-owned) PCI device. Primarily intended ++ * for use by the toolstack, so it can ensure a consistent PCI device ++ * state on VM startup. ++ * ++ * @param dev The device to be reset. ++ * @return Zero on success, or a negated error code on failure. ++ */ ++static int pcistub_reset_pci_dev(struct pci_dev *dev) ++{ ++ int rc; ++ ++ if (!dev) ++ return -EINVAL; ++ ++ /* ++ * Takes the PCI lock. OK to do it as we are never called ++ * from 'unbind' state and don't deadlock. ++ */ ++ rc =__pcistub_raw_device_reset(dev); ++ pci_restore_state(dev); ++ ++ /* This disables the device. */ ++ xen_pcibk_reset_device(dev); ++ ++ /* And cleanup up our emulated fields. */ ++ xen_pcibk_config_reset_dev(dev); ++ return rc; ++} ++ ++ ++ + struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev, + struct pci_dev *dev) + { +@@ -280,11 +512,13 @@ void pcistub_put_pci_dev(struct pci_dev + * pcistub and xen_pcibk when AER is in processing + */ + down_write(&pcistub_sem); +- /* Cleanup our device +- * (so it's ready for the next domain) +- */ + device_lock_assert(&dev->dev); +- __pci_reset_function_locked(dev); ++ /* ++ * Reset is up to the toolstack. ++ * The toolstack has to call 'reset_device' before ++ * providing the PCI device to a guest (see pcistub_reset_device). ++ */ ++ //__pci_reset_function_locked(dev); + + dev_data = pci_get_drvdata(dev); + ret = pci_load_saved_state(dev, dev_data->pci_saved_state); +@@ -1457,6 +1691,41 @@ static ssize_t restrictive_store(struct + } + static DRIVER_ATTR_WO(restrictive); + ++/** ++ * Handles the "reset_device" sysfs attribute. This is the primary reset interface ++ * utilized by the toolstack. ++ */ ++static ssize_t reset_device_store(struct device_driver *drv, const char *buf, size_t count) ++{ ++ int domain, bus, slot, func, err; ++ struct pcistub_device *psdev; ++ ++ //Attempt to convert the user's string to a BDF/slot. ++ err = str_to_slot(buf, &domain, &bus, &slot, &func); ++ if (err) ++ return -ENODEV; ++ ++ //... and then use that slot to find the pciback device. ++ psdev = pcistub_device_find(domain, bus, slot, func); ++ ++ //If we have a device, attempt to reset it using our internal reset path. ++ if (psdev) { ++ err = pcistub_reset_pci_dev(psdev->dev); ++ pcistub_device_put(psdev); ++ ++ //If we were not able to reset the device, return the relevant error code. ++ if(err) ++ err = -ENODEV; ++ } ++ //Otherwise, indicate that there's no such device. ++ else { ++ err = -ENODEV; ++ } ++ ++ return err ? err : count; ++ ++} ++static DRIVER_ATTR_WO(reset_device); + + static void pcistub_exit(void) + { +@@ -1473,6 +1742,8 @@ static void pcistub_exit(void) + &driver_attr_irq_handlers); + driver_remove_file(&xen_pcibk_pci_driver.driver, + &driver_attr_irq_handler_state); ++ driver_remove_file(&xen_pcibk_pci_driver.driver, ++ &driver_attr_reset_device); + pci_unregister_driver(&xen_pcibk_pci_driver); + } + +@@ -1569,6 +1840,9 @@ static int __init pcistub_init(void) + if (!err) + err = driver_create_file(&xen_pcibk_pci_driver.driver, + &driver_attr_irq_handler_state); ++ if (!err) ++ err = driver_create_file(&xen_pcibk_pci_driver.driver, ++ &driver_attr_reset_device); + if (err) + pcistub_exit(); + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/openxt-pv-video-quirks.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/openxt-pv-video-quirks.scc new file mode 100644 index 0000000000..cc397a94bb --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/openxt-pv-video-quirks.scc @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT PV video quirks." +define KFEATURE_COMPATIBILITY all + +# Use maximum absolute width/height dimension for xenkbd to support tablet. +## TODO: determine if this is necessary. +patch xenkbd-tablet-resolution.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/xenkbd-tablet-resolution.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/xenkbd-tablet-resolution.patch new file mode 100644 index 0000000000..75b2500467 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-pv-video-quirks/xenkbd-tablet-resolution.patch @@ -0,0 +1,59 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Use large dimensions for tablet absolute coordinates. + +################################################################################ +LONG DESCRIPTION: +################################################################################ + +################################################################################ +CHANGELOG +################################################################################ +Original author: unknown +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +? + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/input/misc/xen-kbdfront.c ++++ b/drivers/input/misc/xen-kbdfront.c +@@ -303,9 +303,9 @@ static int xenkbd_probe(struct xenbus_de + if (abs) { + __set_bit(EV_ABS, ptr->evbit); + input_set_abs_params(ptr, ABS_X, 0, +- ptr_size[KPARAM_X], 0, 0); ++ XENFB_TABLET_WIDTH, 0, 0); + input_set_abs_params(ptr, ABS_Y, 0, +- ptr_size[KPARAM_Y], 0, 0); ++ XENFB_TABLET_HEIGHT, 0, 0); + } else { + input_set_capability(ptr, EV_REL, REL_X); + input_set_capability(ptr, EV_REL, REL_Y); +--- a/include/xen/interface/io/fbif.h ++++ b/include/xen/interface/io/fbif.h +@@ -137,6 +137,8 @@ struct xenfb_page { + #ifdef __KERNEL__ + #define XENFB_WIDTH 800 + #define XENFB_HEIGHT 600 ++#define XENFB_TABLET_WIDTH 32767 ++#define XENFB_TABLET_HEIGHT 32767 + #define XENFB_DEPTH 32 + #endif + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/dont-suspend-xen-serial-port.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/dont-suspend-xen-serial-port.patch new file mode 100644 index 0000000000..0f0736922e --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/dont-suspend-xen-serial-port.patch @@ -0,0 +1,53 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Remove PNP_DISABLE capability for serial port on 0x3f8 as Xen uses it and will +disable it when going to S3. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Disables the functionality to evaluate ACPI _DIS method on serial 0x3f8 which +is used by Xen logging. Fixes S3 for machines with PNP serial port. Xen is +supposed to disable the serial port as it uses it. + +################################################################################ +CHANGELOG +################################################################################ +Original Author: unknown +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Without this work-around, S3 is known to fail on machines with PNP serial ports. +(Optiplex 980 for example). + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/tty/serial/8250/8250_pnp.c ++++ b/drivers/tty/serial/8250/8250_pnp.c +@@ -454,6 +454,10 @@ serial_pnp_probe(struct pnp_dev *dev, co + } else if (pnp_port_valid(dev, 0)) { + uart.port.iobase = pnp_port_start(dev, 0); + uart.port.iotype = UPIO_PORT; ++ /* Xen uses port 3f8 for logging, turn off ability to disable it as it breaks suspend */ ++ if (uart.port.iobase == 0x3f8) { ++ dev->capabilities &= ~PNP_DISABLE; ++ } + } else if (pnp_mem_valid(dev, 0)) { + uart.port.mapbase = pnp_mem_start(dev, 0); + uart.port.iotype = UPIO_MEM; diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/hvc-kgdb-fix.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/hvc-kgdb-fix.patch new file mode 100644 index 0000000000..212ce7573d --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/hvc-kgdb-fix.patch @@ -0,0 +1,91 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Fall back to cons_ops if tty->driver_data is not ready. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +See http://lists.xen.org/archives/html/xen-devel/2012-06/msg00484.html. + +Use tty->driver_data, if available or fall back to using cons_ops. + +################################################################################ +CHANGELOG +################################################################################ +Original Author: Ben Guthro +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Until fixed upstream. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None, allows kgdb over hvc for debugging. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/tty/hvc/hvc_console.c ++++ b/drivers/tty/hvc/hvc_console.c +@@ -861,11 +861,13 @@ static int hvc_poll_init(struct tty_driv + static int hvc_poll_get_char(struct tty_driver *driver, int line) + { + struct tty_struct *tty = driver->ttys[0]; +- struct hvc_struct *hp = tty->driver_data; ++ struct hvc_struct *hp = tty ? tty->driver_data : NULL; ++ struct hv_ops *ops = (hp && hp->ops) ? hp->ops : cons_ops[last_hvc]; ++ uint32_t vtno = hp ? hp->vtermno : vtermnos[last_hvc]; + int n; + char ch; + +- n = hp->ops->get_chars(hp->vtermno, &ch, 1); ++ n = ops->get_chars(vtno, &ch, 1); + + if (n <= 0) + return NO_POLL_CHAR; +@@ -876,11 +878,14 @@ static int hvc_poll_get_char(struct tty_ + static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch) + { + struct tty_struct *tty = driver->ttys[0]; +- struct hvc_struct *hp = tty->driver_data; ++ struct hvc_struct *hp = tty ? tty->driver_data : NULL; ++ struct hv_ops *ops = (hp && hp->ops) ? hp->ops : cons_ops[last_hvc]; ++ uint32_t vtno = hp ? hp->vtermno : vtermnos[last_hvc]; ++ + int n; + + do { +- n = hp->ops->put_chars(hp->vtermno, &ch, 1); ++ n = ops->put_chars(vtno, &ch, 1); + } while (n <= 0); + } + #endif +--- a/kernel/debug/debug_core.c ++++ b/kernel/debug/debug_core.c +@@ -653,6 +653,7 @@ return_normal: + kgdb_roundup_cpus(); + #endif + ++#ifndef CONFIG_XEN + /* + * Wait for the other CPUs to be notified and be waiting for us: + */ +@@ -663,6 +664,7 @@ return_normal: + udelay(1000); + if (!time_left) + pr_crit("Timed out waiting for secondary CPUs.\n"); ++#endif + + /* + * At this point the primary processor is completely diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/intel-amt-support.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/intel-amt-support.patch new file mode 100644 index 0000000000..387fb1f628 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/intel-amt-support.patch @@ -0,0 +1,45 @@ +--- a/drivers/net/ethernet/intel/e1000/e1000_hw.c ++++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c +@@ -4278,7 +4278,7 @@ static void e1000_init_rx_addrs(struct e + /* Setup the receive address. */ + e_dbg("Programming MAC Address into RAR[0]\n"); + +- e1000_rar_set(hw, hw->mac_addr, 0); ++ e1000_rar_set(hw, hw->perm_mac_addr, 0); + + rar_num = E1000_RAR_ENTRIES; + +--- a/drivers/net/ethernet/intel/e1000/e1000_main.c ++++ b/drivers/net/ethernet/intel/e1000/e1000_main.c +@@ -2216,7 +2216,7 @@ static int e1000_set_mac(struct net_devi + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len); + +- e1000_rar_set(hw, hw->mac_addr, 0); ++ e1000_rar_set(hw, hw->mac_addr, E1000_RAR_ENTRIES - 2); + + if (hw->mac_type == e1000_82542_rev2_0) + e1000_leave_82542_rst(adapter); +--- a/drivers/net/ethernet/intel/e1000e/mac.c ++++ b/drivers/net/ethernet/intel/e1000e/mac.c +@@ -117,7 +117,7 @@ void e1000e_init_rx_addrs(struct e1000_h + /* Setup the receive address */ + e_dbg("Programming MAC Address into RAR[0]\n"); + +- hw->mac.ops.rar_set(hw, hw->mac.addr, 0); ++ hw->mac.ops.rar_set(hw, hw->mac.perm_addr, 0); + + /* Zero out the other (rar_entry_count - 1) receive addresses */ + e_dbg("Clearing RAR[1-%u]\n", rar_count - 1); +--- a/drivers/net/ethernet/intel/e1000e/netdev.c ++++ b/drivers/net/ethernet/intel/e1000e/netdev.c +@@ -4764,7 +4764,8 @@ static int e1000_set_mac(struct net_devi + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); + +- hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0); ++ hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, ++ adapter->hw.mac.rar_entry_count - 2); + + if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) { + /* activate the work around */ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/openxt-serial-quirks.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/openxt-serial-quirks.scc new file mode 100644 index 0000000000..d193f093e8 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-serial-quirks/openxt-serial-quirks.scc @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT serial device quirks." +define KFEATURE_COMPATIBILITY all + +# Remove PNP_DISABLE cap for UART port with iobase 0x3f8. +patch dont-suspend-xen-serial-port.patch + +# Fix AMT support for e1000, e1000e devices? +patch intel-amt-support.patch + +# Fallback to cons_ops if tty->driver_data is not ready. +patch hvc-kgdb-fix.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/disable-csum-xennet.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/disable-csum-xennet.patch new file mode 100644 index 0000000000..31f11e3972 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/disable-csum-xennet.patch @@ -0,0 +1,67 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Do not offload ip checksum to guests. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Disable NETIF_F_IP_CSUM_BIT & NETIF_F_IPV6_CSUM_BIT for xen-netdev. + +################################################################################ +CHANGELOG +################################################################################ +Original Author: unknown +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +"feature-no-csum-offload" and "feature-ipv6-csum-offload" Xenstore nodes can be +used as well to enable the feature or not, this patch only forces it to off in +any case. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None, could be dealt with at guest creation and be configurable. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +Unknown. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/net/xen-netback/interface.c ++++ b/drivers/net/xen-netback/interface.c +@@ -532,9 +532,7 @@ struct xenvif *xenvif_alloc(struct devic + INIT_LIST_HEAD(&vif->fe_mcast_addr); + + dev->netdev_ops = &xenvif_netdev_ops; +- dev->hw_features = NETIF_F_SG | +- NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | +- NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_FRAGLIST; ++ dev->hw_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6; + dev->features = dev->hw_features | NETIF_F_RXCSUM; + dev->ethtool_ops = &xenvif_ethtool_ops; + +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -1313,11 +1313,8 @@ static struct net_device *xennet_create_ + + netdev->netdev_ops = &xennet_netdev_ops; + +- netdev->features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | +- NETIF_F_GSO_ROBUST; +- netdev->hw_features = NETIF_F_SG | +- NETIF_F_IPV6_CSUM | +- NETIF_F_TSO | NETIF_F_TSO6; ++ netdev->features = NETIF_F_RXCSUM | NETIF_F_GSO_ROBUST; ++ netdev->hw_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6; + + /* + * Assume that all hw features are available for now. This set diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netback-skip-frontend-wait-during-shutdown.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netback-skip-frontend-wait-during-shutdown.patch new file mode 100644 index 0000000000..0d7119a3cf --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netback-skip-frontend-wait-during-shutdown.patch @@ -0,0 +1,87 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Close backend without waiting the frontend driver. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Force the put_device() instead of waiting for the frontend driver to close +properly. This is a work-around as some backend may run in service VM that +could eventually wait for frontend in dead guests prohibiting dom0 to +shutdown, sleep or hibernate. + +################################################################################ +CHANGELOG +################################################################################ +Original author: unknown +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Removal will require a better approach to deal with troubled guests sharing a +backend with a service VM. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None, this is an OpenXT work-around. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +Service VM PV backend. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/xen/xenbus/xenbus.h ++++ b/drivers/xen/xenbus/xenbus.h +@@ -133,6 +133,13 @@ int xenbus_read_otherend_details(struct + + void xenbus_ring_ops_init(void); + ++static inline bool xenbus_dev_is_vif(const struct xenbus_device *dev) ++{ ++ return (dev && ++ (!strcmp("vif", dev->devicetype) || ++ !strcmp("vwif", dev->devicetype))); ++} ++ + int xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void *par); + void xenbus_dev_queue_reply(struct xb_req_data *req); + +--- a/drivers/xen/xenbus/xenbus_probe_backend.c ++++ b/drivers/xen/xenbus/xenbus_probe_backend.c +@@ -192,6 +192,19 @@ static void frontend_changed(struct xenb + xenbus_otherend_changed(watch, path, token, 0); + } + ++void xenbus_dev_shutdown_backend(struct device *_dev) ++{ ++ struct xenbus_device *dev = to_xenbus_device(_dev); ++ ++ get_device(&dev->dev); ++ if (system_state > SYSTEM_RUNNING && !xenbus_dev_is_vif(dev)) ++ DPRINTK("%s: skipping wait for frontend to close\n", ++ dev->nodename); ++ else ++ xenbus_dev_shutdown(_dev); ++ put_device(&dev->dev); ++} ++ + static struct xen_bus_type xenbus_backend = { + .root = "backend", + .levels = 3, /* backend/type// */ +@@ -205,7 +218,7 @@ static struct xen_bus_type xenbus_backen + .uevent = xenbus_uevent_backend, + .probe = xenbus_dev_probe, + .remove = xenbus_dev_remove, +- .shutdown = xenbus_dev_shutdown, ++ .shutdown = xenbus_dev_shutdown_backend, + .dev_groups = xenbus_dev_groups, + }, + }; diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netfront-support-backend-relocate.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netfront-support-backend-relocate.patch new file mode 100644 index 0000000000..7d78cd262f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/netfront-support-backend-relocate.patch @@ -0,0 +1,70 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Treat a vanishing backend as a request to close the front-end. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Usual scenario would be dom0 releaving netback responsibility to NDVM ending up +to rmmod its backend module. Xenstore node would disapear and Xenbus switch to +unknown state. We might as well consider it, on the frontend side (e.g, in +UIVM) to be a close request, so the guest will be able to reconnect with the +new backend in the service VM. + +################################################################################ +CHANGELOG +################################################################################ +Original author: Steve Meisner +Port to 3.18: Eric Chanudet +Modified by: Troy Crosley +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Supporting backend relocation would require some work in the current protocol +without this patch. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None, this is an OpenXT work-around. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +Service VM PV backend. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -2022,11 +2022,24 @@ static void netback_changed(struct xenbu + case XenbusStateInitialised: + case XenbusStateReconfiguring: + case XenbusStateReconfigured: ++ break; ++ + case XenbusStateUnknown: ++ /* if the backend vanishes from xenstore, close frontend */ ++ if (!xenbus_exists(XBT_NIL, dev->otherend, "") && ++ (dev->state != XenbusStateUnknown)) { ++ dev_warn(&dev->dev, ++ "backend vanished, closing frontend\n"); ++ if (dev->state != XenbusStateClosed) ++ xenbus_frontend_closed(dev); ++ netif_carrier_off(np->netdev); ++ } + break; + + case XenbusStateInitWait: +- if (dev->state != XenbusStateInitialising) ++ /* allow reconnect if our state is either initialising, or closed */ ++ if (dev->state != XenbusStateInitialising && ++ dev->state != XenbusStateClosed) + break; + if (xennet_connect(netdev) != 0) + break; diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/openxt-service-vms.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/openxt-service-vms.scc new file mode 100644 index 0000000000..7854476caf --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/openxt-service-vms.scc @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT service VMs fixes." +define KFEATURE_COMPATIBILITY all + +# Do not offload ip checksum to guests. +patch disable-csum-xennet.patch + +# Close backend without waiting the frontend closure. +patch netback-skip-frontend-wait-during-shutdown.patch + +# Manage chained backend relying on xenstore-watches. +patch xenbus-move-otherend-watches-on-relocate.patch + +# Handle vanishing backend as request to close the frontend. +patch netfront-support-backend-relocate.patch + +# Do not add tty0 to prefereed consoles. +patch xenpv-no-tty0-as-default-console.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenbus-move-otherend-watches-on-relocate.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenbus-move-otherend-watches-on-relocate.patch new file mode 100644 index 0000000000..ad10423a1b --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenbus-move-otherend-watches-on-relocate.patch @@ -0,0 +1,110 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Manage chained backend relocation. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Tweak xenbus state machine to manage chained back-end domains to be restarted +without loosing the xenstore watches. + +################################################################################ +CHANGELOG +################################################################################ +Original author: unknown +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Disagregation with PV drivers need this patch to run smoothly unless some +refactoring is done to adapt the state machine. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +Complements netfront-support-backend-relocate.patch. +Required for service VM network disagregation. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/xen/xenbus/xenbus_probe.c ++++ b/drivers/xen/xenbus/xenbus_probe.c +@@ -554,12 +554,36 @@ static int strsep_len(const char *str, c + return (len == 0) ? i : -ERANGE; + } + ++static int move_otherend(struct xenbus_device *dev) ++{ ++ int err; ++ ++ /* Only move netdevs. */ ++ if (!dev || !dev->dev.driver) ++ return 0; ++ if (!xenbus_dev_is_vif(dev)) ++ return 0; ++ ++ DPRINTK("xenbus %s: otherend possibly changed location;\ ++ renegotiating connection\n", dev->nodename); ++ err = talk_to_otherend(dev); ++ if (err) { ++ DPRINTK("talk_to_otherend on %s failed.\n", dev->nodename); ++ return err; ++ } ++ err = watch_otherend(dev); ++ if (err) ++ DPRINTK("watch_otherend on %s failed.\n", dev->nodename); ++ ++ return err; ++} ++ + void xenbus_dev_changed(const char *node, struct xen_bus_type *bus) + { +- int exists, rootlen; ++ int exists, nodelen, rootlen; + struct xenbus_device *dev; + char type[XEN_BUS_ID_SIZE]; +- const char *p, *root; ++ const char *p, *root, *ending; + + if (char_count(node, '/') < 2) + return; +@@ -571,6 +595,7 @@ void xenbus_dev_changed(const char *node + } + + /* backend//... or device//... */ ++ nodelen = strnlen(node, INT_MAX); + p = strchr(node, '/') + 1; + snprintf(type, XEN_BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p); + type[XEN_BUS_ID_SIZE-1] = '\0'; +@@ -582,12 +607,20 @@ void xenbus_dev_changed(const char *node + if (!root) + return; + ++ ending = kasprintf(GFP_KERNEL, "%.*s", nodelen - rootlen, node + rootlen); ++ if (!ending) ++ return; + dev = xenbus_device_find(root, &bus->bus); + if (!dev) + xenbus_probe_node(bus, type, root); +- else ++ else { ++ if (!strcmp(ending, "/backend") || !strcmp(ending, "/frontend")) ++ /* reconfigure xenstore watches if backend/frontend node pointer has changed */ ++ move_otherend(dev); + put_device(&dev->dev); ++ } + ++ kfree(ending); + kfree(root); + } + EXPORT_SYMBOL_GPL(xenbus_dev_changed); diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenpv-no-tty0-as-default-console.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenpv-no-tty0-as-default-console.patch new file mode 100644 index 0000000000..825bfe9231 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-service-vms/xenpv-no-tty0-as-default-console.patch @@ -0,0 +1,54 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Do not add tty0 to the preferred consoles. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Preferred consoles behavior used to not affect dom0 until: +47b02f4c621c x86/xen: add tty0 and hvc0 as preferred consoles for dom0 +71dc05635983 x86/Xen: further refine add_preferred_console() invocations + +Since these changes, PV guests will always output on tty0 and hvc0 regardless +of console= parameter. This makes some noise at boot. + +None of the PV kernels used in OpenXT rely on that, yet silencing the loglevel +is not desired as the serial output is often used to debug boot issues. This +change temporarily does _not_ add tty0 as a default preferred console. + +console_set_on_cmdline is not usable at this stage unfortunately since the +cmdline has not been parsed yet. + +################################################################################ +REMOVAL +################################################################################ +Once a better alternative is available, this patch should be removed. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None. + +################################################################################ +PATCHES +################################################################################ +--- a/arch/x86/xen/enlighten_pv.c ++++ b/arch/x86/xen/enlighten_pv.c +@@ -1406,11 +1406,7 @@ asmlinkage __visible void __init xen_sta + #endif + } + +- if (!boot_params.screen_info.orig_video_isVGA) +- add_preferred_console("tty", 0, NULL); + add_preferred_console("hvc", 0, NULL); +- if (boot_params.screen_info.orig_video_isVGA) +- add_preferred_console("tty", 0, NULL); + + #ifdef CONFIG_PCI + /* PCI BIOS service won't work from a PV guest. */ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/openxt-tpm.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/openxt-tpm.scc new file mode 100644 index 0000000000..3827919d70 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/openxt-tpm.scc @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT TPM chardev quirks." +define KFEATURE_COMPATIBILITY all + +# Log the TPM TCG vendor-id, device-id and revision-id. +patch tpm-log-didvid.patch + +# Work-around TPM iomem region being marked as RAM under specific circumstances. +# TODO: determine if this is still necessary (32-bit kernel no longer supported). +patch tpm-tis-force-ioremap.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-log-didvid.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-log-didvid.patch new file mode 100644 index 0000000000..0c829341bc --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-log-didvid.patch @@ -0,0 +1,51 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Trace the TPM TCG vendor ID. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Output the TPM TCG vendor ID with the device ID and the revision ID to identify +the TPM device in use on the log output. + +################################################################################ +CHANGELOG +################################################################################ +Original author: Ross Philipson +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +This patch is for debugging purposes and can be safely removed. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +None. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/char/tpm/tpm_tis_core.c ++++ b/drivers/char/tpm/tpm_tis_core.c +@@ -899,9 +899,9 @@ int tpm_tis_core_init(struct device *dev + if (rc < 0) + goto out_err; + +- dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", ++ dev_info(dev, "%s TPM (vendor-id 0x%X device-id 0x%X, rev-id %d)\n", + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", +- vendor >> 16, rid); ++ vendor & 0xffff, vendor >> 16, rid); + + probe = probe_itpm(chip); + if (probe < 0) { diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-tis-force-ioremap.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-tis-force-ioremap.patch new file mode 100644 index 0000000000..8b5b2dca51 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-tpm/tpm-tis-force-ioremap.patch @@ -0,0 +1,25 @@ +--- a/drivers/char/tpm/tpm_tis.c ++++ b/drivers/char/tpm/tpm_tis.c +@@ -226,8 +226,20 @@ static int tpm_tis_init(struct device *d + return -ENOMEM; + + phy->iobase = devm_ioremap_resource(dev, &tpm_info->res); +- if (IS_ERR(phy->iobase)) +- return PTR_ERR(phy->iobase); ++ if (IS_ERR(phy->iobase)) { ++ /* This region is only reported in one of the SSDT, not the ++ * e820. On a system using a 32bit kernel and enough memory, ++ * the kernel might end up making this region a RAM buffer, ++ * disabling the TPM. ++ * devm_ioremap() was used (prior 4.6?), avoiding the ++ * devm_request_mem_region() that currently fails under the ++ * mentioned circumstances. Fallback to that until a better fix ++ * is found. ++ */ ++ phy->iobase = devm_ioremap(dev, tpm_info->res.start, resource_size(&tpm_info->res)); ++ if (IS_ERR(phy->iobase)) ++ return PTR_ERR(phy->iobase); ++ } + + if (interrupts) + irq = tpm_info->irq; diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/openxt-usbback.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/openxt-usbback.scc new file mode 100644 index 0000000000..62402d529f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/openxt-usbback.scc @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Add OpenXT paravirtualized usb backend driver." +define KFEATURE_COMPATIBILITY all + +patch usbback-base.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/usbback-base.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/usbback-base.patch new file mode 100644 index 0000000000..9a0806ea13 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-usbback/usbback-base.patch @@ -0,0 +1,4440 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +USB backend driver. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Para-virtualized USB backend driver... + +################################################################################ +CHANGELOG +################################################################################ +Original author: unknown +Contributor: Ross Philipson +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Allow and control access to USB devices from guests using the para-virtualized +tools. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +Guest pv-tools. +UIVM interface. +Toolstack in general. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/scsi/sr.c ++++ b/drivers/scsi/sr.c +@@ -269,6 +269,15 @@ static unsigned int sr_check_events(stru + if (!(clearing & DISK_EVENT_MEDIA_CHANGE)) + return events; + do_tur: ++ /* ++ * Earlier GET_EVENT_STATUS_NOTIFICATION and TUR did not agree ++ * for a couple of times in a row. We rely on TUR only for this ++ * likely broken device, to prevent generating incorrect media ++ * changed events for every open(). ++ */ ++ if (cd->ignore_get_event) ++ events &= ~DISK_EVENT_MEDIA_CHANGE; ++ + /* let's see whether the media is there with TUR */ + last_present = cd->media_present; + ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr); +@@ -281,8 +290,19 @@ do_tur: + cd->media_present = scsi_status_is_good(ret) || + (scsi_sense_valid(&sshdr) && sshdr.asc != 0x3a); + +- if (last_present != cd->media_present) ++ if (last_present != cd->media_present) { + cd->device->changed = 1; ++ } else if (events & DISK_EVENT_MEDIA_CHANGE) { ++ if (cd->tur_mismatch > 8) { ++ printk("%s: GET_EVENT and TUR disagree continuously, " ++ "suppress GET_EVENT events\n", cd->cdi.name); ++ cd->ignore_get_event = true; ++ } else { ++ cd->tur_mismatch++; ++ } ++ } else if (!cd->ignore_get_event && cd->tur_mismatch > 0) { ++ cd->tur_mismatch = 0; ++ } + + if (cd->device->changed) { + events |= DISK_EVENT_MEDIA_CHANGE; +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -109,6 +109,17 @@ source "drivers/usb/image/Kconfig" + + source "drivers/usb/usbip/Kconfig" + ++comment "Xen USB devices" ++ ++config XEN_USBDEV_BACKEND ++ tristate "Xen usb-device backend driver" ++ depends on XEN_BACKEND ++ default XEN_BACKEND ++ help ++ The usb-device backend driver allows the kernel to export its ++ usb devices to other guests via a high-performance shared-memory ++ interface. ++ + endif + + source "drivers/usb/cdns3/Kconfig" +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -66,3 +66,5 @@ obj-$(CONFIG_USBIP_CORE) += usbip/ + obj-$(CONFIG_TYPEC) += typec/ + + obj-$(CONFIG_USB_ROLE_SWITCH) += roles/ ++ ++obj-$(CONFIG_XEN_USBDEV_BACKEND) += xen-usbback/ +--- a/drivers/usb/core/Makefile ++++ b/drivers/usb/core/Makefile +@@ -7,6 +7,7 @@ usbcore-y := usb.o hub.o hcd.o urb.o mes + usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o + usbcore-y += devio.o notify.o generic.o quirks.o devices.o + usbcore-y += phy.o port.o ++usbcore-y += dusb.o + + usbcore-$(CONFIG_OF) += of.o + usbcore-$(CONFIG_USB_PCI) += hcd-pci.o +--- /dev/null ++++ b/drivers/usb/core/dusb.c +@@ -0,0 +1,169 @@ ++/*****************************************************************************/ ++ ++/* ++ * dusb.c -- Direct communication with USB devices. ++ * ++ * Copyright (C) 1999-2000 Thomas Sailer (sailer@ife.ee.ethz.ch) ++ * Copyright (C) 2008-2012 Virtual Computer Inc ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * Derived from usb/core/devio.c ++ * ++ */ ++ ++/*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#ifdef CONFIG_PROC_FS ++#include ++#include ++#endif ++#include /* for usbcore internals */ ++ ++#include "usb.h" ++ ++#if 1 ++#define dprintk(args...) ++#define dprintk2(args...) ++#else ++#define dprintk printk ++#define dprintk2 printk ++#endif ++ ++#define lock_kernel() ++#define unlock_kernel() ++ ++static int __match_minor(struct device *dev, const void *data) ++{ ++ const int minor = *((const int *)data); ++ ++ if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) ++ return 1; ++ return 0; ++} ++ ++static struct usb_device *usbdev_lookup_by_minor(int minor) ++{ ++ struct device *dev; ++ ++ dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor); ++ if (!dev) ++ return NULL; ++ ++ return container_of(dev, struct usb_device, dev); ++} ++ ++struct usb_device *dusb_open(unsigned bus, unsigned device) ++{ ++ int minor = ((bus - 1) * 128) + (device - 1); ++ struct usb_device *dev = NULL; ++ ++ dev = usbdev_lookup_by_minor(minor); ++ if (NULL == dev) ++ goto out; ++ ++ usb_lock_device(dev); ++ ++ usb_get_dev(dev); ++ put_device(&dev->dev); ++ usb_unlock_device(dev); ++ ++out: ++ ++ return dev; ++} ++EXPORT_SYMBOL(dusb_open); ++ ++void dusb_close(struct usb_device *dev) ++{ ++ usb_lock_device(dev); ++ ++ /* ++ * Resetting the device will make sure it gets reprobed and ++ * another device driver can claim it. ++ */ ++ usb_reset_device(dev); ++ usb_unlock_device(dev); ++ ++ usb_put_dev(dev); ++} ++EXPORT_SYMBOL(dusb_close); ++ ++int dusb_set_configuration(struct usb_device *dev, int configuration) ++{ ++ return usb_set_configuration(dev, configuration); ++} ++EXPORT_SYMBOL(dusb_set_configuration); ++ ++void dusb_flush_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep) ++{ ++ usb_hcd_flush_endpoint(udev, ep); ++} ++EXPORT_SYMBOL(dusb_flush_endpoint); ++ ++int dusb_reenumerate(unsigned bus, unsigned device) ++{ ++ int minor = ((bus - 1) * 128) + (device - 1); ++ struct usb_device *udev = NULL; ++ ++ udev = usbdev_lookup_by_minor(minor); ++ if (udev) { ++ printk("Forcing re-enumeration of %s - %s\n", ++ udev->product, udev->manufacturer); ++ usb_device_reenumerate(udev); ++ put_device(&udev->dev); ++ } ++ ++ return (udev != NULL); ++} ++EXPORT_SYMBOL(dusb_reenumerate); ++ ++int dusb_dev_running(struct usb_device *udev) ++{ ++ struct usb_hcd *hcd = bus_to_hcd(udev->bus); ++ ++ return (hcd ? HCD_RH_RUNNING(hcd) : 0); ++} ++EXPORT_SYMBOL(dusb_dev_running); ++ ++static int dusb_hcd_speed_super(struct usb_hcd *hcd) ++{ ++ return (hcd->driver->flags & HCD_USB3); ++} ++ ++static int dusb_hcd_speed_high(struct usb_hcd *hcd) ++{ ++ return (hcd->driver->flags & HCD_USB2); ++} ++ ++static int dusb_hcd_speed(struct usb_hcd *hcd) ++{ ++ return (dusb_hcd_speed_super(hcd) ? USB_SPEED_SUPER : ++ (dusb_hcd_speed_high(hcd) ? USB_SPEED_HIGH : USB_SPEED_LOW)); ++} ++ ++int dusb_dev_controller_speed(struct usb_device *udev) ++{ ++ struct usb_hcd *hcd = bus_to_hcd(udev->bus); ++ ++ return (hcd ? dusb_hcd_speed(hcd) : 0); ++} ++EXPORT_SYMBOL(dusb_dev_controller_speed); ++ +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1005,6 +1005,15 @@ int usb_remove_device(struct usb_device + return 0; + } + ++void usb_device_reenumerate(struct usb_device *udev) ++{ ++ struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); ++ int port1 = udev->portnum; ++ ++ hub_port_logical_disconnect(hub, port1); ++} ++EXPORT_SYMBOL(usb_device_reenumerate); ++ + enum hub_activation_type { + HUB_INIT, HUB_INIT2, HUB_INIT3, /* INITs must come first */ + HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, +@@ -5907,7 +5916,7 @@ int usb_reset_device(struct usb_device * + struct usb_driver *drv; + int unbind = 0; + +- if (cintf->dev.driver) { ++ if (cintf && cintf->dev.driver) { + drv = to_usb_driver(cintf->dev.driver); + if (drv->pre_reset && drv->post_reset) + unbind = (drv->pre_reset)(cintf); +@@ -5928,7 +5937,12 @@ int usb_reset_device(struct usb_device * + for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { + struct usb_interface *cintf = config->interface[i]; + struct usb_driver *drv; +- int rebind = cintf->needs_binding; ++ int rebind; ++ ++ if (!cintf) ++ continue; ++ ++ rebind = cintf->needs_binding; + + if (!rebind && cintf->dev.driver) { + drv = to_usb_driver(cintf->dev.driver); +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -289,6 +289,11 @@ static void xhci_pci_quirks(struct devic + if (xhci->quirks & XHCI_RESET_ON_RESUME) + xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, + "QUIRK: Resetting on resume"); ++ ++ /* The use of BEI causes deadlock with VUSB ++ * FIXME: BEI should be made to work with VUSB! ++ */ ++ xhci->quirks |= XHCI_AVOID_BEI; + } + + #ifdef CONFIG_ACPI +--- /dev/null ++++ b/drivers/usb/xen-usbback/Makefile +@@ -0,0 +1,3 @@ ++obj-$(CONFIG_XEN_USBDEV_BACKEND) := usbbk.o ++ ++usbbk-y := usbback.o xenbus.o interface.o vusb.o buffers.o +--- /dev/null ++++ b/drivers/usb/xen-usbback/buffers.c +@@ -0,0 +1,422 @@ ++/****************************************************************************** ++ * usbback/buffers.c ++ * ++ * Routines for managing virtual usb devices. ++ * ++ * Copyright (c) Citrix Systems Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation; or, when distributed ++ * separately from the Linux kernel or incorporated into other ++ * software packages, subject to the following license: ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#include ++ ++#include "common.h" ++ ++#if (DUMP_URB_SZ > 0) ++void dump(uint8_t *buffer, int len) ++{ ++ int i; ++ ++ if ((buffer != NULL) && (len > 0)) { ++ printk(" data: "); ++ for (i=0; (i < len) && (i < DUMP_URB_SZ); i++) { ++ printk("%02x ", buffer[i]); ++ if ((i & 0x3f) == 0x20) ++ printk("\n"); ++ } ++ printk("\n"); ++ } else { ++ printk(" data: none\n"); ++ } ++} ++ ++static void dump_iso_urb(struct urb *urb) ++{ ++ struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc; ++ uint8_t *buffer = urb->transfer_buffer; ++ int i; ++ ++ for (i=0; inumber_of_packets; i++) ++ dump(&buffer[desc[i].offset], desc[i].length); ++} ++#endif ++ ++/* ++ * Move data between DomU and URB buffers ++ */ ++static int copy_first_chunk(uint8_t *dst, uint8_t *src, int offset, int remaining) ++{ ++ int len; ++ ++ if ((PAGE_SIZE - offset) > remaining) ++ len = remaining; ++ else ++ len = (PAGE_SIZE - offset); ++ ++ memcpy(dst, src, len); ++ ++ return len; ++} ++ ++static int copy_chunk(uint8_t *dst, uint8_t *src, int remaining) ++{ ++ return copy_first_chunk(dst, src, 0, remaining); ++} ++ ++static void copy_out_req(pending_req_t *pending_req) ++{ ++ uint8_t *dst, *src; ++ int i, len, remaining, nr_pages; ++ ++ remaining = pending_req->urb->transfer_buffer_length; ++ nr_pages = data_pages(pending_req); ++ ++ if (!nr_pages) ++ return; ++ ++ /* copy first seg */ ++ dst = pending_req->urb->transfer_buffer; ++ src = (uint8_t *)vaddr(pending_req, 0) + pending_req->offset; ++ ++ len = copy_first_chunk(dst, src, pending_req->offset, remaining); ++ ++ dst += len; ++ remaining -= len; ++ ++ /* copy remaining segs */ ++ for (i = 1; i < nr_pages; i++) { ++ src = (uint8_t *)vaddr(pending_req, i); ++ ++ len = copy_chunk(dst, src, remaining); ++ ++ dst += len; ++ remaining -= len; ++ } ++ ++#if (DUMP_URB_SZ > 0) ++ if (usbback_debug_lvl() >= LOG_LVL_DUMP) ++ dump(pending_req->urb->transfer_buffer, ++ pending_req->urb->transfer_buffer_length); ++#endif ++} ++ ++static int setup_sg(struct scatterlist *sg, uint8_t *src, int offset, int remaining) ++{ ++ int len; ++ ++ if ((PAGE_SIZE - offset) > remaining) ++ len = remaining; ++ else ++ len = (PAGE_SIZE - offset); ++ ++ debug_print(LOG_LVL_DEBUG, " sg: ptr %p len %d\n", src + offset, len); ++ ++ sg_set_buf(sg, src + offset, len); ++ ++#if (DUMP_URB_SZ > 0) ++ if (usbback_debug_lvl() >= LOG_LVL_DUMP) ++ dump(src + offset, len); ++#endif ++ ++ return len; ++} ++ ++static void setup_sgs(pending_req_t *pending_req, int iso) ++{ ++ struct urb *urb = pending_req->urb; ++ int i, len, remaining; ++ uint8_t *src; ++ ++ remaining = urb->transfer_buffer_length; ++ if (iso) ++ urb->num_sgs = data_pages(pending_req) - 1; ++ else ++ urb->num_sgs = data_pages(pending_req); ++ ++ sg_init_table(urb->sg, urb->num_sgs); ++ ++ /* setup first seg */ ++ if (iso) ++ src = (uint8_t *)vaddr(pending_req, 1); ++ else ++ src = (uint8_t *)vaddr(pending_req, 0); ++ ++ len = setup_sg(&urb->sg[0], src, pending_req->offset, remaining); ++ debug_print(LOG_LVL_DEBUG, "%d: sg: off %d len %d\n", ++ 0, pending_req->offset, len); ++ ++ remaining -= len; ++ ++ /* setup remaining segs */ ++ for (i = 1; i < urb->num_sgs; i++) { ++ if (iso) ++ src = (uint8_t *)vaddr(pending_req, i + 1); ++ else ++ src = (uint8_t *)vaddr(pending_req, i); ++ ++ len = setup_sg(&urb->sg[i], src, 0, remaining); ++ debug_print(LOG_LVL_DEBUG, "%d: sg: off %d len %d\n", ++ i, 0, len); ++ ++ remaining -= len; ++ } ++} ++ ++static int copy_out_iso_descriptors(pending_req_t *pending_req) ++{ ++ struct usb_iso_packet_descriptor *desc; ++ usbif_iso_packet_info_t *info; ++ int i, length = 0; ++ ++ if (!data_pages(pending_req)) ++ return (length); ++ ++ /* copy ISO packet descriptors */ ++ info = (usbif_iso_packet_info_t *)vaddr(pending_req, 0); ++ desc = pending_req->urb->iso_frame_desc; ++ ++ for (i=0; inr_packets; i++) { ++ int end = info[i].offset + info[i].length; ++ ++ debug_print(LOG_LVL_DEBUG, " %d: iso desc: off %d len %d\n", ++ i, info[i].offset, info[i].length); ++ desc[i].offset = info[i].offset; ++ desc[i].length = info[i].length; ++ desc[i].actual_length = 0; ++ desc[i].status = 0; ++ ++ if (end > length) ++ length = end; ++ } ++ ++ return (length); ++} ++ ++static int copy_out_iso(pending_req_t *pending_req) ++{ ++ uint8_t *dst, *src; ++ int i, len, remaining, nr_pages; ++ ++ remaining = pending_req->urb->transfer_buffer_length; ++ nr_pages = data_pages(pending_req); ++ ++ if (nr_pages < 2) ++ return (0); ++ ++ /* copy first seg */ ++ dst = pending_req->urb->transfer_buffer; ++ src = (uint8_t *)vaddr(pending_req, 1) + pending_req->offset; ++ ++ len = copy_first_chunk(dst, src, pending_req->offset, remaining); ++ ++ dst += len; ++ remaining -= len; ++ ++ /* copy remaining segs */ ++ for (i = 2; i < nr_pages; i++) { ++ src = (uint8_t *)vaddr(pending_req, i); ++ ++ len = copy_chunk(dst, src, remaining); ++ ++ dst += len; ++ remaining -= len; ++ } ++ ++#if (DUMP_URB_SZ > 0) ++ if (usbback_debug_lvl() >= LOG_LVL_DUMP) ++ dump_iso_urb(pending_req->urb); ++#endif ++ return (0); ++} ++ ++int copy_out(pending_req_t *pending_req) ++{ ++ struct urb *urb = pending_req->urb; ++ ++ if (pending_req->type == USBIF_T_ISOC) { ++ if (copy_out_iso_descriptors(pending_req) > ++ pending_req->urb->transfer_buffer_length) ++ return (-EINVAL); ++ ++ if (urb->sg) ++ setup_sgs(pending_req, 1); ++ else if (!pending_req->direction_in) ++ copy_out_iso(pending_req); ++ } else { ++ if (urb->sg) ++ setup_sgs(pending_req, 0); ++ else if (!pending_req->direction_in) ++ copy_out_req(pending_req); ++ } ++ ++ return (0); ++} ++ ++static void copy_in_req(pending_req_t *pending_req) ++{ ++ uint8_t *dst, *src; ++ int i, len, remaining, nr_pages; ++ ++ remaining = pending_req->urb->actual_length; ++ nr_pages = data_pages(pending_req); ++ ++ if (!nr_pages) ++ return; ++ ++ /* copy first seg */ ++ dst = (uint8_t *)vaddr(pending_req, 0) + pending_req->offset; ++ src = pending_req->urb->transfer_buffer; ++ ++ len = copy_first_chunk(dst, src, pending_req->offset, remaining); ++ ++ src += len; ++ remaining -= len; ++ ++ /* copy remaining segs */ ++ for (i = 1; i < nr_pages; i++) { ++ dst = (uint8_t *)vaddr(pending_req, i); ++ ++ len = copy_chunk(dst, src, remaining); ++ ++ src += len; ++ remaining -= len; ++ } ++ ++#if (DUMP_URB_SZ > 0) ++ if (usbback_debug_lvl() >= LOG_LVL_DUMP) ++ dump(pending_req->urb->transfer_buffer, ++ pending_req->urb->actual_length); ++#endif ++} ++ ++static void cleanup_sgs(pending_req_t *pending_req) ++{ ++ struct urb *urb = pending_req->urb; ++ int i; ++ ++ debug_print(LOG_LVL_DEBUG, "sgs: total %d mapped %d\n", ++ urb->num_sgs, urb->num_mapped_sgs); ++ ++ for (i = 0; i < urb->num_sgs; i++) { ++ struct scatterlist *sg = &urb->sg[i]; ++ ++ debug_print(LOG_LVL_DEBUG, " %d: ptr %p len %d\n", ++ i, sg_virt(sg), sg->length); ++ ++#if (DUMP_URB_SZ > 0) ++ if (usbback_debug_lvl() >= LOG_LVL_DUMP) ++ dump(sg_virt(sg), sg->length); ++#endif ++ } ++} ++ ++static int copy_in_iso_descriptors(pending_req_t *pending_req) ++{ ++ struct usb_iso_packet_descriptor *desc; ++ usbif_iso_packet_info_t *info; ++ int i, length = 0; ++ ++ if (!data_pages(pending_req)) ++ return (length); ++ ++ /* copy ISO packet descriptors */ ++ info = (usbif_iso_packet_info_t *)vaddr(pending_req, 0); ++ desc = pending_req->urb->iso_frame_desc; ++ ++ debug_print(LOG_LVL_DEBUG, "iso descs: %d info %p desc %p\n", ++ pending_req->nr_packets, info, desc); ++ ++ for (i=0; inr_packets; i++) { ++ int end = desc[i].offset + desc[i].actual_length; ++ ++ if (pending_req->direction_in) { ++ info[i].length = desc[i].actual_length; ++ info[i].status = get_usb_status(desc[i].status); ++ } ++ debug_print(LOG_LVL_DEBUG, ++ " %d: iso desc: off %d len %d status %d\n", ++ i, desc[i].offset, desc[i].length, desc[i].status); ++ ++ if (end > length) ++ length = end; ++ } ++ ++ return (length); ++} ++ ++static void copy_in_iso(pending_req_t *pending_req, int remaining) ++{ ++ uint8_t *dst, *src; ++ int i, len, nr_pages; ++ ++ nr_pages = data_pages(pending_req); ++ ++ if (data_pages(pending_req) < 2) ++ return; ++ ++ /* copy first seg */ ++ dst = (uint8_t *)vaddr(pending_req, 1) + pending_req->offset; ++ src = pending_req->urb->transfer_buffer; ++ ++ len = copy_first_chunk(dst, src, pending_req->offset, remaining); ++ ++ src += len; ++ remaining -= len; ++ ++ /* copy remaining segs */ ++ for (i = 2; i < nr_pages; i++) { ++ dst = (uint8_t *)vaddr(pending_req, i); ++ ++ len = copy_chunk(dst, src, remaining); ++ ++ src += len; ++ remaining -= len; ++ } ++ ++#if (DUMP_URB_SZ > 0) ++ if (usbback_debug_lvl() >= LOG_LVL_DUMP) ++ dump_iso_urb(pending_req->urb); ++#endif ++} ++ ++void copy_in(pending_req_t *pending_req) ++{ ++ struct urb *urb = pending_req->urb; ++ ++ if (pending_req->type == USBIF_T_ISOC) { ++ int remaining = copy_in_iso_descriptors(pending_req); ++ ++ if (urb->sg) ++ cleanup_sgs(pending_req); ++ else if (pending_req->direction_in) ++ copy_in_iso(pending_req, remaining); ++ } else { ++ if (urb->sg) ++ cleanup_sgs(pending_req); ++ else if (pending_req->direction_in) ++ copy_in_req(pending_req); ++ } ++} ++ +--- /dev/null ++++ b/drivers/usb/xen-usbback/common.h +@@ -0,0 +1,362 @@ ++/* ++ * Copyright (c) Citrix Systems Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation; or, when distributed ++ * separately from the Linux kernel or incorporated into other ++ * software packages, subject to the following license: ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#ifndef __USBIF__BACKEND__COMMON_H__ ++#define __USBIF__BACKEND__COMMON_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define DPRINTK(_f, _a...) \ ++ pr_debug("(file=%s, line=%d) " _f, \ ++ __FILE__ , __LINE__ , ## _a ) ++ ++#undef VUSB_MANAGE_INTERFACES ++#define USBBK_TIMEOUT (15 * HZ) ++#define USBBCK_NRPACKS 1024 ++#define DUMP_URB_SZ 32 ++#undef DEBUG_CHECKS ++#define USBBCK_VERSION 3 ++#define USBBCK_MAX_URB_SZ (10 * 1024 * 1024) ++ ++static inline int usbif_request_type(usbif_request_t *req) ++{ ++ return (req->type); ++} ++ ++static inline int usbif_request_dir_in(usbif_request_t *req) ++{ ++ return ((req->endpoint & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); ++} ++ ++static inline int usbif_request_endpoint_num(usbif_request_t *req) ++{ ++ return (req->endpoint & USB_ENDPOINT_NUMBER_MASK); ++} ++ ++static inline int usbif_request_offset(usbif_request_t *req) ++{ ++ return (req->offset); ++} ++ ++static inline int usbif_request_shortok(usbif_request_t *req) ++{ ++ return (req->flags & USBIF_F_SHORTOK); ++} ++ ++static inline int usbif_request_reset(usbif_request_t *req) ++{ ++ return ((req->flags & USBIF_F_RESET) || (req->type == USBIF_T_RESET)); ++} ++ ++static inline int usbif_request_cycle_port(usbif_request_t *req) ++{ ++ return (req->flags & USBIF_F_CYCLE_PORT); ++} ++ ++static inline int usbif_request_abort_pipe(usbif_request_t *req) ++{ ++ return (req->type == USBIF_T_ABORT_PIPE); ++} ++ ++static inline int usbif_request_get_frame(usbif_request_t *req) ++{ ++ return (req->type == USBIF_T_GET_FRAME); ++} ++ ++static inline int usbif_request_get_speed(usbif_request_t *req) ++{ ++ return (req->type == USBIF_T_GET_SPEED); ++} ++ ++static inline int usbif_request_cancel(usbif_request_t *req) ++{ ++ return (req->type == USBIF_T_CANCEL); ++} ++ ++static inline int usbif_request_type_valid(usbif_request_t *req) ++{ ++ return (req->type <= USBIF_T_MAX); ++} ++ ++static inline int usbif_request_asap(usbif_request_t *req) ++{ ++ return (req->flags & USBIF_F_ASAP); ++} ++ ++static inline int usbif_request_indirect(usbif_request_t *req) ++{ ++ return (req->flags & USBIF_F_INDIRECT); ++} ++ ++static inline int usbif_request_timeout(usbif_request_t *req) ++{ ++ return ((usbif_request_type(req) == USBIF_T_CNTRL) || ++ !usbif_request_dir_in(req)); ++} ++ ++struct usbif_st; ++ ++struct vusb { ++ /* what the domain refers to this vusb as */ ++ usbif_vdev_t handle; ++ unsigned bus; ++ unsigned device; ++ struct usb_device *usbdev; ++ struct usb_anchor anchor; ++ int initted; ++ int active; ++ int canceling_requests; ++ /* maximum sgs supported by HCD this device is attached to */ ++ unsigned max_sgs; ++ int hcd_speed; ++ /* device is allowed to suspend */ ++ int autosuspend : 1; ++ /* copy unaligned transfers? */ ++ int copy_unaligned : 1; ++ struct kref kref; ++}; ++#define KREF_TO_VUSB(d) container_of(d, struct vusb, kref) ++ ++struct backend_info; ++ ++typedef struct usbif_stats_st { ++ int st_oo_req; ++ int st_in_req; ++ int st_out_req; ++ ++ int st_error; ++ int st_reset; ++ ++ int st_in_bandwidth; ++ int st_out_bandwidth; ++ ++ int st_cntrl_req; ++ int st_isoc_req; ++ int st_bulk_req; ++ int st_int_req; ++ int st_ind_req; ++} usbif_stats_t; ++ ++typedef struct usbif_st { ++ /* Unique identifier for this interface. */ ++ domid_t domid; ++ unsigned int handle; ++ /* Physical parameters of the comms window. */ ++ unsigned int irq; ++ /* Comms information. */ ++ enum usbif_protocol usb_protocol; ++ usbif_back_rings_t usb_rings; ++ void *usb_ring_addr; ++ /* The VUSB attached to this interface. */ ++ struct vusb vusb; ++ /* Back pointer to the backend_info. */ ++ struct backend_info *be; ++ /* Private fields. */ ++ spinlock_t usb_ring_lock; ++ atomic_t refcnt; ++ ++ wait_queue_head_t wq; ++ struct task_struct *xenusbd; ++ unsigned int waiting_reqs; ++ ++ /* statistics */ ++ unsigned long st_print; ++ usbif_stats_t stats; ++ ++ wait_queue_head_t waiting_to_free; ++} usbif_t; ++ ++static inline struct usbif_st *usbif_from_vusb(struct vusb *vusb) ++{ ++ return container_of(vusb, struct usbif_st, vusb); ++} ++ ++struct backend_info ++{ ++ struct xenbus_device *dev; ++ usbif_t *usbif; ++ ++ struct xenbus_watch backend_watch; ++ struct xenbus_watch autosuspend_watch; ++ unsigned bus; ++ unsigned device; ++}; ++ ++typedef struct { ++ struct list_head free_list; ++ struct page *page; ++ grant_handle_t grant_handle; ++} pending_segment_t; ++ ++/* ++ * Each outstanding request that we've passed to the lower device layers has a ++ * 'pending_req' allocated to it. When the associated URB completes, the specified domain has a ++ * response queued for it, with the saved 'id' passed back. ++ */ ++typedef struct { ++ usbif_t *usbif; ++ u64 id; ++ int type; ++ int direction_in; ++ uint16_t offset; ++ int nr_pages; ++ int nr_packets; ++ struct list_head free_list; ++ struct list_head to_free_list; ++ struct urb *urb; ++#ifdef USBBK_TIMEOUT ++ struct timer_list timer; ++#endif ++ pending_segment_t *pending_segment[USBIF_MAX_SEGMENTS_PER_REQUEST]; ++ int pending_segments; ++#ifdef INDIRECT_SEGMENTS ++ pending_segment_t **pending_indirect_segment; ++ int pending_indirect_segments; ++ usbif_indirect_request_t *indirect_req[USBIF_MAX_SEGMENTS_PER_REQUEST]; ++#endif ++} pending_req_t; ++ ++static inline int is_indirect(pending_req_t *req) ++{ ++ return (req->pending_indirect_segments > 0); ++} ++ ++static inline unsigned long vaddr_base(pending_req_t *req, int seg) ++{ ++ unsigned long pfn = page_to_pfn(req->pending_segment[seg]->page); ++ return (unsigned long)pfn_to_kaddr(pfn); ++} ++ ++static inline unsigned long vaddr(pending_req_t *req, int seg) ++{ ++#ifdef INDIRECT_SEGMENTS ++ struct page *page = is_indirect(req) ? ++ req->pending_indirect_segment[seg]->page : ++ req->pending_segment[seg]->page; ++ unsigned long pfn = page_to_pfn(page); ++ return (unsigned long)pfn_to_kaddr(pfn); ++#else ++ return vaddr_base(req, seg); ++#endif ++} ++ ++static inline int data_pages(pending_req_t *req) ++{ ++ return (is_indirect(req) ? ++ req->pending_indirect_segments : ++ req->nr_pages); ++} ++ ++ ++usbif_t *usbif_alloc(domid_t domid); ++void usbif_kill_xenusbd(usbif_t *usbif); ++void usbif_disconnect(usbif_t *usbif, struct xenbus_device *dev); ++void usbif_free(usbif_t *usbif); ++int usbif_map(usbif_t *usbif, grant_ref_t shpage_ref, unsigned int evtchn); ++ ++int get_usb_status(int status); ++ ++#define usbif_get(_b) (atomic_inc(&(_b)->refcnt)) ++#define usbif_put(_b) \ ++ do { \ ++ if (atomic_dec_and_test(&(_b)->refcnt)) \ ++ wake_up(&(_b)->waiting_to_free);\ ++ } while (0) ++ ++static inline int vusb_connected(struct vusb *vusb) ++{ ++ return (vusb->usbdev != NULL); ++} ++int vusb_init(void); ++int vusb_create(usbif_t *usbif, usbif_vdev_t vdevice, unsigned bus, ++ unsigned device); ++void vusb_free(struct vusb *vusb); ++int vusb_setup_urb(struct vusb *vusb, usbif_request_t *req, struct urb *urb); ++static inline int vusb_canceling_requests(struct vusb *vusb) ++{ ++ return (vusb->canceling_requests == 1); ++} ++int vusb_reset_device(struct vusb *vusb); ++void vusb_flush(struct vusb *vusb); ++int vusb_flush_endpoint(struct vusb *vusb, usbif_request_t *req); ++int vusb_get_speed(struct vusb *vusb); ++void vusb_free_coherent(struct vusb *vusb, struct urb *urb); ++void *vusb_alloc_coherent(struct vusb *vusb, size_t size, dma_addr_t *dma); ++void vusb_cycle_port(struct vusb *vusb); ++ ++/* vusb power management methods */ ++void vusb_pm_autosuspend_control(struct vusb *vusb, int enable); ++ ++void usbif_interface_init(void); ++ ++int usbif_xenbus_init(void); ++ ++irqreturn_t usbif_be_int(int irq, void *dev_id); ++int usbif_schedule(void *arg); ++ ++int usbback_barrier(struct xenbus_transaction xbt, ++ struct backend_info *be, int state); ++int usbback_suspend(usbif_t *usbif, int suspended); ++ ++unsigned int usbback_debug_lvl(void); ++ ++#define LOG_LVL_ERROR 0 ++#define LOG_LVL_INFO 1 ++#define LOG_LVL_DEBUG 2 ++#define LOG_LVL_DUMP 3 ++ ++#define debug_print(l, _f, ...) \ ++ do { if (usbback_debug_lvl() >= (l)) printk((_f), ##__VA_ARGS__); } while(0) ++ ++static inline unsigned int buffer_pages(unsigned int length) ++{ ++ return ((length + PAGE_SIZE - 1) >> PAGE_SHIFT); ++} ++ ++/* buffer handling routines */ ++int copy_out(pending_req_t *pending_req); ++void copy_in(pending_req_t *pending_req); ++ ++void dump(uint8_t *buffer, int len); ++ ++#endif /* __USBIF__BACKEND__COMMON_H__ */ +--- /dev/null ++++ b/drivers/usb/xen-usbback/interface.c +@@ -0,0 +1,165 @@ ++/****************************************************************************** ++ * ++ * usb device interface management. ++ * ++ * Copyright (c) 2004, Keir Fraser ++ * Copyright (c) 2008-2012, Virtual Computer Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation; or, when distributed ++ * separately from the Linux kernel or incorporated into other ++ * software packages, subject to the following license: ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++ ++static struct kmem_cache *usbif_cachep; ++ ++usbif_t *usbif_alloc(domid_t domid) ++{ ++ usbif_t *usbif; ++ ++ usbif = kmem_cache_alloc(usbif_cachep, GFP_KERNEL); ++ if (!usbif) ++ return ERR_PTR(-ENOMEM); ++ ++ memset(usbif, 0, sizeof(*usbif)); ++ usbif->domid = domid; ++ spin_lock_init(&usbif->usb_ring_lock); ++ atomic_set(&usbif->refcnt, 1); ++ init_waitqueue_head(&usbif->wq); ++ usbif->st_print = jiffies; ++ init_waitqueue_head(&usbif->waiting_to_free); ++ ++ return usbif; ++} ++ ++int usbif_map(usbif_t *usbif, grant_ref_t shpage_ref, unsigned int evtchn) ++{ ++ int err; ++ ++ /* Already connected through? */ ++ if (usbif->irq) ++ return 0; ++ ++ debug_print(LOG_LVL_INFO, "Map shared ring, connect event channel\n"); ++ ++ /* Call the xenbus function to map the shared page. It handles the case ++ * where alloc_vm_area is done in a process context that is not init ++ * but only the init_mm tables are updated. Normally a fault would ++ * correct this in other processes but the supsequent hypercall blocks ++ * that fault handling. Therefore in the hypercall it sees the PTE's ++ * not populated. The xenbus routine also tracks the vm area allocation ++ * and the op.handle for cleanup. ++ */ ++ err = xenbus_map_ring_valloc(usbif->be->dev, ++ &shpage_ref, 1, &(usbif->usb_ring_addr)); ++ if (err) ++ return err; ++ ++ switch (usbif->usb_protocol) { ++ case USBIF_PROTOCOL_NATIVE: ++ { ++ struct usbif_sring *sring; ++ sring = (struct usbif_sring *)usbif->usb_ring_addr; ++ BACK_RING_INIT(&usbif->usb_rings.native, sring, PAGE_SIZE); ++ break; ++ } ++ case USBIF_PROTOCOL_X86_32: ++ { ++ struct usbif_x86_32_sring *sring_x86_32; ++ sring_x86_32 = (struct usbif_x86_32_sring *)usbif->usb_ring_addr; ++ BACK_RING_INIT(&usbif->usb_rings.x86_32, sring_x86_32, PAGE_SIZE); ++ break; ++ } ++ case USBIF_PROTOCOL_X86_64: ++ { ++ struct usbif_x86_64_sring *sring_x86_64; ++ sring_x86_64 = (struct usbif_x86_64_sring *)usbif->usb_ring_addr; ++ BACK_RING_INIT(&usbif->usb_rings.x86_64, sring_x86_64, PAGE_SIZE); ++ break; ++ } ++ default: ++ BUG(); ++ } ++ ++ err = bind_interdomain_evtchn_to_irqhandler_lateeoi( ++ usbif->domid, evtchn, usbif_be_int, 0, "usbif-backend", usbif); ++ if (err < 0) ++ { ++ xenbus_unmap_ring_vfree(usbif->be->dev, usbif->usb_ring_addr); ++ usbif->usb_rings.common.sring = NULL; ++ usbif->usb_ring_addr = NULL; ++ return err; ++ } ++ usbif->irq = err; ++ ++ return 0; ++} ++ ++void usbif_kill_xenusbd(usbif_t *usbif) ++{ ++ struct task_struct *xenusbd = xchg(&usbif->xenusbd, NULL); ++ ++ if (xenusbd && !IS_ERR(xenusbd)) ++ kthread_stop(xenusbd); ++} ++ ++void usbif_disconnect(usbif_t *usbif, struct xenbus_device *dev) ++{ ++ debug_print(LOG_LVL_INFO, "Disconnect shared ring and event channel\n"); ++ usbif_kill_xenusbd(usbif); ++ ++ atomic_dec(&usbif->refcnt); ++ wait_event(usbif->waiting_to_free, atomic_read(&usbif->refcnt) == 0); ++ atomic_inc(&usbif->refcnt); ++ ++ if (usbif->irq) { ++ unbind_from_irqhandler(usbif->irq, usbif); ++ usbif->irq = 0; ++ } ++ ++ if (usbif->usb_rings.common.sring) { ++ xenbus_unmap_ring_vfree(dev, usbif->usb_ring_addr); ++ usbif->usb_rings.common.sring = NULL; ++ usbif->usb_ring_addr = NULL; ++ } ++} ++ ++void usbif_free(usbif_t *usbif) ++{ ++ if (!atomic_dec_and_test(&usbif->refcnt)) ++ BUG(); ++ kmem_cache_free(usbif_cachep, usbif); ++} ++ ++void __init usbif_interface_init(void) ++{ ++ usbif_cachep = kmem_cache_create("usbif_cache", sizeof(usbif_t), ++ 0, 0, NULL); ++} +--- /dev/null ++++ b/drivers/usb/xen-usbback/usbback.c +@@ -0,0 +1,1297 @@ ++/****************************************************************************** ++ * ++ * Back-end of the driver for virtual block devices. This portion of the ++ * driver exports a 'unified' block-device interface that can be accessed ++ * by any operating system that implements a compatible front end. A ++ * reference front-end implementation can be found in: ++ * arch/xen/drivers/blkif/frontend ++ * ++ * Back-end of the driver for PV USB. ++ * ++ * Originally based on blkback: ++ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand ++ * Copyright (c) 2005, Christopher Clark ++ * ++ * PV usbback: ++ * Copyright (c) Citrix Systems Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation; or, when distributed ++ * separately from the Linux kernel or incorporated into other ++ * software packages, subject to the following license: ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++/* derived from xen/blkback/blkback.c */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++ ++static int usbif_reqs = 128; ++module_param_named(reqs, usbif_reqs, int, 0); ++MODULE_PARM_DESC(reqs, "Number of usbback requests to allocate"); ++ ++/* Run-time switchable: /sys/module/usbback/parameters/ */ ++static unsigned int log_stats = 0; ++static unsigned int debug_lvl = 0; ++module_param(log_stats, int, 0644); ++module_param(debug_lvl, int, 0644); ++ ++unsigned int usbback_debug_lvl(void) ++{ ++ return (debug_lvl); ++} ++static pending_req_t *pending_reqs; ++static struct list_head pending_free; ++static DEFINE_SPINLOCK(pending_free_lock); ++static DECLARE_WAIT_QUEUE_HEAD(pending_free_wq); ++ ++#define USBBACK_INVALID_HANDLE (~0) ++ ++static struct page **pending_pages; ++static pending_segment_t *pending_segments; ++static struct list_head pending_segments_free; ++static int pending_segments_free_cnt; ++ ++static DEFINE_SPINLOCK(pending_to_free_lock); ++static struct list_head pending_to_free; ++static void async_free_reqs(unsigned long); ++static DECLARE_TASKLET(async_free_reqs_task, async_free_reqs, 0); ++ ++static int do_usb_io_op(usbif_t *usbif, unsigned int *eoi_flags); ++static void dispatch_usb_io(usbif_t *usbif, ++ usbif_request_t *req, ++ pending_req_t *pending_req); ++static void make_response(usbif_t *usbif, u64 id, int actual_length, ++ int startframe, int status, int error_count); ++ ++/****************************************************************** ++ * misc small helpers ++ */ ++static int populate_req(pending_req_t *req) ++{ ++ unsigned long flags; ++ int index; ++ ++ req->pending_segments = 0; ++#ifdef INDIRECT_SEGMENTS ++ req->pending_indirect_segments = 0; ++#endif ++ ++ spin_lock_irqsave(&pending_free_lock, flags); ++ if (req->nr_pages > pending_segments_free_cnt) { ++ spin_unlock_irqrestore(&pending_free_lock, flags); ++ debug_print(LOG_LVL_ERROR, ++ "%s not enough segs (%d) need (%d)\n", ++ __FUNCTION__, pending_segments_free_cnt, ++ req->nr_pages); ++ return -1; ++ } ++ ++ for (index=0; indexnr_pages; index++) { ++ pending_segment_t *segment = ++ list_entry(pending_segments_free.next, ++ pending_segment_t, free_list); ++ BUG_ON(!segment); ++ list_del(&segment->free_list); ++ pending_segments_free_cnt--; ++ ++#ifdef DEBUG_CHECKS ++ debug_print(LOG_LVL_DEBUG, ++ "%s %p seg %d (%d) page %p\n", ++ __FUNCTION__, req, index, ++ pending_segments_free_cnt, segment->page); ++#endif ++ req->pending_segment[index] = segment; ++ } ++ req->pending_segments = req->nr_pages; ++ spin_unlock_irqrestore(&pending_free_lock, flags); ++ ++ return 0; ++} ++ ++#ifdef INDIRECT_SEGMENTS ++static int populate_indirect(pending_req_t *req, int segs) ++{ ++ unsigned long flags; ++ int index; ++ ++ spin_lock_irqsave(&pending_free_lock, flags); ++ if (segs > pending_segments_free_cnt) { ++ spin_unlock_irqrestore(&pending_free_lock, flags); ++ debug_print(LOG_LVL_ERROR, ++ "%s not enough segs (%d) need (%d)\n", ++ __FUNCTION__, pending_segments_free_cnt, ++ req->nr_pages); ++ return -1; ++ } ++ ++ for (index=0; indexfree_list); ++ pending_segments_free_cnt--; ++ ++#ifdef DEBUG_CHECKS ++ debug_print(LOG_LVL_DEBUG, ++ "%s req %p seg %d (%d) page %p\n", ++ __FUNCTION__, req, index, pending_segments_free_cnt, ++ segment->page); ++#endif ++ req->pending_indirect_segment[index] = segment; ++ } ++ ++ req->pending_indirect_segments = segs; ++ ++ spin_unlock_irqrestore(&pending_free_lock, flags); ++ ++ return 0; ++} ++#endif ++ ++static pending_req_t* alloc_req(void) ++{ ++ pending_req_t *req = NULL; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pending_free_lock, flags); ++ if (!list_empty(&pending_free)) { ++ req = list_entry(pending_free.next, pending_req_t, free_list); ++ list_del(&req->free_list); ++ } ++ spin_unlock_irqrestore(&pending_free_lock, flags); ++ ++ debug_print(LOG_LVL_DEBUG, "%s req %p\n", __FUNCTION__, req); ++ ++ return req; ++} ++ ++#ifdef INDIRECT_SEGMENTS ++static void free_indirect_segments(pending_req_t *req) ++{ ++ int index; ++ ++ assert_spin_locked(&pending_free_lock); ++ ++ for (index=0; indexpending_indirect_segments; index++) { ++ pending_segment_t *segment = req->pending_indirect_segment[index]; ++ ++ BUG_ON(!segment); ++ req->pending_indirect_segment[index] = NULL; ++ list_add(&segment->free_list, &pending_segments_free); ++ pending_segments_free_cnt++; ++ ++#ifdef DEBUG_CHECKS ++ debug_print(LOG_LVL_DEBUG, "%s req %p seg %d (%d) page %p\n", ++ __FUNCTION__, req, index, pending_segments_free_cnt, ++ segment->page); ++#endif ++ } ++ ++ kfree(req->pending_indirect_segment); ++ req->pending_indirect_segment = NULL; ++ req->pending_indirect_segments = 0; ++} ++#endif ++ ++static void free_segments(pending_req_t *req) ++{ ++ int index; ++ ++ assert_spin_locked(&pending_free_lock); ++ ++#ifdef INDIRECT_SEGMENTS ++ if (is_indirect(req)) ++ free_indirect_segments(req); ++#endif ++ ++ for (index=0; indexpending_segments; index++) { ++ pending_segment_t *segment = req->pending_segment[index]; ++ ++ BUG_ON(!segment); ++ req->pending_segment[index] = NULL; ++ ++ list_add(&segment->free_list, &pending_segments_free); ++ pending_segments_free_cnt++; ++ ++#ifdef DEBUG_CHECKS ++ debug_print(LOG_LVL_DEBUG, "%s req %p seg %d (%d) page %p\n", ++ __FUNCTION__, req, index, pending_segments_free_cnt, ++ segment->page); ++#endif ++ } ++ req->pending_segments = 0; ++ req->nr_pages = 0; ++} ++ ++static void free_req(pending_req_t *req) ++{ ++ unsigned long flags; ++ int was_empty; ++ struct urb *urb = req->urb; ++ ++ req->urb = NULL; ++ if (urb) { ++ if (urb->transfer_buffer_length) { ++ struct vusb *vusb = &req->usbif->vusb; ++ vusb_free_coherent(vusb, urb); ++ } ++ if (urb->setup_packet) { ++ kfree(urb->setup_packet); ++ urb->setup_packet = NULL; ++ } ++ if (urb->sg) { ++ kfree(urb->sg); ++ urb->sg = NULL; ++ } ++ } ++ req->usbif = NULL; ++ ++ debug_print(LOG_LVL_DEBUG, "%s %p\n", __FUNCTION__, req); ++ ++ spin_lock_irqsave(&pending_free_lock, flags); ++ free_segments(req); ++ was_empty = list_empty(&pending_free); ++ list_add(&req->free_list, &pending_free); ++ spin_unlock_irqrestore(&pending_free_lock, flags); ++ if (was_empty) ++ wake_up(&pending_free_wq); ++} ++ ++static void async_free_reqs(unsigned long data) ++{ ++ struct list_head tmp; ++ pending_req_t *req; ++ struct urb *urb; ++ unsigned long flags; ++ ++ INIT_LIST_HEAD(&tmp); ++ ++ /* Copy to temp list */ ++ spin_lock_irqsave(&pending_to_free_lock, flags); ++ list_splice_init(&pending_to_free, &tmp); ++ spin_unlock_irqrestore(&pending_to_free_lock, flags); ++ ++ /* Run actual free outside of interrupt context */ ++ while (!list_empty(&tmp)) { ++ req = list_entry(tmp.next, pending_req_t, to_free_list); ++ list_del(&req->to_free_list); ++ ++ /* Stash the urb and call the real free_req routine */ ++ urb = req->urb; ++ free_req(req); ++ ++ /* ++ * The urb had its ref count bumped to keep it alive before being queued for ++ * cleanup in this bottom half routine. Dropping that ref here will likely ++ * cleanup and release the urb. ++ */ ++ if (urb) ++ usb_put_urb(urb); ++ } ++} ++ ++#ifdef INDIRECT_SEGMENTS ++static void fast_flush_area_indirect(pending_req_t *req) ++{ ++ struct gnttab_unmap_grant_ref *unmap; ++ unsigned int i, invcount = 0; ++ grant_handle_t *handle; ++ pending_segment_t *indirect_seg; ++ struct page **pages; ++ int ret; ++ ++ debug_print(LOG_LVL_DEBUG, "%s Flushing %d indirect segs!\n", ++ __FUNCTION__, req->pending_indirect_segments); ++ ++ unmap = kmalloc(sizeof(struct gnttab_unmap_grant_ref) * ++ req->pending_indirect_segments, GFP_ATOMIC); ++ if (!unmap) { ++ debug_print(LOG_LVL_ERROR, "%s kmalloc failed for %zu bytes!\n", ++ __FUNCTION__, sizeof(struct gnttab_unmap_grant_ref) * ++ req->pending_indirect_segments); ++ return; ++ } ++ ++ pages = kmalloc_array(req->pending_indirect_segments, sizeof(pages[0]), GFP_ATOMIC); ++ if (!pages) { ++ debug_print(LOG_LVL_ERROR, "%s: req %p malloc %d pages failed\n", ++ __FUNCTION__, req, req->pending_indirect_segments); ++ ret = -1; ++ goto free_unmap; ++ } ++ ++ for (i = 0; i < req->pending_indirect_segments; i++) { ++ indirect_seg = req->pending_indirect_segment[i]; ++ BUG_ON(!indirect_seg); ++ ++ handle = &indirect_seg->grant_handle; ++ if (*handle == USBBACK_INVALID_HANDLE) ++ continue; ++ gnttab_set_unmap_op(&unmap[i], vaddr(req, i), ++ GNTMAP_host_map, *handle); ++ *handle = USBBACK_INVALID_HANDLE; ++ invcount++; ++ pages[i] = indirect_seg->page; ++ } ++ ret = gnttab_unmap_refs(unmap, NULL, pages, invcount); ++ BUG_ON(ret); ++ ++ kfree(pages); ++free_unmap: ++ kfree(unmap); ++} ++#endif ++ ++static void fast_flush_area(pending_req_t *req) ++{ ++ struct gnttab_unmap_grant_ref unmap[USBIF_MAX_SEGMENTS_PER_REQUEST]; ++ unsigned int i, invcount = 0; ++ grant_handle_t *handle; ++ struct page **pages; ++ int ret; ++ ++#ifdef INDIRECT_SEGMENTS ++ if (is_indirect(req)) ++ fast_flush_area_indirect(req); ++#endif ++ ++ pages = kmalloc_array(req->nr_pages, sizeof(pages[0]), GFP_ATOMIC); ++ if (!pages) { ++ debug_print(LOG_LVL_ERROR, "%s: req %p malloc %d pages failed\n", ++ __FUNCTION__, req, req->nr_pages); ++ return; ++ } ++ ++ debug_print(LOG_LVL_DEBUG, "%s Flushing %d segs!\n", ++ __FUNCTION__, req->nr_pages); ++ ++ for (i = 0; i < req->nr_pages; i++) { ++ handle = &req->pending_segment[i]->grant_handle; ++ if (*handle == USBBACK_INVALID_HANDLE) ++ continue; ++ gnttab_set_unmap_op(&unmap[i], vaddr_base(req, i), GNTMAP_host_map, ++ *handle); ++ *handle = USBBACK_INVALID_HANDLE; ++ invcount++; ++ pages[i] = req->pending_segment[i]->page; ++ } ++ ++ ret = gnttab_unmap_refs(unmap, NULL, pages, invcount); ++ BUG_ON(ret); ++ ++ kfree(pages); ++} ++ ++/* ++ * This is our special version of usb_kill_anchored_urbs. Our routine ++ * is a bit like that one except it is used to snipe a single URB. ++ */ ++static void cancel_urb(struct usb_anchor *anchor, u64 cancel_id) ++{ ++ struct urb *victim; ++ bool found = false; ++ ++ spin_lock_irq(&anchor->lock); ++ list_for_each_entry(victim, &anchor->urb_list, anchor_list) { ++ if (((pending_req_t*)victim->context)->id == cancel_id) { ++ usb_get_urb(victim); ++ found = true; ++ break; ++ } ++ } ++ spin_unlock_irq(&anchor->lock); ++ ++ if (!found) ++ return; ++ ++ /* ++ * Now there is an extra ref of the URB. After killing it, drop the ref ++ * count. The docs say the URB cannot be deleted within the kill call. ++ * The ref count will prevent the async cleanup part of the completion ++ * routines from doing this. ++ */ ++ usb_kill_urb(victim); ++ usb_put_urb(victim); ++} ++ ++/****************************************************************** ++ * SCHEDULER FUNCTIONS ++ */ ++ ++static void print_stats(usbif_t *usbif) ++{ ++ usbif_stats_t *stats = &usbif->stats; ++ ++ printk("%s: oo %3d | in %4d (%6d) | out %4d (%6d) | cntrl %4d | " ++ "isoc %4d | bulk %4d | int %4d | ind %4d | err %4d | rst %4d\n", ++ current->comm, stats->st_oo_req, stats->st_in_req, ++ stats->st_in_bandwidth, stats->st_out_req, ++ stats->st_out_bandwidth, stats->st_cntrl_req, ++ stats->st_isoc_req, stats->st_bulk_req, stats->st_int_req, ++ stats->st_ind_req, stats->st_error, stats->st_reset); ++ usbif->st_print = jiffies + msecs_to_jiffies(10 * 1000); ++ memset(&usbif->stats, 0, sizeof(usbif_stats_t)); ++} ++ ++int usbif_schedule(void *arg) ++{ ++ usbif_t *usbif = arg; ++ bool do_eoi; ++ unsigned int eoi_flags = XEN_EOI_FLAG_SPURIOUS; ++ ++ usbif_get(usbif); ++ ++ debug_print(LOG_LVL_INFO, "%s: started\n", current->comm); ++ ++ while (!kthread_should_stop()) { ++ if (try_to_freeze()) ++ continue; ++ ++ wait_event_interruptible( ++ usbif->wq, ++ usbif->waiting_reqs || kthread_should_stop()); ++ wait_event_interruptible( ++ pending_free_wq, ++ !list_empty(&pending_free) || kthread_should_stop()); ++ ++ if (!kthread_should_stop()) { ++ do_eoi = usbif->waiting_reqs; ++ usbif->waiting_reqs = 0; ++ smp_mb(); /* clear flag *before* checking for work */ ++ ++ if (do_usb_io_op(usbif, &eoi_flags)) ++ usbif->waiting_reqs = 1; ++ ++ if (do_eoi && !usbif->waiting_reqs) { ++ xen_irq_lateeoi(usbif->irq, eoi_flags); ++ eoi_flags |= XEN_EOI_FLAG_SPURIOUS; ++ } ++ ++ if (log_stats && time_after(jiffies, usbif->st_print)) ++ print_stats(usbif); ++ } ++ } ++ ++ /* cancel any outstanding URBs */ ++ vusb_flush(&usbif->vusb); ++ ++ if (log_stats) ++ print_stats(usbif); ++ ++ debug_print(LOG_LVL_INFO, "%s: exiting\n", current->comm); ++ ++ usbif_put(usbif); ++ ++ return 0; ++} ++ ++static char *get_usb_statmsg(int status) ++{ ++ static char unkmsg[28]; ++ ++ switch (status) { ++ case 0: ++ return "success"; ++ case -ENOENT: ++ return "unlinked (sync)"; ++ case -EINPROGRESS: ++ return "pending"; ++ case -EPROTO: ++ return "bit stuffing error, timeout, or unknown USB error"; ++ case -EILSEQ: ++ return "CRC mismatch, timeout, or unknown USB error"; ++ case -ETIME: ++ return "timed out"; ++ case -EPIPE: ++ return "endpoint stalled"; ++ case -ECOMM: ++ return "IN buffer overrun"; ++ case -ENOSR: ++ return "OUT buffer underrun"; ++ case -EOVERFLOW: ++ return "too much data"; ++ case -EREMOTEIO: ++ return "short packet detected"; ++ case -ENODEV: ++ case -EHOSTUNREACH: ++ return "device removed"; ++ case -EXDEV: ++ return "partial isochronous transfer"; ++ case -EINVAL: ++ return "invalid argument"; ++ case -ECONNRESET: ++ return "unlinked (async)"; ++ case -ESHUTDOWN: ++ return "device shut down"; ++ default: ++ snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status); ++ return unkmsg; ++ } ++} ++ ++int get_usb_status(int status) ++{ ++ switch (status) { ++ case 0: ++ /* success */ ++ return USBIF_RSP_OKAY; ++ case -ENOENT: ++ /* unlinked (sync) */ ++ return USBIF_RSP_USB_CANCELED; ++ case -EINPROGRESS: ++ /* pending */ ++ return USBIF_RSP_USB_PENDING; ++ case -EPROTO: ++ /* bit stuffing error, timeout, or unknown USB error */ ++ return USBIF_RSP_USB_PROTO; ++ case -EILSEQ: ++ /* CRC mismatch, timeout, or unknown USB error */ ++ return USBIF_RSP_USB_CRC; ++ case -ETIME: ++ /* timed out */ ++ return USBIF_RSP_USB_TIMEOUT; ++ case -EPIPE: ++ /* endpoint stall */ ++ return USBIF_RSP_USB_STALLED; ++ case -ECOMM: ++ /* IN buffer overrun */ ++ return USBIF_RSP_USB_INBUFF; ++ case -ENOSR: ++ /* OUT buffer underrun */ ++ return USBIF_RSP_USB_OUTBUFF; ++ case -EOVERFLOW: ++ /* too much data */ ++ return USBIF_RSP_USB_OVERFLOW; ++ case -EREMOTEIO: ++ /* short packet detected */ ++ return USBIF_RSP_USB_SHORTPKT; ++ case -ENODEV: ++ /* device removed */ ++ return USBIF_RSP_USB_DEVRMVD; ++ case -EXDEV: ++ /* partial isochronous transfer */ ++ return USBIF_RSP_USB_PARTIAL; ++ case -EMSGSIZE: ++ case -EINVAL: ++ /* invalid argument */ ++ return USBIF_RSP_USB_INVALID; ++ case -ECONNRESET: ++ /* unlinked (async) */ ++ return USBIF_RSP_USB_RESET; ++ case -ESHUTDOWN: ++ /* device shut down */ ++ return USBIF_RSP_USB_SHUTDOWN; ++ default: ++ return USBIF_RSP_USB_UNKNOWN; ++ } ++} ++ ++/* ++ * Handle timeouts ++ */ ++#ifdef USBBK_TIMEOUT ++static void timeout_usb_io_op(struct timer_list *t) ++{ ++ pending_req_t *req = from_timer(req, t, timer); ++ ++ debug_print(LOG_LVL_DEBUG, "%s: urb %p\n", __FUNCTION__, req->urb); ++ ++ usb_unlink_urb(req->urb); ++} ++ ++static void set_timeout(pending_req_t *pending_req) ++{ ++ timer_setup(&pending_req->timer, timeout_usb_io_op, 0); ++ pending_req->timer.expires = jiffies + USBBK_TIMEOUT; ++ add_timer(&pending_req->timer); ++} ++ ++static void cancel_timeout(pending_req_t *pending_req) ++{ ++ if (timer_pending(&pending_req->timer)) ++ del_timer(&pending_req->timer); ++} ++#endif ++ ++/* ++ * COMPLETION CALLBACK ++ */ ++static void end_usb_io_op(struct urb *urb) ++{ ++ pending_req_t *pending_req = (pending_req_t *)urb->context; ++ usbif_t *usbif = pending_req->usbif; ++ int status = vusb_canceling_requests(&usbif->vusb) ? ++ -ECONNRESET : urb->status; ++ unsigned long flags; ++ ++ debug_print(LOG_LVL_INFO, "end id %llu len %d status %d %s\n", ++ pending_req->id, urb->actual_length, status, ++ get_usb_statmsg(status)); ++ ++#ifdef USBBK_TIMEOUT ++ cancel_timeout(pending_req); ++#endif ++ ++ /* ++ * Don't need to unanchor, usb_hcd_giveback_urb has already done it ++ * before calling this completion routine. ++ */ ++ if ((urb->status != -ENODEV) && /* device removed */ ++ (urb->status != -ESHUTDOWN) && /* device disabled */ ++ (urb->status != -EPROTO)) { /* timeout or unknown USB error */ ++ copy_in(pending_req); ++ ++ if (pending_req->direction_in) ++ usbif->stats.st_in_bandwidth += ++ urb->transfer_buffer_length; ++ else ++ usbif->stats.st_out_bandwidth += ++ urb->transfer_buffer_length; ++ } ++ ++ fast_flush_area(pending_req); ++ make_response(usbif, pending_req->id, urb->actual_length, ++ urb->start_frame, get_usb_status(status), ++ (pending_req->type == USBIF_T_ISOC) ? urb->error_count : 0); ++ usbif_put(pending_req->usbif); ++ ++ /* ++ * Schedule async free as it causes an oops on 32bit kernel doing dma frees in ++ * this completion handler with irqs disabled (the WARN_ON(irqs_disabled()) ++ * in dma_free_attrs). We have to bump the ref count on the urb since it will ++ * be released after this completion routine returns. See the code in ++ * hcd.c:usb_hcd_giveback_urb() that call the completion callback. ++ */ ++ urb = usb_get_urb(urb); ++ spin_lock_irqsave(&pending_to_free_lock, flags); ++ list_add_tail(&pending_req->to_free_list, &pending_to_free); ++ spin_unlock_irqrestore(&pending_to_free_lock, flags); ++ tasklet_schedule(&async_free_reqs_task); ++} ++ ++/****************************************************************************** ++ * NOTIFICATION FROM GUEST OS. ++ */ ++ ++static void usbif_notify_work(usbif_t *usbif) ++{ ++ usbif->waiting_reqs = 1; ++ wake_up(&usbif->wq); ++} ++ ++irqreturn_t usbif_be_int(int irq, void *dev_id) ++{ ++ usbif_notify_work(dev_id); ++ return IRQ_HANDLED; ++} ++ ++ ++/****************************************************************** ++ * DOWNWARD CALLS -- These interface with the usb-device layer proper. ++ */ ++ ++static int do_usb_io_op(usbif_t *usbif, unsigned int *eoi_flags) ++{ ++ usbif_back_rings_t *usb_rings = &usbif->usb_rings; ++ usbif_request_t req; ++ pending_req_t *pending_req; ++ RING_IDX rc, rp; ++ int more_to_do = 0; ++ ++ rc = usb_rings->common.req_cons; ++ rp = usb_rings->common.sring->req_prod; ++ rmb(); /* Ensure we see queued requests up to 'rp'. */ ++ ++ while ((rc != rp) && !kthread_should_stop()) { ++ ++ if (RING_REQUEST_CONS_OVERFLOW(&usb_rings->common, rc)) ++ break; ++ ++ /* We have a request, clean the spurious flag. */ ++ *eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS; ++ ++ pending_req = alloc_req(); ++ if (NULL == pending_req) { ++ usbif->stats.st_oo_req++; ++ more_to_do = 1; ++ break; ++ } ++ ++ switch (usbif->usb_protocol) { ++ case USBIF_PROTOCOL_NATIVE: ++ memcpy(&req, RING_GET_REQUEST(&usb_rings->native, rc), sizeof(req)); ++ break; ++ case USBIF_PROTOCOL_X86_32: ++ usbif_get_x86_32_req(&req, RING_GET_REQUEST(&usb_rings->x86_32, rc)); ++ break; ++ case USBIF_PROTOCOL_X86_64: ++ usbif_get_x86_64_req(&req, RING_GET_REQUEST(&usb_rings->x86_64, rc)); ++ break; ++ default: ++ BUG(); ++ } ++ usb_rings->common.req_cons = ++rc; /* before make_response() */ ++ ++ if (!usbif_request_type_valid(&req)) { ++ debug_print(LOG_LVL_ERROR, "%s: type %d not valid\n", ++ __FUNCTION__, usbif_request_type(&req)); ++ make_response(usbif, req.id, 0, 0, USBIF_RSP_ERROR, 0); ++ free_req(pending_req); ++ } else if (usbif_request_reset(&req)) { ++ int ret = vusb_reset_device(&usbif->vusb) ++ ? USBIF_RSP_ERROR : USBIF_RSP_OKAY; ++ ++ make_response(usbif, req.id, 0, 0, ret, 0); ++ free_req(pending_req); ++ } else if (usbif_request_cycle_port(&req)) { ++ vusb_cycle_port(&usbif->vusb); ++ ++ make_response(usbif, req.id, 0, 0, USBIF_RSP_OKAY, 0); ++ free_req(pending_req); ++ } else if (usbif_request_abort_pipe(&req)) { ++ int ret = vusb_flush_endpoint(&usbif->vusb, &req) ++ ? USBIF_RSP_ERROR : USBIF_RSP_OKAY; ++ ++ make_response(usbif, req.id, 0, 0, ret, 0); ++ free_req(pending_req); ++ } else if (usbif_request_get_frame(&req)) { ++ int frame = usb_get_current_frame_number(usbif->vusb.usbdev); ++ ++ if (frame >= 0) ++ make_response(usbif, req.id, 0, frame, 0, 0); ++ else ++ make_response(usbif, req.id, 0, 0, USBIF_RSP_ERROR, 0); ++ free_req(pending_req); ++ } else if (usbif_request_get_speed(&req)) { ++ make_response(usbif, req.id, 0, ++ vusb_get_speed(&usbif->vusb), 0, 0); ++ free_req(pending_req); ++ } else if (usbif_request_cancel(&req)) { ++ cancel_urb(&usbif->vusb.anchor, *((u64*)(&req.u.data[0]))); ++ ++ make_response(usbif, req.id, 0, 0, USBIF_RSP_OKAY, 0); ++ free_req(pending_req); ++ } else ++ dispatch_usb_io(usbif, &req, pending_req); ++ } ++ ++ return more_to_do; ++} ++ ++static struct urb * setup_urb(pending_req_t *pending_req, int length, int* err) ++{ ++ struct vusb *vusb = &pending_req->usbif->vusb; ++ struct urb *urb = usb_alloc_urb(pending_req->nr_packets, GFP_KERNEL); ++ *err=0; ++ ++ pending_req->urb = urb; ++ if (urb == NULL) { ++ *err=1; ++ return (NULL); ++ } ++ ++ /* struct urb is pre zeroed, only init to non zero values */ ++ urb->context = pending_req; ++ urb->complete = end_usb_io_op; ++ urb->number_of_packets = pending_req->nr_packets; ++ ++ if (length > 0) { ++ int pages = buffer_pages(pending_req->offset + length); ++ ++ /* ++ * 1. Linux currently only supports scatter gather for bulk ++ * transfers. ++ * 2. Some controllers can't handle unaligned multipage ++ * DMA transfers. ++ */ ++ if ((vusb->max_sgs > 0) && (pages <= vusb->max_sgs) && ++ ((pages == 1) || (!vusb->copy_unaligned || !pending_req->offset)) && ++ (pending_req->type == USBIF_T_BULK)) { ++ urb->sg = kzalloc(pages * sizeof(struct scatterlist), ++ GFP_KERNEL); ++ if (urb->sg == NULL) { ++ *err=2; ++ return (NULL); ++ } ++ } else { ++ urb->transfer_buffer = vusb_alloc_coherent(vusb, ++ length, &urb->transfer_dma); ++ if (urb->transfer_buffer == NULL) { ++ *err=3; ++ return (NULL); ++ } ++ ++ urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; ++ } ++ urb->transfer_buffer_length = length; ++ } ++ ++ if (unlikely(pending_req->type == USBIF_T_CNTRL)) { ++ urb->setup_packet = ++ kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); ++ if (urb->setup_packet == NULL) { ++ *err=4; ++ return (NULL); ++ } ++ } ++ ++ return (urb); ++} ++ ++static int map_request(pending_req_t *pending_req, int offset, domid_t domid, ++ grant_ref_t *gref, unsigned int nseg, int readonly, ++ int indirect) ++{ ++ struct gnttab_map_grant_ref *map; ++ struct page **pages; ++ int i, ret; ++ ++ BUG_ON(nseg > USBIF_MAX_SEGMENTS_PER_IREQUEST); ++ ++ map = kmalloc(sizeof(struct gnttab_map_grant_ref) * nseg, GFP_KERNEL); ++ if (!map) { ++ debug_print(LOG_LVL_ERROR, "%s: req %p offset %d nseg %d indirect %d\n", ++ __FUNCTION__, pending_req, offset, nseg, indirect); ++ return (-1); ++ } ++ ++ pages = kmalloc_array(nseg, sizeof(pages[0]), GFP_KERNEL); ++ if (!pages) { ++ debug_print(LOG_LVL_ERROR, "%s: req %p offset %d nseg %d indirect %d\n", ++ __FUNCTION__, pending_req, offset, nseg, indirect); ++ ret = -1; ++ goto free_map; ++ } ++ ++ for (i = 0; i < nseg; i++) { ++ uint32_t flags; ++#ifdef INDIRECT_SEGMENTS ++ int page_nr = i + offset; ++ unsigned long virtual_address = indirect ? vaddr(pending_req, page_nr) ++ : vaddr_base(pending_req, page_nr); ++#else ++ unsigned long virtual_address = vaddr_base(pending_req, i); ++#endif ++ ++ if (readonly) ++ flags = (GNTMAP_host_map|GNTMAP_readonly); ++ else ++ flags = GNTMAP_host_map; ++ gnttab_set_map_op(&map[i], virtual_address, flags, gref[i], domid); ++ ++ pages[i] = is_indirect(pending_req) ? ++ pending_req->pending_indirect_segment[page_nr]->page : ++ pending_req->pending_segment[page_nr]->page; ++#ifdef DEBUG_CHECKS ++ debug_print(LOG_LVL_DEBUG, "%s: %d of %d gref %x flags %x vaddr %lx\n", ++ __FUNCTION__, i, nseg, gref[i], flags, virtual_address); ++#endif ++ } ++ ++ ret = gnttab_map_refs(map, NULL, pages, nseg); ++ ++ for (i = 0; i < nseg; i++) { ++ int page_nr = i + offset; ++ ++ if (unlikely(map[i].status != 0)) { ++ debug_print(LOG_LVL_ERROR, ++ "invalid buffer -- could not remap it\n"); ++ map[i].handle = USBBACK_INVALID_HANDLE; ++ ret |= !ret; ++ } ++ ++#ifdef INDIRECT_SEGMENTS ++ if (indirect) ++ pending_req->pending_indirect_segment[page_nr]->grant_handle = map[i].handle; ++ else ++#endif ++ pending_req->pending_segment[i]->grant_handle = map[i].handle; ++ } ++ ++ kfree(pages); ++free_map: ++ kfree(map); ++ ++ return (ret); ++} ++ ++#ifdef INDIRECT_SEGMENTS ++static int setup_indirect(usbif_t *usbif, pending_req_t *pending_req, int segs, int in) ++{ ++ unsigned int indirect_req, mapped_segs = 0; ++ ++ debug_print(LOG_LVL_DEBUG, "%s req %p segs %d\n", __FUNCTION__, pending_req, segs); ++ ++ usbif->stats.st_ind_req++; ++ ++ pending_req->pending_indirect_segment = kmalloc(sizeof(pending_segment_t *) * segs, GFP_KERNEL); ++ if (!pending_req->pending_indirect_segment) { ++ debug_print(LOG_LVL_ERROR, "kmalloc indirect segments failed!\n"); ++ return (-1); ++ } ++ ++ if (populate_indirect(pending_req, segs)) { ++ kfree(pending_req->pending_indirect_segment); ++ pending_req->pending_indirect_segment = NULL; ++ debug_print(LOG_LVL_ERROR, "populate indirect failed!\n"); ++ return (-1); ++ } ++ ++ for (indirect_req=0; indirect_reqnr_pages; indirect_req++) { ++ usbif_indirect_request_t *indirect = ++ (usbif_indirect_request_t *)vaddr_base(pending_req, indirect_req); ++ ++ debug_print(LOG_LVL_DEBUG, "%s req %p indirect %d : %p segs %d\n", ++ __FUNCTION__, pending_req, indirect_req, indirect, ++ indirect->nr_segments); ++#if (DUMP_URB_SZ > 0) ++ if (usbback_debug_lvl() >= LOG_LVL_DUMP) ++ dump((uint8_t *)indirect, PAGE_SIZE); ++#endif ++ ++ pending_req->indirect_req[indirect_req] = indirect; ++ ++ if ((indirect->nr_segments == 0) || ++ (indirect->nr_segments > USBIF_MAX_SEGMENTS_PER_IREQUEST)) { ++ debug_print(LOG_LVL_ERROR, "req bad indirect segs!\n"); ++ return (-1); ++ } ++ ++ if (map_request(pending_req, mapped_segs, ++ usbif->domid, indirect->gref, ++ indirect->nr_segments, in, 1)) { ++ debug_print(LOG_LVL_ERROR, "indirect map failed!\n"); ++ return (-1); ++ } ++ ++ mapped_segs += indirect->nr_segments; ++ } ++ ++ BUG_ON(mapped_segs != segs); ++ ++ return (0); ++} ++#endif ++ ++static void dispatch_usb_io(usbif_t *usbif, usbif_request_t *req, ++ pending_req_t *pending_req) ++{ ++ struct urb *urb; ++ int ret = -EINVAL; ++ int type = usbif_request_type(req); ++ int indirect = usbif_request_indirect(req); ++ int err; ++ ++ debug_print(LOG_LVL_INFO, "start %d id %llu %s type %d end %d" ++ " len %d off %d segs %d flags %x pr %p\n", ++ usbif->vusb.handle, req->id, ++ usbif_request_dir_in(req) ? "IN" : "OUT", ++ type, usbif_request_endpoint_num(req), req->length, ++ usbif_request_offset(req), req->nr_segments, ++ (int)req->flags, pending_req); ++ ++ pending_req->usbif = usbif; ++ pending_req->id = req->id; ++ pending_req->type = req->type; ++ pending_req->direction_in = usbif_request_dir_in(req); ++ pending_req->offset = usbif_request_offset(req); ++ pending_req->nr_pages = req->nr_segments; ++ pending_req->nr_packets = req->nr_packets; ++ pending_req->urb = NULL; ++ ++ if (unlikely(req->length > USBBCK_MAX_URB_SZ)) { ++ debug_print(LOG_LVL_ERROR, ++ "Bad req size %d (%d)\n", ++ req->length, USBBCK_MAX_URB_SZ); ++ goto fail_response; ++ } ++ ++ if (unlikely(pending_req->nr_packets > USBBCK_NRPACKS)) { ++ debug_print(LOG_LVL_ERROR, ++ "Bad number of packets in request (%d : %d)\n", ++ req->nr_packets, USBBCK_NRPACKS); ++ goto fail_response; ++ } ++ ++ if (populate_req(pending_req) < 0) { ++ debug_print(LOG_LVL_ERROR, "Failed populate req\n"); ++ goto fail_response; ++ } ++ ++ urb = setup_urb(pending_req, req->length, &err); ++ if (unlikely(urb == NULL)) { ++ if (printk_ratelimit()) ++ debug_print(LOG_LVL_ERROR, "Failed urb alloc, reason = %d\n", err); ++ goto fail_response; ++ } ++ ++ if (req->length > 0) { ++ /* Check that number of segments is sane. */ ++ int pages = buffer_pages(pending_req->offset + req->length); ++ ++ /* ISO requests have one addition page for the desciptors */ ++ if (type == USBIF_T_ISOC) ++ pages++; ++ if (unlikely(req->nr_segments == 0) || ++ unlikely(req->nr_segments ++ > USBIF_MAX_SEGMENTS_PER_REQUEST) || ++ (unlikely(pages != req->nr_segments) && !indirect)) { ++ debug_print(LOG_LVL_ERROR, ++ "Bad number of segments in request (%d : %d)\n", ++ req->nr_segments, pages); ++ goto fail_response; ++ } ++ ++ if ((err = map_request(pending_req, 0, usbif->domid, req->u.gref, ++ req->nr_segments, ++ !usbif_request_dir_in(req) || indirect, ++ 0))) { ++ debug_print(LOG_LVL_ERROR, ++ "map_request failed, err=%d\n",err); ++ goto fail_flush; ++ } ++ ++ if (indirect) { ++#ifdef INDIRECT_SEGMENTS ++ if ((err = setup_indirect(usbif, pending_req, pages, ++ !usbif_request_dir_in(req))) < 0) { ++ debug_print(LOG_LVL_ERROR, ++ "setup_indirect failed, err=%d\n",err); ++ goto fail_flush; ++ } ++#else ++ debug_print(LOG_LVL_ERROR, ++ "indirect specified but not compiled in\n"); ++ goto fail_flush; ++#endif ++ } ++ ++ ret = copy_out(pending_req); ++ if (unlikely(ret < 0)) { ++ debug_print(LOG_LVL_ERROR, ++ "copy iso failed urb %p, ret %d\n", urb, ret); ++ goto fail_flush; ++ } ++ } ++ ++ ret = vusb_setup_urb(&usbif->vusb, req, urb); ++ if (unlikely(ret < 0)) { ++ debug_print(LOG_LVL_ERROR, ++ "setup failed for urb %p, ret %d\n", urb, ret); ++ goto fail_flush; ++ } else if (unlikely(ret > 0)) { ++ debug_print(LOG_LVL_INFO, ++ "control success for urb %p\n", urb); ++ ret = 0; ++ goto early_success; ++ } ++ ++ usbif_get(usbif); ++ ++#ifdef USBBK_TIMEOUT ++ if (usbif_request_timeout(req)) { ++ debug_print(LOG_LVL_DEBUG, ++ "Timeout set for urb for %llu\n", req->id); ++ set_timeout(pending_req); ++ } ++#endif ++ ++ usb_anchor_urb(urb, &usbif->vusb.anchor); ++ ++ ret = usb_submit_urb(urb, GFP_KERNEL); ++ if (unlikely(ret < 0)) { ++ debug_print(LOG_LVL_ERROR, ++ "submit failed for urb %p, ret %d\n", urb, ret); ++ usb_unanchor_urb(urb); ++#ifdef USBBK_TIMEOUT ++ cancel_timeout(pending_req); ++#endif ++ usbif_put(usbif); ++ goto fail_flush; ++ } ++ ++ /* release our urb reference from the alloc, the core now owns it */ ++ usb_free_urb(urb); ++ ++ debug_print(LOG_LVL_INFO, "%s: Submitted urb for %llu\n", ++ __FUNCTION__, req->id); ++ ++ return; ++ ++ early_success: ++ fail_flush: ++ fast_flush_area(pending_req); ++ fail_response: ++ make_response(usbif, req->id, 0, 0, get_usb_status(ret), 0); ++ urb = pending_req->urb; ++ free_req(pending_req); ++ usb_free_urb(urb); ++} ++ ++ ++ ++/****************************************************************** ++ * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING ++ */ ++ ++ ++static void make_response(usbif_t *usbif, u64 id, int actual_length, ++ int data, int status, int error_count) ++{ ++ usbif_response_t resp; ++ unsigned long flags; ++ usbif_back_rings_t *usb_rings = &usbif->usb_rings; ++ int more_to_do = 0; ++ int notify; ++ ++ debug_print(LOG_LVL_INFO, ++ "%s: id %llu len %d data %d status %d\n", ++ __FUNCTION__, id, actual_length, data, status); ++ ++ if (status) ++ usbif->stats.st_error++; ++ ++ resp.id = id; ++ resp.actual_length = actual_length; ++ resp.data = data; ++ resp.status = status; ++ resp.error_count = error_count; /* used for ISOCH only */ ++ ++ spin_lock_irqsave(&usbif->usb_ring_lock, flags); ++ /* Place on the response ring for the relevant domain. */ ++ switch (usbif->usb_protocol) { ++ case USBIF_PROTOCOL_NATIVE: ++ memcpy(RING_GET_RESPONSE(&usb_rings->native, usb_rings->native.rsp_prod_pvt), ++ &resp, sizeof(resp)); ++ break; ++ case USBIF_PROTOCOL_X86_32: ++ memcpy(RING_GET_RESPONSE(&usb_rings->x86_32, usb_rings->x86_32.rsp_prod_pvt), ++ &resp, sizeof(resp)); ++ break; ++ case USBIF_PROTOCOL_X86_64: ++ memcpy(RING_GET_RESPONSE(&usb_rings->x86_64, usb_rings->x86_64.rsp_prod_pvt), ++ &resp, sizeof(resp)); ++ break; ++ default: ++ BUG(); ++ } ++ usb_rings->common.rsp_prod_pvt++; ++ RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&usb_rings->common, notify); ++ if (usb_rings->common.rsp_prod_pvt == usb_rings->common.req_cons) { ++ /* ++ * Tail check for pending requests. Allows frontend to avoid ++ * notifications if requests are already in flight (lower ++ * overheads and promotes batching). ++ */ ++ RING_FINAL_CHECK_FOR_REQUESTS(&usb_rings->common, more_to_do); ++ ++ } else if (RING_HAS_UNCONSUMED_REQUESTS(&usb_rings->common)) { ++ more_to_do = 1; ++ } ++ ++ spin_unlock_irqrestore(&usbif->usb_ring_lock, flags); ++ ++ if (more_to_do) ++ usbif_notify_work(usbif); ++ ++ /* ++ * OXT-311 it is unlikely the Xen ring code is broken since it is ++ * the backbone of PV drivers. This needs investigation and fixing. ++ */ ++ /* always notify, there seems to be a bug in the Xen ring code */ ++ /*if (notify)*/ ++ notify_remote_via_irq(usbif->irq); ++} ++ ++static int __init usbif_init(void) ++{ ++ int i, mmap_pages; ++ ++ if (vusb_init()) ++ return -EINVAL; ++ ++ mmap_pages = usbif_reqs * USBIF_MAX_SEGMENTS_PER_REQUEST; ++ ++ pending_reqs = kzalloc(sizeof(pending_reqs[0]) * ++ usbif_reqs, GFP_KERNEL); ++ pending_pages = vzalloc(sizeof(pending_pages[0]) * mmap_pages); ++ ++ pending_segments = kzalloc(sizeof(pending_segments[0]) * ++ mmap_pages, GFP_KERNEL); ++ ++ if (!pending_reqs || !pending_pages || !pending_segments) ++ goto out_of_memory; ++ ++ if (gnttab_alloc_pages(mmap_pages, pending_pages)) ++ goto out_of_memory; ++ ++ INIT_LIST_HEAD(&pending_segments_free); ++ ++ for (i = 0; i < mmap_pages; i++) { ++ pending_segments[i].grant_handle = USBBACK_INVALID_HANDLE; ++ pending_segments[i].page = pending_pages[i]; ++ list_add_tail(&pending_segments[i].free_list, &pending_segments_free); ++ } ++ pending_segments_free_cnt = mmap_pages; ++ ++ usbif_interface_init(); ++ ++ INIT_LIST_HEAD(&pending_free); ++ ++ for (i = 0; i < usbif_reqs; i++) { ++ timer_setup(&pending_reqs[i].timer, NULL, 0); ++ list_add_tail(&pending_reqs[i].free_list, &pending_free); ++ } ++ ++ INIT_LIST_HEAD(&pending_to_free); ++ ++ if (usbif_xenbus_init()) { ++ pr_warning("Could not register xenbus backend for usbback.\n"); ++ BUG(); ++ } ++ ++ printk("USB backend driver intialized!\n"); ++ ++ return 0; ++ ++ out_of_memory: ++ kfree(pending_reqs); ++ kfree(pending_segments); ++ vfree(pending_pages); ++ printk("%s: out of memory\n", __FUNCTION__); ++ return -ENOMEM; ++} ++ ++module_init(usbif_init); ++ ++MODULE_LICENSE("Dual BSD/GPL"); +--- /dev/null ++++ b/drivers/usb/xen-usbback/vusb.c +@@ -0,0 +1,938 @@ ++/****************************************************************************** ++ * usbback/vusb.c ++ * ++ * Routines for managing virtual usb devices. ++ * ++ * Copyright (c) Citrix Systems Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation; or, when distributed ++ * separately from the Linux kernel or incorporated into other ++ * software packages, subject to the following license: ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++ ++#include "common.h" ++ ++struct vusb_map ++{ ++ int bus; ++ int device; ++ struct vusb *vusb; ++}; ++ ++#define VUSB_MAX_DEVICES 512 ++static struct vusb_map vusb_map[VUSB_MAX_DEVICES]; ++static spinlock_t vusb_map_lock; ++ ++ ++/* Add or update bus,dev to map to new vusb ++ There can be only one of each {bus,device} pair */ ++static int ++vusb_map_device(struct vusb *vusb, int bus, int device) ++{ ++ unsigned long flags; ++ int index; ++ int ret = -1; ++ ++ spin_lock_irqsave(&vusb_map_lock, flags); ++ for (index=0; indexvusb == NULL) || ((map->bus == bus) && (map->device == device)) ){ ++ if (map->vusb) ++ debug_print(LOG_LVL_ERROR, "%s: removing dup\n",__FUNCTION__); ++ map->vusb = vusb; ++ map->bus = bus; ++ map->device = device; ++ ret = 0; ++ break; ++ } ++ } ++ index++; ++ /* flush any remaining dulpicate pairs */ ++ while (indexbus == bus) && (map->device == device)) { ++ debug_print(LOG_LVL_ERROR, "%s: removing dup\n",__FUNCTION__); ++ map->vusb = NULL; ++ map->bus = 0; ++ map->device = 0; ++ } ++ index++; ++ } ++ ++ spin_unlock_irqrestore(&vusb_map_lock, flags); ++ ++ return ret; ++} ++ ++static int ++vusb_unmap_device(struct vusb *vusb) ++{ ++ unsigned long flags; ++ int index; ++ int ret = -1; ++ ++ spin_lock_irqsave(&vusb_map_lock, flags); ++ for (index=0; indexvusb == vusb) { ++ map->vusb = NULL; ++ map->bus = 0; ++ map->device = 0; ++ ret = 0; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&vusb_map_lock, flags); ++ ++ return ret; ++} ++ ++static struct vusb * ++vusb_find_device(int bus, int device) ++{ ++ unsigned long flags; ++ int index; ++ struct vusb *vusb = NULL; ++ ++ spin_lock_irqsave(&vusb_map_lock, flags); ++ for (index=0; indexvusb && (map->bus == bus) && (map->device == device)) { ++ vusb = map->vusb; ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&vusb_map_lock, flags); ++ ++ return vusb; ++} ++ ++static void vusb_delete(struct kref *kref) ++{ ++ struct vusb *vusb = KREF_TO_VUSB(kref); ++ ++ debug_print(LOG_LVL_ERROR, "%s: vusb %p\n", __FUNCTION__, vusb); ++ vusb->active = 0; ++ ++ vusb_flush(vusb); ++} ++ ++static int vusb_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *udev = interface_to_usbdev(intf); ++ int bus = udev->bus->busnum; ++ int port = udev->portnum; ++ int device = udev->devnum; ++ struct vusb *vusb = vusb_find_device(bus, device); ++ ++ debug_print(LOG_LVL_ERROR, "%s: intf %p vusb %p for %d:%d (port %d)\n", ++ __FUNCTION__, intf, vusb, bus, device, port); ++ ++ if (vusb) { ++ if (!vusb->active) { ++ /* ++ * The driver released all of its interfacesi, is now ++ * reprobing. reference counting needs to be restarted ++ * and the device marked active. ++ */ ++ kref_init(&vusb->kref); ++ vusb->active = 1; ++ } else { ++ kref_get(&vusb->kref); ++ } ++ usb_set_intfdata(intf, vusb); ++ return 0; ++ } ++ ++ return -ENODEV; ++} ++ ++static void vusb_disconnect(struct usb_interface *intf) ++{ ++ struct vusb *vusb = usb_get_intfdata(intf); ++ ++ debug_print(LOG_LVL_ERROR, "%s: intf %p vusb %p\n", ++ __FUNCTION__, intf, vusb); ++ ++ if (!vusb) ++ return; ++ ++ /* Mark the interface for later rebinding */ ++ intf->needs_binding = 1; ++ ++ usb_set_intfdata(intf, NULL); ++ kref_put(&vusb->kref, vusb_delete); ++} ++ ++static int vusb_suspend(struct usb_interface *intf, pm_message_t message) ++{ ++ struct vusb *vusb = usb_get_intfdata(intf); ++ ++ debug_print(LOG_LVL_ERROR, "%s: intf %p vusb %p\n", ++ __FUNCTION__, intf, vusb); ++ ++ if (!vusb || !vusb->initted) ++ return -1; ++ ++ usbback_suspend(usbif_from_vusb(vusb), 1); ++ vusb_flush(vusb); ++ return 0; ++} ++ ++static int vusb_resume(struct usb_interface *intf) ++{ ++ struct vusb *vusb = usb_get_intfdata(intf); ++ ++ debug_print(LOG_LVL_ERROR, "%s: intf %p vusb %p\n", ++ __FUNCTION__, intf, vusb); ++ ++ if (!vusb || !vusb->initted) ++ return -1; ++ ++ usbback_suspend(usbif_from_vusb(vusb), 0); ++ return 0; ++} ++ ++static int vusb_reset_resume(struct usb_interface *intf) ++{ ++ struct vusb *vusb = usb_get_intfdata(intf); ++ ++ debug_print(LOG_LVL_ERROR, "%s: intf %p vusb %p\n", ++ __FUNCTION__, intf, vusb); ++ ++ return vusb_resume(intf); ++} ++ ++static int vusb_pre_reset(struct usb_interface *intf) ++{ ++ struct vusb *vusb = usb_get_intfdata(intf); ++ ++ debug_print(LOG_LVL_ERROR, "%s: intf %p vusb %p\n", ++ __FUNCTION__, intf, vusb); ++ ++ if (!vusb) ++ return -ENODEV; ++ ++ vusb->canceling_requests = 1; ++ return 0; ++} ++ ++static int vusb_post_reset(struct usb_interface *intf) ++{ ++ struct vusb *vusb = usb_get_intfdata(intf); ++ ++ debug_print(LOG_LVL_ERROR, "%s: intf %p vusb %p\n", ++ __FUNCTION__, intf, vusb); ++ ++ if (!vusb) ++ return -ENODEV; ++ ++ vusb->canceling_requests = 0; ++ return 0; ++} ++ ++struct usb_driver vusb_driver = { ++ .name = "vusb", ++ .probe = vusb_probe, ++ .disconnect = vusb_disconnect, ++ .suspend = vusb_suspend, ++ .resume = vusb_resume, ++ .reset_resume = vusb_reset_resume, ++ .pre_reset = vusb_pre_reset, ++ .post_reset = vusb_post_reset, ++ .supports_autosuspend = 1, ++ .soft_unbind = 0, ++}; ++ ++static int ++vusb_claim_interface(struct vusb *vusb, struct usb_interface *intf) ++{ ++ struct device *dev = &intf->dev; ++ int ret; ++ ++ debug_print(LOG_LVL_DEBUG, ++ "%s: claim interface if %p, vusb %p\n", __FUNCTION__, intf, vusb); ++ ++ if (dev->driver) { ++ struct usb_driver *driver = to_usb_driver(dev->driver); ++ ++ /* Even if this driver already owns it, its probably with ++ * the wrong vusb, so we still need to release it, and ++ * claim it properly ++ */ ++ ++ if (driver == &vusb_driver) { ++ struct vusb *old_vusb = usb_get_intfdata(intf); ++ debug_print(LOG_LVL_ERROR, ++ "%s: release ourselves with vusb %p " ++ "from interface if %p\n", __FUNCTION__, ++ old_vusb,intf); ++ } else { ++ debug_print(LOG_LVL_ERROR, ++ "%s: release old driver from interface if %p\n", ++ __FUNCTION__, intf); ++ } ++ usb_driver_release_interface(driver, intf); ++ } ++ ++ ret = usb_driver_claim_interface(&vusb_driver, intf, vusb); ++ if (ret) ++ debug_print(LOG_LVL_ERROR, ++ "%s: claim_interface failed for if %p ret %d\n", ++ __FUNCTION__, intf, ret); ++ else ++ usb_set_intfdata(intf, vusb); ++ ++ return (ret); ++} ++ ++static void ++vusb_claim_config(struct vusb *vusb, struct usb_host_config *config) ++{ ++ unsigned int ifs = config->desc.bNumInterfaces; ++ unsigned int ifnum; ++ ++ for (ifnum = 0; ifnum < ifs; ifnum++) { ++ struct usb_interface *intf = config->interface[ifnum]; ++ ++ /* ++ * If there is an interface and we end up with ownership, ++ * count it. ++ */ ++ if (intf && (vusb_claim_interface(vusb, intf) == 0)) ++ kref_get(&vusb->kref); ++ } ++} ++ ++/* precondition: usb_lock_device should be called */ ++ ++static void ++vusb_claim_dev(struct vusb *vusb, struct usb_device *udev) ++{ ++ unsigned int confs = udev->descriptor.bNumConfigurations; ++ unsigned int confnum; ++ ++ debug_print(LOG_LVL_ERROR, ++ "%s: claim device %p (%d.%d (port %d)), vusb %p\n", __FUNCTION__, ++ udev, udev->bus->busnum, udev->devnum, udev->portnum, vusb); ++ ++ for (confnum = 0; confnum < confs; confnum++) { ++ struct usb_host_config *config = &udev->config[confnum]; ++ ++ if (config) ++ vusb_claim_config(vusb, config); ++ } ++ return; ++} ++ ++static void ++vusb_release_config(struct vusb *vusb, struct usb_host_config *config) ++{ ++ unsigned int ifnum; ++ ++ debug_print(LOG_LVL_DEBUG, "%s[%d]: vusb %p config %p\n", ++ __FUNCTION__, __LINE__, vusb, config); ++ ++ for (ifnum = 0; ifnum < config->desc.bNumInterfaces; ifnum++) { ++ struct usb_interface *intf = config->interface[ifnum]; ++ struct device *dev = &intf->dev; ++ struct usb_driver *driver = to_usb_driver(dev->driver); ++ ++ /* ++ * Only release the interface if we own it. Releasing it will ++ * result in our disconnect handler being called. ++ */ ++ if (driver == &vusb_driver) { ++ struct vusb *old_vusb = usb_get_intfdata(intf); ++ if (old_vusb == vusb) { ++ debug_print(LOG_LVL_ERROR, "%s[%d]: vusb %p intf %p\n", ++ __FUNCTION__, __LINE__, vusb, intf); ++ usb_driver_release_interface(&vusb_driver, intf); ++ } else { ++ debug_print(LOG_LVL_ERROR, "%s[%d]: not releasing vusb %p config %p\n", ++ __FUNCTION__, __LINE__, old_vusb, config); ++ } ++ } ++ } ++} ++ ++static void vusb_release_dev(struct vusb *vusb, struct usb_device *udev) ++{ ++ debug_print(LOG_LVL_DEBUG, "%s[%d]: vusb %p dev %p (%d.%d (port %d))\n", ++ __FUNCTION__, __LINE__, vusb, udev, ++ udev->bus->busnum, udev->devnum, udev->portnum); ++ ++ if (udev->actconfig) ++ vusb_release_config(vusb, udev->actconfig); ++ ++ return; ++} ++ ++int vusb_init(void) ++{ ++ spin_lock_init(&vusb_map_lock); ++ ++ return usb_register(&vusb_driver); ++} ++ ++void vusb_cleanup(void) ++{ ++ usb_deregister(&vusb_driver); ++} ++ ++int vusb_create(usbif_t *usbif, usbif_vdev_t handle, unsigned bus, ++ unsigned device) ++{ ++ struct vusb *vusb; ++ struct usb_device *usbdev; ++ ++ vusb = &usbif->vusb; ++ vusb->handle = handle; ++ vusb->bus = bus; ++ vusb->device = device; ++ vusb->active = 1; ++ ++ kref_init(&vusb->kref); ++ ++ init_usb_anchor(&vusb->anchor); ++ ++ usbdev = dusb_open(bus, device); ++ if (NULL == usbdev) { ++ printk("VUSB: failed to open %d.%d\n", bus, device); ++ return -1; ++ } ++ ++ usb_lock_device(usbdev); ++ vusb_map_device(vusb, bus, device); ++ ++ /* validate */ ++ if ((device != usbdev->devnum) || (bus != usbdev->bus->busnum)) ++ debug_print(LOG_LVL_ERROR, "Device mismatch %d.%d vs %d.%d\n", ++ bus, device, usbdev->devnum, usbdev->bus->busnum); ++ ++ vusb_claim_dev(vusb, usbdev); ++ vusb->usbdev = usbdev; ++ vusb->max_sgs = usbdev->bus->sg_tablesize; ++ vusb->hcd_speed = dusb_dev_controller_speed(usbdev); ++ /* EHCI fails unaligned transfers with BABBLE (EOVERFLOW) */ ++ vusb->copy_unaligned = (vusb->hcd_speed != USB_SPEED_SUPER); ++ ++ /* don't allow the device to suspend until the frontend says so */ ++ usb_disable_autosuspend(usbdev); ++ ++ vusb->initted = 1; ++ ++ usb_unlock_device(usbdev); ++ kref_put(&vusb->kref, vusb_delete); ++ ++ debug_print(LOG_LVL_ERROR, ++ "Created vusb %p (%d) device %d.%d (dom=%u) max sgs %u\n", ++ vusb, vusb->kref.refcount.refs.counter, bus, device, usbif->domid, ++ vusb->max_sgs); ++ debug_print(LOG_LVL_ERROR, ++ "VUSB: device %s - %s - %s speed %s on %s\n", ++ usbdev->product, usbdev->manufacturer, usbdev->serial, ++ (usbdev->speed == USB_SPEED_SUPER) ? "super" : ++ (usbdev->speed == USB_SPEED_HIGH) ? "high" : "low", ++ (vusb->hcd_speed == USB_SPEED_SUPER) ? "super" : ++ (vusb->hcd_speed == USB_SPEED_HIGH) ? "high" : "low"); ++ return 0; ++} ++ ++void vusb_free(struct vusb *vusb) ++{ ++ struct usb_device *usbdev = vusb->usbdev; ++ ++ if (usbdev) { ++ usb_lock_device(usbdev); ++ ++ debug_print(LOG_LVL_ERROR, "VUSB: close device %s %s %s\n", ++ usbdev->product, usbdev->manufacturer, usbdev->serial); ++ ++ vusb->usbdev = NULL; ++ vusb_unmap_device(vusb); ++ ++ /* flush any remaining requests */ ++ vusb_flush(vusb); ++ ++ /* ++ * If we haven't received cleanup callbacks from the USB side ++ * yet, do the USB cleanup. ++ */ ++ if (vusb->active) ++ vusb_release_dev(vusb, usbdev); ++ ++ usb_unlock_device(usbdev); ++ dusb_close(usbdev); ++ } ++} ++ ++static char * setup_type(int type) ++{ ++ switch((type & USB_TYPE_MASK)) { ++ case USB_TYPE_STANDARD: ++ return "standard"; ++ case USB_TYPE_CLASS: ++ return "class"; ++ case USB_TYPE_VENDOR: ++ return "reserved"; ++ case USB_TYPE_RESERVED: ++ default: ++ return "reserved"; ++ } ++} ++ ++static char * setup_recip(int type) ++{ ++ switch((type & USB_RECIP_MASK)) { ++ case USB_RECIP_DEVICE: ++ return "device"; ++ case USB_RECIP_INTERFACE: ++ return "interface"; ++ case USB_RECIP_ENDPOINT: ++ return "endpoint"; ++ case USB_RECIP_OTHER: ++ return "other"; ++ case USB_RECIP_PORT: ++ return "port"; ++ case USB_RECIP_RPIPE: ++ return "rpipe"; ++ default: ++ return "recip unknown"; ++ } ++} ++ ++static int maybe_set_configuration(struct usb_device *dev, int configuration) ++{ ++ struct usb_host_config *cp = NULL; ++ int i; ++ ++ for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { ++ if (dev->config[i].desc.bConfigurationValue == ++ configuration) { ++ cp = &dev->config[i]; ++ break; ++ } ++ } ++ if (cp && cp == dev->actconfig) ++ return 0; ++ return dusb_set_configuration(dev, configuration); ++} ++ ++static int setup_control_urb(struct vusb *vusb, usbif_request_t *req, ++ struct urb *urb) ++{ ++ struct usb_device *usbdev = vusb->usbdev; ++ usbif_stats_t *stats = &(usbif_from_vusb(vusb)->stats); ++ struct usb_ctrlrequest *setup = ++ (struct usb_ctrlrequest *)urb->setup_packet; ++ int value, index, length; ++ int ret = 0; ++ ++ memcpy(urb->setup_packet, &req->setup, sizeof(struct usb_ctrlrequest)); ++ ++ value = __le16_to_cpup(&setup->wValue); ++ index = __le16_to_cpup(&setup->wIndex); ++ length = __le16_to_cpup(&setup->wLength); ++ ++ debug_print(LOG_LVL_DEBUG, ++ "%s: setup: %s %s %s req %x val %x idx %x len %x\n", ++ __FUNCTION__, ++ (setup->bRequestType & USB_DIR_IN) ? "IN" : "OUT", ++ setup_type(setup->bRequestType), ++ setup_recip(setup->bRequestType), ++ (int)setup->bRequest, ++ value, index, length); ++ ++ switch (setup->bRequestType & USB_RECIP_MASK) { ++ case USB_RECIP_DEVICE: ++ if (setup->bRequest == USB_REQ_CLEAR_FEATURE) { ++ debug_print(LOG_LVL_DEBUG, "clear feature\n"); ++ } else if (setup->bRequest == USB_REQ_SET_CONFIGURATION) { ++ int confnum = value; ++ ++ debug_print(LOG_LVL_DEBUG, "set config %d\n", confnum); ++ ++ usb_lock_device(usbdev); ++ ret = maybe_set_configuration(usbdev, confnum); ++ usb_unlock_device(usbdev); ++ if (ret == 0) ++ return (1); ++ } else if (setup->bRequest == USB_REQ_GET_DESCRIPTOR) { ++ int type = value >> 8; ++ int id = value & 0xff; ++ ++ if ((type == USB_DT_STRING) && (id > 0)) { ++ debug_print(LOG_LVL_DEBUG, ++ "get string descriptor index %d language %x\n", ++ id, index); ++ } else { ++ debug_print(LOG_LVL_DEBUG, ++ "get descriptor type %d index %d\n", ++ type, id); ++ } ++ } ++ break; ++ ++ case USB_RECIP_INTERFACE: ++ if (setup->bRequest == USB_REQ_CLEAR_FEATURE) { ++ debug_print(LOG_LVL_DEBUG, "clear feature\n"); ++ } else if (setup->bRequest == USB_REQ_SET_INTERFACE) { ++ int ifnum = index; ++ int alt = value; ++ ++ debug_print(LOG_LVL_DEBUG, "set interface %d\n", ifnum); ++ ++ ret = usb_set_interface(usbdev, ifnum, alt); ++ if (ret == 0) ++ return (1); ++ } ++ break; ++ ++ case USB_RECIP_ENDPOINT: ++ if (setup->bRequest == USB_REQ_GET_STATUS) { ++ debug_print(LOG_LVL_DEBUG, "get status %d\n", index); ++ } else if ((setup->bRequest == USB_REQ_CLEAR_FEATURE) && ++ (value == USB_ENDPOINT_HALT)) { ++ int ep = index; ++ int epnum = ep & 0x7f; ++ int pipe; ++ ++ debug_print(LOG_LVL_DEBUG, "clear halt %d\n", epnum); ++ if (ep & USB_DIR_IN) ++ pipe = usb_rcvbulkpipe(usbdev, epnum); ++ else ++ pipe = usb_sndbulkpipe(usbdev, epnum); ++ ret = usb_clear_halt(usbdev, pipe); ++ if ((ret == 0) || (ret == -EPIPE)) ++ return (1); ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ urb->interval = 1; ++ ++ if (usbif_request_dir_in(req)) { ++ urb->pipe = usb_rcvctrlpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_in_req++; ++ } else { ++ urb->pipe = usb_sndctrlpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_out_req++; ++ } ++ stats->st_cntrl_req++; ++ ++ return (ret); ++} ++ ++static void setup_isoc_urb(struct vusb *vusb, usbif_request_t *req, ++ struct urb *urb, struct usb_host_endpoint *ep) ++{ ++ struct usb_device *usbdev = vusb->usbdev; ++ usbif_stats_t *stats = &(usbif_from_vusb(vusb)->stats); ++ ++ urb->interval = 1 << min(15, ep->desc.bInterval - 1); ++ urb->start_frame = req->startframe; ++ ++ if (usbif_request_asap(req)) ++ urb->transfer_flags |= URB_ISO_ASAP; ++ ++ debug_print(LOG_LVL_DEBUG, "%s: interval %x sf %d packets %d\n", ++ __FUNCTION__, urb->interval, urb->start_frame, ++ urb->number_of_packets); ++ ++ if (usbif_request_dir_in(req)) { ++ urb->pipe = usb_rcvisocpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_in_req++; ++ } else { ++ urb->pipe = usb_sndisocpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_out_req++; ++ } ++ stats->st_isoc_req++; ++} ++ ++static void setup_bulk_urb(struct vusb *vusb, usbif_request_t *req, ++ struct urb *urb) ++{ ++ struct usb_device *usbdev = vusb->usbdev; ++ usbif_stats_t *stats = &(usbif_from_vusb(vusb)->stats); ++ ++ debug_print(LOG_LVL_DEBUG, "%s\n", __FUNCTION__); ++ ++ urb->interval = 1; ++ ++ if (usbif_request_dir_in(req)) { ++ urb->pipe = usb_rcvbulkpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_in_req++; ++ } else { ++ urb->pipe = usb_sndbulkpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_out_req++; ++ } ++ stats->st_bulk_req++; ++} ++ ++static void setup_int_urb(struct vusb *vusb, usbif_request_t *req, ++ struct urb *urb, struct usb_host_endpoint *ep) ++{ ++ struct usb_device *usbdev = vusb->usbdev; ++ usbif_stats_t *stats = &(usbif_from_vusb(vusb)->stats); ++ ++ switch (usbdev->speed) { ++ case USB_SPEED_HIGH: ++ case USB_SPEED_SUPER: ++ urb->interval = 1 << min(15, ep->desc.bInterval - 1); ++ break; ++ case USB_SPEED_FULL: ++ case USB_SPEED_LOW: ++ urb->interval = ep->desc.bInterval; ++ break; ++ default: ++ debug_print(LOG_LVL_ERROR, "%s: bad speed %x\n", ++ __FUNCTION__, usbdev->speed); ++ break; ++ } ++ ++ debug_print(LOG_LVL_DEBUG, "%s: interval %x\n", __FUNCTION__, ++ urb->interval); ++ ++ if (usbif_request_dir_in(req)) { ++ urb->pipe = usb_rcvintpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_in_req++; ++ } else { ++ urb->pipe = usb_sndintpipe(usbdev, ++ usbif_request_endpoint_num(req)); ++ stats->st_out_req++; ++ } ++ stats->st_int_req++; ++} ++ ++static struct usb_device *vusb_device(struct vusb *vusb) ++{ ++ return ((vusb->active && vusb->usbdev && ++ dusb_dev_running(vusb->usbdev)) ? vusb->usbdev : NULL); ++} ++ ++int vusb_setup_urb(struct vusb *vusb, usbif_request_t *req, struct urb *urb) ++{ ++ struct usb_device *usbdev = vusb_device(vusb); ++ struct usb_host_endpoint *ep; ++ int endpointnum = usbif_request_endpoint_num(req); ++ int ret = 0; ++ ++ if ((usbdev == NULL) || ((usbdev->state != USB_STATE_ADDRESS) && ++ (usbdev->state != USB_STATE_CONFIGURED))) { ++ return -ENODEV; ++ } ++ ++ if (usbif_request_dir_in(req)) ++ ep = usbdev->ep_in[endpointnum]; ++ else ++ ep = usbdev->ep_out[endpointnum]; ++ if (!ep) { ++ debug_print(LOG_LVL_ERROR, "endpoint not found (%d)\n", endpointnum); ++ return -ENOENT; ++ } ++ ++ urb->dev = usbdev; ++ if (!usbif_request_shortok(req) && usbif_request_dir_in(req)) ++ urb->transfer_flags |= URB_SHORT_NOT_OK; ++ ++ switch((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)) { ++ case USB_ENDPOINT_XFER_CONTROL: ++ ret = setup_control_urb(vusb, req, urb); ++ break; ++ ++ case USB_ENDPOINT_XFER_ISOC: ++ setup_isoc_urb(vusb, req, urb, ep); ++ break; ++ ++ case USB_ENDPOINT_XFER_BULK: ++ setup_bulk_urb(vusb, req, urb); ++ break; ++ ++ default: ++ case USB_ENDPOINT_XFER_INT: ++ setup_int_urb(vusb, req, urb, ep); ++ break; ++ } ++ ++ return (ret); ++} ++ ++int vusb_reset_device(struct vusb *vusb) ++{ ++ struct usb_device *usbdev = vusb_device(vusb); ++ usbif_stats_t *stats = &(usbif_from_vusb(vusb)->stats); ++ int ret; ++ ++ if (!usbdev) ++ return (-1); ++ ++ debug_print(LOG_LVL_ERROR, "%s vusb %p, usbdev %p (%d.%d (port %d)) Start\n", ++ __FUNCTION__, vusb, usbdev, ++ usbdev->bus->busnum, usbdev->devnum, usbdev->portnum); ++ ++ /* pre and post reset handlers set and clear canceling_requests */ ++ usb_lock_device(usbdev); ++ ret = usb_reset_device(usbdev); ++ usb_unlock_device(usbdev); ++ ++ stats->st_reset++; ++ ++ debug_print(LOG_LVL_ERROR, "%s vusb %p, usbdev %p (%d.%d (port %d)) Done\n", ++ __FUNCTION__, vusb, usbdev, ++ usbdev->bus->busnum, usbdev->devnum, usbdev->portnum); ++ ++ return ret; ++} ++ ++void vusb_flush(struct vusb *vusb) ++{ ++ debug_print(LOG_LVL_INFO, "%s\n", __FUNCTION__); ++ ++ vusb->canceling_requests = 1; ++ ++ usb_kill_anchored_urbs(&vusb->anchor); ++ ++ vusb->canceling_requests = 0; ++} ++ ++int vusb_flush_endpoint(struct vusb *vusb, usbif_request_t *req) ++{ ++ int endpointnum = usbif_request_endpoint_num(req); ++ struct usb_device *usbdev = vusb_device(vusb); ++ struct usb_host_endpoint *ep; ++ ++ debug_print(LOG_LVL_DEBUG, "%s udev %p\n", __FUNCTION__, usbdev); ++ ++ if (usbdev) { ++ if (usbif_request_dir_in(req)) ++ ep = usbdev->ep_in[endpointnum]; ++ else ++ ep = usbdev->ep_out[endpointnum]; ++ if (!ep) { ++ debug_print(LOG_LVL_ERROR, "endpoint not found (%d)\n", endpointnum); ++ return -ENOENT; ++ } ++ ++ vusb->canceling_requests = 1; ++ ++ dusb_flush_endpoint(usbdev, ep); ++ ++ vusb->canceling_requests = 0; ++ } else { ++ vusb_flush(vusb); ++ } ++ ++ debug_print(LOG_LVL_DEBUG, "%s - udev %p end\n", __FUNCTION__, usbdev); ++ ++ return (0); ++} ++ ++int vusb_get_speed(struct vusb *vusb) ++{ ++ struct usb_device *usbdev = vusb_device(vusb); ++ ++ return (usbdev ? usbdev->speed : -1); ++} ++ ++void vusb_free_coherent(struct vusb *vusb, struct urb *urb) ++{ ++ struct usb_device *usbdev = urb->dev ? urb->dev : vusb->usbdev; ++ ++ if (usbdev) ++ usb_free_coherent(usbdev, urb->transfer_buffer_length, ++ urb->transfer_buffer, urb->transfer_dma); ++ else ++ debug_print(LOG_LVL_ERROR, "%s: leaking buffer! no dev!", ++ __FUNCTION__); ++ urb->transfer_buffer = NULL; ++} ++ ++void *vusb_alloc_coherent(struct vusb *vusb, size_t size, dma_addr_t *dma) ++{ ++ struct usb_device *usbdev = vusb_device(vusb); ++ ++ void *ret = (usbdev ? usb_alloc_coherent(usbdev, size, GFP_KERNEL, dma) : NULL); ++ ++ if (!ret) { ++ debug_print((usbdev != NULL) ? LOG_LVL_DEBUG : LOG_LVL_ERROR, ++ "%s: Failed: vusb:%p, udbdev:%p, " ++ "active:%d, running:%s\n", ++ __FUNCTION__, ++ vusb, vusb->usbdev, vusb->active, ++ usbdev && dusb_dev_running(usbdev) ? "yes" : "no"); ++ } ++ ++ return (ret); ++} ++ ++void vusb_cycle_port(struct vusb *vusb) ++{ ++ struct usb_device *usbdev = vusb_device(vusb); ++ ++ if (usbdev) { ++ debug_print(LOG_LVL_ERROR, "%s vusb %p, usbdev %p (%d.%d (port %d)) Start\n", ++ __FUNCTION__, vusb, usbdev, ++ usbdev->bus->busnum, usbdev->devnum, usbdev->portnum); ++ usb_device_reenumerate(usbdev); ++ debug_print(LOG_LVL_ERROR, "%s vusb %p, usbdev %p (%d.%d (port %d)) Done\n", ++ __FUNCTION__, vusb, usbdev, ++ usbdev->bus->busnum, usbdev->devnum, usbdev->portnum); ++ } ++} ++ ++ ++/* power management methods */ ++void vusb_pm_autosuspend_control(struct vusb *vusb, int enable) ++{ ++ struct usb_device *usbdev = vusb_device(vusb); ++ ++ if (usbdev && (vusb->autosuspend != enable)) { ++ debug_print(LOG_LVL_INFO, "%s vusb %p, udev %p enable %d\n", ++ __FUNCTION__, vusb, usbdev, enable); ++ ++ vusb->autosuspend = enable; ++ if (enable) ++ usb_enable_autosuspend(usbdev); ++ else ++ usb_disable_autosuspend(usbdev); ++ } ++} ++ +--- /dev/null ++++ b/drivers/usb/xen-usbback/xenbus.c +@@ -0,0 +1,583 @@ ++/* Xenbus code for usbif backend ++ Copyright (C) 2005 Rusty Russell ++ Copyright (C) 2005 XenSource Ltd ++ Copyright (C) 2008-2012 Virtual Computer Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++*/ ++ ++#include ++#include ++#include ++#include "common.h" ++ ++#undef DPRINTK ++#define DPRINTK(fmt, args...) \ ++ pr_debug("usbback/xenbus (%s:%d) " fmt ".\n", \ ++ __FUNCTION__, __LINE__, ##args) ++ ++static void connect(struct backend_info *); ++static int connect_ring(struct backend_info *); ++ ++static void update_usbif_status(usbif_t *usbif) ++{ ++ int err; ++ char name[TASK_COMM_LEN]; ++ ++ /* Not ready to connect? */ ++ if (!usbif->irq) ++ return; ++ ++ /* Already connected? */ ++ if (usbif->be->dev->state == XenbusStateConnected) ++ return; ++ ++ /* Attempt to connect: exit if we fail to. */ ++ connect(usbif->be); ++ if (usbif->be->dev->state != XenbusStateConnected) ++ return; ++ ++ snprintf(name, TASK_COMM_LEN, "usbback.%d.%d.%d", ++ usbif->domid, usbif->be->bus, usbif->be->device); ++ ++ usbif->xenusbd = kthread_run(usbif_schedule, usbif, name); ++ if (IS_ERR(usbif->xenusbd)) { ++ err = PTR_ERR(usbif->xenusbd); ++ usbif->xenusbd = NULL; ++ xenbus_dev_error(usbif->be->dev, err, "start xenusbd"); ++ } ++ else ++ debug_print(LOG_LVL_DEBUG, "Started xenusbd\n"); ++} ++ ++/**************************************************************** ++ * sysfs interface for VUSB I/O requests ++ */ ++#define USB_SHOW(name, format, args...) \ ++ static ssize_t show_##name(struct device *_dev, \ ++ struct device_attribute *attr, \ ++ char *buf) \ ++ { \ ++ ssize_t ret = -ENODEV; \ ++ struct xenbus_device *dev; \ ++ struct backend_info *be; \ ++ \ ++ if (!get_device(_dev)) \ ++ return ret; \ ++ dev = to_xenbus_device(_dev); \ ++ if ((be = dev_get_drvdata(&dev->dev)) != NULL) \ ++ ret = sprintf(buf, format, ##args); \ ++ put_device(_dev); \ ++ return ret; \ ++ } \ ++ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) ++ ++ ++USB_SHOW(oo_req, "%d\n", be->usbif->stats.st_oo_req); ++USB_SHOW(in_req, "%d\n", be->usbif->stats.st_in_req); ++USB_SHOW(out_req, "%d\n", be->usbif->stats.st_out_req); ++ ++USB_SHOW(error, "%d\n", be->usbif->stats.st_error); ++USB_SHOW(reset, "%d\n", be->usbif->stats.st_reset); ++ ++USB_SHOW(in_bandwidth, "%d\n", be->usbif->stats.st_in_bandwidth); ++USB_SHOW(out_bandwidth, "%d\n", be->usbif->stats.st_out_bandwidth); ++ ++USB_SHOW(cntrl_req, "%d\n", be->usbif->stats.st_cntrl_req); ++USB_SHOW(isoc_req, "%d\n", be->usbif->stats.st_isoc_req); ++USB_SHOW(bulk_req, "%d\n", be->usbif->stats.st_bulk_req); ++USB_SHOW(int_req, "%d\n", be->usbif->stats.st_int_req); ++ ++static struct attribute *usbstat_attrs[] = { ++ &dev_attr_oo_req.attr, ++ &dev_attr_in_req.attr, ++ &dev_attr_out_req.attr, ++ &dev_attr_error.attr, ++ &dev_attr_reset.attr, ++ &dev_attr_in_bandwidth.attr, ++ &dev_attr_out_bandwidth.attr, ++ &dev_attr_cntrl_req.attr, ++ &dev_attr_isoc_req.attr, ++ &dev_attr_bulk_req.attr, ++ &dev_attr_int_req.attr, ++ NULL ++}; ++ ++static struct attribute_group usbstat_group = { ++ .name = "statistics", ++ .attrs = usbstat_attrs, ++}; ++ ++USB_SHOW(physical_device, "%x.%x\n", be->bus, be->device); ++ ++int xenusb_sysfs_addif(struct xenbus_device *dev) ++{ ++ int error; ++ ++ error = device_create_file(&dev->dev, &dev_attr_physical_device); ++ if (error) ++ goto fail1; ++ ++ error = sysfs_create_group(&dev->dev.kobj, &usbstat_group); ++ if (error) ++ goto fail2; ++ ++ return 0; ++ ++fail2: sysfs_remove_group(&dev->dev.kobj, &usbstat_group); ++fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); ++ return error; ++} ++ ++void xenusb_sysfs_delif(struct xenbus_device *dev) ++{ ++ sysfs_remove_group(&dev->dev.kobj, &usbstat_group); ++ device_remove_file(&dev->dev, &dev_attr_physical_device); ++} ++ ++static int usbback_remove(struct xenbus_device *dev) ++{ ++ struct backend_info *be = dev_get_drvdata(&dev->dev); ++ ++ debug_print(LOG_LVL_ERROR, "usbback_remove\n"); ++ ++ if (be->bus || be->device) ++ xenusb_sysfs_delif(dev); ++ ++ if (be->backend_watch.node) { ++ unregister_xenbus_watch(&be->backend_watch); ++ kfree(be->backend_watch.node); ++ be->backend_watch.node = NULL; ++ } ++ ++ if (be->autosuspend_watch.node) { ++ unregister_xenbus_watch(&be->autosuspend_watch); ++ kfree(be->autosuspend_watch.node); ++ be->autosuspend_watch.node = NULL; ++ } ++ ++ if (be->usbif) { ++ usbif_t *usbif = be->usbif; ++ ++ /* ++ * Disconnect the be and usbif since the call to vusb_free can ++ * cause callbacks like usbback_suspend which dereference ++ * usbif to be and make calls on the be. ++ */ ++ be->usbif = NULL; ++ usbif->be = NULL; ++ /* ++ * Kill the per device kthread so we don't process any more ++ * frontend requests. ++ */ ++ debug_print(LOG_LVL_ERROR, "Disconnecting vusb %p\n", &usbif->vusb); ++ usbif_disconnect(usbif, be->dev); ++ /* Shutdown the Linux USB class driver */ ++ debug_print(LOG_LVL_ERROR, "Freeing vusb %p\n", &usbif->vusb); ++ vusb_free(&usbif->vusb); ++ usbif_free(usbif); ++ } ++ ++ kfree(be); ++ dev_set_drvdata(&dev->dev, NULL); ++ return 0; ++} ++ ++int usbback_barrier(struct xenbus_transaction xbt, ++ struct backend_info *be, int state) ++{ ++ struct xenbus_device *dev = be->dev; ++ int err; ++ ++ err = xenbus_printf(xbt, dev->nodename, "feature-barrier", ++ "%d", state); ++ if (err) ++ xenbus_dev_fatal(dev, err, "writing feature-barrier"); ++ ++ return err; ++} ++ ++/* tell the frontend that the device's suspend state has changed */ ++int usbback_suspend(usbif_t *usbif, int suspended) ++{ ++ struct xenbus_device *dev = usbif->be ? usbif->be->dev : NULL; ++ int err; ++ ++ debug_print(LOG_LVL_ERROR, "%s: usbif %p dev %p node %s\n", ++ __FUNCTION__, usbif, dev, dev ? dev->nodename : ""); ++ ++ if (dev) ++ err = 0; ++ else ++ err = -ENODEV; ++ ++ return err; ++} ++ ++/** ++ * Callback received when the hotplug scripts have placed the physical-device ++ * node. Read it and create a vusb. If the frontend is ready, connect. ++ */ ++static void backend_changed(struct xenbus_watch *watch, ++ const char *path, const char *token) ++{ ++ int err; ++ unsigned bus; ++ unsigned device; ++ struct backend_info *be ++ = container_of(watch, struct backend_info, backend_watch); ++ struct xenbus_device *dev = be->dev; ++ ++ err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%d.%d", ++ &bus, &device); ++ if (XENBUS_EXIST_ERR(err)) { ++ /* Since this watch will fire once immediately after it is ++ registered, we expect this. Ignore it, and wait for the ++ hotplug scripts. */ ++ return; ++ } ++ if (err != 2) { ++ xenbus_dev_fatal(dev, err, "reading physical-device"); ++ return; ++ } ++ ++ if ((be->bus || be->device) && (bus || device) && ++ ((be->bus != bus) || (be->device != device))) { ++ debug_print(LOG_LVL_ERROR, ++ "usbback: changing physical device (from %x.%x to " ++ "%x.%x) not supported.\n", be->bus, be->device, ++ bus, device); ++ return; ++ } ++ ++ if (be->bus == 0 && be->device == 0) { ++ /* Front end dir is a number, which is used as the handle. */ ++ ++ char *p = strrchr(dev->otherend, '/') + 1; ++ long handle = simple_strtoul(p, NULL, 0); ++ ++ be->bus = bus; ++ be->device = device; ++ ++ err = vusb_create(be->usbif, handle, bus, device); ++ if (err) { ++ be->bus = be->device = 0; ++ xenbus_dev_fatal(dev, err, "creating vusb structure"); ++ return; ++ } ++ ++ err = xenusb_sysfs_addif(dev); ++ if (err) { ++ vusb_free(&be->usbif->vusb); ++ be->bus = be->device = 0; ++ xenbus_dev_fatal(dev, err, "creating sysfs entries"); ++ return; ++ } ++ ++ /* We're potentially connected now */ ++ update_usbif_status(be->usbif); ++ } else if (bus == 0 && device == 0) { ++ /* Device is being unassigned -- simulate hot unplug */ ++ vusb_cycle_port(&be->usbif->vusb); ++ } ++} ++ ++/** ++ * Callback received when the frontend changes the atosuspend element. ++ */ ++static void autosuspend_changed(struct xenbus_watch *watch, ++ const char *path, const char* token) ++{ ++ struct backend_info *be ++ = container_of(watch, struct backend_info, autosuspend_watch); ++ struct xenbus_device *dev = be->dev; ++ unsigned autosuspend; ++ int err; ++ ++ err = xenbus_scanf(XBT_NIL, dev->otherend, "autosuspend", "%d", ++ &autosuspend); ++ if (XENBUS_EXIST_ERR(err)) { ++ /* Since this watch will fire once immediately after it is ++ registered, we expect this. Ignore it, and wait for the ++ hotplug scripts. */ ++ return; ++ } ++ if (err != 1) { ++ xenbus_dev_error(dev, err, "reading autosuspend"); ++ return; ++ } ++ ++ err = xenbus_scanf(XBT_NIL, dev->otherend, "autosuspend", "%d", ++ &autosuspend); ++ vusb_pm_autosuspend_control(&be->usbif->vusb, autosuspend); ++ ++ debug_print(LOG_LVL_INFO, "Autosuspend changed %d\n", autosuspend); ++} ++ ++ ++/** ++ * Entry point to this code when a new device is created. Allocate the basic ++ * structures, and watch the store waiting for the hotplug scripts to tell us ++ * the device's physical major and minor numbers. Switch to InitWait. ++ */ ++#define VERSION_SZ 4 ++static int usbback_probe(struct xenbus_device *dev, ++ const struct xenbus_device_id *id) ++{ ++ int err; ++ char version[VERSION_SZ]; ++ struct backend_info *be = kzalloc(sizeof(struct backend_info), ++ GFP_KERNEL); ++ if (!be) { ++ xenbus_dev_fatal(dev, -ENOMEM, ++ "allocating backend structure"); ++ return -ENOMEM; ++ } ++ be->dev = dev; ++ dev_set_drvdata(&dev->dev, be); ++ ++ be->usbif = usbif_alloc(dev->otherend_id); ++ if (IS_ERR(be->usbif)) { ++ err = PTR_ERR(be->usbif); ++ be->usbif = NULL; ++ xenbus_dev_fatal(dev, err, "creating block interface"); ++ goto fail; ++ } ++ ++ /* setup back pointer */ ++ be->usbif->be = be; ++ ++ err = xenbus_watch_pathfmt(dev, &be->backend_watch, NULL, backend_changed, ++ "%s/%s", dev->nodename, "physical-device"); ++ if (err) ++ goto fail; ++ ++ err = xenbus_watch_pathfmt(dev, &be->autosuspend_watch, NULL, ++ autosuspend_changed, "%s/%s", dev->otherend, ++ "autosuspend"); ++ if (err) ++ goto fail; ++ ++ debug_print(LOG_LVL_ERROR, "Setup watch for %s/%s\n", dev->otherend, "autosuspend"); ++ ++ err = snprintf(version, VERSION_SZ, "%d", USBBCK_VERSION); ++ if (err < 0) ++ goto fail; ++ ++ err = xenbus_write(XBT_NIL, dev->nodename, "version", version); ++ if (err) ++ goto fail; ++ ++ err = xenbus_switch_state(dev, XenbusStateInitWait); ++ if (err) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ debug_print(LOG_LVL_ERROR, "Probe failed\n"); ++ usbback_remove(dev); ++ return err; ++} ++ ++/** ++ * Callback received when the frontend's state changes. ++ */ ++static void frontend_changed(struct xenbus_device *dev, ++ enum xenbus_state frontend_state) ++{ ++ struct backend_info *be = dev_get_drvdata(&dev->dev); ++ int err; ++ ++ debug_print(LOG_LVL_INFO, "Frontend state: %s Backend state: %s\n", ++ xenbus_strstate(frontend_state), xenbus_strstate(dev->state)); ++ ++ switch (frontend_state) { ++ case XenbusStateInitialising: ++ if (dev->state == XenbusStateClosed) { ++ printk(KERN_INFO "%s: %s: prepare for reconnect\n", ++ __FUNCTION__, dev->nodename); ++ xenbus_switch_state(dev, XenbusStateInitWait); ++ } ++ break; ++ ++ case XenbusStateInitialised: ++ case XenbusStateConnected: ++ /* Ensure we connect even when two watches fire in ++ close successsion and we miss the intermediate value ++ of frontend_state. */ ++ if (dev->state == XenbusStateConnected) ++ break; ++ ++ err = connect_ring(be); ++ if (err) ++ break; ++ update_usbif_status(be->usbif); ++ break; ++ ++ case XenbusStateClosing: ++ usbif_disconnect(be->usbif, be->dev); ++ xenbus_switch_state(dev, XenbusStateClosing); ++ break; ++ ++ case XenbusStateClosed: ++ xenbus_switch_state(dev, XenbusStateClosed); ++ if (xenbus_dev_is_online(dev)) ++ break; ++ /* fall through if not online */ ++ fallthrough; ++ case XenbusStateUnknown: ++ device_unregister(&dev->dev); ++ break; ++ ++ default: ++ xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", ++ frontend_state); ++ break; ++ } ++} ++ ++ ++/* ** Connection ** */ ++ ++ ++/** ++ * Write the physical details regarding the usb device to the store, and ++ * switch to Connected state. ++ */ ++static void connect(struct backend_info *be) ++{ ++ struct xenbus_transaction xbt; ++ int err; ++ struct xenbus_device *dev = be->dev; ++ ++ debug_print(LOG_LVL_INFO, "Connect: %s\n", dev->otherend); ++ ++ /* Supply the information about the device the frontend needs */ ++again: ++ err = xenbus_transaction_start(&xbt); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "starting transaction"); ++ return; ++ } ++ ++ err = usbback_barrier(xbt, be, 1); ++ if (err) ++ goto abort; ++ ++ err = xenbus_transaction_end(xbt, 0); ++ if (err == -EAGAIN) ++ goto again; ++ if (err) ++ xenbus_dev_fatal(dev, err, "ending transaction"); ++ ++ err = xenbus_switch_state(dev, XenbusStateConnected); ++ if (err) ++ xenbus_dev_fatal(dev, err, "switching to Connected state"); ++ ++ return; ++ abort: ++ xenbus_transaction_end(xbt, 1); ++} ++ ++static int connect_ring(struct backend_info *be) ++{ ++ struct xenbus_device *dev = be->dev; ++ grant_ref_t ring_ref; ++ unsigned int evtchn; ++ unsigned int version; ++ char protocol[64] = ""; ++ int err; ++ ++ debug_print(LOG_LVL_INFO, "Connect ring: %s\n", dev->otherend); ++ ++ err = xenbus_scanf(XBT_NIL, dev->otherend, "version", "%d", ++ &version); ++ if (XENBUS_EXIST_ERR(err)) { ++ debug_print(LOG_LVL_ERROR, "frontend version doesn't exist, must be old\n"); ++ return -1; ++ } ++ if (err != 1) { ++ xenbus_dev_fatal(dev, err, "reading version"); ++ return -1; ++ } ++ debug_print(LOG_LVL_INFO, "frontend version %d\n", version); ++ if (version < USBBCK_VERSION) { ++ xenbus_dev_fatal(dev, EINVAL, "frontend doesn't match backend (%d)", version); ++ return -1; ++ } ++ ++ err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu", &ring_ref, ++ "event-channel", "%u", &evtchn, NULL); ++ if (err) { ++ xenbus_dev_fatal(dev, err, ++ "reading %s/ring-ref and event-channel", ++ dev->otherend); ++ return err; ++ } ++ ++ be->usbif->usb_protocol = USBIF_PROTOCOL_NATIVE; ++ err = xenbus_gather(XBT_NIL, dev->otherend, "protocol", ++ "%63s", protocol, NULL); ++ if (err) { ++ strcpy(protocol, "unspecified"); ++// be->usbif->usb_protocol = xen_guest_usbif_protocol(be->usbif->domid); ++ } ++ else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) ++ be->usbif->usb_protocol = USBIF_PROTOCOL_NATIVE; ++ else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) ++ be->usbif->usb_protocol = USBIF_PROTOCOL_X86_32; ++ else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) ++ be->usbif->usb_protocol = USBIF_PROTOCOL_X86_64; ++ else { ++ xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); ++ return -1; ++ } ++ debug_print(LOG_LVL_INFO, ++ "usbback: ring-ref %d, event-channel %d, protocol %d (%s)\n", ++ ring_ref, evtchn, be->usbif->usb_protocol, protocol); ++ ++ /* Map the shared frame, irq etc. */ ++ err = usbif_map(be->usbif, ring_ref, evtchn); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "mapping ring-ref %d port %u", ++ ring_ref, evtchn); ++ return err; ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * Driver Registration ++ */ ++static const struct xenbus_device_id usbback_ids[] = { ++ { "vusb" }, ++ { "" } ++}; ++ ++static struct xenbus_driver usbback_driver = { ++ .name = "usbback", ++ .ids = usbback_ids, ++ .probe = usbback_probe, ++ .remove = usbback_remove, ++ .otherend_changed = frontend_changed ++}; ++ ++int usbif_xenbus_init(void) ++{ ++ return xenbus_register_backend(&usbback_driver); ++} +--- /dev/null ++++ b/include/linux/dusb.h +@@ -0,0 +1,44 @@ ++/*****************************************************************************/ ++ ++/* ++ * dusb.c -- Direct communication with USB devices. ++ * ++ * Copyright (C) 1999-2000 Thomas Sailer (sailer@ife.ee.ethz.ch) ++ * Copyright (C) 2008-2012 Virtual Computer Inc ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * Derived from usb/core/devio.c ++ * ++ */ ++ ++/*****************************************************************************/ ++ ++#ifndef __LINUX_DUSB_H ++#define __LINUX_DUSB_H ++ ++extern struct usb_device *dusb_open(unsigned bus, unsigned device); ++extern void dusb_close(struct usb_device *dev); ++extern int dusb_set_configuration(struct usb_device *dev, int configuration); ++extern void dusb_flush_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep); ++ ++extern int dusb_dev_running(struct usb_device *udev); ++extern int dusb_dev_controller_speed(struct usb_device *udev); ++ ++/* hub.c */ ++extern void usb_device_reenumerate(struct usb_device *udev); ++ ++#endif +--- /dev/null ++++ b/include/xen/interface/io/usbif.h +@@ -0,0 +1,196 @@ ++/****************************************************************************** ++ * usbif.h ++ * ++ * Unified usb-device I/O interface for Xen guest OSes. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Derived from blkif.h ++ * ++ * Copyright (c) 2003-2004, Keir Fraser ++ * Copyright (c) 2008, Virtual Computer Inc. ++ */ ++ ++#ifndef __XEN_PUBLIC_IO_USBIF_H__ ++#define __XEN_PUBLIC_IO_USBIF_H__ ++ ++#include "ring.h" ++#include "../grant_table.h" ++ ++/* ++ * Front->back notifications: When enqueuing a new request, sending a ++ * notification can be made conditional on req_event (i.e., the generic ++ * hold-off mechanism provided by the ring macros). Backends must set ++ * req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()). ++ * ++ * Back->front notifications: When enqueuing a new response, sending a ++ * notification can be made conditional on rsp_event (i.e., the generic ++ * hold-off mechanism provided by the ring macros). Frontends must set ++ * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()). ++ */ ++ ++#ifndef usbif_vdev_t ++#define usbif_vdev_t uint16_t ++#endif ++ ++/* URB operations */ ++#define USBIF_T_CNTRL 0 ++#define USBIF_T_ISOC 1 ++#define USBIF_T_BULK 2 ++#define USBIF_T_INT 3 ++ ++/* non URB operations */ ++#define USBIF_T_RESET 4 ++#define USBIF_T_ABORT_PIPE 5 ++#define USBIF_T_GET_FRAME 6 ++#define USBIF_T_GET_SPEED 7 ++#define USBIF_T_CANCEL 8 ++ ++#define USBIF_T_MAX (USBIF_T_CANCEL) ++ ++#define USBIF_F_SHORTOK 0x01 ++#define USBIF_F_RESET 0x02 ++#define USBIF_F_ASAP 0x04 /* start ISO request on next available frame */ ++#define USBIF_F_INDIRECT 0x08 /* this request contains indirect segments */ ++#define USBIF_F_CYCLE_PORT 0x10 /* force re-enumeration of this device */ ++#define USBIF_F_DIRECT_DATA 0x20 /* request contains data directly inline */ ++ ++/* ++ * Maximum scatter/gather segments per request. ++ * This is carefully chosen so that sizeof(usbif_ring_t) <= PAGE_SIZE. ++ * NB. ++ */ ++#define USBIF_MAX_SEGMENTS_PER_REQUEST 17 ++#define USBIF_MAX_ISO_SEGMENTS (USBIF_MAX_SEGMENTS_PER_REQUEST - 1) ++ ++typedef uint32_t usbif_request_len_t; ++ ++struct usbif_request { ++ uint64_t id; /* private guest value, echoed in resp */ ++ uint64_t setup; ++ uint8_t type; /* USBIF_T_??? */ ++ uint8_t endpoint; ++ uint16_t offset; ++ usbif_request_len_t length; ++ uint8_t nr_segments; /* number of segments */ ++ uint8_t flags; ++ uint16_t nr_packets; /* number of ISO packets */ ++ uint32_t startframe; ++ union { ++ grant_ref_t gref[USBIF_MAX_SEGMENTS_PER_REQUEST]; ++ uint8_t data[sizeof(grant_ref_t)*USBIF_MAX_SEGMENTS_PER_REQUEST]; ++ } u; ++ uint32_t pad; ++}; ++typedef struct usbif_request usbif_request_t; ++ ++#define INDIRECT_SEGMENTS ++ ++#ifdef INDIRECT_SEGMENTS ++#define USBIF_MAX_SEGMENTS_PER_IREQUEST 1023 ++struct usbif_indirect_request { ++ uint32_t nr_segments; ++ grant_ref_t gref[USBIF_MAX_SEGMENTS_PER_IREQUEST]; ++}; ++typedef struct usbif_indirect_request usbif_indirect_request_t; ++#endif ++ ++struct usbif_iso_packet_info { ++ usbif_request_len_t offset; ++ uint16_t length; ++ uint16_t status; ++}; ++typedef struct usbif_iso_packet_info usbif_iso_packet_info_t; ++ ++struct usbif_response { ++ uint64_t id; /* copied from request */ ++ usbif_request_len_t actual_length; ++ uint32_t data; ++ int16_t status; /* USBIF_RSP_??? */ ++ uint32_t error_count; /* total ISOCH error count */ ++}; ++typedef struct usbif_response usbif_response_t; ++ ++/* ++ * STATUS RETURN CODES. ++ */ ++ /* USB errors */ ++#define USBIF_RSP_USB_ERROR -10 ++ ++#define USBIF_USB_CANCELED -1 ++#define USBIF_RSP_USB_CANCELED (USBIF_RSP_USB_ERROR + USBIF_USB_CANCELED) ++#define USBIF_USB_PENDING -2 ++#define USBIF_RSP_USB_PENDING (USBIF_RSP_USB_ERROR + USBIF_USB_PENDING) ++#define USBIF_USB_PROTO -3 ++#define USBIF_RSP_USB_PROTO (USBIF_RSP_USB_ERROR + USBIF_USB_PROTO) ++#define USBIF_USB_CRC -4 ++#define USBIF_RSP_USB_CRC (USBIF_RSP_USB_ERROR + USBIF_USB_CRC) ++#define USBIF_USB_TIMEOUT -5 ++#define USBIF_RSP_USB_TIMEOUT (USBIF_RSP_USB_ERROR + USBIF_USB_TIMEOUT) ++#define USBIF_USB_STALLED -6 ++#define USBIF_RSP_USB_STALLED (USBIF_RSP_USB_ERROR + USBIF_USB_STALLED) ++#define USBIF_USB_INBUFF -7 ++#define USBIF_RSP_USB_INBUFF (USBIF_RSP_USB_ERROR + USBIF_USB_INBUFF) ++#define USBIF_USB_OUTBUFF -8 ++#define USBIF_RSP_USB_OUTBUFF (USBIF_RSP_USB_ERROR + USBIF_USB_OUTBUFF) ++#define USBIF_USB_OVERFLOW -9 ++#define USBIF_RSP_USB_OVERFLOW (USBIF_RSP_USB_ERROR + USBIF_USB_OVERFLOW) ++#define USBIF_USB_SHORTPKT -10 ++#define USBIF_RSP_USB_SHORTPKT (USBIF_RSP_USB_ERROR + USBIF_USB_SHORTPKT) ++#define USBIF_USB_DEVRMVD -11 ++#define USBIF_RSP_USB_DEVRMVD (USBIF_RSP_USB_ERROR + USBIF_USB_DEVRMVD) ++#define USBIF_USB_PARTIAL -12 ++#define USBIF_RSP_USB_PARTIAL (USBIF_RSP_USB_ERROR + USBIF_USB_PARTIAL) ++#define USBIF_USB_INVALID -13 ++#define USBIF_RSP_USB_INVALID (USBIF_RSP_USB_ERROR + USBIF_USB_INVALID) ++#define USBIF_USB_RESET -14 ++#define USBIF_RSP_USB_RESET (USBIF_RSP_USB_ERROR + USBIF_USB_RESET) ++#define USBIF_USB_SHUTDOWN -15 ++#define USBIF_RSP_USB_SHUTDOWN (USBIF_RSP_USB_ERROR + USBIF_USB_SHUTDOWN) ++#define USBIF_USB_UNKNOWN -16 ++#define USBIF_RSP_USB_UNKNOWN (USBIF_RSP_USB_ERROR + USBIF_USB_UNKNOWN) ++ ++ /* Operation not supported. */ ++#define USBIF_RSP_EOPNOTSUPP -2 ++ /* Operation failed for some unspecified reason (-EIO). */ ++#define USBIF_RSP_ERROR -1 ++ /* Operation completed successfully. */ ++#define USBIF_RSP_OKAY 0 ++ ++#define USBIF_S_LOW 1 ++#define USBIF_S_FULL 2 ++#define USBIF_S_HIGH 3 ++ ++/* ++ * Generate usbif ring structures and types. ++ */ ++ ++DEFINE_RING_TYPES(usbif, struct usbif_request, struct usbif_response); ++ ++#endif /* __XEN_PUBLIC_IO_USBIF_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null ++++ b/include/xen/vusb.h +@@ -0,0 +1,56 @@ ++#ifndef __XEN_VUSB_H__ ++#define __XEN_VUSB_H__ ++ ++#include ++#include ++#include ++ ++/* Not a real protocol. Used to generate ring structs which contain ++ * the elements common to all protocols only. This way we get a ++ * compiler-checkable way to use common struct elements, so we can ++ * avoid using switch(protocol) in a number of places. */ ++struct usbif_common_request { ++ char dummy; ++}; ++struct usbif_common_response { ++ char dummy; ++}; ++ ++/* i386 protocol version */ ++typedef struct usbif_request usbif_x86_32_request_t; ++typedef struct usbif_response usbif_x86_32_response_t; ++ ++ ++/* x86_64 protocol version */ ++typedef struct usbif_request usbif_x86_64_request_t; ++typedef struct usbif_response usbif_x86_64_response_t; ++ ++DEFINE_RING_TYPES(usbif_common, struct usbif_common_request, struct usbif_common_response); ++DEFINE_RING_TYPES(usbif_x86_32, struct usbif_request, struct usbif_response); ++DEFINE_RING_TYPES(usbif_x86_64, struct usbif_request, struct usbif_response); ++ ++union usbif_back_rings { ++ struct usbif_back_ring native; ++ struct usbif_common_back_ring common; ++ struct usbif_x86_32_back_ring x86_32; ++ struct usbif_x86_64_back_ring x86_64; ++}; ++typedef union usbif_back_rings usbif_back_rings_t; ++ ++enum usbif_protocol { ++ USBIF_PROTOCOL_NATIVE = 1, ++ USBIF_PROTOCOL_X86_32 = 2, ++ USBIF_PROTOCOL_X86_64 = 3, ++}; ++ ++static void inline usbif_get_x86_32_req(usbif_request_t *dst, usbif_x86_32_request_t *src) ++{ ++ memcpy(dst, src, sizeof(usbif_request_t)); ++} ++ ++static void inline usbif_get_x86_64_req(usbif_request_t *dst, usbif_x86_64_request_t *src) ++{ ++ memcpy(dst, src, sizeof(usbif_request_t)); ++} ++ ++#endif /* __XEN_VUSB_H__ */ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/acpi-video-delay-init.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/acpi-video-delay-init.patch new file mode 100644 index 0000000000..a7d4910fdf --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/acpi-video-delay-init.patch @@ -0,0 +1,92 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Add cmdline option "delay_init" to force acpi_video_register early on even if +intel opregion is detected on the system. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +This sounds dangerous at best since for old hardware (sandy-bridge and before?) +with an acpi opregion, acpi_video_register() is explicitely by-passed in +acpi_video_init(). + +################################################################################ +CHANGELOG +################################################################################ +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +Recommended for removal unless we figure out why this is in here. + +################################################################################ +UPSTREAM PLAN +################################################################################ +None, upstream clearly does something different. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +xenclient-dom0-tweak adds delay_init on grub's kernel cmdline. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/acpi/acpi_video.c ++++ b/drivers/acpi/acpi_video.c +@@ -76,6 +76,9 @@ module_param(device_id_scheme, bool, 044 + static int only_lcd = -1; + module_param(only_lcd, int, 0444); + ++static bool delay_init = 0; ++module_param(delay_init, bool, 0644); ++ + static int register_count; + static DEFINE_MUTEX(register_count_mutex); + static DEFINE_MUTEX(video_list_lock); +@@ -2258,6 +2261,22 @@ bool acpi_video_handles_brightness_key_p + } + EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses); + ++static ssize_t store_init_acpi_video(struct bus_type *bus, ++ const char *buf, size_t count) ++{ ++ unsigned int val; ++ if (kstrtouint(buf, 10, &val) || val != 1) ++ return -EINVAL; ++ acpi_video_register(); ++ return count; ++} ++ ++static struct bus_attribute init_acpi_video_attr = { ++ .attr = {.name = "init_acpi_video", .mode = 0644}, ++ .show = NULL, ++ .store = store_init_acpi_video, ++}; ++ + /* + * This is kind of nasty. Hardware using Intel chipsets may require + * the video opregion code to be run first in order to initialise +@@ -2278,6 +2297,9 @@ static int __init acpi_video_init(void) + if (acpi_disabled) + return 0; + ++ if (delay_init) ++ return bus_create_file(&acpi_bus_type, &init_acpi_video_attr); ++ + if (intel_opregion_present()) + return 0; + +@@ -2286,6 +2308,9 @@ static int __init acpi_video_init(void) + + static void __exit acpi_video_exit(void) + { ++ if (delay_init) ++ bus_remove_file(&acpi_bus_type, &init_acpi_video_attr); ++ + acpi_video_detect_exit(); + acpi_video_unregister(); + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/openxt-video-quirks.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/openxt-video-quirks.scc new file mode 100644 index 0000000000..80fd082688 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/openxt-video-quirks.scc @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply OpenXT video quirks." +define KFEATURE_COMPATIBILITY board + +# Cmdline option to force acpi_video_register() to run early, even when it presumably should not. +## TODO: determine if this is necessary. +#patch acpi-video-delay-init.patch + +# Give additional flags to /dev/mem mmap'ed memory (surfman?) +## TODO: determine if this is necessary. +#patch realmem-mmap.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/realmem-mmap.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/realmem-mmap.patch new file mode 100644 index 0000000000..87d2f877f2 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-video-quirks/realmem-mmap.patch @@ -0,0 +1,57 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +Give additional flags to /dev/mem mmap()'ed pages. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Force VM_SPECIAL (special vmas that are non-mergable, non-mlock()able) and +VM_DONTDUMP (Do not include in the core dump) flags on pages mapped using +/dev/mem char device. + +################################################################################ +CHANGELOG +################################################################################ +Original author: unknown +Port to 3.18: Eric Chanudet +Port to 4.14: Richard Turner +Port to 4.19: Richard Turner + +################################################################################ +REMOVAL +################################################################################ +? + +################################################################################ +UPSTREAM PLAN +################################################################################ +None. + +################################################################################ +INTERNAL DEPENDENCIES +################################################################################ +? + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/char/mem.c ++++ b/drivers/char/mem.c +@@ -396,9 +396,13 @@ static int mmap_mem(struct file *file, s + &vma->vm_page_prot)) + return -EINVAL; + +- vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, +- size, +- vma->vm_page_prot); ++ vma->vm_flags |= VM_DONTDUMP | VM_SPECIAL; ++ vma->vm_page_prot = __pgprot( ++ pgprot_val(vm_get_page_prot(vma->vm_flags)) | ++ pgprot_val(phys_mem_access_prot(file, ++ vma->vm_pgoff, ++ size, ++ vma->vm_page_prot))); + + vma->vm_ops = &mmap_mem_ops; + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/netback-vwif-support.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/netback-vwif-support.patch new file mode 100644 index 0000000000..1a2d1ecd90 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/netback-vwif-support.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/xen-netback/xenbus.c ++++ b/drivers/net/xen-netback/xenbus.c +@@ -1134,6 +1134,7 @@ static int read_xenbus_vif_flags(struct + + static const struct xenbus_device_id netback_ids[] = { + { "vif" }, ++ { "vwif" }, + { "" } + }; + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/openxt-vwif.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/openxt-vwif.scc new file mode 100644 index 0000000000..5d2efc8266 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/openxt-vwif/openxt-vwif.scc @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "OpenXT VWIF PV wireless device." +define KFEATURE_COMPATIBILITY all + +# Add "vwif" as a xenbus netback ID. +patch netback-vwif-support.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-add-xen-txt-eventlog-module.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-add-xen-txt-eventlog-module.patch new file mode 100644 index 0000000000..0b2642e4de --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-add-xen-txt-eventlog-module.patch @@ -0,0 +1,303 @@ +From fee3e4a2677f133a45f2b9bea40c8d7715f58b16 Mon Sep 17 00:00:00 2001 +From: "Daniel P. Smith" +Date: Thu, 18 May 2017 17:48:52 -0400 +Subject: [PATCH] xen-txt: add xen txt eventlog module + +--- + arch/x86/include/asm/xen/hypercall.h | 6 ++ + drivers/xen/Kconfig | 7 ++ + drivers/xen/Makefile | 1 + + drivers/xen/txt.c | 200 +++++++++++++++++++++++++++++++++++ + include/xen/interface/xen.h | 8 ++ + 5 files changed, 222 insertions(+) + create mode 100644 drivers/xen/txt.c + +--- a/arch/x86/include/asm/xen/hypercall.h ++++ b/arch/x86/include/asm/xen/hypercall.h +@@ -446,6 +446,12 @@ HYPERVISOR_dm_op( + return ret; + } + ++static inline int ++HYPERVISOR_txt_op(unsigned int op, void *arg) ++{ ++ return _hypercall2(int, txt_op, op, arg); ++} ++ + static inline void + MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set) + { +--- a/drivers/xen/Kconfig ++++ b/drivers/xen/Kconfig +@@ -177,6 +177,15 @@ config SWIOTLB_XEN + def_bool y + select SWIOTLB + ++config XEN_TXT ++ tristate "Xen TXT event log retrieval" ++ depends on X86 && TCG_TPM ++ default n ++ help ++ Support the Xen hypercall to retrieve the tboot TXT ++ event log. The log can be read through securityfs ++ txt/tpm12_binary_evtlog or txt/tpm20_binary_evtlog ++ + config XEN_PCIDEV_BACKEND + tristate "Xen PCI-device backend driver" + depends on PCI && X86 && XEN +--- a/drivers/xen/Makefile ++++ b/drivers/xen/Makefile +@@ -23,6 +23,7 @@ obj-$(CONFIG_XEN_GRANT_DEV_ALLOC) += xen + obj-$(CONFIG_XENFS) += xenfs/ + obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o + obj-$(CONFIG_XEN_PVHVM) += platform-pci.o ++obj-$(CONFIG_XEN_TXT) += txt.o + obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o + obj-$(CONFIG_XEN_MCE_LOG) += mcelog.o + obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback/ +--- /dev/null ++++ b/drivers/xen/txt.c +@@ -0,0 +1,212 @@ ++/* ++ * Copyright (C) 2017 Apertus Solutions, LLC ++ * ++ * Authors: ++ * Daniel P. Smith ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define FS_LOG_ENTRY 0 ++#define FS_DIR_ENTRY 1 /* must be last */ ++#define FS_ENTRIES 2 ++ ++static struct txt_op txt_log; ++static struct dentry *fs_entries[FS_ENTRIES]; ++ ++ ++#define TPM_LOG_BLOCK_SIZE 1024 ++ ++static void *tpm_evtlog_start(struct seq_file *m, loff_t *pos) ++{ ++ struct txt_op *log = m->private; ++ void *addr = log->buffer; ++ ++ addr += *pos * TPM_LOG_BLOCK_SIZE; ++ ++ if (addr > log->buffer + log->size) ++ return NULL; ++ ++ return addr; ++} ++ ++static void *tpm_evtlog_next(struct seq_file *m, void *v, loff_t *pos) ++{ ++ size_t size = 0; ++ struct txt_op *log = m->private; ++ void *addr = v; ++ ++ size = (log->buffer + log->size) - addr; ++ size = size > TPM_LOG_BLOCK_SIZE ? TPM_LOG_BLOCK_SIZE : size; ++ ++ if ((size == 0) || ++ ((addr + size) > (log->buffer + log->size))) ++ return NULL; ++ ++ addr += size; ++ (*pos)++; ++ ++ return addr; ++} ++ ++static void tpm_evtlog_stop(struct seq_file *m, void *v) ++{ ++} ++ ++static int tpm_evtlog_show(struct seq_file *m, void *v) ++{ ++ size_t size; ++ struct txt_op *log = m->private; ++ void *addr = v; ++ ++ size = ((log->buffer + log->size) - addr) > TPM_LOG_BLOCK_SIZE ? ++ TPM_LOG_BLOCK_SIZE : (log->buffer + log->size) - addr; ++ ++ if ((size != 0) && ++ ((addr + size) <= (log->buffer + log->size))) ++ seq_write(m, addr, size); ++ ++ return 0; ++} ++ ++const struct seq_operations tpm_evtlog_seqops = { ++ .start = tpm_evtlog_start, ++ .next = tpm_evtlog_next, ++ .stop = tpm_evtlog_stop, ++ .show = tpm_evtlog_show, ++}; ++ ++static int tpm_evtlog_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct seq_file *seq; ++ ++ err = seq_open(file, &tpm_evtlog_seqops); ++ if (!err) { ++ seq = file->private_data; ++ seq->private = &txt_log; ++ } ++ ++ return err; ++} ++ ++static const struct file_operations tpm_evtlog_ops = { ++ .open = tpm_evtlog_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = seq_release, ++}; ++ ++ ++static long expose_evtlog(const char *name) ++{ ++ long ret = 0; ++ char *filename; ++ ++ fs_entries[FS_DIR_ENTRY] = securityfs_create_dir(name, NULL); ++ if (IS_ERR(fs_entries[FS_DIR_ENTRY])) { ++ ret = PTR_ERR(fs_entries[FS_DIR_ENTRY]); ++ goto out; ++ } ++ ++ switch (txt_log.format) { ++ case TXTOP_EVTLOG_FORMAT_TCG_12: ++ filename = "tpm12_binary_evtlog"; ++ break; ++ case TXTOP_EVTLOG_FORMAT_LEGACY_20: ++ filename = "tpm20_binary_evtlog_legacy"; ++ break; ++ case TXTOP_EVTLOG_FORMAT_TCG_20: ++ filename = "tpm20_binary_evtlog_tcg"; ++ break; ++ default: ++ printk(KERN_ERR "Incompatible event-log format: %x\n", txt_log.format); ++ ret = EINVAL; ++ goto out_dir; ++ } ++ ++ fs_entries[FS_LOG_ENTRY] = ++ securityfs_create_file(filename, ++ S_IRUSR | S_IRGRP, ++ fs_entries[FS_DIR_ENTRY], NULL, ++ &tpm_evtlog_ops); ++ if (IS_ERR(fs_entries[FS_LOG_ENTRY])) { ++ ret = PTR_ERR(fs_entries[FS_LOG_ENTRY]); ++ goto out_dir; ++ } ++ ++ return 0; ++ ++out_dir: ++ securityfs_remove(fs_entries[FS_DIR_ENTRY]); ++out: ++ return ret; ++} ++ ++void teardown_evtlog(void) ++{ ++ int i; ++ ++ for (i = 0; i < FS_ENTRIES; i++) ++ securityfs_remove(fs_entries[i]); ++} ++ ++static int __init txt_init(void) ++{ ++ int err; ++ ++ if (!xen_domain()) ++ return -ENODEV; ++ ++ txt_log.size = 0; ++ txt_log.buffer = NULL; ++ txt_log.format = 0; ++ if ((err = HYPERVISOR_txt_op(TXTOP_GET, &txt_log)) != 0) ++ return err; ++ ++ if (!txt_log.size) ++ return -ENODEV; ++ ++ txt_log.buffer = kmalloc(txt_log.size, GFP_KERNEL); ++ if (txt_log.buffer == NULL) ++ return -ENOMEM; ++ ++ if ((err = HYPERVISOR_txt_op(TXTOP_GET, &txt_log)) != 0) ++ goto error; ++ ++ if ((err = expose_evtlog("txt")) != 0) ++ goto error; ++ ++ return 0; ++ ++error: ++ kfree(txt_log.buffer); ++ return err; ++} ++ ++static void __exit txt_exit(void) ++{ ++ teardown_evtlog(); ++ ++ if (txt_log.buffer) ++ kfree(txt_log.buffer); ++} ++ ++module_init(txt_init); ++module_exit(txt_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Daniel P. Smith "); ++MODULE_DESCRIPTION("TXT TPM Event log"); +--- a/include/xen/interface/xen.h ++++ b/include/xen/interface/xen.h +@@ -82,6 +82,7 @@ + #define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */ + #define __HYPERVISOR_xenpmu_op 40 + #define __HYPERVISOR_dm_op 41 ++#define __HYPERVISOR_txt_op 42 + + /* Architecture-specific hypercall definitions. */ + #define __HYPERVISOR_arch_0 48 +@@ -745,6 +746,20 @@ typedef uint64_t cpumap_t; + + typedef uint8_t xen_domain_handle_t[16]; + ++#define TXTOP_GET 0 ++ ++struct txt_op { ++ uint64_t size; ++ ++#define TXTOP_EVTLOG_FORMAT_UNKNOWN 0x0 ++#define TXTOP_EVTLOG_FORMAT_TCG_12 0x1 ++#define TXTOP_EVTLOG_FORMAT_LEGACY_20 0x2 ++#define TXTOP_EVTLOG_FORMAT_TCG_20 0x3 ++ uint8_t format; ++ uint8_t _pad[7]; ++ void *buffer; ++}; ++ + /* Turn a plain number into a C unsigned long constant. */ + #define __mk_unsigned_long(x) x ## UL + #define mk_unsigned_long(x) __mk_unsigned_long(x) diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg new file mode 100644 index 0000000000..16de16c726 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg @@ -0,0 +1 @@ +CONFIG_XEN_TXT=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.scc new file mode 100644 index 0000000000..46327960da --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.scc @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Expose TXT eventlog through securityfs." +define KFEATURE_COMPATIBILITY all + +# Use Xen custom hypercall to retrieve and expose the eventlog in the securityfs. +patch xen-txt-add-xen-txt-eventlog-module.patch + +kconf hardware xen-txt-evtlog.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-add-RING_COPY_RESPONSE.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-add-RING_COPY_RESPONSE.patch new file mode 100644 index 0000000000..b6b5728697 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-add-RING_COPY_RESPONSE.patch @@ -0,0 +1,52 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +QSB-023 (https://github.com/QubesOS/qubes-secpack/blob/master/QSBs/qsb-023-2015) +XSA-155 additional patches for the Xen network and block frontends from Qubes +OS Project. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Source: https://github.com/QubesOS/qubes-linux-kernel/tree/stable-3.18/patches.xen +Patch: xsa155-linux-0008-xen-Add-RING_COPY_RESPONSE.patch + +Using RING_GET_RESPONSE() on a shared ring is easy to use incorrectly +(i.e., by not considering that the other end may alter the data in the +shared ring while it is being inspected). Safe usage of a response +generally requires taking a local copy. + +Provide a RING_COPY_RESPONSE() macro to use instead of +RING_GET_RESPONSE() and an open-coded memcpy(). This takes care of +ensuring that the copy is done correctly regardless of any possible +compiler optimizations. + +Use a volatile source to prevent the compiler from reordering or +omitting the copy. + +################################################################################ +PATCHES +################################################################################ +--- a/include/xen/interface/io/ring.h ++++ b/include/xen/interface/io/ring.h +@@ -201,6 +201,20 @@ struct __name##_back_ring { \ + #define RING_GET_RESPONSE(_r, _idx) \ + (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp)) + ++/* ++ * Get a local copy of a response. ++ * ++ * Use this in preference to RING_GET_RESPONSE() so all processing is ++ * done on a local copy that cannot be modified by the other end. ++ * ++ * Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may cause this ++ * to be ineffective where _rsp is a struct which consists of only bitfields. ++ */ ++#define RING_COPY_RESPONSE(_r, _idx, _rsp) do { \ ++ /* Use volatile to force the copy into _rsp. */ \ ++ *(_rsp) = *(volatile typeof(_rsp))RING_GET_RESPONSE(_r, _idx); \ ++} while (0) ++ + /* Loop termination condition: Would the specified index overflow the ring? */ + #define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \ + (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r)) diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-make-local-copy-of-response-before-usin.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-make-local-copy-of-response-before-usin.patch new file mode 100644 index 0000000000..76634baa46 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-make-local-copy-of-response-before-usin.patch @@ -0,0 +1,122 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +QSB-023 (https://github.com/QubesOS/qubes-secpack/blob/master/QSBs/qsb-023-2015) +XSA-155 additional patches for the Xen network and block frontends from Qubes +OS Project. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Source: https://github.com/QubesOS/qubes-linux-kernel/tree/stable-3.18/patches.xen +Patch: xsa155-linux312-0012-xen-blkfront-make-local-copy-of-response-before-usin.patch + +Data on the shared page can be changed at any time by the backend. Make +a local copy, which is no longer controlled by the backend. And only +then access it. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1549,7 +1549,7 @@ static bool blkif_completion(unsigned lo + static irqreturn_t blkif_interrupt(int irq, void *dev_id) + { + struct request *req; +- struct blkif_response *bret; ++ struct blkif_response bret; + RING_IDX i, rp; + unsigned long flags; + struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id; +@@ -1566,8 +1566,8 @@ static irqreturn_t blkif_interrupt(int i + for (i = rinfo->ring.rsp_cons; i != rp; i++) { + unsigned long id; + +- bret = RING_GET_RESPONSE(&rinfo->ring, i); +- id = bret->id; ++ RING_COPY_RESPONSE(&rinfo->ring, i, &bret); ++ id = bret.id; + /* + * The backend has messed up and given us an id that we would + * never have given to it (we stamp it up to BLK_RING_SIZE - +@@ -1575,39 +1575,39 @@ static irqreturn_t blkif_interrupt(int i + */ + if (id >= BLK_RING_SIZE(info)) { + WARN(1, "%s: response to %s has incorrect id (%ld)\n", +- info->gd->disk_name, op_name(bret->operation), id); ++ info->gd->disk_name, op_name(bret.operation), id); + /* We can't safely get the 'struct request' as + * the id is busted. */ + continue; + } + req = rinfo->shadow[id].request; + +- if (bret->operation != BLKIF_OP_DISCARD) { ++ if (bret.operation != BLKIF_OP_DISCARD) { + /* + * We may need to wait for an extra response if the + * I/O request is split in 2 + */ +- if (!blkif_completion(&id, rinfo, bret)) ++ if (!blkif_completion(&id, rinfo, &bret)) + continue; + } + + if (add_id_to_freelist(rinfo, id)) { + WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n", +- info->gd->disk_name, op_name(bret->operation), id); ++ info->gd->disk_name, op_name(bret.operation), id); + continue; + } + +- if (bret->status == BLKIF_RSP_OKAY) ++ if (bret.status == BLKIF_RSP_OKAY) + blkif_req(req)->error = BLK_STS_OK; + else + blkif_req(req)->error = BLK_STS_IOERR; + +- switch (bret->operation) { ++ switch (bret.operation) { + case BLKIF_OP_DISCARD: +- if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { ++ if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) { + struct request_queue *rq = info->rq; + printk(KERN_WARNING "blkfront: %s: %s op failed\n", +- info->gd->disk_name, op_name(bret->operation)); ++ info->gd->disk_name, op_name(bret.operation)); + blkif_req(req)->error = BLK_STS_NOTSUPP; + info->feature_discard = 0; + info->feature_secdiscard = 0; +@@ -1617,15 +1617,15 @@ static irqreturn_t blkif_interrupt(int i + break; + case BLKIF_OP_FLUSH_DISKCACHE: + case BLKIF_OP_WRITE_BARRIER: +- if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { ++ if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) { + printk(KERN_WARNING "blkfront: %s: %s op failed\n", +- info->gd->disk_name, op_name(bret->operation)); ++ info->gd->disk_name, op_name(bret.operation)); + blkif_req(req)->error = BLK_STS_NOTSUPP; + } +- if (unlikely(bret->status == BLKIF_RSP_ERROR && ++ if (unlikely(bret.status == BLKIF_RSP_ERROR && + rinfo->shadow[id].req.u.rw.nr_segments == 0)) { + printk(KERN_WARNING "blkfront: %s: empty %s op failed\n", +- info->gd->disk_name, op_name(bret->operation)); ++ info->gd->disk_name, op_name(bret.operation)); + blkif_req(req)->error = BLK_STS_NOTSUPP; + } + if (unlikely(blkif_req(req)->error)) { +@@ -1638,9 +1638,9 @@ static irqreturn_t blkif_interrupt(int i + /* fall through */ + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: +- if (unlikely(bret->status != BLKIF_RSP_OKAY)) ++ if (unlikely(bret.status != BLKIF_RSP_OKAY)) + dev_dbg(&info->xbdev->dev, "Bad return from blkdev data " +- "request: %x\n", bret->status); ++ "request: %x\n", bret.status); + + break; + default: diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-prepare-request-locally-only-then-put-i.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-prepare-request-locally-only-then-put-i.patch new file mode 100644 index 0000000000..63d5b5ba50 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-blkfront-prepare-request-locally-only-then-put-i.patch @@ -0,0 +1,136 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +QSB-023 (https://github.com/QubesOS/qubes-secpack/blob/master/QSBs/qsb-023-2015) +XSA-155 additional patches for the Xen network and block frontends from Qubes +OS Project. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Source: https://github.com/QubesOS/qubes-linux-kernel/tree/stable-3.18/patches.xen +Patch: xsa155-linux318-0013-xen-blkfront-prepare-request-locally-only-then-put-i.patch + +Do not reuse data which theoretically might be already modified by the +backend. This is mostly about private copy of the request +(info->shadow[id].req) - make sure the request saved there is really the +one just filled. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -692,7 +692,8 @@ static void blkif_setup_extra_req(struct + static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *rinfo) + { + struct blkfront_info *info = rinfo->dev_info; +- struct blkif_request *ring_req, *extra_ring_req = NULL; ++ struct blkif_request ring_req, extra_ring_req; ++ struct blkif_request *__ring_req, *__extra_ring_req = NULL; + unsigned long id, extra_id = NO_ASSOCIATED_ID; + bool require_extra_req = false; + int i; +@@ -737,7 +738,8 @@ static int blkif_queue_rw_req(struct req + } + + /* Fill out a communications ring structure. */ +- id = blkif_ring_get_request(rinfo, req, &ring_req); ++ id = blkif_ring_get_request(rinfo, req, &__ring_req); ++ ring_req = *__ring_req; + + num_sg = blk_rq_map_sg(req->q, req, rinfo->shadow[id].sg); + num_grant = 0; +@@ -757,16 +759,16 @@ static int blkif_queue_rw_req(struct req + * BLKIF_OP_WRITE + */ + BUG_ON(req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA); +- ring_req->operation = BLKIF_OP_INDIRECT; +- ring_req->u.indirect.indirect_op = rq_data_dir(req) ? ++ ring_req.operation = BLKIF_OP_INDIRECT; ++ ring_req.u.indirect.indirect_op = rq_data_dir(req) ? + BLKIF_OP_WRITE : BLKIF_OP_READ; +- ring_req->u.indirect.sector_number = (blkif_sector_t)blk_rq_pos(req); +- ring_req->u.indirect.handle = info->handle; +- ring_req->u.indirect.nr_segments = num_grant; ++ ring_req.u.indirect.sector_number = (blkif_sector_t)blk_rq_pos(req); ++ ring_req.u.indirect.handle = info->handle; ++ ring_req.u.indirect.nr_segments = num_grant; + } else { +- ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req); +- ring_req->u.rw.handle = info->handle; +- ring_req->operation = rq_data_dir(req) ? ++ ring_req.u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req); ++ ring_req.u.rw.handle = info->handle; ++ ring_req.operation = rq_data_dir(req) ? + BLKIF_OP_WRITE : BLKIF_OP_READ; + if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) { + /* +@@ -777,25 +779,25 @@ static int blkif_queue_rw_req(struct req + * since it is guaranteed ordered WRT previous writes.) + */ + if (info->feature_flush && info->feature_fua) +- ring_req->operation = ++ ring_req.operation = + BLKIF_OP_WRITE_BARRIER; + else if (info->feature_flush) +- ring_req->operation = ++ ring_req.operation = + BLKIF_OP_FLUSH_DISKCACHE; + else +- ring_req->operation = 0; ++ ring_req.operation = 0; + } +- ring_req->u.rw.nr_segments = num_grant; ++ ring_req.u.rw.nr_segments = num_grant; + if (unlikely(require_extra_req)) { +- extra_id = blkif_ring_get_request(rinfo, req, +- &extra_ring_req); ++ extra_id = blkif_ring_get_request(rinfo, req, &__extra_ring_req); ++ extra_ring_req = *__extra_ring_req; + /* + * Only the first request contains the scatter-gather + * list. + */ + rinfo->shadow[extra_id].num_sg = 0; + +- blkif_setup_extra_req(ring_req, extra_ring_req); ++ blkif_setup_extra_req(&ring_req, &extra_ring_req); + + /* Link the 2 requests together */ + rinfo->shadow[extra_id].associated_id = id; +@@ -803,12 +805,12 @@ static int blkif_queue_rw_req(struct req + } + } + +- setup.ring_req = ring_req; ++ setup.ring_req = &ring_req; + setup.id = id; + + setup.require_extra_req = require_extra_req; + if (unlikely(require_extra_req)) +- setup.extra_ring_req = extra_ring_req; ++ setup.extra_ring_req = &extra_ring_req; + + for_each_sg(rinfo->shadow[id].sg, sg, num_sg, i) { + BUG_ON(sg->offset + sg->length > PAGE_SIZE); +@@ -830,10 +832,16 @@ static int blkif_queue_rw_req(struct req + if (setup.segments) + kunmap_atomic(setup.segments); + ++ /* make the request available to the backend */ ++ *__ring_req = ring_req; ++ + /* Keep a private copy so we can reissue requests when recovering. */ +- rinfo->shadow[id].req = *ring_req; +- if (unlikely(require_extra_req)) +- rinfo->shadow[extra_id].req = *extra_ring_req; ++ rinfo->shadow[id].req = ring_req; ++ ++ if (unlikely(require_extra_req)) { ++ rinfo->shadow[extra_id].req = extra_ring_req; ++ *__extra_ring_req = extra_ring_req; ++ } + + if (new_persistent_gnts) + gnttab_free_grant_references(setup.gref_head); diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-add-range-check-for-Tx-response-id.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-add-range-check-for-Tx-response-id.patch new file mode 100644 index 0000000000..b43c937bb2 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-add-range-check-for-Tx-response-id.patch @@ -0,0 +1,29 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +QSB-023 (https://github.com/QubesOS/qubes-secpack/blob/master/QSBs/qsb-023-2015) +XSA-155 additional patches for the Xen network and block frontends from Qubes +OS Project. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Source: https://github.com/QubesOS/qubes-linux-kernel/tree/stable-3.18/patches.xen +Patch: xsa155-linux-0011-xen-netfront-add-range-check-for-Tx-response-id.patch + +Tx response ID is fetched from shared page, so make sure it is sane +before using it as an array index. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -394,6 +394,7 @@ static void xennet_tx_buf_gc(struct netf + continue; + + id = txrsp->id; ++ BUG_ON(id >= NET_TX_RING_SIZE); + skb = queue->tx_skbs[id].skb; + if (unlikely(gnttab_query_foreign_access( + queue->grant_tx_ref[id]) != 0)) { diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-copy-response-out-of-shared-buffer-befo.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-copy-response-out-of-shared-buffer-befo.patch new file mode 100644 index 0000000000..9f04c47cfc --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-copy-response-out-of-shared-buffer-befo.patch @@ -0,0 +1,174 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +QSB-023 (https://github.com/QubesOS/qubes-secpack/blob/master/QSBs/qsb-023-2015) +XSA-155 additional patches for the Xen network and block frontends from Qubes +OS Project. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Source: https://github.com/QubesOS/qubes-linux-kernel/tree/stable-3.18/patches.xen +Patch: xsa155-linux318-0009-xen-netfront-copy-response-out-of-shared-buffer-befo.patch + +Make local copy of the response, otherwise backend might modify it while +frontend is already processing it - leading to time of check / time of +use issue. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -387,13 +387,13 @@ static void xennet_tx_buf_gc(struct netf + rmb(); /* Ensure we see responses up to 'rp'. */ + + for (cons = queue->tx.rsp_cons; cons != prod; cons++) { +- struct xen_netif_tx_response *txrsp; ++ struct xen_netif_tx_response txrsp; + +- txrsp = RING_GET_RESPONSE(&queue->tx, cons); +- if (txrsp->status == XEN_NETIF_RSP_NULL) ++ RING_COPY_RESPONSE(&queue->tx, cons, &txrsp); ++ if (txrsp.status == XEN_NETIF_RSP_NULL) + continue; + +- id = txrsp->id; ++ id = txrsp.id; + BUG_ON(id >= NET_TX_RING_SIZE); + skb = queue->tx_skbs[id].skb; + if (unlikely(gnttab_query_foreign_access( +@@ -742,7 +742,7 @@ static int xennet_get_extras(struct netf + RING_IDX rp) + + { +- struct xen_netif_extra_info *extra; ++ struct xen_netif_extra_info extra; + struct device *dev = &queue->info->netdev->dev; + RING_IDX cons = queue->rx.rsp_cons; + int err = 0; +@@ -758,24 +758,23 @@ static int xennet_get_extras(struct netf + break; + } + +- extra = (struct xen_netif_extra_info *) +- RING_GET_RESPONSE(&queue->rx, ++cons); ++ RING_COPY_RESPONSE(&queue->rx, ++cons, &extra); + +- if (unlikely(!extra->type || +- extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { ++ if (unlikely(!extra.type || ++ extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + if (net_ratelimit()) + dev_warn(dev, "Invalid extra type: %d\n", +- extra->type); ++ extra.type); + err = -EINVAL; + } else { +- memcpy(&extras[extra->type - 1], extra, +- sizeof(*extra)); ++ memcpy(&extras[extra.type - 1], &extra, ++ sizeof(extra)); + } + + skb = xennet_get_rx_skb(queue, cons); + ref = xennet_get_rx_ref(queue, cons); + xennet_move_rx_slot(queue, skb, ref); +- } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); ++ } while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE); + + queue->rx.rsp_cons = cons; + return err; +@@ -785,28 +784,28 @@ static int xennet_get_responses(struct n + struct netfront_rx_info *rinfo, RING_IDX rp, + struct sk_buff_head *list) + { +- struct xen_netif_rx_response *rx = &rinfo->rx; ++ struct xen_netif_rx_response rx = rinfo->rx; + struct xen_netif_extra_info *extras = rinfo->extras; + struct device *dev = &queue->info->netdev->dev; + RING_IDX cons = queue->rx.rsp_cons; + struct sk_buff *skb = xennet_get_rx_skb(queue, cons); + grant_ref_t ref = xennet_get_rx_ref(queue, cons); +- int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD); ++ int max = XEN_NETIF_NR_SLOTS_MIN + (rx.status <= RX_COPY_THRESHOLD); + int slots = 1; + int err = 0; + unsigned long ret; + +- if (rx->flags & XEN_NETRXF_extra_info) { ++ if (rx.flags & XEN_NETRXF_extra_info) { + err = xennet_get_extras(queue, extras, rp); + cons = queue->rx.rsp_cons; + } + + for (;;) { +- if (unlikely(rx->status < 0 || +- rx->offset + rx->status > XEN_PAGE_SIZE)) { ++ if (unlikely(rx.status < 0 || ++ rx.offset + rx.status > XEN_PAGE_SIZE)) { + if (net_ratelimit()) +- dev_warn(dev, "rx->offset: %u, size: %d\n", +- rx->offset, rx->status); ++ dev_warn(dev, "rx.offset: %u, size: %d\n", ++ rx.offset, rx.status); + xennet_move_rx_slot(queue, skb, ref); + err = -EINVAL; + goto next; +@@ -820,7 +819,7 @@ static int xennet_get_responses(struct n + if (ref == GRANT_INVALID_REF) { + if (net_ratelimit()) + dev_warn(dev, "Bad rx response id %d.\n", +- rx->id); ++ rx.id); + err = -EINVAL; + goto next; + } +@@ -833,7 +832,7 @@ static int xennet_get_responses(struct n + __skb_queue_tail(list, skb); + + next: +- if (!(rx->flags & XEN_NETRXF_more_data)) ++ if (!(rx.flags & XEN_NETRXF_more_data)) + break; + + if (cons + slots == rp) { +@@ -843,7 +842,7 @@ next: + break; + } + +- rx = RING_GET_RESPONSE(&queue->rx, cons + slots); ++ RING_COPY_RESPONSE(&queue->rx, cons + slots, &rx); + skb = xennet_get_rx_skb(queue, cons + slots); + ref = xennet_get_rx_ref(queue, cons + slots); + slots++; +@@ -898,9 +897,9 @@ static int xennet_fill_frags(struct netf + struct sk_buff *nskb; + + while ((nskb = __skb_dequeue(list))) { +- struct xen_netif_rx_response *rx = +- RING_GET_RESPONSE(&queue->rx, ++cons); ++ struct xen_netif_rx_response rx; + skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0]; ++ RING_COPY_RESPONSE(&queue->rx, ++cons, &rx); + + if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) { + unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to; +@@ -916,7 +915,7 @@ static int xennet_fill_frags(struct netf + + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + skb_frag_page(nfrag), +- rx->offset, rx->status, PAGE_SIZE); ++ rx.offset, rx.status, PAGE_SIZE); + + skb_shinfo(nskb)->nr_frags = 0; + kfree_skb(nskb); +@@ -1014,7 +1013,7 @@ static int xennet_poll(struct napi_struc + i = queue->rx.rsp_cons; + work_done = 0; + while ((i != rp) && (work_done < budget)) { +- memcpy(rx, RING_GET_RESPONSE(&queue->rx, i), sizeof(*rx)); ++ RING_COPY_RESPONSE(&queue->rx, i, rx); + memset(extras, 0, sizeof(rinfo.extras)); + + err = xennet_get_responses(queue, &rinfo, rp, &tmpq); diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-do-not-use-data-already-exposed-to-back.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-do-not-use-data-already-exposed-to-back.patch new file mode 100644 index 0000000000..c69bdfffb3 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155-qsb-023-xen-netfront-do-not-use-data-already-exposed-to-back.patch @@ -0,0 +1,59 @@ +################################################################################ +SHORT DESCRIPTION: +################################################################################ +QSB-023 (https://github.com/QubesOS/qubes-secpack/blob/master/QSBs/qsb-023-2015) +XSA-155 additional patches for the Xen network and block frontends from Qubes +OS Project. + +################################################################################ +LONG DESCRIPTION: +################################################################################ +Source: https://github.com/QubesOS/qubes-linux-kernel/tree/stable-3.18/patches.xen +Patch: xsa155-linux318-0010-xen-netfront-do-not-use-data-already-exposed-to-back.patch + +Backend may freely modify anything on shared page, so use data which was +supposed to be written there, instead of reading it back from the shared pckend +may freely modify anything on shared page, so use data which was supposed to be +written there, instead of reading it back from the shared page. + +################################################################################ +PATCHES +################################################################################ +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -459,7 +459,7 @@ static void xennet_tx_setup_grant(unsign + tx->flags = 0; + + info->tx = tx; +- info->size += tx->size; ++ info->size += len; + } + + static struct xen_netif_tx_request *xennet_make_first_txreq( +@@ -575,7 +575,7 @@ static netdev_tx_t xennet_start_xmit(str + int slots; + struct page *page; + unsigned int offset; +- unsigned int len; ++ unsigned int len, this_len; + unsigned long flags; + struct netfront_queue *queue = NULL; + unsigned int num_queues = dev->real_num_tx_queues; +@@ -635,14 +635,15 @@ static netdev_tx_t xennet_start_xmit(str + } + + /* First request for the linear area. */ ++ this_len = min_t(unsigned int, PAGE_SIZE - offset, len); + first_tx = tx = xennet_make_first_txreq(queue, skb, + page, offset, len); +- offset += tx->size; ++ offset += this_len; + if (offset == PAGE_SIZE) { + page++; + offset = 0; + } +- len -= tx->size; ++ len -= this_len; + + if (skb->ip_summed == CHECKSUM_PARTIAL) + /* local packet? */ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155.scc new file mode 100644 index 0000000000..901695c60e --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xsa-155/xsa-155.scc @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Apply XSA-155 mitigation patches for service VM" +define KFEATURE_COMPATIBILITY all + +patch xsa-155-qsb-023-add-RING_COPY_RESPONSE.patch +patch xsa-155-qsb-023-xen-blkfront-make-local-copy-of-response-before-usin.patch +patch xsa-155-qsb-023-xen-blkfront-prepare-request-locally-only-then-put-i.patch +patch xsa-155-qsb-023-xen-netfront-add-range-check-for-Tx-response-id.patch +patch xsa-155-qsb-023-xen-netfront-copy-response-out-of-shared-buffer-befo.patch +patch xsa-155-qsb-023-xen-netfront-do-not-use-data-already-exposed-to-back.patch From 6226abdf4109122cc8c7a163a1eb8c1c5fa290c2 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 17:24:01 -0500 Subject: [PATCH 05/15] kmeta: OpenXT BSP configuration fragments The upstream provided generic common-pc/intel-x86 configuration fragments tend to enable (builtin or as module) a lot more than what the existing defconfigs for OpenXT do. Add generic configuration fragments for: - lvm/luks required components - initrd, gz compressed (the others can be disabled) - openxt-common.scc is only for convenience to include ubiquitous features in current OpenXT service-VMs. Arguably BSP: - laptop-hp, - laptop-dell, - laptop-thinkpad, for various OEM specific configurations. common-pc-drivers-reduced.scc tries to provide a finer grained selection of modules than common-pc-drivers.scc provided by yocto-kernel-cache. common-pc-*{,-extended} add/define fragments for hardware OpenXT supports but that is not provided by yocto-kernel-cache as configuration fragment. common-xen-vm provides configuration overrides to service-vms (currently only disables unavailable components). intel-x86-reduced is intel-x86.scc without components that are not available in VMs that still have access to some hardware/emulated things. bsp/xen/intel-x86-64* gives a KMACHINE=intel-x86-64 base configuration for each service VM. Additional features can be then configured at the recipe level through KERNEL_FEATURES. A convenience intel-x86-64-vm.cfg file factorizes commonalities for pv, pvh, hvm guests. Signed-off-by: Eric Chanudet --- .../common-pc/common-pc-drivers-reduced.cfg | 65 +++++++ .../bsp/common-pc/common-pc-eth-extended.cfg | 9 + .../bsp/common-pc/common-pc-eth-extended.scc | 2 + .../bsp/common-pc/common-pc-hid.cfg | 40 +++++ .../bsp/common-pc/common-pc-hid.scc | 1 + .../bsp/common-pc/common-pc-wifi-extended.cfg | 18 ++ .../bsp/common-pc/common-pc-wifi-extended.scc | 2 + .../bsp/common-xen-vm/common-xen-vm.cfg | 11 ++ .../bsp/intel-x86/intel-x86-reduced.cfg | 165 ++++++++++++++++++ .../openxt-kmeta/bsp/laptop/laptop-dell.cfg | 10 ++ .../openxt-kmeta/bsp/laptop/laptop-dell.scc | 7 + .../openxt-kmeta/bsp/laptop/laptop-hp.cfg | 4 + .../openxt-kmeta/bsp/laptop/laptop-hp.scc | 5 + .../bsp/laptop/laptop-thinkpad.cfg | 1 + .../bsp/laptop/laptop-thinkpad.scc | 5 + .../bsp/xen/intel-x86-64-dom0.cfg | 16 ++ .../bsp/xen/intel-x86-64-dom0.scc | 24 +++ .../bsp/xen/intel-x86-64-ndvm.cfg | 10 ++ .../bsp/xen/intel-x86-64-ndvm.scc | 15 ++ .../openxt-kmeta/bsp/xen/intel-x86-64-smp.cfg | 10 ++ .../bsp/xen/intel-x86-64-stubdom.cfg | 0 .../bsp/xen/intel-x86-64-stubdom.scc | 15 ++ .../bsp/xen/intel-x86-64-uivm.cfg | 9 + .../bsp/xen/intel-x86-64-uivm.scc | 15 ++ .../openxt-kmeta/bsp/xen/intel-x86-64-vm.cfg | 10 ++ .../files/openxt-kmeta/cfg/initrd-gz.cfg | 6 + .../files/openxt-kmeta/cfg/initrd-gz.scc | 4 + .../linux/files/openxt-kmeta/cfg/luks-lvm.cfg | 9 + .../linux/files/openxt-kmeta/cfg/luks-lvm.scc | 4 + .../files/openxt-kmeta/cfg/openxt-common.cfg | 36 ++++ .../files/openxt-kmeta/cfg/openxt-common.scc | 21 +++ 31 files changed, 549 insertions(+) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-drivers-reduced.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/common-xen-vm/common-xen-vm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/intel-x86/intel-x86-reduced.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-smp.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-stubdom.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-stubdom.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-vm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-drivers-reduced.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-drivers-reduced.cfg new file mode 100644 index 0000000000..863b1dc673 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-drivers-reduced.cfg @@ -0,0 +1,65 @@ +# +# Serial ATA and Parallel ATA drivers (libata) +# +CONFIG_ATA=y +CONFIG_SATA_AHCI=y + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_EVDEV=y + +# +# Input Device Drivers +# +CONFIG_INPUT_MOUSE=y + +CONFIG_MOUSE_PS2=m + +CONFIG_MOUSE_APPLETOUCH=m +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_INPUT_TABLET=y + +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_WACOM_I2C=m +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m + +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_RTC_CLASS=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_I801=y + +# +# USB HID support +# +CONFIG_USB_HID=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +CONFIG_I2C_HID=m + +# +# NVME Support +# +CONFIG_BLK_DEV_NVME=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.cfg new file mode 100644 index 0000000000..0f0efe6725 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.cfg @@ -0,0 +1,9 @@ +CONFIG_BNX2=m +CONFIG_CAVIUM_PTP=m +CONFIG_IGB=m +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_IXGBEVF=m +CONFIG_I40E=m +CONFIG_I40EVF=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.scc new file mode 100644 index 0000000000..01ede57bc0 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-eth-extended.scc @@ -0,0 +1,2 @@ +kconf hardware bsp/common-pc/common-pc-eth.cfg +kconf hardware common-pc-eth-extended.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.cfg new file mode 100644 index 0000000000..6f2e00ed7b --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.cfg @@ -0,0 +1,40 @@ +# +# HID support +# +CONFIG_HID=m +CONFIG_HIDRAW=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EZKEY=m +CONFIG_HID_KYE=m +CONFIG_HID_GYRATION=m +CONFIG_HID_ITE=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_LOGITECH_DJ=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTRIG=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_ZEROPLUS=m +CONFIG_HID_ALPS=m +CONFIG_HID_WACOM=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.scc new file mode 100644 index 0000000000..4c110a4954 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-hid.scc @@ -0,0 +1 @@ +kconf hardware common-pc-hid.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.cfg new file mode 100644 index 0000000000..5570f64915 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.cfg @@ -0,0 +1,18 @@ +CONFIG_B43=m +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2100_DEBUG=y +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +CONFIG_IPW2200_DEBUG=y +CONFIG_LIBIPW=m +CONFIG_LIBIPW_DEBUG=y +CONFIG_IWL4965=m +CONFIG_IWL3945=m +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_RTL8723AE=m +CONFIG_RTLWIFI=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.scc new file mode 100644 index 0000000000..a73fa0bdc0 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-pc/common-pc-wifi-extended.scc @@ -0,0 +1,2 @@ +kconf hardware bsp/common-pc/common-pc-wifi.cfg +kconf hardware common-pc-wifi-extended.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/common-xen-vm/common-xen-vm.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-xen-vm/common-xen-vm.cfg new file mode 100644 index 0000000000..283de352cb --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/common-xen-vm/common-xen-vm.cfg @@ -0,0 +1,11 @@ +# +# Power management and ACPI options +# +# CONFIG_SUSPEND is not set +# CONFIG_SCHED_MC is not set + +# +# Device drivers +# +# CONFIG_PPS is not set +# CONFIG_PTP_1588_CLOCK is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/intel-x86/intel-x86-reduced.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/intel-x86/intel-x86-reduced.cfg new file mode 100644 index 0000000000..ea57869207 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/intel-x86/intel-x86-reduced.cfg @@ -0,0 +1,165 @@ +# SPDX-License-Identifier: MIT +#......................................................................... +# WARNING +# +# This file is a kernel configuration fragment, and not a full kernel +# configuration file. The final kernel configuration is made up of +# an assembly of processed fragments, each of which is designed to +# capture a specific part of the final configuration (e.g. platform +# configuration, feature configuration, and board specific hardware +# configuration). For more information on kernel configuration, please +# consult the product documentation. +# +#......................................................................... + +# +# Processor type and features +# +CONFIG_MCORE2=y +CONFIG_SMP=y + +#CONFIG_X86_EXTENDED_PLATFORM is not set +#CONFIG_X86_INTEL_MID is not set + +CONFIG_MEMORY_FAILURE=y +CONFIG_HWPOISON_INJECT=m + +CONFIG_X86_INTEL_LPSS=y + +# +# Binary Emulations +# +# CONFIG_IA32_EMULATION is not set + +# +# I2C options +# +CONFIG_I2C_DESIGNWARE_PLATFORM=y +CONFIG_I2C_DESIGNWARE_PCI=y + +# +# PC SMBus host controller drivers +# +CONFIG_I2C_I801=m +CONFIG_I2C_ISCH=m +CONFIG_I2C_ISMT=m + +# +# Power management and ACPI options +# +CONFIG_PM=y + +CONFIG_HIBERNATION=y + +# +# Multifunction device drivers +# +CONFIG_LPC_ICH=m + +# +# x86 CPU frequency scaling drivers +# +CONFIG_X86_PCC_CPUFREQ=m +CONFIG_X86_ACPI_CPUFREQ=m +CONFIG_CPU_FREQ_GOV_POWERSAVE=m + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +CONFIG_PCI_MSI=y +# CONFIG_HOTPLUG_PCI is not set + +CONFIG_PCIEPORTBUS=y + +CONFIG_PCI_STUB=m +CONFIG_PCI_IOV=y +# CONFIG_HOTPLUG_PCI_PCIE is not set + +# +#SD/MMC +# +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PCI=y +CONFIG_MMC_SDHCI_ACPI=y +CONFIG_MMC_SDHCI_PLTFM=y + +# +# Serial ATA and Parallel ATA drivers +# +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI_PLATFORM=y + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_ISCI=y +CONFIG_SCSI_MPT2SAS=y + +# +# EEPROM support +# + +# +# Hardware Monitoring support +# +CONFIG_SENSORS_ACPI_POWER=m +CONFIG_SENSORS_CORETEMP=m + +# +# Input device support +# +CONFIG_INPUT_MISC=y + +# +# PC SMBus host controller drivers +# +CONFIG_I2C_CHARDEV=m + +# +# Real Time Clock +# +CONFIG_RTC_CLASS=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y + +# +# Firmware Drivers +# +CONFIG_DMI_SYSFS=y + +# +# Library routines +# +CONFIG_CRC_T10DIF=y + +# +# Digest +# +CONFIG_CRYPTO=y + +# +# Ciphers +# +CONFIG_CRYPTO_AES_NI_INTEL=m + +# +# HID +# +CONFIG_HID=m +CONFIG_I2C_HID=m +CONFIG_HID_SENSOR_HUB=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m + +# NVMe support +CONFIG_BLK_DEV_NVME=y + +# Touchscreen and zforce +CONFIG_INPUT_TOUCHSCREEN=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.cfg new file mode 100644 index 0000000000..03538f1323 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.cfg @@ -0,0 +1,10 @@ +CONFIG_ACPI_WMI=m + +CONFIG_DCDBAS=y +CONFIG_DELL_SMBIOS=m +CONFIG_DELL_LAPTOP=m +CONFIG_DELL_WMI=m +CONFIG_DELL_WMI_AIO=m +# CONFIG_DELL_WMI_LED is not set +CONFIG_DELL_SMO8800=m +CONFIG_DELL_RBTN=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.scc new file mode 100644 index 0000000000..24f68cbf81 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-dell.scc @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Enable support for Dell laptop extra features" +define KFEATURE_COMPATIBILITY board + +include features/rfkill/rfkill.scc + +kconf hardware laptop-dell.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.cfg new file mode 100644 index 0000000000..fd7ed7ab70 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.cfg @@ -0,0 +1,4 @@ +CONFIG_HP_ACCEL=m +CONFIG_HP_WIRELESS=m +CONFIG_HP_WMI=m +# CONFIG_LG_LAPTOP is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.scc new file mode 100644 index 0000000000..21e0f01f05 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-hp.scc @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Enable support for HP laptop extra features" +define KFEATURE_COMPATIBILITY board + +kconf hardware laptop-hp.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.cfg new file mode 100644 index 0000000000..b56a7701d5 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.cfg @@ -0,0 +1 @@ +CONFIG_THINKPAD_ACPI=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.scc new file mode 100644 index 0000000000..103df7b0a7 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/laptop/laptop-thinkpad.scc @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Enable support for Thinkpad laptop extra features" +define KFEATURE_COMPATIBILITY board + +kconf hardware laptop-thinkpad.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.cfg new file mode 100644 index 0000000000..97b03b5448 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.cfg @@ -0,0 +1,16 @@ +CONFIG_XEN_MCE_LOG=y + +# +# Networking support +# +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y + +# +# Device Drivers +# +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set + +# CONFIG_ATA_SFF is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.scc new file mode 100644 index 0000000000..8a57e5a509 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-dom0.scc @@ -0,0 +1,24 @@ +define KMACHINE intel-x86-64 +define KTYPE dom0 +define KARCH x86_64 + +include ktypes/xen/dom0.scc + +# +# Generic intel/x86_64 +# +## intel-x86.scc includes too much support. +kconf hardware bsp/intel-x86/intel-x86-reduced.cfg +kconf hardware bsp/intel-x86/intel-x86-acpi.cfg +kconf hardware bsp/xen/intel-x86-64-smp.cfg + +# +# Include common PC support +# +kconf hardware bsp/common-pc/common-pc-drivers-reduced.cfg +kconf hardware bsp/common-pc/common-pc-gfx.cfg + +# +# Overrides for dom0, keep last. +# +kconf hardware bsp/xen/intel-x86-64-dom0.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.cfg new file mode 100644 index 0000000000..282d24c843 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.cfg @@ -0,0 +1,10 @@ +# +# Networking support +# +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y + +# +# General architecture-dependent options +# +# CONFIG_BLK_DEV_INITRD is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.scc new file mode 100644 index 0000000000..0399ec43f2 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-ndvm.scc @@ -0,0 +1,15 @@ +define KMACHINE intel-x86-64 +define KTYPE ndvm +define KARCH x86_64 + +include ktypes/xen/ndvm.scc + +# +# CPU configuration +# +kconf hardware bsp/xen/intel-x86-64-smp.cfg +kconf hardware bsp/common-xen-vm/common-xen-vm.cfg + +kconf hardware intel-x86-64-vm.cfg + +kconf hardware intel-x86-64-ndvm.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-smp.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-smp.cfg new file mode 100644 index 0000000000..bd7ff445ab --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-smp.cfg @@ -0,0 +1,10 @@ +# +# Processor type and features +# +CONFIG_SMP=y +CONFIG_NR_CPUS=8 + +# +# Binary Emulations +# +# CONFIG_IA32_EMULATION is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-stubdom.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-stubdom.cfg new file mode 100644 index 0000000000..e69de29bb2 diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-stubdom.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-stubdom.scc new file mode 100644 index 0000000000..9f15c4e918 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-stubdom.scc @@ -0,0 +1,15 @@ +define KMACHINE intel-x86-64 +define KTYPE stubdom +define KARCH x86_64 + +include ktypes/xen/stubdom.scc + +# +# CPU configuration +# +kconf hardware bsp/xen/intel-x86-64-smp.cfg +kconf hardware bsp/common-xen-vm/common-xen-vm.cfg + +kconf hardware intel-x86-64-vm.cfg + +kconf hardware intel-x86-64-stubdom.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.cfg new file mode 100644 index 0000000000..76ad70bd3b --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.cfg @@ -0,0 +1,9 @@ +# +# General architecture-dependent options +# +# CONFIG_BLK_DEV_INITRD is not set + +# +# Device drivers +# +# CONFIG_ATA_SFF is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.scc new file mode 100644 index 0000000000..dac8cd7a30 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-uivm.scc @@ -0,0 +1,15 @@ +define KMACHINE intel-x86-64 +define KTYPE uivm +define KARCH x86_64 + +include ktypes/xen/uivm.scc + +# +# CPU configuration +# +kconf hardware bsp/xen/intel-x86-64-smp.cfg +kconf hardware bsp/common-xen-vm/common-xen-vm.cfg + +kconf hardware intel-x86-64-vm.cfg + +kconf hardware intel-x86-64-uivm.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-vm.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-vm.cfg new file mode 100644 index 0000000000..be4d8232a4 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/xen/intel-x86-64-vm.cfg @@ -0,0 +1,10 @@ +# +# Processor type and features +# +# CONFIG_X86_EXTENDED_PLATFORM is not set +# CONFIG_X86_MCE is not set + +# +# Device drivers +# +# CONFIG_X86_PLATFORM_DEVICES is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.cfg b/recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.cfg new file mode 100644 index 0000000000..397ec34147 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.cfg @@ -0,0 +1,6 @@ +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.scc b/recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.scc new file mode 100644 index 0000000000..7a4e7d2156 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/initrd-gz.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable initrd gzip compression scheme" +define KFEATURE_COMPATIBILITY all + +kconf non-hardware initrd-gz.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.cfg b/recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.cfg new file mode 100644 index 0000000000..97be880cc3 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.cfg @@ -0,0 +1,9 @@ +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y + +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_SHA256=y + +CONFIG_CRYPTO_XTS=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.scc b/recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.scc new file mode 100644 index 0000000000..b0c68a961f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/luks-lvm.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable multi-device driver and crypto" +define KFEATURE_COMPATIBILITY all + +kconf non-hardware luks-lvm.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.cfg b/recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.cfg new file mode 100644 index 0000000000..733fc1181f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.cfg @@ -0,0 +1,36 @@ +# +# General architecture-dependent options +# +# CONFIG_KPROBES is not set + +# +# Networking +# +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_PACKET=y +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_IPV6 is not set + +# +# File systems +# +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Cryptographic API +# +# CONFIG_CRYPTO_HW is not set + +# +# Kernel hacking +# +# CONFIG_UPROBE_EVENTS is not set +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.scc b/recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.scc new file mode 100644 index 0000000000..97e2c8fd6c --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/openxt-common.scc @@ -0,0 +1,21 @@ +define KFEATURE_DESCRIPTION "Standard OpenXT service VMs configuration" +define KFEATURE_COMPATIBILITY all + +# +# Force module signing +# +include features/module-signing/signing.scc +include features/module-signing/force-signing.scc + +# +# Security kernel configurations. +# +include features/security/security.scc + +# +# File-systems +# +include cfg/fs/ext3.scc +include cfg/fs/ext4.scc + +kconf non-hardware openxt-common.cfg From 7f0f0559c7e8ea4af18ba5c7064d0b33e664c98b Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 17:44:46 -0500 Subject: [PATCH 06/15] linux: linux-yocto based OpenXT kernel recipes Add recipes to use linux-yocto kernel sources and yocto-kernel-cache configuration fragments for each OpenXT kernel configuration. Signed-off-by: Eric Chanudet --- .../features/netfilter/netfilter-physdev.cfg | 1 + .../features/netfilter/netfilter-physdev.scc | 5 ++ .../linux/linux-yocto-openxt-5.4.inc | 30 ++++++++ .../linux/linux-yocto-openxt-dom0_5.4.bb | 68 +++++++++++++++++++ .../linux/linux-yocto-openxt-ndvm_5.4.bb | 23 +++++++ .../linux/linux-yocto-openxt-stubdom_5.4.bb | 19 ++++++ .../linux/linux-yocto-openxt-uivm_5.4.bb | 20 ++++++ 7 files changed, 166 insertions(+) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.scc create mode 100644 recipes-kernel/linux/linux-yocto-openxt-5.4.inc create mode 100644 recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb create mode 100644 recipes-kernel/linux/linux-yocto-openxt-ndvm_5.4.bb create mode 100644 recipes-kernel/linux/linux-yocto-openxt-stubdom_5.4.bb create mode 100644 recipes-kernel/linux/linux-yocto-openxt-uivm_5.4.bb diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.cfg b/recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.cfg new file mode 100644 index 0000000000..756371f03a --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.cfg @@ -0,0 +1 @@ +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.scc b/recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.scc new file mode 100644 index 0000000000..68d98ae9bb --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/features/netfilter/netfilter-physdev.scc @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Enable netfilter physdev packet matching module." +define KFEATURE_COMPATIBILITY arch + +kconf non-hardware netfilter-physdev.cfg diff --git a/recipes-kernel/linux/linux-yocto-openxt-5.4.inc b/recipes-kernel/linux/linux-yocto-openxt-5.4.inc new file mode 100644 index 0000000000..bdc2dac9fb --- /dev/null +++ b/recipes-kernel/linux/linux-yocto-openxt-5.4.inc @@ -0,0 +1,30 @@ +KBRANCH ?= "v5.4/standard/base" + +require recipes-kernel/linux/linux-yocto.inc + +SRC_URI = " \ + git://git.yoctoproject.org/linux-yocto.git;name=machine;branch=${KBRANCH}; \ + git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.4;destsuffix=${KMETA} \ +" +SRC_URI_append += " \ + file://openxt-kmeta;type=kmeta;destsuffix=openxt-kmeta \ +" + +SRCREV_machine = "v5.4.75" +SRCREV_meta = "8d0ed83a864cc91eef4d2abbc90f13d4ecd1c213" + +LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814" +LINUX_VERSION ?= "5.4.75" + +inherit kernel-module-signing + +DEPENDS += " \ + ${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)} \ + openssl-native \ + util-linux-native \ +" + +PV = "${LINUX_VERSION}+git${SRCPV}" + +KMETA = "kernel-data" +KCONF_BSP_AUDIT_LEVEL = "2" diff --git a/recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb b/recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb new file mode 100644 index 0000000000..0659d36a16 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb @@ -0,0 +1,68 @@ +COMPATIBLE_MACHINE = "openxt-dom0" + +KMACHINE = "intel-x86-64" +LINUX_KERNEL_TYPE = "dom0" + +KERNEL_FEATURES += " \ + \ + features/rfkill/rfkill.scc \ + \ + features/mmc/mmc-sdhci.scc \ + \ + features/scsi/disk.scc \ + features/scsi/cdrom.scc \ + \ + features/input/input.scc \ + \ + cfg/vesafb.scc \ + cfg/usb-mass-storage.scc \ + cfg/efi-ext.scc \ + \ + features/power/intel.scc \ + \ + features/i915/i915.scc \ + features/drm-gma500/drm-gma500.scc \ + features/sound/snd_hda_intel.scc \ + \ + features/tpm/tpm.scc \ + \ + features/xen/xen-net-fe.scc \ + features/xen/xen-balloon.scc \ + features/xen/xen-blk-be.scc \ + features/xen/xen-pci-be.scc \ + \ + cgl/features/selinux/selinux.scc \ + \ + bsp/laptop/laptop-dell.scc \ + bsp/laptop/laptop-hp.scc \ + bsp/laptop/laptop-thinkpad.scc \ + \ + bsp/common-pc/common-pc-hid.scc \ + \ + bsp/gpu/nouveau.scc \ + bsp/gpu/radeon.scc \ + \ + features/usb/touchscreen-composite.scc \ + features/usb/ehci-hcd.scc \ + features/usb/uhci-hcd.scc \ + features/usb/ohci-hcd.scc \ + features/usb/xhci-hcd.scc \ + \ + cfg/openxt-common.scc \ + cfg/luks-lvm.cfg \ + cfg/initrd-gz.scc \ + \ + patches/backports/backports.scc \ + patches/blktap2/blktap2.scc \ + patches/openxt-input-quirks/openxt-input-quirks.scc \ + patches/openxt-pci-quirks/openxt-pci-quirks.scc \ + patches/openxt-serial-quirks/openxt-serial-quirks.scc \ + patches/openxt-service-vms/openxt-service-vms.scc \ + patches/openxt-tpm/openxt-tpm.scc \ + patches/openxt-usbback/openxt-usbback.scc \ + patches/openxt-video-quirks/openxt-video-quirks.scc \ + patches/xen-txt-evtlog/xen-txt-evtlog.scc \ + patches/xsa-155/xsa-155.scc \ +" + +require linux-yocto-openxt-5.4.inc diff --git a/recipes-kernel/linux/linux-yocto-openxt-ndvm_5.4.bb b/recipes-kernel/linux/linux-yocto-openxt-ndvm_5.4.bb new file mode 100644 index 0000000000..dada160d67 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto-openxt-ndvm_5.4.bb @@ -0,0 +1,23 @@ +COMPATIBLE_MACHINE = "openxt-ndvm" + +KMACHINE = "intel-x86-64" +LINUX_KERNEL_TYPE = "ndvm" + +KERNEL_FEATURES += " \ + cgl/features/selinux/selinux.scc \ + features/netfilter/netfilter.scc \ + features/netfilter/netfilter-physdev.scc \ + \ + cfg/openxt-common.scc \ + \ + bsp/common-pc/common-pc-eth-extended.scc \ + bsp/common-pc/common-pc-wifi-extended.scc \ + \ + patches/backports/backports.scc \ + patches/openxt-service-vms/openxt-service-vms.scc \ + patches/openxt-bridge-quirks/openxt-bridge-quirks.scc \ + patches/openxt-vwif/openxt-vwif.scc \ + patches/xsa-155/xsa-155.scc \ +" + +require linux-yocto-openxt-5.4.inc diff --git a/recipes-kernel/linux/linux-yocto-openxt-stubdom_5.4.bb b/recipes-kernel/linux/linux-yocto-openxt-stubdom_5.4.bb new file mode 100644 index 0000000000..efa92a131c --- /dev/null +++ b/recipes-kernel/linux/linux-yocto-openxt-stubdom_5.4.bb @@ -0,0 +1,19 @@ +COMPATIBLE_MACHINE = "openxt-stubdom" + +KMACHINE = "intel-x86-64" +LINUX_KERNEL_TYPE = "stubdom" + +KERNEL_FEATURES += " \ + features/xen/xen-blk-fe.scc \ + features/xen/xen-net-fe.scc \ + features/xen/xen-pci-fe.scc \ + \ + cfg/openxt-common.scc \ + cfg/initrd-gz.scc \ + \ + patches/backports/backports.scc \ + patches/openxt-service-vms/openxt-service-vms.scc \ + patches/xsa-155/xsa-155.scc \ +" + +require linux-yocto-openxt-5.4.inc diff --git a/recipes-kernel/linux/linux-yocto-openxt-uivm_5.4.bb b/recipes-kernel/linux/linux-yocto-openxt-uivm_5.4.bb new file mode 100644 index 0000000000..46dc1083b6 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto-openxt-uivm_5.4.bb @@ -0,0 +1,20 @@ +COMPATIBLE_MACHINE = "openxt-uivm" + +KMACHINE = "intel-x86-64" +LINUX_KERNEL_TYPE = "uivm" + +KERNEL_FEATURES += " \ + features/xen/xen-blk-fe.scc \ + features/xen/xen-net-fe.scc \ + features/xen/xen-vkbd-fe.scc \ + features/xen/xen-vfb-fe.scc \ + \ + cfg/openxt-common.scc \ + \ + patches/backports/backports.scc \ + patches/openxt-pv-video-quirks/openxt-pv-video-quirks.scc \ + patches/openxt-service-vms/openxt-service-vms.scc \ + patches/xsa-155/xsa-155.scc \ +" + +require linux-yocto-openxt-5.4.inc From 464efa73ac359d61f35ee659f0dda6fa4ccc26fc Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 17:51:04 -0500 Subject: [PATCH 07/15] kmeta/linux: linux-yocto installer recipe The live installer for OpenXT should handle input/output hardware handled by dom0, ndvm and potentially other service VMs, but does not require Xen support. Add a livecd.scc ktype and BSP to compose a new configuration, intel-x86-64-standard provided by yocto-kernel-cache has a lot more feature than what dom0 and the service VMs will allow to handle. To support the BIOS legacy installation path, livecd-xen.scc is provided. This is because the legacy installer loads Xen and a dom0, but does not use or start any VM or any Xen tool. It also makes it easier to review compatibility between the installer and OpenXT. Signed-off-by: Eric Chanudet --- .../bsp/livecd/intel-x86-64-livecd-xen.scc | 19 ++++++++ .../bsp/livecd/intel-x86-64-livecd.scc | 19 ++++++++ .../files/openxt-kmeta/cfg/livecd-fs.cfg | 3 ++ .../files/openxt-kmeta/cfg/livecd-fs.scc | 4 ++ .../openxt-kmeta/ktypes/livecd/livecd-xen.cfg | 42 +++++++++++++++++ .../openxt-kmeta/ktypes/livecd/livecd-xen.scc | 6 +++ .../openxt-kmeta/ktypes/livecd/livecd.cfg | 42 +++++++++++++++++ .../openxt-kmeta/ktypes/livecd/livecd.scc | 27 +++++++++++ .../linux/linux-yocto-openxt-5.4.inc | 6 +-- .../linux/linux-yocto-openxt-installer_5.4.bb | 47 +++++++++++++++++++ 10 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd-xen.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.scc create mode 100644 recipes-kernel/linux/linux-yocto-openxt-installer_5.4.bb diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd-xen.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd-xen.scc new file mode 100644 index 0000000000..9e3df93cdf --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd-xen.scc @@ -0,0 +1,19 @@ +define KMACHINE intel-x86-64 +define KTYPE livecd-xen +define KARCH x86_64 + +include ktypes/livecd/livecd-xen.scc + +# +# Generic intel/x86_64 +# +## intel-x86.scc includes too much support. +kconf hardware bsp/intel-x86/intel-x86-reduced.cfg +kconf hardware bsp/intel-x86/intel-x86-acpi.cfg +kconf hardware bsp/xen/intel-x86-64-smp.cfg + +# +# Include common PC support +# +kconf hardware bsp/common-pc/common-pc-drivers-reduced.cfg +kconf hardware bsp/common-pc/common-pc-gfx.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd.scc new file mode 100644 index 0000000000..4aee71754e --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/livecd/intel-x86-64-livecd.scc @@ -0,0 +1,19 @@ +define KMACHINE intel-x86-64 +define KTYPE livecd +define KARCH x86_64 + +include ktypes/livecd/livecd.scc + +# +# Generic intel/x86_64 +# +## intel-x86.scc includes too much support. +kconf hardware bsp/intel-x86/intel-x86-reduced.cfg +kconf hardware bsp/intel-x86/intel-x86-acpi.cfg +kconf hardware bsp/xen/intel-x86-64-smp.cfg + +# +# Include common PC support +# +kconf hardware bsp/common-pc/common-pc-drivers-reduced.cfg +kconf hardware bsp/common-pc/common-pc-gfx.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.cfg b/recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.cfg new file mode 100644 index 0000000000..9abbf064b1 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.cfg @@ -0,0 +1,3 @@ +CONFIG_ISO9660_FS=m +CONFIG_ZISOFS=y +CONFIG_JOLIET=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.scc b/recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.scc new file mode 100644 index 0000000000..9d6c5d2fec --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/cfg/livecd-fs.scc @@ -0,0 +1,4 @@ +define KFEATURE_DESCRIPTION "Enable live CD file-system support" +define KFEATURE_COMPATIBILITY all + +kconf non-hardware livecd-fs.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.cfg new file mode 100644 index 0000000000..7a6fcf605d --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.cfg @@ -0,0 +1,42 @@ +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y + +# +# General architecture-dependent options +# +# CONFIG_VIRTUALIZATION is not set + +# +# Security options +# +CONFIG_SECURITY=y + +# +# Networking support +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set + +# +# Device Drivers +# +# CONFIG_VIRTIO_MENU is not set + +CONFIG_BLK_DEV_LOOP=y + +# CONFIG_IOMMU_SUPPORT is not set + +# CONFIG_LEGACY_PTYS is not set + +# +# Processor type and features +# +# CONFIG_KVM_GUEST is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.scc new file mode 100644 index 0000000000..e667c8984f --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd-xen.scc @@ -0,0 +1,6 @@ +define KERNEL_VERSION 5.4 +branch v5.4 + +force kconf non-hardware livecd.cfg + +include ktypes/xen/dom0.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.cfg b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.cfg new file mode 100644 index 0000000000..7a6fcf605d --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.cfg @@ -0,0 +1,42 @@ +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y + +# +# General architecture-dependent options +# +# CONFIG_VIRTUALIZATION is not set + +# +# Security options +# +CONFIG_SECURITY=y + +# +# Networking support +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set + +# +# Device Drivers +# +# CONFIG_VIRTIO_MENU is not set + +CONFIG_BLK_DEV_LOOP=y + +# CONFIG_IOMMU_SUPPORT is not set + +# CONFIG_LEGACY_PTYS is not set + +# +# Processor type and features +# +# CONFIG_KVM_GUEST is not set diff --git a/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.scc b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.scc new file mode 100644 index 0000000000..a80105c431 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/ktypes/livecd/livecd.scc @@ -0,0 +1,27 @@ +define KERNEL_VERSION 5.4 +branch v5.4 + +force kconf non-hardware livecd.cfg + +include features/lttng/lttng.scc + +include features/blktrace/blktrace.scc + +include features/utrace/utrace.scc + +include features/seccomp/seccomp.scc + +include features/ftrace/ftrace.scc + +# Initramfs gen_initramfs_list.sh hook +include features/initramfs/initramfs.scc + +include features/tmpfs/tmpfs-posix-acl.scc + +include features/edac/edac.scc + +# individual cfg block section +include cfg/fs/devtmpfs.scc +include cfg/fs/debugfs.scc + +include cfg/systemd.scc diff --git a/recipes-kernel/linux/linux-yocto-openxt-5.4.inc b/recipes-kernel/linux/linux-yocto-openxt-5.4.inc index bdc2dac9fb..cb5f3e9a39 100644 --- a/recipes-kernel/linux/linux-yocto-openxt-5.4.inc +++ b/recipes-kernel/linux/linux-yocto-openxt-5.4.inc @@ -10,11 +10,11 @@ SRC_URI_append += " \ file://openxt-kmeta;type=kmeta;destsuffix=openxt-kmeta \ " -SRCREV_machine = "v5.4.75" -SRCREV_meta = "8d0ed83a864cc91eef4d2abbc90f13d4ecd1c213" +SRCREV_machine = "v5.4.106" +SRCREV_meta = "6144556fdee152870d8e792d41948ddcf9a684f1" LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814" -LINUX_VERSION ?= "5.4.75" +LINUX_VERSION ?= "5.4.106" inherit kernel-module-signing diff --git a/recipes-kernel/linux/linux-yocto-openxt-installer_5.4.bb b/recipes-kernel/linux/linux-yocto-openxt-installer_5.4.bb new file mode 100644 index 0000000000..c1a478d22e --- /dev/null +++ b/recipes-kernel/linux/linux-yocto-openxt-installer_5.4.bb @@ -0,0 +1,47 @@ +COMPATIBLE_MACHINE = "openxt-live-installer" + +KMACHINE = "intel-x86-64" +LINUX_KERNEL_TYPE = "livecd-xen" + +KERNEL_FEATURES += " \ + cfg/vesafb.scc \ + cfg/usb-mass-storage.scc \ + cfg/efi-ext.scc \ + \ + features/power/intel.scc \ + \ + features/i915/i915.scc \ + features/drm-gma500/drm-gma500.scc \ + features/sound/snd_hda_intel.scc \ + \ + features/tpm/tpm.scc \ + \ + bsp/laptop/laptop-dell.scc \ + bsp/laptop/laptop-hp.scc \ + bsp/laptop/laptop-thinkpad.scc \ + \ + bsp/common-pc/common-pc-hid.scc \ + features/usb/touchscreen-composite.scc \ + \ + bsp/gpu/nouveau.scc \ + bsp/gpu/radeon.scc \ + \ + features/usb/ehci-hcd.scc \ + features/usb/uhci-hcd.scc \ + features/usb/ohci-hcd.scc \ + features/usb/xhci-hcd.scc \ + \ + bsp/common-pc/common-pc-eth-extended.scc \ + bsp/common-pc/common-pc-wifi-extended.scc \ + \ + cfg/openxt-common.scc \ + cfg/luks-lvm.cfg \ + cfg/initrd-gz.scc \ + cfg/livecd-fs.scc \ + \ + patches/backports/backports.scc \ + patches/openxt-input-quirks/openxt-input-quirks.scc \ + patches/openxt-tpm/openxt-tpm.scc \ +" + +require linux-yocto-openxt-5.4.inc From 8b32043d94fa605eb856ed5499bb2c3416a58c02 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 9 Dec 2020 17:56:01 -0500 Subject: [PATCH 08/15] conf: linux-yocto machine/images PREFERED_PROVIDER_virtual/kernel should be defined at the MACHINE level given each MACHINE has its own configuration. It is also hinted in the documentation: https://www.yoctoproject.org/docs/latest/bsp-guide/bsp-guide.html#bsp-filelayout-machine MACHINE=openxt-{dom0,uivm,ndvm,stubdom,live-installer} replace the former xenclient-* equivalent and set virtual/kernel preference. DISTRO=openxt-tip is openxt-main with no preference on the kernel. meta-virtualization has an annoying linux-%.bbappend, mask it. Remove MACHINE specific restrictions on initrdscripts. Signed-off-by: Eric Chanudet --- conf/distro/openxt-tip.conf | 120 ++++++++++++++++++ conf/layer.conf | 1 + conf/machine/openxt-common.conf | 7 + conf/machine/openxt-dom0.conf | 31 +++++ conf/machine/openxt-live-installer.conf | 23 ++++ conf/machine/openxt-ndvm.conf | 26 ++++ conf/machine/openxt-stubdom.conf | 26 ++++ conf/machine/openxt-uivm.conf | 24 ++++ recipes-core/images/openxt-dom0-image.bb | 120 ++++++++++++++++++ .../images/openxt-dom0-initramfs-image.bb | 40 ++++++ .../images/openxt-live-installer-image.bb | 102 +++++++++++++++ recipes-core/images/openxt-ndvm-image.bb | 88 +++++++++++++ .../images/openxt-stubdom-initramfs-image.bb | 45 +++++++ recipes-core/images/openxt-uivm-image.bb | 115 +++++++++++++++++ .../initrdscripts/initramfs-stubdomain_1.0.bb | 2 +- 15 files changed, 769 insertions(+), 1 deletion(-) create mode 100644 conf/distro/openxt-tip.conf create mode 100644 conf/machine/openxt-common.conf create mode 100644 conf/machine/openxt-dom0.conf create mode 100644 conf/machine/openxt-live-installer.conf create mode 100644 conf/machine/openxt-ndvm.conf create mode 100644 conf/machine/openxt-stubdom.conf create mode 100644 conf/machine/openxt-uivm.conf create mode 100644 recipes-core/images/openxt-dom0-image.bb create mode 100644 recipes-core/images/openxt-dom0-initramfs-image.bb create mode 100644 recipes-core/images/openxt-live-installer-image.bb create mode 100644 recipes-core/images/openxt-ndvm-image.bb create mode 100644 recipes-core/images/openxt-stubdom-initramfs-image.bb create mode 100644 recipes-core/images/openxt-uivm-image.bb diff --git a/conf/distro/openxt-tip.conf b/conf/distro/openxt-tip.conf new file mode 100644 index 0000000000..ccd96feb4f --- /dev/null +++ b/conf/distro/openxt-tip.conf @@ -0,0 +1,120 @@ +# +# This is how bitbake will establish its configuration: +# +# require conf/abi_version.conf +# include conf/site.conf +# include conf/auto.conf +# include conf/local.conf +# include conf/build/${BUILD_SYS}.conf +# include conf/target/${TARGET_SYS}.conf +# include conf/machine/${MACHINE}.conf +# include conf/machine-sdk/${SDKMACHINE}.conf +# include conf/distro/${DISTRO}.conf +# include conf/distro/defaultsetup.conf +# include conf/documentation.conf +# include conf/licenses.conf +# require conf/sanity.conf +# + +# openembedded-core sets a default list of DISTRO_FEATURES that do not match +# OpenXT's machine needs. +# See: openembedded-core/meta/conf/distro/include/default-distrovars.inc +# Another way would be hard setting DISTRO_FEATURES. +# Another way would be to redefine DISTRO_FEATURES_DEFAULT. +# Down the road this should probably be a machine config thing so it is possible +# to have images that do not include selinux +DISTRO_FEATURES_remove = "zeroconf nfs" +DISTRO_FEATURES_append += "pam selinux multiarch virtualization polkit opengl" + +# Dojosdk preferred version. +PREFERRED_VERSION_dojosdk-native ?= "1.7.12" +# ${MACHINE}.conf is overriden by ${DISTRO}.conf +# xenmgr_data and sync-wui (uivm and syncui machines) apparently depends on +# different versions, so preserve that. +PREFERRED_VERSION_dojosdk-native_xenclient-syncui ?= "1.8.1" + +# Prefer openssl to libressl. +PREFERRED_PROVIDER_openssl = "openssl" +PREFERRED_PROVIDER_openssl-native = "openssl-native" +PREFERRED_PROVIDER_openssl-conf = "openssl-conf" +PREFERRED_PROVIDER_nativesdk-openssl = "nativesdk-openssl" +PREFERRED_PROVIDER_nativesdk-openssl-conf = "nativesdk-openssl-conf" +# Prefer libcrypto and libssl to alternatives. +PREFERRED_PROVIDER_libcrypto = "libcrypto" +PREFERRED_PROVIDER_libssl = "libssl" + +# Prefer libx11 to libx11-diet. +PREFERRED_PROVIDER_virtual/libx11 = "libx11" + +# Force specific package versions +PREFERRED_VERSION_networkmanager = "1.18.4" +PREFERRED_VERSION_network-manager-applet = "1.8.22" + +PREFERRED_PROVIDER_iasl = "acpica" +PREFERRED_PROVIDER_iasl-native = "${PREFERRED_PROVIDER_iasl}-native" + +PREFERRED_VERSION_refpolicy-mcs = "2.20190201" + +# Select our preferred providers +PREFERRED_PROVIDER_sysvinit-inittab = "sysvinit" +PREFERRED_PROVIDER_virtual/java-initial = "cacao-initial" +PREFERRED_PROVIDER_virtual/java-initial-native = "cacao-initial-native" +PREFERRED_PROVIDER_virtual/java-native = "jamvm-native" +PREFERRED_PROVIDER_virtual/javac-native = "ecj-bootstrap-native" +PREFERRED_PROVIDER_jpeg-native = "jpeg-native" + +# Set the preferred version to C xenstored from xen-tools +PREFERRED_PROVIDER_virtual/xenstored = "xen-tools" +PREFERRED_RPROVIDER_virtual/xenstored = "xen-tools-xenstored" +# Force exclusion of the OCaml xenstored since the above preferences +# are not sufficient to override that as the default selection: +PACKAGE_EXCLUDE += " xen-ocaml-libs-xenstored" + +# The C and OCaml xenstored packages can be installed together +# and this whitelisting is necessary to allow both to be built +MULTI_PROVIDER_WHITELIST += " virtual/xenstored" + +# Default to rsyslog recipe which RPROVIDES rsyslog-conf +# Dom0 and Installer install rsyslog-conf-dom0 instead. +PREFERRED_RPROVIDER_rsyslog-conf = "rsyslog" + +# Default to lvm2 recipe which RPROVIDES lvm2-conf +# Initramfs and installer install lvm2-conf-initramfs and lvm2-conf-installer. +PREFERRED_RPROVIDER_lvm2-conf = "lvm2" + +# Enable tui for GDB by default. This makes it easier to debug small things +# using the gdb ipk. +PACKAGECONFIG_append_pn-gdb = " tui" + +# rpcgen staging and install paths. +require xc-rpcgen.inc + +FILESYSTEM_PERMS_TABLES = "files/openxt-fs-perms.txt" + +# Declare the MACHINE type and KERNEL image name for stubdomains +STUBDOMAIN_MACHINE ?= "openxt-stubdom" +STUBDOMAIN_KERNEL ?= "bzImage" + +# Set our root home +ROOT_HOME = "/root" + +# multilib is required for building Xen's hvmloader, which needs +# materials from a 32-bit libc +require conf/multilib.conf +MULTILIBS = "multilib:lib32" +DEFAULTTUNE_virtclass-multilib-lib32 = "x86" + +# multilib directory settings : 64-bit in /lib, 32-bit in /lib32 +# as required by the OpenXT haskell toolchain +BASE_LIB_tune-core2-32 = "lib32" +BASE_LIB_tune-core2-32 = "lib32" +BASE_LIB_tune-i586 = "lib32" +BASE_LIB_tune-i686 = "lib32" +BASE_LIB_tune-x86 = "lib32" + +BASE_LIB_tune-x86-64 = "lib" +BASE_LIB_tune-x86-64 = "lib" +BASE_LIB_tune-core2-64 = "lib" + +BASE_LIB_tune-core2-64-x32 = "libx32" +BASE_LIB_tune-x86-64-x32 = "libx32" diff --git a/conf/layer.conf b/conf/layer.conf index 4e9fe63670..1a9b0e9676 100644 --- a/conf/layer.conf +++ b/conf/layer.conf @@ -10,6 +10,7 @@ BBMASK = " \ meta-virtualization/recipes-extended/images/xen-guest-image-minimal.bb \ meta-virtualization/recipes-devtools/go/go-build_git.bb \ meta-virtualization/recipes-core/runx/runx_git.bb \ + meta-virtualization/recipes-kernel/linux/linux-%.bbappend \ " # We have a recipes directory, add to BBFILES diff --git a/conf/machine/openxt-common.conf b/conf/machine/openxt-common.conf new file mode 100644 index 0000000000..1ed420ae09 --- /dev/null +++ b/conf/machine/openxt-common.conf @@ -0,0 +1,7 @@ +require conf/machine/include/tune-core2.inc + +DEFAULTTUNE = "core2-64" + +KERNEL_IMAGETYPE = "bzImage" + +MACHINE_FEATURES_BACKFILL_CONSIDERED += "rtc" diff --git a/conf/machine/openxt-dom0.conf b/conf/machine/openxt-dom0.conf new file mode 100644 index 0000000000..2df54b2c9a --- /dev/null +++ b/conf/machine/openxt-dom0.conf @@ -0,0 +1,31 @@ +#@TYPE: Machine +#@NAME: xenclient-dom0 +#@DESCRIPTION: Machine configuration for OpenXT dom0. + +require openxt-common.conf + +MACHINE_FEATURES = " \ + acpi \ + ethernet \ + ext2 \ + keyboard \ + pci \ + rtc \ + screen \ + usbhost \ + x86 \ +" + +KERNEL_MODULE_AUTOLOAD += " \ + xen-acpi-processor \ + xen-gntalloc \ + xen-gntdev \ + xen-pciback \ + xen-netfront \ +" + +# Use OpenXT Linux patched kernel. +PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-openxt-dom0" + +# Use ivc2/ivcdaemon +PREFERRED_PROVIDER_virtual/libivc = "libivc2" diff --git a/conf/machine/openxt-live-installer.conf b/conf/machine/openxt-live-installer.conf new file mode 100644 index 0000000000..08cb908b5e --- /dev/null +++ b/conf/machine/openxt-live-installer.conf @@ -0,0 +1,23 @@ +# Copyright (C) 2010 Citrix Systems +# Copyright (C) 2018 AIS +# Released under the MIT license (see packages/COPYING) +#@TYPE: Machine +#@NAME: openxt-installer +#@DESCRIPTION: Machine configuration for OpenXT installer + +require xenclient-common.conf + +MACHINE_FEATURES = " \ + acpi \ + ethernet \ + ext2 \ + keyboard \ + pci \ + rtc \ + screen \ + usbhost \ + x86 \ +" + +# Use OpenXT Linux patched kernel. +PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-openxt-installer" diff --git a/conf/machine/openxt-ndvm.conf b/conf/machine/openxt-ndvm.conf new file mode 100644 index 0000000000..376383c775 --- /dev/null +++ b/conf/machine/openxt-ndvm.conf @@ -0,0 +1,26 @@ +#@TYPE: Machine +#@NAME: openxt-ndvm +#@DESCRIPTION: Machine configuration for OpenXT NDVM. + +require openxt-common.conf + +MACHINE_FEATURES = " \ + ethernet \ + ext2 \ + pci \ + serial \ + x86 \ +" + +APPEND = "root=/dev/xvda2 ro console=hvc0 iommu=soft" + +USE_VT = "0" + +KERNEL_MODULE_AUTOLOAD += " \ + xen-gntalloc \ + xen-gntdev \ + xen-netback \ +" + +# Use OpenXT Linux patched kernel. +PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-openxt-ndvm" diff --git a/conf/machine/openxt-stubdom.conf b/conf/machine/openxt-stubdom.conf new file mode 100644 index 0000000000..64f69c97d9 --- /dev/null +++ b/conf/machine/openxt-stubdom.conf @@ -0,0 +1,26 @@ +#@TYPE: Machine +#@NAME: openxt-stubdom +#@DESCRIPTION: Machine configuration for OpenXT stub-domain. + +require openxt-common.conf + +MACHINE_FEATURES = " \ + ethernet \ + ext2 \ + pci \ + serial \ + x86 \ +" + +USE_VT = "0" + +KERNEL_MODULE_AUTOLOAD += " \ + xen-gntalloc \ + xen-gntdev \ +" + +# Use OpenXT Linux patched kernel. +PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-openxt-stubdom" + +# Use /dev/ivc. +PREFERRED_PROVIDER_virtual/libivc = "libivc" diff --git a/conf/machine/openxt-uivm.conf b/conf/machine/openxt-uivm.conf new file mode 100644 index 0000000000..fd04c8e308 --- /dev/null +++ b/conf/machine/openxt-uivm.conf @@ -0,0 +1,24 @@ +#@TYPE: Machine +#@NAME: openxt-uivm +#@DESCRIPTION: Machine configuration for OpenXT UIVM. + +require openxt-common.conf + +MACHINE_FEATURES = " \ + ethernet \ + ext2 \ + screen \ + serial \ + x86 \ +" + +USE_VT = "0" + +KERNEL_MODULE_AUTOLOAD += " \ + xen-gntalloc \ + xen-gntdev \ + openxtfb \ +" + +# Use OpenXT Linux patched kernel. +PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-openxt-uivm" diff --git a/recipes-core/images/openxt-dom0-image.bb b/recipes-core/images/openxt-dom0-image.bb new file mode 100644 index 0000000000..9f9969b148 --- /dev/null +++ b/recipes-core/images/openxt-dom0-image.bb @@ -0,0 +1,120 @@ +# XenClient dom0 image. + +LICENSE = "GPLv2 & MIT" +LIC_FILES_CHKSUM = " \ + file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 \ + file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ +" + +inherit openxt-selinux-image +inherit openxt-vm-common + +INITRD_VM = "openxt-dom0-initramfs-image" +INSTALL_VM_INITRD = "1" + +IMAGE_FEATURES += " \ + package-management \ + read-only-rootfs \ + root-bash-shell \ + wildcard-sshd-argo \ + allow-root-login \ +" +IMAGE_FSTYPES = "ext3.gz" +export IMAGE_BASENAME = "openxt-dom0-image" + +COMPATIBLE_MACHINE = "(openxt-dom0)" + + +# xserver-xorg should not live in dom0, but UIVM. +BAD_RECOMMENDATIONS += " \ + xserver-xorg \ + avahi-daemon \ + avahi-autoipd \ + ${@bb.utils.contains('IMAGE_FEATURES', 'web-certificates', '', 'ca-certificates', d)} \ + libivc \ +" + +IMAGE_INSTALL += "\ + initscripts \ + packagegroup-core-boot \ + packagegroup-base \ + packagegroup-xenclient-common \ + packagegroup-xenclient-dom0 \ + packagegroup-openxt-test \ + argo-module \ + txt-info-module \ + xenclient-preload-hs-libs \ + linux-firmware-i915 \ + devicemodel-stubdom \ + ${@bb.utils.contains('IMAGE_FEATURES', 'debug-tweaks', 'packagegroup-selinux-policycoreutils audit', '' ,d)} \ +" + +inherit xenclient-licences + +require xenclient-version.inc + +post_rootfs_shell_commands() { + mkdir -p ${IMAGE_ROOTFS}/config/etc + mv ${IMAGE_ROOTFS}/etc/passwd ${IMAGE_ROOTFS}/config/etc + mv ${IMAGE_ROOTFS}/etc/shadow ${IMAGE_ROOTFS}/config/etc + ln -s ../config/etc/passwd ${IMAGE_ROOTFS}/etc/passwd + ln -s ../config/etc/shadow ${IMAGE_ROOTFS}/etc/shadow + ln -s ../config/etc/.pwd.lock ${IMAGE_ROOTFS}/etc/.pwd.lock + + rm ${IMAGE_ROOTFS}/etc/hosts + ln -s /var/run/hosts ${IMAGE_ROOTFS}/etc/hosts + ln -s /var/volatile/etc/resolv.conf ${IMAGE_ROOTFS}/etc/resolv.conf + + echo 'kernel.printk_ratelimit = 0' >> ${IMAGE_ROOTFS}/etc/sysctl.conf + + # Create mountpoint for /mnt/secure + mkdir -p ${IMAGE_ROOTFS}/mnt/secure + + # Create mountpoint for /mnt/upgrade + mkdir -p ${IMAGE_ROOTFS}/mnt/upgrade + + # Create mountpoint for boot/system + mkdir -p ${IMAGE_ROOTFS}/boot/system + + # Create XL-related files and directories + mkdir -p ${IMAGE_ROOTFS}/var/lib/xen + mkdir -p ${IMAGE_ROOTFS}/etc/xen + touch ${IMAGE_ROOTFS}/etc/xen/xl.conf + + # Write coredumps in /var/cores + echo 'kernel.core_pattern = /var/cores/%e-%t.%p.core' >> ${IMAGE_ROOTFS}/etc/sysctl.conf +} +ROOTFS_POSTPROCESS_COMMAND += "post_rootfs_shell_commands; " + +# Get rid of unneeded initscripts +remove_initscripts() { + remove_initscript "rmnologin.sh" + remove_initscript "finish.sh" +} +ROOTFS_POSTPROCESS_COMMAND += "remove_initscripts; " + +# After ensuring that the correct number of xenstored daemon(s) are installed, +# enforce that the init script is active: +activate_xenstored_initscript() { + update-rc.d -r ${IMAGE_ROOTFS} xenstored defaults 05 +} +ROOTFS_POSTPROCESS_COMMAND += "activate_xenstored_initscript; " + +# Handle required configuration of the rootfs to store persistent files on +# encripted /config partition. +rw_config_partition() { + # If we are using openssh but want the persistent data to be stored in the + # encrypted config partition, replace or append SYSCONFDIR in + # /etc/default/ssh. + # This should only be done after read_only_rootfs_hook(s) have been done. + if [ -d ${IMAGE_ROOTFS}${sysconfdir}/ssh ]; then + sed -i -e '/^SYSCONFDIR=/{h;s/=.*/=\$\{SYSCONFDIR:-\/config\/etc\/ssh\}/};${x;/^$/{s//SYSCONFDIR=\$\{SYSCONFDIR:-\/config\/etc\/ssh\}/;H};x}' ${IMAGE_ROOTFS}${sysconfdir}/default/ssh + sed -i -e 's/HostKey .*\/ssh\/ssh_host_\(.*\)key/HostKey \/config\/etc\/ssh\/ssh_host_\1key/' ${IMAGE_ROOTFS}${sysconfdir}/ssh/sshd_config_readonly + echo "HostKey /config/etc/ssh/ssh_host_dsa_key" >> ${IMAGE_ROOTFS}${sysconfdir}/ssh/sshd_config + echo "HostKey /config/etc/ssh/ssh_host_rsa_key" >> ${IMAGE_ROOTFS}${sysconfdir}/ssh/sshd_config + echo "HostKey /config/etc/ssh/ssh_host_ecdsa_key" >> ${IMAGE_ROOTFS}${sysconfdir}/ssh/sshd_config + echo "HostKey /config/etc/ssh/ssh_host_ed25519_key" >> ${IMAGE_ROOTFS}${sysconfdir}/ssh/sshd_config + fi +} +ROOTFS_POSTPROCESS_COMMAND += "rw_config_partition; " +ROOTFS_POSTPROCESS_COMMAND += "start_tty_on_hvc0;" diff --git a/recipes-core/images/openxt-dom0-initramfs-image.bb b/recipes-core/images/openxt-dom0-initramfs-image.bb new file mode 100644 index 0000000000..60b1c2962f --- /dev/null +++ b/recipes-core/images/openxt-dom0-initramfs-image.bb @@ -0,0 +1,40 @@ +SUMMARY = "Initramfs image for OpenXT dom0" +DESCRIPTION = "Initramfs image containing the early boot components required to \ +bootsrap OpenXT dom0." +LICENSE = "GPLv2 & MIT" +LIC_FILES_CHKSUM = " \ + file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 \ + file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ +" +COMPATIBLE_MACHINE = "(openxt-dom0)" + +IMAGE_FSTYPES = "cpio.gz" +IMAGE_INSTALL = " \ + busybox \ + initramfs-module-functions \ + initramfs-module-lvm \ + initramfs-module-udev \ + initramfs-module-bootfs \ + initramfs-module-tpm \ + initramfs-module-tpm2 \ + initramfs-module-selinux \ +" +IMAGE_LINGUAS = "en-us" + +inherit image + +NO_RECOMMENDATIONS = "1" +BAD_RECOMMENDATIONS += " \ + ldconfig \ + busybox-syslog \ + busybox-udhcpc \ +" + +PACKAGE_REMOVE = " \ + kernel-image-* \ +" +post_rootfs_shell_commands() { + rm -f ${IMAGE_ROOTFS}/sbin/udhcpc; + rm -rvf ${IMAGE_ROOTFS}/usr/lib/opkg; +} +ROOTFS_POSTPROCESS_COMMAND += " post_rootfs_shell_commands; " diff --git a/recipes-core/images/openxt-live-installer-image.bb b/recipes-core/images/openxt-live-installer-image.bb new file mode 100644 index 0000000000..1d1ff6bb3d --- /dev/null +++ b/recipes-core/images/openxt-live-installer-image.bb @@ -0,0 +1,102 @@ +# Part 1 of the XenClient host installer. +# +# This is responsible for retrieving the XenClient repository and extracting +# and running part 2 of the host installer, which contains the logic to install +# or upgrade a specific version of XenClient. + +LICENSE = "GPLv2 & MIT" +LIC_FILES_CHKSUM = " \ + file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 \ + file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ +" + +PR = "r16" + +IMAGE_FSTYPES = "cpio.gz" +export IMAGE_BASENAME = "openxt-live-installer-image" + +COMPATIBLE_MACHINE = "(openxt-live-installer)" + +BAD_RECOMMENDATIONS += " \ + ${@bb.utils.contains('IMAGE_FEATURES', 'web-certificates', '', 'ca-certificates', d)} \ +" + +INITSCRIPT_REMOVE = " \ + blktap \ + sshd-argo \ +" + +IMAGE_FEATURES += " \ + empty-root-password \ + root-bash-shell \ +" + +IMAGE_INSTALL = "\ + initscripts \ + packagegroup-core-boot \ + packagegroup-base \ + packagegroup-xenclient-common \ + packagegroup-xenclient-installer \ + linux-firmware-iwlwifi \ + linux-firmware-bnx2 \ + linux-firmware-i915 \ + linux-firmware-nvidia \ + linux-firmware-radeon \ + libdrm-nouveau \ + libdrm-radeon \ +" +# The entire installer rootfs is passed as the initramfs. +# Inflate the maximum value to 512M to reflect that (original definition is +# 128M in bitbake.conf) +INITRAMFS_MAXSIZE = "524288" + +inherit openxt-image +inherit xenclient-licences + +require xenclient-version.inc + +post_rootfs_shell_commands() { + # Create /init symlink + ln -s sbin/init ${IMAGE_ROOTFS}/init; + + # Update /etc/inittab + sed -i '/^1:/d' ${IMAGE_ROOTFS}/etc/inittab; + { + echo '1:2345:once:/install/part1/autostart-main < /dev/tty1 > /dev/tty1'; + echo '2:2345:respawn:/usr/bin/tail -F /var/log/installer > /dev/tty2'; + echo '3:2345:respawn:/sbin/getty 38400 tty3'; + echo '4:2345:respawn:/usr/bin/tail -F /var/log/messages > /dev/tty4'; + echo '5:2345:respawn:/sbin/getty 38400 tty5'; + echo '6:2345:respawn:/sbin/getty 38400 tty6'; + echo '7:2345:respawn:/install/part1/autostart-status < /dev/tty7 > /dev/tty7'; + echo 'ca::ctrlaltdel:/sbin/reboot'; + echo 'S0:12345:respawn:/sbin/getty 115200 ttyS0'; + } >> ${IMAGE_ROOTFS}/etc/inittab; + + # Update /etc/network/interfaces + { + echo 'auto lo'; + echo 'iface lo inet loopback'; + } > ${IMAGE_ROOTFS}/etc/network/interfaces; + + # Password files are expected in /config + mkdir -p ${IMAGE_ROOTFS}/config/etc; + mv ${IMAGE_ROOTFS}/etc/shadow ${IMAGE_ROOTFS}/config/etc/shadow; + mv ${IMAGE_ROOTFS}/etc/passwd ${IMAGE_ROOTFS}/config/etc/passwd; + ln -s /config/etc/shadow ${IMAGE_ROOTFS}/etc/shadow; + ln -s /config/etc/passwd ${IMAGE_ROOTFS}/etc/passwd; + + # Create file to identify this as the host installer filesystem + touch ${IMAGE_ROOTFS}/etc/xenclient-host-installer; +} +ROOTFS_POSTPROCESS_COMMAND += "post_rootfs_shell_commands; " +ROOTFS_POSTPROCESS_COMMAND += "start_tty_on_hvc0; " + +# Install Xen in the installer image. +# This is a legacy procedure as the installer does not require Xen to run, +# presumably this was done so that users would know immediately before +# installing that Xen cannot be run on the hardware. +xen_install() { + cp -f ${IMAGE_ROOTFS}/boot/xen.gz ${DEPLOY_DIR_IMAGE}/ +} +IMAGE_POSTPROCESS_COMMAND += "xen_install; " diff --git a/recipes-core/images/openxt-ndvm-image.bb b/recipes-core/images/openxt-ndvm-image.bb new file mode 100644 index 0000000000..900291bbd1 --- /dev/null +++ b/recipes-core/images/openxt-ndvm-image.bb @@ -0,0 +1,88 @@ +# XenClient Network VM image. + +LICENSE = "GPLv2 & MIT" +LIC_FILES_CHKSUM = " \ + file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 \ + file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ +" + +inherit openxt-selinux-image + +IMAGE_FEATURES += " \ + package-management \ + read-only-rootfs \ + empty-root-password \ + root-bash-shell \ +" + +IMAGE_FSTYPES = "ext3.disk.vhd.gz" +export IMAGE_BASENAME = "openxt-ndvm-image" + +COMPATIBLE_MACHINE = "(openxt-ndvm)" + + +BAD_RECOMMENDATIONS += " \ + avahi-daemon \ + avahi-autoipd \ + ca-certificates \ +" +# List of packages that should not be installed +PACKAGE_REMOVE = " \ + hicolor-icon-theme \ +" + +IMAGE_FEATURES += "empty-root-password" + +INITSCRIPT_REMOVE = " \ + urandom \ + sshd \ +" + +IMAGE_INSTALL = " \ + ${ROOTFS_PKGMANAGE} \ + packagegroup-core-boot \ + packagegroup-base \ + packagegroup-xenclient-common \ + util-linux-mount \ + util-linux-umount \ + openssh \ + kernel-modules \ + libargo \ + libargo-bin \ + dbus \ + xenclient-dbusbouncer \ + networkmanager \ + linux-firmware-iwlwifi \ + linux-firmware-bnx2 \ + bridge-utils \ + iptables \ + xenclient-ndvm-tweaks \ + rsyslog \ + argo-module \ + xen-tools-libxenstore \ + xen-tools-xenstore \ + wget \ + ethtool \ + carrier-detect \ + xenclient-nws \ + modemmanager \ + ppp \ + iputils-ping \ + dbd-tools-vm \ + xen-vif-scripts-ndvm \ +" + +require xenclient-version.inc +inherit xenclient-licences + +post_rootfs_shell_commands() { + # Trick to resolve dom0 name with argo. + echo '1.0.0.0 dom0' >> ${IMAGE_ROOTFS}/etc/hosts; + + # enable ctrlaltdel reboot because PV driver uses ctrl+alt+del to interpret reboot issued via xenstore + echo 'ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now' >> ${IMAGE_ROOTFS}/etc/inittab; + + # NDVM doesn't have a /dev/tty1, disable the login shell on it + sed -i 's/[^#].*getty.*tty1$/#&/' ${IMAGE_ROOTFS}/etc/inittab ; +} +ROOTFS_POSTPROCESS_COMMAND += "post_rootfs_shell_commands; " diff --git a/recipes-core/images/openxt-stubdom-initramfs-image.bb b/recipes-core/images/openxt-stubdom-initramfs-image.bb new file mode 100644 index 0000000000..5073e6249f --- /dev/null +++ b/recipes-core/images/openxt-stubdom-initramfs-image.bb @@ -0,0 +1,45 @@ +# Stubdomain initramfs image. + +LICENSE = "GPLv2 & MIT" +LIC_FILES_CHKSUM = " \ + file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 \ + file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ +" + +IMAGE_FSTYPES = "cpio.gz" + +COMPATIBLE_MACHINE = "(openxt-stubdom)" + +BAD_RECOMMENDATIONS += " \ + libivc2 \ +" + +IMAGE_INSTALL = " \ + busybox \ + bridge-utils \ + initramfs-stubdomain \ + xen-tools-xenstore \ + qemu-dm-stubdom \ + argo-module \ + kernel-modules \ +" +IMAGE_LINGUAS = "" + +# List of packages removed at rootfs-postprocess. +# - Remove any kernel-image that the kernel-module-* packages may have pulled in. +# - Remove udev (use busybox-mdev instead, this is a simple initramfs). +# - Remove sysvinit (no need for init management). +PACKAGE_REMOVE = " \ + kernel-image-* \ + udev \ + sysvinit \ +" + +inherit openxt-image + +post_rootfs_shell_commands() { + rm -f ${IMAGE_ROOTFS}/sbin/udhcpc; + rm -f ${IMAGE_ROOTFS}/sbin/ldconfig; + rm -rvf ${IMAGE_ROOTFS}/usr/lib/opkg; +} +ROOTFS_POSTPROCESS_COMMAND += " post_rootfs_shell_commands; " diff --git a/recipes-core/images/openxt-uivm-image.bb b/recipes-core/images/openxt-uivm-image.bb new file mode 100644 index 0000000000..6fdad0a2e7 --- /dev/null +++ b/recipes-core/images/openxt-uivm-image.bb @@ -0,0 +1,115 @@ +# XenClient UIVM image + +LICENSE = "GPLv2 & MIT" +LIC_FILES_CHKSUM = " \ + file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6 \ + file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302 \ +" + +inherit openxt-image + +IMAGE_FEATURES += " \ + package-management \ + read-only-rootfs \ + empty-root-password \ + root-bash-shell \ +" +IMAGE_FSTYPES = "ext3.vhd.gz" +export IMAGE_BASENAME = "openxt-uivm-image" + +COMPATIBLE_MACHINE = "(openxt-uivm)" + + +BAD_RECOMMENDATIONS += " \ + avahi-daemon \ + avahi-autoipd \ +" + +INITSCRIPT_REMOVE = " \ + finish.sh \ + rmnologin.sh \ + sshd \ + urandom \ + networking \ +" + +# Specifies the list of locales to install into the image during the root +# filesystem construction process. +# http://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-IMAGE_LINGUAS +IMAGE_LINGUAS = " \ + en-us \ +" + +# Refine xserver packages installed by packagegroup-core-x11-xserver. +XSERVER = " \ + xserver-xorg \ + xf86-input-evdev \ + xf86-input-mouse \ + xf86-input-keyboard \ + xf86-video-openxtfb \ +" + +IMAGE_INSTALL += "\ + ${XSERVER} \ + packagegroup-xenclient-common \ + packagegroup-xenclient-xfce-minimal \ + openssh \ + packagegroup-base \ + kernel-modules \ + argo-module \ + libargo \ + libargo-bin \ + xinit \ + xprop \ + xrandr \ + surf \ + network-manager-applet \ + network-manager-applet-locale-de \ + network-manager-applet-locale-es \ + network-manager-applet-locale-fr \ + network-manager-applet-locale-ja \ + network-manager-applet-locale-zh-cn \ + gnome-keyring-locale-de \ + gnome-keyring-locale-es \ + gnome-keyring-locale-fr \ + gnome-keyring-locale-ja \ + gnome-keyring-locale-zh-cn \ + iso-codes-locale-de \ + iso-codes-locale-es \ + iso-codes-locale-fr \ + iso-codes-locale-ja \ + iso-codes-locale-zh-cn \ + xterm \ + gconf \ + xenclient-uivm-xsessionconfig \ + setxkbmap \ + libx11-locale \ + rsyslog \ + glibc-gconv-libjis \ + glibc-gconv-euc-jp \ + mobile-broadband-provider-info \ + ttf-dejavu-sans \ + ttf-dejavu-sans-mono \ + uim \ + uim-common \ + uim-gtk2.0 \ + anthy \ + matchbox-keyboard \ + matchbox-keyboard-im \ + kernel-module-openxtfb \ +" + +require xenclient-version.inc +inherit xenclient-licences + +post_rootfs_shell_commands() { + # Start WM right away. + echo 'x:5:respawn:/bin/su - root -c /usr/bin/startxfce4' >> ${IMAGE_ROOTFS}/etc/inittab + + # enable ctrlaltdel reboot because PV driver uses ctrl+alt+del to interpret reboot issued via xenstore + echo 'ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now' >> ${IMAGE_ROOTFS}/etc/inittab + + # Trick to resolve dom0 name with argo. + echo '1.0.0.0 dom0' >> ${IMAGE_ROOTFS}/etc/hosts +} +ROOTFS_POSTPROCESS_COMMAND += "post_rootfs_shell_commands; " diff --git a/recipes-core/initrdscripts/initramfs-stubdomain_1.0.bb b/recipes-core/initrdscripts/initramfs-stubdomain_1.0.bb index 240fc13c8d..dc47bf5bbc 100644 --- a/recipes-core/initrdscripts/initramfs-stubdomain_1.0.bb +++ b/recipes-core/initrdscripts/initramfs-stubdomain_1.0.bb @@ -2,7 +2,7 @@ DESCRIPTION = "Stubdomain initscript." LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" -COMPATIBLE_MACHINE = "xenclient-stubdomain" +COMPATIBLE_MACHINE = "openxt-stubdom" SRC_URI = " \ file://init.sh \ From 8760da0882e096a443f2a776b23a454589232675 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 16 Dec 2020 19:09:36 -0500 Subject: [PATCH 09/15] initscript: no logger available at mountall.sh The system log isn't started yet and /dev/log does not obviously exist at that point (bootlogd is 07, right after mountall 06). Remove logger invocation. Signed-off-by: Eric Chanudet --- recipes-core/initscripts/initscripts-1.0/mountall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recipes-core/initscripts/initscripts-1.0/mountall.sh b/recipes-core/initscripts/initscripts-1.0/mountall.sh index ffe4d0d1fd..57ee5b5fe7 100755 --- a/recipes-core/initscripts/initscripts-1.0/mountall.sh +++ b/recipes-core/initscripts/initscripts-1.0/mountall.sh @@ -34,7 +34,7 @@ RESTORECON=/sbin/restorecon # about this. So we mount "proc" filesystems without -v. # test "$VERBOSE" != no && echo "Mounting local filesystems..." -mount -a $MOUNTALL 2>&1 | logger -s -p user.err +mount -a $MOUNTALL 2>&1 # # We might have mounted something over /dev, see if /dev/initctl is there. From 514d1828f59a838af8a8522ce4f6ca928cac4a80 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 16 Dec 2020 19:20:36 -0500 Subject: [PATCH 10/15] layer: openxt- machine integration Changes in this patch are required to use differently named machines and images than then xenclient- prefixed ones. Signed-off-by: Eric Chanudet --- .../base-files/base-files_3.%.bbappend | 10 +++ .../base-files/files/openxt-dom0/fstab | 45 ++++++++++++ .../files/openxt-live-installer/fstab | 12 ++++ .../base-files/files/openxt-ndvm/fstab | 37 ++++++++++ .../base-files/files/openxt-uivm/fstab | 36 ++++++++++ .../base-files/files/openxt-uivm/fstab.early | 15 ++++ .../init-ifupdown-1.0/openxt-dom0/interfaces | 9 +++ .../init-ifupdown-1.0/openxt-ndvm/interfaces | 22 ++++++ .../init-ifupdown-1.0/openxt-uivm/interfaces | 10 +++ .../initscripts-1.0/openxt-dom0/mountall.sh | 62 +++++++++++++++++ .../initscripts-1.0/openxt-dom0/urandom | 61 ++++++++++++++++ .../initscripts-1.0/openxt-dom0/volatiles | 37 ++++++++++ .../initscripts-1.0/openxt-ndvm/finish.sh | 23 +++++++ .../initscripts-1.0/openxt-ndvm/volatiles | 37 ++++++++++ .../initscripts-1.0/openxt-uivm/mountall.sh | 69 +++++++++++++++++++ .../initscripts-1.0/openxt-uivm/single | 21 ++++++ .../initscripts-1.0/openxt-uivm/volatiles | 37 ++++++++++ .../xserver-xf86-config/openxt-uivm/xorg.conf | 15 ++++ .../stubdomains/devicemodel-stubdom_1.0.bb | 2 +- .../stubdomains/openxt-stubdom-kernel_1.0.bb | 28 ++++++++ .../refpolicy/refpolicy-mcs_2.%.bbappend | 5 ++ 21 files changed, 592 insertions(+), 1 deletion(-) create mode 100644 recipes-core/base-files/files/openxt-dom0/fstab create mode 100644 recipes-core/base-files/files/openxt-live-installer/fstab create mode 100644 recipes-core/base-files/files/openxt-ndvm/fstab create mode 100644 recipes-core/base-files/files/openxt-uivm/fstab create mode 100644 recipes-core/base-files/files/openxt-uivm/fstab.early create mode 100644 recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-dom0/interfaces create mode 100644 recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-ndvm/interfaces create mode 100644 recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-uivm/interfaces create mode 100755 recipes-core/initscripts/initscripts-1.0/openxt-dom0/mountall.sh create mode 100755 recipes-core/initscripts/initscripts-1.0/openxt-dom0/urandom create mode 100644 recipes-core/initscripts/initscripts-1.0/openxt-dom0/volatiles create mode 100644 recipes-core/initscripts/initscripts-1.0/openxt-ndvm/finish.sh create mode 100644 recipes-core/initscripts/initscripts-1.0/openxt-ndvm/volatiles create mode 100755 recipes-core/initscripts/initscripts-1.0/openxt-uivm/mountall.sh create mode 100755 recipes-core/initscripts/initscripts-1.0/openxt-uivm/single create mode 100644 recipes-core/initscripts/initscripts-1.0/openxt-uivm/volatiles create mode 100644 recipes-graphics/xorg-xserver/xserver-xf86-config/openxt-uivm/xorg.conf create mode 100644 recipes-openxt/stubdomains/openxt-stubdom-kernel_1.0.bb diff --git a/recipes-core/base-files/base-files_3.%.bbappend b/recipes-core/base-files/base-files_3.%.bbappend index 52f72318e8..03d39232b7 100644 --- a/recipes-core/base-files/base-files_3.%.bbappend +++ b/recipes-core/base-files/base-files_3.%.bbappend @@ -31,6 +31,10 @@ dirs755_append_xenclient-dom0 = " \ /storage \ ${localstatedir}/cores \ " +dirs755_append_openxt-dom0 = " \ + /storage \ + ${localstatedir}/cores \ +" # OpenXT: UIVM has only root as user, pre-create local conf directories. dirs755_append_xenclient-uivm = " \ /root/.gconf \ @@ -38,6 +42,12 @@ dirs755_append_xenclient-uivm = " \ /root/.cache \ /root/.ssh \ " +dirs755_append_openxt-uivm = " \ + /root/.gconf \ + /root/.gnome2 \ + /root/.cache \ + /root/.ssh \ +" volatiles = "" conffiles = " \ diff --git a/recipes-core/base-files/files/openxt-dom0/fstab b/recipes-core/base-files/files/openxt-dom0/fstab new file mode 100644 index 0000000000..bed1c4c49d --- /dev/null +++ b/recipes-core/base-files/files/openxt-dom0/fstab @@ -0,0 +1,45 @@ +# proc is presumably mounted by /etc/init.d/rcS script. +# /etc/init.d/rcS might use this file, so match this entry with +# /etc/fstab.early. +proc /proc proc nosuid,noexec,nodev 0 0 + +# OpenXT read-only root tmpfs: +# These have to be either absent from this file or match /etc/fstab.early +# exactly for mountearly.sh and mountall.sh to work correctly. +sysfs /sys sysfs nosuid,noexec,nodev 0 0 +devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 +tmpfs /run tmpfs defaults,rootcontext=system_u:object_r:var_run_t:s0,size=5M 0 0 +tmpfs /tmp tmpfs defaults,rootcontext=system_u:object_r:tmp_t:s0,size=100M 0 0 + +tmpfs /var/volatile tmpfs defaults,rootcontext=system_u:object_r:var_t:s0,size=2M 0 0 +tmpfs /var/cache tmpfs defaults,rootcontext=system_u:object_r:var_t:s0,size=100M 0 0 + +# OpenXT read-only root: +# mountall.sh should take care of these. +rootfs / auto defaults,ro,noatime 1 1 + +securityfs /sys/kernel/security securityfs defaults 0 0 + +devpts /dev/pts devpts mode=0620,gid=5 0 0 +tmpfs /dev/shm tmpfs mode=0777,size=1M 0 0 + +xenfs /proc/xen xenfs defaults 0 0 + +tmpfs /var/lib/ovf tmpfs defaults,rootcontext=system_u:object_r:xc_ovf_var_lib_t:s0,size=100M 0 0 +tmpfs /var/lib/dbus tmpfs defaults,rootcontext=system_u:object_r:system_dbusd_var_lib_t:s0,size=1M 0 0 +tmpfs /var/lib/xen tmpfs defaults,rootcontext=system_u:object_r:xend_var_lib_t:s0,size=1M 0 0 + +tmpfs /root/.ssh tmpfs defaults,rootcontext=system_u:object_r:ssh_home_t:s0,size=1M 0 0 +tmpfs /mnt/upgrade tmpfs defaults,size=1M 0 0 +ramfs /mnt/secure ramfs context=system_u:object_r:xc_secure_t:s0,size=1M 0 0 + +/dev/mapper/log /var/log ext4 errors=remount-ro,noatime 1 2 +/dev/mapper/cores /var/cores ext4 errors=remount-ro,noatime,rootcontext=system_u:object_r:var_core_t:s0 1 3 +/dev/mapper/xenclient-boot /boot/system ext4 errors=remount-ro,noatime 1 4 +/dev/mapper/xenclient-storage /storage ext4 errors=remount-ro,user_xattr,noatime 1 5 +/dev/mapper/swap none swap sw 0 0 + +# OpenXT: The following mount will fail on non-UEFI installs. +# For some reason, at boot time, that usually results in the rest of this file getting ignored. +# Having it be the last one makes it a non-issue. +efivarfs /sys/firmware/efi/efivars efivarfs ro,nosuid,nodev,noexec,noatime 0 0 diff --git a/recipes-core/base-files/files/openxt-live-installer/fstab b/recipes-core/base-files/files/openxt-live-installer/fstab new file mode 100644 index 0000000000..64b9e79f37 --- /dev/null +++ b/recipes-core/base-files/files/openxt-live-installer/fstab @@ -0,0 +1,12 @@ +proc /proc proc nosuid,noexec,nodev 0 0 + +sysfs /sys sysfs nosuid,noexec,nodev 0 0 +devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 +devpts /dev/pts devpts mode=0620,gid=5 0 0 + +rootfs / auto rw,defaults,noatime 1 1 + +securityfs /sys/kernel/security securityfs defaults 0 0 +xenfs /proc/xen xenfs defaults 0 0 + +efivarfs /sys/firmware/efi/efivars efivarfs rw,nosuid,nodev,noexec,noatime,nofail 0 0 diff --git a/recipes-core/base-files/files/openxt-ndvm/fstab b/recipes-core/base-files/files/openxt-ndvm/fstab new file mode 100644 index 0000000000..2942324bc4 --- /dev/null +++ b/recipes-core/base-files/files/openxt-ndvm/fstab @@ -0,0 +1,37 @@ +# proc is presumably mounted by /etc/init.d/rcS script. +# /etc/init.d/rcS might use this file, so match this entry with +# /etc/fstab.early. +proc /proc proc nosuid,noexec,nodev 0 0 + +# OpenXT read-only root tmpfs: +# These have to be either absent from this file or match /etc/fstab.early +# exactly for mountearly.sh and mountall.sh to work correctly. +sysfs /sys sysfs nosuid,noexec,nodev 0 0 +devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 +tmpfs /run tmpfs defaults,rootcontext=system_u:object_r:var_run_t:s0,size=5M 0 0 +tmpfs /tmp tmpfs defaults,rootcontext=system_u:object_r:tmp_t:s0,size=100M 0 0 + +tmpfs /var/volatile tmpfs defaults,rootcontext=system_u:object_r:var_t:s0,size=2M 0 0 +tmpfs /var/cache tmpfs defaults,rootcontext=system_u:object_r:var_t:s0,size=100M 0 0 + +# OpenXT read-only root: +# mountall.sh should take care of these. +rootfs / auto defaults,ro,noatime 1 1 + +devpts /dev/pts devpts mode=0620,gid=5 0 0 +tmpfs /dev/shm tmpfs mode=0777,size=1M 0 0 + +xenfs /proc/xen xenfs defaults 0 0 + +tmpfs /var/log tmpfs defaults,rootcontext=system_u:object_r:var_log_t:s0,size=10M 0 0 +tmpfs /var/lib/dbus tmpfs defaults,rootcontext=system_u:object_r:system_dbusd_var_lib_t:s0,size=1M 0 0 +tmpfs /var/lib/dhcp tmpfs defaults,rootcontext=system_u:object_r:dhcp_state_t:s0,size=1M 0 0 +tmpfs /var/lib/NetworkManager tmpfs defaults,rootcontext=system_u:object_r:NetworkManager_var_lib_t:s0,size=1M 0 0 + +tmpfs /media/ram tmpfs defaults,size=1M 0 0 + +tmpfs /etc/NetworkManager tmpfs defaults,rootcontext=system_u:object_r:NetworkManager_etc_t:s0,size=2M 0 0 +tmpfs /etc/dnsmasq-config tmpfs defaults,rootcontext=system_u:object_r:dnsmasq_etc_t:s0,size=1M 0 0 +tmpfs /etc/iproute2 tmpfs defaults,rootcontext=system_u:object_r:net_conf_t:s0,size=1M 0 0 + +/dev/xvdb none swap sw 0 0 diff --git a/recipes-core/base-files/files/openxt-uivm/fstab b/recipes-core/base-files/files/openxt-uivm/fstab new file mode 100644 index 0000000000..e816bdbe6d --- /dev/null +++ b/recipes-core/base-files/files/openxt-uivm/fstab @@ -0,0 +1,36 @@ +# proc is presumably mounted by /etc/init.d/rcS script. +# /etc/init.d/rcS might use this file, so match this entry with +# /etc/fstab.early. +proc /proc proc nosuid,noexec,nodev 0 0 + +# OpenXT read-only root tmpfs: +# These have to be either absent from this file or match /etc/fstab.early +# exactly for mountearly.sh and mountall.sh to work correctly. +sysfs /sys sysfs nosuid,noexec,nodev 0 0 +devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 +tmpfs /run tmpfs defaults,size=5M 0 0 +tmpfs /tmp tmpfs defaults,size=100M 0 0 + +# OpenXT read-only root: +# mountall.sh should take care of these. +rootfs / auto defaults,ro,noatime 1 1 + +devpts /dev/pts devpts mode=0620,gid=5 0 0 +tmpfs /dev/shm tmpfs mode=0777,size=1M 0 0 + +tmpfs /var/volatile tmpfs defaults,size=2M 0 0 +tmpfs /var/cache tmpfs defaults,size=100M 0 0 +tmpfs /var/log tmpfs defaults,size=10M 0 0 +tmpfs /var/lib/dbus tmpfs defaults,size=1M 0 0 + +tmpfs /media/ram tmpfs defaults,size=1M 0 0 + +# TODO: Could be handled with volatiles? +tmpfs /root/.gconf tmpfs defaults,size=10M 0 0 +tmpfs /root/.ssh tmpfs defaults,size=1M 0 0 +tmpfs /root/.cache tmpfs defaults,size=1M 0 0 +tmpfs /var/lib/NetworkManager tmpfs defaults,size=1M 0 0 + +xenfs /proc/xen xenfs defaults 0 0 + +/dev/xvda2 none swap sw 0 0 diff --git a/recipes-core/base-files/files/openxt-uivm/fstab.early b/recipes-core/base-files/files/openxt-uivm/fstab.early new file mode 100644 index 0000000000..378d766d1c --- /dev/null +++ b/recipes-core/base-files/files/openxt-uivm/fstab.early @@ -0,0 +1,15 @@ +# proc is presumably mounted by /etc/init.d/rcS script. +# /etc/init.d/rcS might use /etc/fstab when not modified accordingly, so match +# this entry with /etc/fstab. +proc /proc proc nosuid,noexec,nodev 0 0 + +# OpenXT read-only root tmpfs: +# These have to be either absent from this file or match /etc/fstab exactly for +# mountearly.sh and mountall.sh to work correctly. +sysfs /sys sysfs nosuid,noexec,nodev 0 0 +devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 +tmpfs /run tmpfs defaults,size=5M 0 0 +tmpfs /tmp tmpfs defaults,size=100M 0 0 + +tmpfs /var/volatile tmpfs defaults,size=2M 0 0 +tmpfs /var/cache tmpfs defaults,size=100M 0 0 diff --git a/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-dom0/interfaces b/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-dom0/interfaces new file mode 100644 index 0000000000..e9d591b301 --- /dev/null +++ b/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-dom0/interfaces @@ -0,0 +1,9 @@ +# Configure Loopback +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet manual + +auto uivm +iface uivm inet manual diff --git a/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-ndvm/interfaces b/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-ndvm/interfaces new file mode 100644 index 0000000000..7cbfb03f8a --- /dev/null +++ b/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-ndvm/interfaces @@ -0,0 +1,22 @@ +# Configure Loopback +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet manual + +auto uivm +iface uivm inet manual + +auto brinternal +iface brinternal inet manual + +auto brshared +iface brshared inet manual + +auto brwireless +iface brwireless inet manual + +auto brbridged +iface brbridged inet dhcp + diff --git a/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-uivm/interfaces b/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-uivm/interfaces new file mode 100644 index 0000000000..ed87a0a6b2 --- /dev/null +++ b/recipes-core/init-ifupdown/init-ifupdown-1.0/openxt-uivm/interfaces @@ -0,0 +1,10 @@ +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet dhcp +udhcpc_opts -b + +auto eth1 +iface eth1 inet dhcp +udhcpc_opts -b diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-dom0/mountall.sh b/recipes-core/initscripts/initscripts-1.0/openxt-dom0/mountall.sh new file mode 100755 index 0000000000..0661b6aee8 --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-dom0/mountall.sh @@ -0,0 +1,62 @@ +# +# Copyright (c) 2012 Citrix Systems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# mountall.sh Mount all filesystems. +# +# Version: @(#)mountall.sh 2.83-2 01-Nov-2001 miquels@cistron.nl +# +. /etc/default/rcS +if test -f /etc/default/mountall; then + . /etc/default/mountall +fi + +. /etc/init.d/functions + +mkdir -p /dev/shm /dev/pts +restore /dev/shm /dev/pts + +# Mount local filesystems in /etc/fstab. For some reason, people +# might want to mount "proc" several times, and mount -v complains +# about this. So we mount "proc" filesystems without -v. +# +test "$VERBOSE" != no && echo "Mounting local filesystems..." +mount -a $MOUNTALL 2>&1 | logger -s -p user.err + +# +# We might have mounted something over /dev, see if /dev/initctl is there. +# +if test ! -p /dev/initctl +then + rm -f /dev/initctl + mknod -m 600 /dev/initctl p + restore /dev/initctl +fi + +# /config is relabeled earlier in boot (xenclient-config-access). +restore_firstboot -r /storage /var/log /var/cores /boot/system + +kill -USR1 1 + +# +# Execute swapon command again, in case we want to swap to +# a file on a now mounted filesystem. +# +swapon -a 2> /dev/null + +: exit 0 diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-dom0/urandom b/recipes-core/initscripts/initscripts-1.0/openxt-dom0/urandom new file mode 100755 index 0000000000..d7c363cd43 --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-dom0/urandom @@ -0,0 +1,61 @@ +#! /bin/sh +# +# Copyright (c) 2013 Citrix Systems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# urandom This script saves the random seed between reboots. +# It is called from the boot, halt and reboot scripts. +# +# Version: @(#)urandom 1.33 22-Jun-1998 miquels@cistron.nl +# + +test -c /dev/urandom || exit 0 +. /etc/default/rcS + +SEED_FILE=/config/random-seed +POOL_SIZE=`cat /proc/sys/kernel/random/poolsize` || POOL_SIZE=4096 + +case "$1" in + start|"") + test "$VERBOSE" != no && echo "Initializing random number generator..." + # Carry a random seed from start-up to start-up. + # Load and then save the whole entropy pool. + if [ -f $SEED_FILE ]; then + cat $SEED_FILE > /dev/urandom + else + touch $SEED_FILE + fi + chmod 600 $SEED_FILE + dd if=/dev/urandom of=$SEED_FILE count=1 bs=$POOL_SIZE + ;; + stop) + # Carry a random seed from shut-down to start-up; + # see documentation in linux/drivers/char/random.c + test "$VERBOSE" != no && echo "Saving random seed..." + echo "Saving random seed..." + touch $SEED_FILE + chmod 600 $SEED_FILE + dd if=/dev/urandom of=$SEED_FILE count=1 bs=$POOL_SIZE + ;; + *) + echo "Usage: urandom {start|stop}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-dom0/volatiles b/recipes-core/initscripts/initscripts-1.0/openxt-dom0/volatiles new file mode 100644 index 0000000000..8c726075b8 --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-dom0/volatiles @@ -0,0 +1,37 @@ +# This configuration file lists filesystem objects that should get verified +# during startup and be created if missing. +# +# Every line must either be a comment starting with # +# or a definition of format: +# +# where the items are separated by whitespace ! +# +# : d|f|l : (d)irectory|(f)ile|(l)ink +# +# A linking example: +# l root root 0777 /var/test /tmp/testfile +# f root root 0644 /var/test none +# +# Understanding links: +# When populate-volatile is to verify/create a directory or file, it will first +# check it's existence. If a link is found to exist in the place of the target, +# the path of the target is replaced with the target the link points to. +# Thus, if a link is in the place to be verified, the object will be created +# in the place the link points to instead. +# This explains the order of "link before object" as in the example above, where +# a link will be created at /var/test pointing to /tmp/testfile and due to this +# link the file defined as /var/test will actually be created as /tmp/testfile. +d root root 1777 /run/lock none +l root root 1777 /var/lock /run/lock +d root root 0755 /var/lock/subsys none +f root root 0644 /var/log/lastlog none +f root root 0664 /var/run/utmp none +d root root 0755 /var/volatile/etc none +l root root 0777 /etc/asound.conf /var/volatile/etc/asound.conf +f root root 0644 /etc/asound.conf none +f root root 0644 /var/volatile/etc/resolv.conf none +f root root 0644 /var/volatile/etc/ifstate none +d root root 0755 /var/volatile/log none +f root root 0644 /var/volatile/log/wtmp none +f root root 0644 /var/run/hosts none + diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-ndvm/finish.sh b/recipes-core/initscripts/initscripts-1.0/openxt-ndvm/finish.sh new file mode 100644 index 0000000000..6dd3ce332a --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-ndvm/finish.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Copyright (c) 2013 Citrix Systems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# Only used if boot-sentinel is set in the VM configuration +xenstore-write booted 1 + +exit 0 diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-ndvm/volatiles b/recipes-core/initscripts/initscripts-1.0/openxt-ndvm/volatiles new file mode 100644 index 0000000000..ba00080f89 --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-ndvm/volatiles @@ -0,0 +1,37 @@ +# This configuration file lists filesystem objects that should get verified +# during startup and be created if missing. +# +# Entries have the following format: +# +# where the items are separated by whitespace ! +# +# The # character introduces a comment lasting until end of line. +# Blank lines are ignored. +# +# : d|f|l : (d)irectory|(f)ile|(l)ink +# +# A linking example: +# l root root 0777 /var/test /tmp/testfile +# f root root 0644 /var/test none +# +# Understanding links: +# When populate-volatile is to verify/create a directory or file, it will first +# check it's existence. If a link is found to exist in the place of the target, +# the path of the target is replaced with the target the link points to. +# Thus, if a link is in the place to be verified, the object will be created +# in the place the link points to instead. +# This explains the order of "link before object" as in the example above, where +# a link will be created at /var/test pointing to /tmp/testfile and due to this +# link the file defined as /var/test will actually be created as /tmp/testfile. +d root root 1777 /run/lock none +l root root 1777 /var/lock /run/lock +d root root 0755 /var/volatile/log none +d root root 1777 /var/volatile/tmp none +d root root 0755 /var/volatile/etc none +l root root 0644 /etc/resolv.conf /var/run/NetworkManager/resolv.conf +f root root 0644 /var/volatile/etc/ifstate none +l root root 0755 /var/run /run +l root root 1777 /var/tmp /var/volatile/tmp +d root root 0755 /var/lock/subsys none +f root root 0664 /var/log/wtmp none +f root root 0664 /var/run/utmp none diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-uivm/mountall.sh b/recipes-core/initscripts/initscripts-1.0/openxt-uivm/mountall.sh new file mode 100755 index 0000000000..1eef5a4ed1 --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-uivm/mountall.sh @@ -0,0 +1,69 @@ +# +# Copyright (c) 2013 Citrix Systems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# +# mountall.sh Mount all filesystems. +# +# Version: @(#)mountall.sh 2.83-2 01-Nov-2001 miquels@cistron.nl +# +. /etc/default/rcS + +[ -x /usr/bin/udevadm ] && /usr/bin/udevadm settle + +if test -f /etc/default/mountall; then + . /etc/default/mountall +fi + +mkdir -p /dev/pts /dev/shm + +# +# Mount local filesystems in /etc/fstab. For some reason, people +# might want to mount "proc" several times, and mount -v complains +# about this. So we mount "proc" filesystems without -v. +# +test "$VERBOSE" != no && echo "Mounting local filesystems..." +mount -a $MOUNTALL 2>&1 | logger -s -p user.err + +# +# Check if there's a /dev/xvda3. If so, mount it to /root/.gconf +# +if test -e /dev/xvda3 +then + umount /root/.gconf + mount -t ext3 /dev/xvda3 /root/.gconf + mount --bind /root/.gconf /root/.gnome2 +fi + +# +# We might have mounted something over /dev, see if /dev/initctl is there. +# +if test ! -p /dev/initctl +then + rm -f /dev/initctl + mknod -m 600 /dev/initctl p +fi +kill -USR1 1 + +# +# Execute swapon command again, in case we want to swap to +# a file on a now mounted filesystem. +# +swapon -a 2> /dev/null + +: exit 0 + diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-uivm/single b/recipes-core/initscripts/initscripts-1.0/openxt-uivm/single new file mode 100755 index 0000000000..2d177ebb62 --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-uivm/single @@ -0,0 +1,21 @@ +#! /bin/sh +# +# single executed by init(8) upon entering runlevel 1 (single). +# +# Version: @(#)single 1.20 26-Geb-2001 miquels@cistron.nl +# + +PATH="/sbin:/bin:/usr/sbin:/usr/bin" + +# Kill all processes. +echo "Sending all processes the TERM signal..." +killall5 -15 +sleep 5 +echo "Sending all processes the KILL signal..." +killall5 -9 + +# We start update here, since we just killed it. +test -x /sbin/update && update + +echo "Entering single-user mode..." +exec init -t1 S diff --git a/recipes-core/initscripts/initscripts-1.0/openxt-uivm/volatiles b/recipes-core/initscripts/initscripts-1.0/openxt-uivm/volatiles new file mode 100644 index 0000000000..0c3d0fae0f --- /dev/null +++ b/recipes-core/initscripts/initscripts-1.0/openxt-uivm/volatiles @@ -0,0 +1,37 @@ +# This configuration file lists filesystem objects that should get verified +# during startup and be created if missing. +# +# Every line must either be a comment starting with # +# or a definition of format: +# +# where the items are separated by whitespace ! +# +# : d|f|l : (d)irectory|(f)ile|(l)ink +# +# A linking example: +# l root root 0777 /var/test /tmp/testfile +# f root root 0644 /var/test none +# +# Understanding links: +# When populate-volatile is to verify/create a directory or file, it will first +# check it's existence. If a link is found to exist in the place of the target, +# the path of the target is replaced with the target the link points to. +# Thus, if a link is in the place to be verified, the object will be created +# in the place the link points to instead. +# This explains the order of "link before object" as in the example above, where +# a link will be created at /var/test pointing to /tmp/testfile and due to this +# link the file defined as /var/test will actually be created as /tmp/testfile. +d root root 1777 /run/lock none +l root root 1777 /var/lock /run/lock +d root root 0755 /var/lock/subsys none +f root root 0644 /var/log/lastlog none +f root root 0664 /var/run/utmp none +d root root 0755 /var/volatile/etc none +d root root 0755 /var/volatile/etc/asound none +f root root 0644 /var/volatile/etc/resolv.conf none +f root root 0644 /var/volatile/etc/ifstate none +d root root 0755 /var/volatile/log none +f root root 0644 /var/volatile/log/wtmp none +f root root 0644 /var/run/hosts none +d root root 0755 /var/volatile/dbus-session-root none +l root root 0755 /root/.dbus /var/volatile/dbus-session-root diff --git a/recipes-graphics/xorg-xserver/xserver-xf86-config/openxt-uivm/xorg.conf b/recipes-graphics/xorg-xserver/xserver-xf86-config/openxt-uivm/xorg.conf new file mode 100644 index 0000000000..d01a2b46b9 --- /dev/null +++ b/recipes-graphics/xorg-xserver/xserver-xf86-config/openxt-uivm/xorg.conf @@ -0,0 +1,15 @@ +# Xorg configuration for UIVM. + +Section "ServerFlags" + Option "DontZap" "true" + Option "DontVTSwitch" "true" + Option "BlankTime" "0" + Option "StandbyTime" "0" + Option "SuspendTime" "0" + Option "OffTime" "0" +EndSection + +Section "Device" + Identifier "openxtfb" + Driver "openxtfb" +EndSection diff --git a/recipes-openxt/stubdomains/devicemodel-stubdom_1.0.bb b/recipes-openxt/stubdomains/devicemodel-stubdom_1.0.bb index 2d3ea4fcb1..7a8f76fccc 100644 --- a/recipes-openxt/stubdomains/devicemodel-stubdom_1.0.bb +++ b/recipes-openxt/stubdomains/devicemodel-stubdom_1.0.bb @@ -4,7 +4,7 @@ LICENSE = "GPLv2" LIC_FILES_CHKSUM ?= "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" STUBDOMAIN_DIR = "${DEPLOY_DIR}/images/${STUBDOMAIN_MACHINE}" -STUBDOMAIN_NAME = "xenclient-stubdomain-initramfs-image" +STUBDOMAIN_NAME = "openxt-stubdom-initramfs-image" FILESEXTRAPATHS_prepend := "${STUBDOMAIN_DIR}:" diff --git a/recipes-openxt/stubdomains/openxt-stubdom-kernel_1.0.bb b/recipes-openxt/stubdomains/openxt-stubdom-kernel_1.0.bb new file mode 100644 index 0000000000..1d1c858285 --- /dev/null +++ b/recipes-openxt/stubdomains/openxt-stubdom-kernel_1.0.bb @@ -0,0 +1,28 @@ +SUMMARY = "Recipe for packaging stubdomain kernel" +HOMEPAGE = "https://openxt.org" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM ?= "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" + +STUBDOMAIN_DIR = "${DEPLOY_DIR}/images/${STUBDOMAIN_MACHINE}" + +FILESEXTRAPATHS_prepend := "${STUBDOMAIN_DIR}:" + +SRC_URI = " \ + file://${STUBDOMAIN_KERNEL}-${STUBDOMAIN_MACHINE}.bin \ +" + +do_install() { + install -d ${D}${libdir}/xen/boot + install -m 0644 ${WORKDIR}/${STUBDOMAIN_KERNEL}-${STUBDOMAIN_MACHINE}.bin \ + ${D}${libdir}/xen/boot/stubdomain-bzImage +} + +do_checkimage() { + if [ ! -e "${STUBDOMAIN_DIR}/${STUBDOMAIN_KERNEL}-${STUBDOMAIN_MACHINE}.bin" ]; then + bbfatal "The stubdomain kernel must be built first" + fi +} +addtask checkimage before do_fetch + +FILES_${PN} = "${libdir}/xen/boot/stubdomain-bzImage" + diff --git a/recipes-security/refpolicy/refpolicy-mcs_2.%.bbappend b/recipes-security/refpolicy/refpolicy-mcs_2.%.bbappend index 32f88c4130..199ca037cc 100644 --- a/recipes-security/refpolicy/refpolicy-mcs_2.%.bbappend +++ b/recipes-security/refpolicy/refpolicy-mcs_2.%.bbappend @@ -228,3 +228,8 @@ pkg_postinst_${PN}_append_xenclient-dom0 () { ${base_sbindir}/setfiles "${sysconfdir}/selinux/${POLICY_NAME}/contexts/files/file_contexts" /config /storage fi } +pkg_postinst_${PN}_append_openxt-dom0 () { + if [ -z "$D" ]; then + ${base_sbindir}/setfiles "${sysconfdir}/selinux/${POLICY_NAME}/contexts/files/file_contexts" /config /storage + fi +} From 8a01c01b8347f83d65a22fdffee9748c409d1442 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Wed, 16 Dec 2020 19:22:00 -0500 Subject: [PATCH 11/15] initrdscripts: load modules with modprobe linux-yocto-openxt-stubdom includes modules, which are shipped in the initramfs. Load them using modprobe, it seems to be working just fine. Signed-off-by: Eric Chanudet --- recipes-core/initrdscripts/initramfs-stubdomain/init.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/recipes-core/initrdscripts/initramfs-stubdomain/init.sh b/recipes-core/initrdscripts/initramfs-stubdomain/init.sh index 428583a89f..7935a6f524 100755 --- a/recipes-core/initrdscripts/initramfs-stubdomain/init.sh +++ b/recipes-core/initrdscripts/initramfs-stubdomain/init.sh @@ -33,6 +33,12 @@ exec 0< /dev/hvc0 exec 1> /dev/hvc0 exec 2> /dev/hvc0 +modprobe xen-argo +modprobe xen-gntalloc +modprobe xen-gntdev +modprobe xen-netfront +modprobe xen-pcifront + sync mkdir -p /proc /sys /mnt /tmp mount -t proc proc /proc From 5b22c51e2c7397895205ea0e4a6b76f0cb84b92c Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Fri, 18 Dec 2020 15:02:12 -0500 Subject: [PATCH 12/15] linux/cmdline: i915 is builtin i915 is builtin since the gem-foreign relies on internal kernel interfaces. Pass the parameter to disable PSR on the cmdline. Signed-off-by: Eric Chanudet --- .../xenclient-dom0-tweaks/grub.cfg | 2 +- .../xenclient-dom0-tweaks/openxt.cfg | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/grub.cfg b/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/grub.cfg index 935d7cd66e..95516ef53b 100644 --- a/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/grub.cfg +++ b/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/grub.cfg @@ -31,7 +31,7 @@ fi TBOOT_COMMON_CMD="min_ram=0x2000000 loglvl=all serial=115200,8n1,0x3f8 logging=serial,memory" XEN_COMMON_CMD="dom0_mem=min:768M,max:768M,768M mbi-video vga=current flask=enforcing loglvl=debug guest_loglvl=debug ucode=-2 smt=0 bootscrub=1 argo=yes,mac-permissive=1" -LINUX_COMMON_CMD="console=hvc0 root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3" +LINUX_COMMON_CMD="console=hvc0 root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 i915.enable_psr=0" menuentry "XenClient: Normal" { background_image /grub/booting.png diff --git a/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/openxt.cfg b/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/openxt.cfg index a726c97308..9c1f3f2dc0 100644 --- a/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/openxt.cfg +++ b/recipes-openxt/xenclient-dom0-tweaks/xenclient-dom0-tweaks/openxt.cfg @@ -6,30 +6,30 @@ ucode=microcode_intel.bin [openxt-normal] options=placeholder console=com1 dom0_mem=min:768M,max:768M,768M efi=rs,attr=uc com1=115200,8n1,pci mbi-video vga=current flask=enforcing loglvl=debug guest_loglvl=debug smt=0 ucode=-1 bootscrub=1 argo=yes,mac-permissive=1 -kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 autostart +kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 i915.enable_psr=0 autostart ramdisk=initrd xsm=policy.24 [openxt-support-safe-graphics] options=console=com1 dom0_mem=min:768M,max:768M,768M efi=rs,attr=uc com1=115200,8n1,pci mbi-video vga=current flask=enforcing loglvl=debug guest_loglvl=debug smt=0 ucode=-1 bootscrub=1 argo=yes,mac-permissive=1 -kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 safe-graphic nomodeset +kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 i915.enable_psr=0 safe-graphic nomodeset ramdisk=initrd xsm=policy.24 [openxt-support-amt] options=console=com1,vga dom0_mem=min:768M,max:768M,768M efi=rs,attr=uc com1=115200,8n1,amt mbi-video vga=current flask=enforcing loglvl=debug guest_loglvl=debug smt=0 ucode=-1 bootscrub=1 argo=yes,mac-permissive=1 -kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 +kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 i915.enable_psr=0 ramdisk=initrd xsm=policy.24 [openxt-support-console] options=console=com1,vga dom0_mem=min:768M,max:768M,768M efi=rs,attr=uc com1=115200,8n1,pci mbi-video vga=current flask=enforcing loglvl=debug guest_loglvl=debug sync_console smt=0 ucode=-1 bootscrub=1 argo=yes,mac-permissive=1 -kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 console=tty0 fbcon runlevel=3 +kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 console=tty0 fbcon runlevel=3 i915.enable_psr=0 ramdisk=initrd xsm=policy.24 [openxt-support-console-amt] options=console=com1,vga dom0_mem=min:768M,max:768M,768M efi=rs,attr=uc com1=115200,8n1,amt mbi-video vga=current flask=enforcing loglvl=debug guest_loglvl=debug sync_console smt=0 ucode=-1 bootscrub=1 argo=yes,mac-permissive=1 -kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 console=tty0 fbcon runlevel=3 +kernel=bzImage root=/dev/mapper/xenclient-root ro boot=/dev/mapper/xenclient-boot swiotlb=16384 xen_pciback.passthrough=1 consoleblank=0 video.delay_init=1 vt.global_cursor_default=0 rootfstype=ext3 bootfstype=ext3 console=hvc0 console=tty0 fbcon runlevel=3 i915.enable_psr=0 ramdisk=initrd xsm=policy.24 From 41aeb0d8f05efe863556efbc2f7d07ca817bbb49 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Fri, 18 Dec 2020 15:04:05 -0500 Subject: [PATCH 13/15] txt: The txt module is now builtin Since the patch introducing this module is only applied in dom0, it is now builtin. Remove the runtime dependency. This out-of-tree module should be added to openxt-kmeta as a patch too in the end. Signed-off-by: Eric Chanudet --- recipes-openxt/txt-info-module/txt-info-module_1.0.bb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/recipes-openxt/txt-info-module/txt-info-module_1.0.bb b/recipes-openxt/txt-info-module/txt-info-module_1.0.bb index a1131ba0d0..7f9c0b66a7 100644 --- a/recipes-openxt/txt-info-module/txt-info-module_1.0.bb +++ b/recipes-openxt/txt-info-module/txt-info-module_1.0.bb @@ -17,8 +17,4 @@ S = "${WORKDIR}/sources" inherit module inherit module-signing -KERNEL_MODULE_AUTOLOAD += "txt_info" - -RDEPENDS_${PN} += " \ - kernel-module-txt \ -" +KERNEL_MODULE_AUTOLOAD += "txt-info" From 3311586fc16bc39dc8f38887bab5b0bd19a62728 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Mon, 21 Jun 2021 18:34:33 -0400 Subject: [PATCH 14/15] openxt-kmeta: add fragments for radeon/nouveau vGlass can compose guests using radeon/nouveau drivers. Provide config fragments to include these in installer/dom0 where they can be used. Signed-off-by: Eric Chanudet --- recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.cfg | 1 + recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.scc | 5 +++++ recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.cfg | 2 ++ recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.scc | 5 +++++ 4 files changed, 13 insertions(+) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.scc create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.scc diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.cfg new file mode 100644 index 0000000000..9375fdfc7a --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.cfg @@ -0,0 +1 @@ +CONFIG_DRM_NOUVEAU=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.scc new file mode 100644 index 0000000000..64e2e11626 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/nouveau.scc @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Enable DRM support for Nouveau drivers" +define KFEATURE_COMPATIBILITY board + +kconf hardware nouveau.cfg diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.cfg b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.cfg new file mode 100644 index 0000000000..bf442e24d9 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.cfg @@ -0,0 +1,2 @@ +CONFIG_DRM_RADEON=m +CONFIG_FB_RADEON=m diff --git a/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.scc b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.scc new file mode 100644 index 0000000000..9c810dd861 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/bsp/gpu/radeon.scc @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MIT +define KFEATURE_DESCRIPTION "Enable DRM support for Radeon drivers" +define KFEATURE_COMPATIBILITY board + +kconf hardware radeon.cfg From d0e6c22c3397d943f70f8c89598c28a072d0edf3 Mon Sep 17 00:00:00 2001 From: Eric Chanudet Date: Thu, 24 Jun 2021 15:17:32 -0400 Subject: [PATCH 15/15] txt_info: add as a patch config fragment Hosting txt_info.c as an out-of-tree module with its sources in the layer is not very elegant. The changes are small and configurable, and useful only to dom0. Make the out-of-tree module a patch against the kernel and create the associated configuration fragment so dom0's kernel can select it. Signed-off-by: Eric Chanudet --- recipes-core/images/openxt-dom0-image.bb | 1 - .../patches/xen-txt-evtlog/xen-txt-evtlog.cfg | 1 - ...xpose-TXT-conf-registers-to-userland.patch | 227 ++++++++++++++++++ .../xen-txt-add-xen-txt-eventlog-module.patch | 0 .../openxt-kmeta/patches/xen-txt/xen-txt.cfg | 2 + .../xen-txt.scc} | 4 +- .../linux/linux-yocto-openxt-dom0_5.4.bb | 2 +- .../txt-info-module/files/sources/Kbuild | 3 - .../txt-info-module/files/sources/Makefile | 20 -- .../txt-info-module/files/sources/txt_info.c | 167 ------------- .../txt-info-module/txt-info-module_1.0.bb | 20 -- 11 files changed, 233 insertions(+), 214 deletions(-) delete mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/0001-txt_info-expose-TXT-conf-registers-to-userland.patch rename recipes-kernel/linux/files/openxt-kmeta/patches/{xen-txt-evtlog => xen-txt}/xen-txt-add-xen-txt-eventlog-module.patch (100%) create mode 100644 recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt.cfg rename recipes-kernel/linux/files/openxt-kmeta/patches/{xen-txt-evtlog/xen-txt-evtlog.scc => xen-txt/xen-txt.scc} (60%) delete mode 100644 recipes-openxt/txt-info-module/files/sources/Kbuild delete mode 100644 recipes-openxt/txt-info-module/files/sources/Makefile delete mode 100644 recipes-openxt/txt-info-module/files/sources/txt_info.c delete mode 100644 recipes-openxt/txt-info-module/txt-info-module_1.0.bb diff --git a/recipes-core/images/openxt-dom0-image.bb b/recipes-core/images/openxt-dom0-image.bb index 9f9969b148..ffbd83786d 100644 --- a/recipes-core/images/openxt-dom0-image.bb +++ b/recipes-core/images/openxt-dom0-image.bb @@ -42,7 +42,6 @@ IMAGE_INSTALL += "\ packagegroup-xenclient-dom0 \ packagegroup-openxt-test \ argo-module \ - txt-info-module \ xenclient-preload-hs-libs \ linux-firmware-i915 \ devicemodel-stubdom \ diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg deleted file mode 100644 index 16de16c726..0000000000 --- a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.cfg +++ /dev/null @@ -1 +0,0 @@ -CONFIG_XEN_TXT=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/0001-txt_info-expose-TXT-conf-registers-to-userland.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/0001-txt_info-expose-TXT-conf-registers-to-userland.patch new file mode 100644 index 0000000000..07f8faba86 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/0001-txt_info-expose-TXT-conf-registers-to-userland.patch @@ -0,0 +1,227 @@ +From acff0fec046e730871aa7342fe8118479eb092d2 Mon Sep 17 00:00:00 2001 +From: Eric Chanudet +Date: Wed, 23 Jun 2021 10:12:42 -0400 +Subject: [PATCH] txt_info: expose TXT conf registers to userland + +TXT exposes configuration registers documented in its Software +Development Guide. Accessing these registers in sometimes necessary for +userland software to perform checks and validate compatibility with +software resources. + +Expose the previously mentioned resources through a platform device +driver in the sysfs. + +Signed-off-by: Eric Chanudet +--- + drivers/misc/Kconfig | 10 +++ + drivers/misc/Makefile | 1 + + drivers/misc/txt_info.c | 167 ++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 178 insertions(+) + create mode 100644 drivers/misc/txt_info.c + +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index c55b63750757..2d3479593610 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -466,6 +466,16 @@ config PVPANIC + a paravirtualized device provided by QEMU; it lets a virtual machine + (guest) communicate panic events to the host. + ++config TXT_INFO ++ tristate "Add TXT configuration registers in securityfs" ++ depends on X86 && TCG_TPM ++ default n ++ help ++ Expose the values of TXT configuration registers via the sysfs for ++ use in userland. To compile this as a module choose M. ++ ++ If unsure, say N. ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index c1860d35dc7e..4ebacab15df2 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -57,3 +57,4 @@ obj-y += cardreader/ + obj-$(CONFIG_PVPANIC) += pvpanic.o + obj-$(CONFIG_HABANA_AI) += habanalabs/ + obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o ++obj-$(CONFIG_TXT_INFO) += txt_info.o +diff --git a/drivers/misc/txt_info.c b/drivers/misc/txt_info.c +new file mode 100644 +index 000000000000..ebece6a50612 +--- /dev/null ++++ b/drivers/misc/txt_info.c +@@ -0,0 +1,167 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#define TXT_PUB_CR_BASE 0xfed30000 ++#define TXT_PUB_CR_SIZE 0x10000 ++static const struct resource txt_resources[] = { ++ { ++ .start = TXT_PUB_CR_BASE, ++ .end = TXT_PUB_CR_BASE + TXT_PUB_CR_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++#define TXT_PUB_CR_INDEX 0 ++ ++struct platform_device *pdev; ++struct txt_info { ++ void __iomem *cr_pub; ++ void __iomem *cr_priv; ++}; ++static struct txt_info txt_info; ++ ++static void __iomem *txt_info_map_regs(struct platform_device *pdev, ++ size_t index) ++{ ++ struct resource *res; ++ void __iomem *base; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, index); ++ if (IS_ERR(res)) { ++ dev_dbg(&pdev->dev, ++ "Failed to access IOMEM resource %zu.\n", index); ++ return res; ++ } ++ ++ base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); ++ if (IS_ERR(base)) ++ dev_dbg(&pdev->dev, ++ "Failed to ioremap configuration registers.\n"); ++ ++ return base; ++} ++ ++/* Registers offset from TXT_PUB_CR_BASE */ ++#define TXT_STS_OFFSET 0x000 ++#define TXT_ESTS_OFFSET 0x008 ++#define TXT_ERRORCODE_OFFSET 0x030 ++#define TXT_VER_FSBIF_OFFSET 0x100 ++#define TXT_DIDVID_OFFSET 0x110 ++#define TXT_VER_QPIIF_OFFSET 0x200 ++ ++#define DECLARE_PUB_SHOW_U8(name, offset) \ ++static ssize_t name##_show(struct kobject *kobj, \ ++ struct kobj_attribute *attr, char *buf) \ ++{ \ ++ uint8_t v = ioread8(txt_info.cr_pub + (offset)); \ ++ return sprintf(buf, "%#04x\n", v); \ ++} \ ++static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); ++ ++#define DECLARE_PUB_SHOW_U32(name, offset) \ ++static ssize_t name##_show(struct kobject *kobj, \ ++ struct kobj_attribute *attr, char *buf) \ ++{ \ ++ uint32_t v = ioread32(txt_info.cr_pub + (offset)); \ ++ return sprintf(buf, "%#010x\n", v); \ ++} \ ++static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); ++ ++#define DECLARE_PUB_SHOW_U64(name, offset) \ ++static ssize_t name##_show(struct kobject *kobj, \ ++ struct kobj_attribute *attr, char *buf) \ ++{ \ ++ uint64_t v = ioread32(txt_info.cr_pub + (offset) + 0x4); \ ++ v <<= 32; \ ++ v |= ioread32(txt_info.cr_pub + (offset)); \ ++ return sprintf(buf, "%#018llx\n", v); \ ++} \ ++static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); ++ ++DECLARE_PUB_SHOW_U64(sts, TXT_STS_OFFSET); ++DECLARE_PUB_SHOW_U8(ests, TXT_ESTS_OFFSET); ++DECLARE_PUB_SHOW_U32(errorcode, TXT_ERRORCODE_OFFSET); ++DECLARE_PUB_SHOW_U32(ver_fsbif, TXT_VER_FSBIF_OFFSET); ++DECLARE_PUB_SHOW_U64(didvid, TXT_DIDVID_OFFSET); ++DECLARE_PUB_SHOW_U32(ver_qpiif, TXT_VER_QPIIF_OFFSET); ++ ++static struct attribute *txt_subsys_attrs[] = { ++ &txt_attr_sts.attr, ++ &txt_attr_ests.attr, ++ &txt_attr_errorcode.attr, ++ &txt_attr_ver_fsbif.attr, ++ &txt_attr_didvid.attr, ++ &txt_attr_ver_qpiif.attr, ++ NULL, ++}; ++ ++static umode_t txt_attr_is_visible(struct kobject *kobj, ++ struct attribute *attr, int n) ++{ ++ return attr->mode; ++} ++ ++static const struct attribute_group txt_subsys_attr_group = { ++ .attrs = txt_subsys_attrs, ++ .is_visible = txt_attr_is_visible, ++}; ++ ++struct kobject *txt_kobj; ++ ++static int __init init_txt_info(void) ++{ ++ int rc; ++ void __iomem *base; ++ ++ pr_info("%s\n", __func__); ++ ++ pdev = platform_device_register_simple( ++ "txt", -1, txt_resources, ARRAY_SIZE(txt_resources)); ++ if (IS_ERR(pdev)) { ++ rc = PTR_ERR(pdev); ++ pr_err("Failed to register txt platform device driver (%d).\n", rc); ++ goto fail_register; ++ } ++ ++ base = txt_info_map_regs(pdev, TXT_PUB_CR_INDEX); ++ if (IS_ERR(base)) { ++ rc = PTR_ERR(base); ++ dev_err(&pdev->dev, ++ "Failed to map TXT public resources (%d).\n", rc); ++ goto fail_map_pub; ++ } ++ txt_info.cr_pub = base; ++ ++ rc = sysfs_create_group(&pdev->dev.kobj, &txt_subsys_attr_group); ++ if (rc) { ++ dev_err(&pdev->dev, "Failed to create sysfs group (%d).\n", rc); ++ goto fail_sysfs; ++ } ++ ++ return 0; ++ ++fail_sysfs: ++ devm_iounmap(&pdev->dev, txt_info.cr_pub); ++fail_map_pub: ++ platform_device_unregister(pdev); ++fail_register: ++ return rc; ++} ++ ++static void __exit cleanup_txt_info(void) ++{ ++ pr_info("%s\n", __func__); ++ ++ if (pdev) ++ platform_device_unregister(pdev); ++} ++ ++module_init(init_txt_info); ++module_exit(cleanup_txt_info); ++ ++MODULE_AUTHOR("Assured Information Security, Inc"); ++MODULE_DESCRIPTION("TXT driver."); ++MODULE_VERSION("1.0"); ++MODULE_LICENSE("GPL"); +-- +2.17.1 + diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-add-xen-txt-eventlog-module.patch b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt-add-xen-txt-eventlog-module.patch similarity index 100% rename from recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-add-xen-txt-eventlog-module.patch rename to recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt-add-xen-txt-eventlog-module.patch diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt.cfg b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt.cfg new file mode 100644 index 0000000000..46904f44b7 --- /dev/null +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt.cfg @@ -0,0 +1,2 @@ +CONFIG_XEN_TXT=y +CONTIG_TXT_INFO=y diff --git a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.scc b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt.scc similarity index 60% rename from recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.scc rename to recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt.scc index 46327960da..c8dca1c461 100644 --- a/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt-evtlog/xen-txt-evtlog.scc +++ b/recipes-kernel/linux/files/openxt-kmeta/patches/xen-txt/xen-txt.scc @@ -4,5 +4,7 @@ define KFEATURE_COMPATIBILITY all # Use Xen custom hypercall to retrieve and expose the eventlog in the securityfs. patch xen-txt-add-xen-txt-eventlog-module.patch +# Add a small platform device to expose TXT configuration registers in the securityfs. +patch 0001-txt_info-expose-TXT-conf-registers-to-userland.patch -kconf hardware xen-txt-evtlog.cfg +kconf hardware xen-txt.cfg diff --git a/recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb b/recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb index 0659d36a16..e62e5fd648 100644 --- a/recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb +++ b/recipes-kernel/linux/linux-yocto-openxt-dom0_5.4.bb @@ -61,7 +61,7 @@ KERNEL_FEATURES += " \ patches/openxt-tpm/openxt-tpm.scc \ patches/openxt-usbback/openxt-usbback.scc \ patches/openxt-video-quirks/openxt-video-quirks.scc \ - patches/xen-txt-evtlog/xen-txt-evtlog.scc \ + patches/xen-txt/xen-txt.scc \ patches/xsa-155/xsa-155.scc \ " diff --git a/recipes-openxt/txt-info-module/files/sources/Kbuild b/recipes-openxt/txt-info-module/files/sources/Kbuild deleted file mode 100644 index 0aaa2a8a5a..0000000000 --- a/recipes-openxt/txt-info-module/files/sources/Kbuild +++ /dev/null @@ -1,3 +0,0 @@ -obj-m += txt_info.o - -ccflags-y := -I$(src)/include diff --git a/recipes-openxt/txt-info-module/files/sources/Makefile b/recipes-openxt/txt-info-module/files/sources/Makefile deleted file mode 100644 index 4a9cce3b0d..0000000000 --- a/recipes-openxt/txt-info-module/files/sources/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -ifneq ($(KERNELRELEASE),) -# kbuild part of makefile -include Kbuild - -else -# normal makefile -KERNEL_VERSION ?= `uname -r` -KERNEL_SRC ?= /lib/modules/$(KERNEL_VERSION)/build -INSTALL_HDR_PATH ?= /usr - -default: - $(MAKE) -C $(KERNEL_SRC) M=$$PWD - -clean: - $(MAKE) -C $(KERNEL_SRC) M=$$PWD clean - -modules_install: - $(MAKE) -C $(KERNEL_SRC) M=$$PWD modules_install - -endif diff --git a/recipes-openxt/txt-info-module/files/sources/txt_info.c b/recipes-openxt/txt-info-module/files/sources/txt_info.c deleted file mode 100644 index ebece6a506..0000000000 --- a/recipes-openxt/txt-info-module/files/sources/txt_info.c +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include -#include -#include - -#define TXT_PUB_CR_BASE 0xfed30000 -#define TXT_PUB_CR_SIZE 0x10000 -static const struct resource txt_resources[] = { - { - .start = TXT_PUB_CR_BASE, - .end = TXT_PUB_CR_BASE + TXT_PUB_CR_SIZE - 1, - .flags = IORESOURCE_MEM, - }, -}; -#define TXT_PUB_CR_INDEX 0 - -struct platform_device *pdev; -struct txt_info { - void __iomem *cr_pub; - void __iomem *cr_priv; -}; -static struct txt_info txt_info; - -static void __iomem *txt_info_map_regs(struct platform_device *pdev, - size_t index) -{ - struct resource *res; - void __iomem *base; - - res = platform_get_resource(pdev, IORESOURCE_MEM, index); - if (IS_ERR(res)) { - dev_dbg(&pdev->dev, - "Failed to access IOMEM resource %zu.\n", index); - return res; - } - - base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (IS_ERR(base)) - dev_dbg(&pdev->dev, - "Failed to ioremap configuration registers.\n"); - - return base; -} - -/* Registers offset from TXT_PUB_CR_BASE */ -#define TXT_STS_OFFSET 0x000 -#define TXT_ESTS_OFFSET 0x008 -#define TXT_ERRORCODE_OFFSET 0x030 -#define TXT_VER_FSBIF_OFFSET 0x100 -#define TXT_DIDVID_OFFSET 0x110 -#define TXT_VER_QPIIF_OFFSET 0x200 - -#define DECLARE_PUB_SHOW_U8(name, offset) \ -static ssize_t name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ -{ \ - uint8_t v = ioread8(txt_info.cr_pub + (offset)); \ - return sprintf(buf, "%#04x\n", v); \ -} \ -static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); - -#define DECLARE_PUB_SHOW_U32(name, offset) \ -static ssize_t name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ -{ \ - uint32_t v = ioread32(txt_info.cr_pub + (offset)); \ - return sprintf(buf, "%#010x\n", v); \ -} \ -static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); - -#define DECLARE_PUB_SHOW_U64(name, offset) \ -static ssize_t name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, char *buf) \ -{ \ - uint64_t v = ioread32(txt_info.cr_pub + (offset) + 0x4); \ - v <<= 32; \ - v |= ioread32(txt_info.cr_pub + (offset)); \ - return sprintf(buf, "%#018llx\n", v); \ -} \ -static struct kobj_attribute txt_attr_##name = __ATTR_RO(name); - -DECLARE_PUB_SHOW_U64(sts, TXT_STS_OFFSET); -DECLARE_PUB_SHOW_U8(ests, TXT_ESTS_OFFSET); -DECLARE_PUB_SHOW_U32(errorcode, TXT_ERRORCODE_OFFSET); -DECLARE_PUB_SHOW_U32(ver_fsbif, TXT_VER_FSBIF_OFFSET); -DECLARE_PUB_SHOW_U64(didvid, TXT_DIDVID_OFFSET); -DECLARE_PUB_SHOW_U32(ver_qpiif, TXT_VER_QPIIF_OFFSET); - -static struct attribute *txt_subsys_attrs[] = { - &txt_attr_sts.attr, - &txt_attr_ests.attr, - &txt_attr_errorcode.attr, - &txt_attr_ver_fsbif.attr, - &txt_attr_didvid.attr, - &txt_attr_ver_qpiif.attr, - NULL, -}; - -static umode_t txt_attr_is_visible(struct kobject *kobj, - struct attribute *attr, int n) -{ - return attr->mode; -} - -static const struct attribute_group txt_subsys_attr_group = { - .attrs = txt_subsys_attrs, - .is_visible = txt_attr_is_visible, -}; - -struct kobject *txt_kobj; - -static int __init init_txt_info(void) -{ - int rc; - void __iomem *base; - - pr_info("%s\n", __func__); - - pdev = platform_device_register_simple( - "txt", -1, txt_resources, ARRAY_SIZE(txt_resources)); - if (IS_ERR(pdev)) { - rc = PTR_ERR(pdev); - pr_err("Failed to register txt platform device driver (%d).\n", rc); - goto fail_register; - } - - base = txt_info_map_regs(pdev, TXT_PUB_CR_INDEX); - if (IS_ERR(base)) { - rc = PTR_ERR(base); - dev_err(&pdev->dev, - "Failed to map TXT public resources (%d).\n", rc); - goto fail_map_pub; - } - txt_info.cr_pub = base; - - rc = sysfs_create_group(&pdev->dev.kobj, &txt_subsys_attr_group); - if (rc) { - dev_err(&pdev->dev, "Failed to create sysfs group (%d).\n", rc); - goto fail_sysfs; - } - - return 0; - -fail_sysfs: - devm_iounmap(&pdev->dev, txt_info.cr_pub); -fail_map_pub: - platform_device_unregister(pdev); -fail_register: - return rc; -} - -static void __exit cleanup_txt_info(void) -{ - pr_info("%s\n", __func__); - - if (pdev) - platform_device_unregister(pdev); -} - -module_init(init_txt_info); -module_exit(cleanup_txt_info); - -MODULE_AUTHOR("Assured Information Security, Inc"); -MODULE_DESCRIPTION("TXT driver."); -MODULE_VERSION("1.0"); -MODULE_LICENSE("GPL"); diff --git a/recipes-openxt/txt-info-module/txt-info-module_1.0.bb b/recipes-openxt/txt-info-module/txt-info-module_1.0.bb deleted file mode 100644 index 7f9c0b66a7..0000000000 --- a/recipes-openxt/txt-info-module/txt-info-module_1.0.bb +++ /dev/null @@ -1,20 +0,0 @@ -SUMMARY = "Out-of-tree module to expose TXT resources to user-land." -DESCRIPTION = "TXT exposes configuration registers documented in its Software \ -Development Guide. Accessing these registers in sometimes necessary for \ -userland software to perform checks and validate compatibility with software \ -resources." -LICENSE = "GPLv2" -LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" - -SRC_URI = " \ - file://sources/Kbuild \ - file://sources/Makefile \ - file://sources/txt_info.c \ -" - -S = "${WORKDIR}/sources" - -inherit module -inherit module-signing - -KERNEL_MODULE_AUTOLOAD += "txt-info"