diff options
Diffstat (limited to 'debian/patches/features')
25 files changed, 4071 insertions, 0 deletions
diff --git a/debian/patches/features/all/aufs5/aufs5-base.patch b/debian/patches/features/all/aufs5/aufs5-base.patch new file mode 100644 index 000000000..60f24b56b --- /dev/null +++ b/debian/patches/features/all/aufs5/aufs5-base.patch @@ -0,0 +1,332 @@ +From: J. R. Okajima <hooanon05@yahoo.co.jp> +Date: Tue Apr 7 22:14:47 2020 +0900 +Subject: aufs5.6 base patch +Origin: https://github.com/sfjro/aufs5-standalone/tree/7c07d9737e9de058981f020d66ac0d4407a80899 +Bug-Debian: https://bugs.debian.org/541828 + +Patch headers added by debian/bin/genpatch-aufs + +SPDX-License-Identifier: GPL-2.0 +aufs5.6 base patch + +diff --git a/MAINTAINERS b/MAINTAINERS +index b4a43a9e7fbc..32f7c8c48001 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2984,6 +2984,19 @@ F: include/linux/audit.h + F: include/uapi/linux/audit.h + F: kernel/audit* + ++AUFS (advanced multi layered unification filesystem) FILESYSTEM ++M: "J. R. Okajima" <hooanon05g@gmail.com> ++L: aufs-users@lists.sourceforge.net (members only) ++L: linux-unionfs@vger.kernel.org ++W: http://aufs.sourceforge.net ++T: git://github.com/sfjro/aufs4-linux.git ++S: Supported ++F: Documentation/filesystems/aufs/ ++F: Documentation/ABI/testing/debugfs-aufs ++F: Documentation/ABI/testing/sysfs-aufs ++F: fs/aufs/ ++F: include/uapi/linux/aufs_type.h ++ + AUXILIARY DISPLAY DRIVERS + M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com> + S: Maintained +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 475e1a738560..8d77e68aa52b 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -763,6 +763,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + return error; + } + ++/* ++ * for AUFS ++ * no get/put for file. ++ */ ++struct file *loop_backing_file(struct super_block *sb) ++{ ++ struct file *ret; ++ struct loop_device *l; ++ ++ ret = NULL; ++ if (MAJOR(sb->s_dev) == LOOP_MAJOR) { ++ l = sb->s_bdev->bd_disk->private_data; ++ ret = l->lo_backing_file; ++ } ++ return ret; ++} ++EXPORT_SYMBOL_GPL(loop_backing_file); ++ + /* loop sysfs attributes */ + + static ssize_t loop_attr_show(struct device *dev, char *page, +diff --git a/fs/dcache.c b/fs/dcache.c +index 361ea7ab30ea..3cd36474f302 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1285,7 +1285,7 @@ enum d_walk_ret { + * + * The @enter() callbacks are called with d_lock held. + */ +-static void d_walk(struct dentry *parent, void *data, ++void d_walk(struct dentry *parent, void *data, + enum d_walk_ret (*enter)(void *, struct dentry *)) + { + struct dentry *this_parent; +diff --git a/fs/fcntl.c b/fs/fcntl.c +index 2e4c0fa2074b..0b28a37f7e50 100644 +--- a/fs/fcntl.c ++++ b/fs/fcntl.c +@@ -32,7 +32,7 @@ + + #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) + +-static int setfl(int fd, struct file * filp, unsigned long arg) ++int setfl(int fd, struct file *filp, unsigned long arg) + { + struct inode * inode = file_inode(filp); + int error = 0; +@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg) + + if (filp->f_op->check_flags) + error = filp->f_op->check_flags(arg); ++ if (!error && filp->f_op->setfl) ++ error = filp->f_op->setfl(filp, arg); + if (error) + return error; + +diff --git a/fs/inode.c b/fs/inode.c +index 72c4c347afb7..a7ff2099c2ef 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1768,7 +1768,7 @@ EXPORT_SYMBOL(generic_update_time); + * This does the actual work of updating an inodes time or version. Must have + * had called mnt_want_write() before calling this. + */ +-static int update_time(struct inode *inode, struct timespec64 *time, int flags) ++int update_time(struct inode *inode, struct timespec64 *time, int flags) + { + if (inode->i_op->update_time) + return inode->i_op->update_time(inode, time, flags); +diff --git a/fs/namespace.c b/fs/namespace.c +index f30ed401cc6d..8ddebaf7ad57 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -792,6 +792,12 @@ static inline int check_mnt(struct mount *mnt) + return mnt->mnt_ns == current->nsproxy->mnt_ns; + } + ++/* for aufs, CONFIG_AUFS_BR_FUSE */ ++int is_current_mnt_ns(struct vfsmount *mnt) ++{ ++ return check_mnt(real_mount(mnt)); ++} ++ + /* + * vfsmount lock must be held for write + */ +diff --git a/fs/read_write.c b/fs/read_write.c +index 4fb797822567..744831cd0094 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -507,6 +507,28 @@ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t + return ret; + } + ++vfs_readf_t vfs_readf(struct file *file) ++{ ++ const struct file_operations *fop = file->f_op; ++ ++ if (fop->read) ++ return fop->read; ++ if (fop->read_iter) ++ return new_sync_read; ++ return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */ ++} ++ ++vfs_writef_t vfs_writef(struct file *file) ++{ ++ const struct file_operations *fop = file->f_op; ++ ++ if (fop->write) ++ return fop->write; ++ if (fop->write_iter) ++ return new_sync_write; ++ return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */ ++} ++ + /* caller is responsible for file_start_write/file_end_write */ + ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) + { +diff --git a/fs/splice.c b/fs/splice.c +index d7c8a7c4db07..f0b625e27554 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -839,8 +839,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); + /* + * Attempt to initiate a splice from pipe to file. + */ +-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, +- loff_t *ppos, size_t len, unsigned int flags) ++long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags) + { + if (out->f_op->splice_write) + return out->f_op->splice_write(pipe, out, ppos, len, flags); +@@ -850,9 +850,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + /* + * Attempt to initiate a splice from a file to a pipe. + */ +-static long do_splice_to(struct file *in, loff_t *ppos, +- struct pipe_inode_info *pipe, size_t len, +- unsigned int flags) ++long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) + { + int ret; + +diff --git a/fs/sync.c b/fs/sync.c +index 1373a610dc78..b7b5a0a0df6f 100644 +--- a/fs/sync.c ++++ b/fs/sync.c +@@ -28,7 +28,7 @@ + * wait == 1 case since in that case write_inode() functions do + * sync_dirty_buffer() and thus effectively write one block at a time. + */ +-static int __sync_filesystem(struct super_block *sb, int wait) ++int __sync_filesystem(struct super_block *sb, int wait) + { + if (wait) + sync_inodes_sb(sb); +diff --git a/include/linux/fs.h b/include/linux/fs.h +index f5abba86107d..0b008da5678d 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1360,6 +1360,7 @@ extern void fasync_free(struct fasync_struct *); + /* can be called from interrupts */ + extern void kill_fasync(struct fasync_struct **, int, int); + ++extern int setfl(int fd, struct file *filp, unsigned long arg); + extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); + extern int f_setown(struct file *filp, unsigned long arg, int force); + extern void f_delown(struct file *filp); +@@ -1848,6 +1849,7 @@ struct file_operations { + ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); + unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + int (*check_flags)(int); ++ int (*setfl)(struct file *, unsigned long); + int (*flock) (struct file *, int, struct file_lock *); + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); + ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); +@@ -1918,6 +1920,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, + struct iovec *fast_pointer, + struct iovec **ret_pointer); + ++typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *); ++typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t, ++ loff_t *); ++vfs_readf_t vfs_readf(struct file *file); ++vfs_writef_t vfs_writef(struct file *file); ++ + extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); + extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); + extern ssize_t vfs_readv(struct file *, const struct iovec __user *, +@@ -2352,6 +2360,7 @@ extern int current_umask(void); + extern void ihold(struct inode * inode); + extern void iput(struct inode *); + extern int generic_update_time(struct inode *, struct timespec64 *, int); ++extern int update_time(struct inode *, struct timespec64 *, int); + + /* /sys/fs */ + extern struct kobject *fs_kobj; +@@ -2633,6 +2642,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) + return false; + } + #endif ++extern int __sync_filesystem(struct super_block *, int); + extern int sync_filesystem(struct super_block *); + extern const struct file_operations def_blk_fops; + extern const struct file_operations def_chr_fops; +diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h +index 8fce5c98a4b0..c1a3f172e97a 100644 +--- a/include/linux/lockdep.h ++++ b/include/linux/lockdep.h +@@ -395,6 +395,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock, + return lock->key == key; + } + ++struct lock_class *lockdep_hlock_class(struct held_lock *hlock); ++ + /* + * Acquire a lock. + * +@@ -540,6 +542,7 @@ struct lockdep_map { }; + + #define lockdep_depth(tsk) (0) + ++#define lockdep_is_held(lock) (1) + #define lockdep_is_held_type(l, r) (1) + + #define lockdep_assert_held(l) do { (void)(l); } while (0) +diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h +index 8f882f5881e8..6b9808f09843 100644 +--- a/include/linux/mnt_namespace.h ++++ b/include/linux/mnt_namespace.h +@@ -7,12 +7,15 @@ struct mnt_namespace; + struct fs_struct; + struct user_namespace; + struct ns_common; ++struct vfsmount; + + extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *, + struct user_namespace *, struct fs_struct *); + extern void put_mnt_ns(struct mnt_namespace *ns); + extern struct ns_common *from_mnt_ns(struct mnt_namespace *); + ++extern int is_current_mnt_ns(struct vfsmount *mnt); ++ + extern const struct file_operations proc_mounts_operations; + extern const struct file_operations proc_mountinfo_operations; + extern const struct file_operations proc_mountstats_operations; +diff --git a/include/linux/splice.h b/include/linux/splice.h +index 5c47013f708e..fef6c59ed92a 100644 +--- a/include/linux/splice.h ++++ b/include/linux/splice.h +@@ -93,4 +93,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *); + + extern const struct pipe_buf_operations page_cache_pipe_buf_ops; + extern const struct pipe_buf_operations default_pipe_buf_ops; ++ ++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags); ++extern long do_splice_to(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags); + #endif +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index 29a8de4c50b9..6cfff5e18c84 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -169,7 +169,7 @@ static + struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; + static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS); + +-static inline struct lock_class *hlock_class(struct held_lock *hlock) ++inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) + { + unsigned int class_idx = hlock->class_idx; + +@@ -190,6 +190,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock) + */ + return lock_classes + class_idx; + } ++#define hlock_class(hlock) lockdep_hlock_class(hlock) + + #ifdef CONFIG_LOCK_STAT + static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); +-- +2.27.0 + diff --git a/debian/patches/features/all/aufs5/aufs5-mmap.patch b/debian/patches/features/all/aufs5/aufs5-mmap.patch new file mode 100644 index 000000000..4cf1e0b2b --- /dev/null +++ b/debian/patches/features/all/aufs5/aufs5-mmap.patch @@ -0,0 +1,405 @@ +From: J. R. Okajima <hooanon05@yahoo.co.jp> +Date: Tue Apr 7 22:14:47 2020 +0900 +Subject: aufs5.6 mmap patch +Origin: https://github.com/sfjro/aufs5-standalone/tree/7c07d9737e9de058981f020d66ac0d4407a80899 +Bug-Debian: https://bugs.debian.org/541828 + +Patch headers added by debian/bin/genpatch-aufs + +SPDX-License-Identifier: GPL-2.0 +aufs5.6 mmap patch + +Index: debian-kernel/fs/proc/base.c +=================================================================== +--- debian-kernel.orig/fs/proc/base.c ++++ debian-kernel/fs/proc/base.c +@@ -2170,7 +2170,7 @@ static int map_files_get_link(struct den + rc = -ENOENT; + vma = find_exact_vma(mm, vm_start, vm_end); + if (vma && vma->vm_file) { +- *path = vma->vm_file->f_path; ++ *path = vma_pr_or_file(vma)->f_path; + path_get(path); + rc = 0; + } +Index: debian-kernel/fs/proc/nommu.c +=================================================================== +--- debian-kernel.orig/fs/proc/nommu.c ++++ debian-kernel/fs/proc/nommu.c +@@ -40,7 +40,10 @@ static int nommu_region_show(struct seq_ + file = region->vm_file; + + if (file) { +- struct inode *inode = file_inode(region->vm_file); ++ struct inode *inode; ++ ++ file = vmr_pr_or_file(region); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + } +Index: debian-kernel/fs/proc/task_mmu.c +=================================================================== +--- debian-kernel.orig/fs/proc/task_mmu.c ++++ debian-kernel/fs/proc/task_mmu.c +@@ -280,7 +280,10 @@ show_map_vma(struct seq_file *m, struct + const char *name = NULL; + + if (file) { +- struct inode *inode = file_inode(vma->vm_file); ++ struct inode *inode; ++ ++ file = vma_pr_or_file(vma); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; +@@ -1793,7 +1796,7 @@ static int show_numa_map(struct seq_file + struct proc_maps_private *proc_priv = &numa_priv->proc_maps; + struct vm_area_struct *vma = v; + struct numa_maps *md = &numa_priv->md; +- struct file *file = vma->vm_file; ++ struct file *file = vma_pr_or_file(vma); + struct mm_struct *mm = vma->vm_mm; + struct mempolicy *pol; + char buffer[64]; +Index: debian-kernel/fs/proc/task_nommu.c +=================================================================== +--- debian-kernel.orig/fs/proc/task_nommu.c ++++ debian-kernel/fs/proc/task_nommu.c +@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_fil + file = vma->vm_file; + + if (file) { +- struct inode *inode = file_inode(vma->vm_file); ++ struct inode *inode; ++ ++ file = vma_pr_or_file(vma); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; +Index: debian-kernel/include/linux/mm.h +=================================================================== +--- debian-kernel.orig/include/linux/mm.h ++++ debian-kernel/include/linux/mm.h +@@ -1684,6 +1684,28 @@ static inline void unmap_shared_mapping_ + unmap_mapping_range(mapping, holebegin, holelen, 0); + } + ++extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int); ++extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[], ++ int); ++extern void vma_do_get_file(struct vm_area_struct *, const char[], int); ++extern void vma_do_fput(struct vm_area_struct *, const char[], int); ++ ++#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ ++ __LINE__) ++#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ ++ __LINE__) ++#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) ++#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) ++ ++#ifndef CONFIG_MMU ++extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); ++extern void vmr_do_fput(struct vm_region *, const char[], int); ++ ++#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ ++ __LINE__) ++#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__) ++#endif /* !CONFIG_MMU */ ++ + extern int access_process_vm(struct task_struct *tsk, unsigned long addr, + void *buf, int len, unsigned int gup_flags); + extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, +Index: debian-kernel/include/linux/mm_types.h +=================================================================== +--- debian-kernel.orig/include/linux/mm_types.h ++++ debian-kernel/include/linux/mm_types.h +@@ -276,6 +276,7 @@ struct vm_region { + unsigned long vm_top; /* region allocated to here */ + unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ + struct file *vm_file; /* the backing file or NULL */ ++ struct file *vm_prfile; /* the virtual backing file or NULL */ + + int vm_usage; /* region usage count (access under nommu_region_sem) */ + bool vm_icache_flushed : 1; /* true if the icache has been flushed for +@@ -355,6 +356,7 @@ struct vm_area_struct { + unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE + units */ + struct file * vm_file; /* File we map to (can be NULL). */ ++ struct file *vm_prfile; /* shadow of vm_file */ + void * vm_private_data; /* was vm_pte (shared mem) */ + + #ifdef CONFIG_SWAP +Index: debian-kernel/kernel/fork.c +=================================================================== +--- debian-kernel.orig/kernel/fork.c ++++ debian-kernel/kernel/fork.c +@@ -570,7 +570,7 @@ static __latent_entropy int dup_mmap(str + struct inode *inode = file_inode(file); + struct address_space *mapping = file->f_mapping; + +- get_file(file); ++ vma_get_file(tmp); + if (tmp->vm_flags & VM_DENYWRITE) + atomic_dec(&inode->i_writecount); + i_mmap_lock_write(mapping); +Index: debian-kernel/mm/Makefile +=================================================================== +--- debian-kernel.orig/mm/Makefile ++++ debian-kernel/mm/Makefile +@@ -52,7 +52,7 @@ obj-y := filemap.o mempool.o oom_kill. + mm_init.o percpu.o slab_common.o \ + compaction.o vmacache.o \ + interval_tree.o list_lru.o workingset.o \ +- debug.o gup.o $(mmu-y) ++ prfile.o debug.o gup.o $(mmu-y) + + # Give 'page_alloc' its own module-parameter namespace + page-alloc-y := page_alloc.o +Index: debian-kernel/mm/filemap.c +=================================================================== +--- debian-kernel.orig/mm/filemap.c ++++ debian-kernel/mm/filemap.c +@@ -2676,7 +2676,7 @@ vm_fault_t filemap_page_mkwrite(struct v + vm_fault_t ret = VM_FAULT_LOCKED; + + sb_start_pagefault(inode->i_sb); +- file_update_time(vmf->vma->vm_file); ++ vma_file_update_time(vmf->vma); + lock_page(page); + if (page->mapping != inode->i_mapping) { + unlock_page(page); +Index: debian-kernel/mm/mmap.c +=================================================================== +--- debian-kernel.orig/mm/mmap.c ++++ debian-kernel/mm/mmap.c +@@ -179,7 +179,7 @@ static struct vm_area_struct *remove_vma + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + mpol_put(vma_policy(vma)); + vm_area_free(vma); + return next; +@@ -910,7 +910,7 @@ again: + if (remove_next) { + if (file) { + uprobe_munmap(next, next->vm_start, next->vm_end); +- fput(file); ++ vma_fput(vma); + } + if (next->anon_vma) + anon_vma_merge(vma, next); +@@ -1831,8 +1831,8 @@ out: + return addr; + + unmap_and_free_vma: ++ vma_fput(vma); + vma->vm_file = NULL; +- fput(file); + + /* Undo any partial mapping done by a device driver. */ + unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); +@@ -2683,7 +2683,7 @@ int __split_vma(struct mm_struct *mm, st + goto out_free_mpol; + + if (new->vm_file) +- get_file(new->vm_file); ++ vma_get_file(new); + + if (new->vm_ops && new->vm_ops->open) + new->vm_ops->open(new); +@@ -2702,7 +2702,7 @@ int __split_vma(struct mm_struct *mm, st + if (new->vm_ops && new->vm_ops->close) + new->vm_ops->close(new); + if (new->vm_file) +- fput(new->vm_file); ++ vma_fput(new); + unlink_anon_vmas(new); + out_free_mpol: + mpol_put(vma_policy(new)); +@@ -2894,7 +2894,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsign + struct vm_area_struct *vma; + unsigned long populate = 0; + unsigned long ret = -EINVAL; +- struct file *file; ++ struct file *file, *prfile; + + pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", + current->comm, current->pid); +@@ -2969,10 +2969,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsign + } + } + +- file = get_file(vma->vm_file); ++ vma_get_file(vma); ++ file = vma->vm_file; ++ prfile = vma->vm_prfile; + ret = do_mmap_pgoff(vma->vm_file, start, size, + prot, flags, pgoff, &populate, NULL); ++ if (!IS_ERR_VALUE(ret) && file && prfile) { ++ struct vm_area_struct *new_vma; ++ ++ new_vma = find_vma(mm, ret); ++ if (!new_vma->vm_prfile) ++ new_vma->vm_prfile = prfile; ++ if (new_vma != vma) ++ get_file(prfile); ++ } ++ /* ++ * two fput()s instead of vma_fput(vma), ++ * coz vma may not be available anymore. ++ */ + fput(file); ++ if (prfile) ++ fput(prfile); + out: + mmap_write_unlock(mm); + if (populate) +@@ -3263,7 +3280,7 @@ struct vm_area_struct *copy_vma(struct v + if (anon_vma_clone(new_vma, vma)) + goto out_free_mempol; + if (new_vma->vm_file) +- get_file(new_vma->vm_file); ++ vma_get_file(new_vma); + if (new_vma->vm_ops && new_vma->vm_ops->open) + new_vma->vm_ops->open(new_vma); + vma_link(mm, new_vma, prev, rb_link, rb_parent); +Index: debian-kernel/mm/nommu.c +=================================================================== +--- debian-kernel.orig/mm/nommu.c ++++ debian-kernel/mm/nommu.c +@@ -540,7 +540,7 @@ static void __put_nommu_region(struct vm + up_write(&nommu_region_sem); + + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + + /* IO memory and memory shared directly out of the pagecache + * from ramfs/tmpfs mustn't be released here */ +@@ -672,7 +672,7 @@ static void delete_vma(struct mm_struct + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + put_nommu_region(vma->vm_region); + vm_area_free(vma); + } +@@ -1195,7 +1195,7 @@ unsigned long do_mmap(struct file *file, + goto error_just_free; + } + } +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + region = pregion; + result = start; +@@ -1272,10 +1272,10 @@ error_just_free: + up_write(&nommu_region_sem); + error: + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + vm_area_free(vma); + return ret; + +Index: debian-kernel/mm/prfile.c +=================================================================== +--- /dev/null ++++ debian-kernel/mm/prfile.c +@@ -0,0 +1,86 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Mainly for aufs which mmap(2) different file and wants to print different ++ * path in /proc/PID/maps. ++ * Call these functions via macros defined in linux/mm.h. ++ * ++ * See Documentation/filesystems/aufs/design/06mmap.txt ++ * ++ * Copyright (c) 2014-2020 Junjro R. Okajima ++ * Copyright (c) 2014 Ian Campbell ++ */ ++ ++#include <linux/mm.h> ++#include <linux/file.h> ++#include <linux/fs.h> ++ ++/* #define PRFILE_TRACE */ ++static inline void prfile_trace(struct file *f, struct file *pr, ++ const char func[], int line, const char func2[]) ++{ ++#ifdef PRFILE_TRACE ++ if (pr) ++ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); ++#endif ++} ++ ++void vma_do_file_update_time(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ file_update_time(f); ++ if (f && pr) ++ file_update_time(pr); ++} ++ ++struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ get_file(f); ++ if (f && pr) ++ get_file(pr); ++} ++ ++void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++ ++#ifndef CONFIG_MMU ++struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[], ++ int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vmr_do_fput(struct vm_region *region, const char func[], int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++#endif /* !CONFIG_MMU */ diff --git a/debian/patches/features/all/aufs5/aufs5-standalone.patch b/debian/patches/features/all/aufs5/aufs5-standalone.patch new file mode 100644 index 000000000..ffd06c8ce --- /dev/null +++ b/debian/patches/features/all/aufs5/aufs5-standalone.patch @@ -0,0 +1,308 @@ +From: J. R. Okajima <hooanon05@yahoo.co.jp> +Date: Tue Apr 7 22:14:47 2020 +0900 +Subject: aufs5.6 standalone patch +Origin: https://github.com/sfjro/aufs5-standalone/tree/7c07d9737e9de058981f020d66ac0d4407a80899 +Bug-Debian: https://bugs.debian.org/541828 + +Patch headers added by debian/bin/genpatch-aufs + +SPDX-License-Identifier: GPL-2.0 +aufs5.6 standalone patch + +Index: debian-kernel/fs/dcache.c +=================================================================== +--- debian-kernel.orig/fs/dcache.c ++++ debian-kernel/fs/dcache.c +@@ -1390,6 +1390,7 @@ rename_retry: + seq = 1; + goto again; + } ++EXPORT_SYMBOL_GPL(d_walk); + + struct check_mount { + struct vfsmount *mnt; +@@ -2935,6 +2936,7 @@ void d_exchange(struct dentry *dentry1, + + write_sequnlock(&rename_lock); + } ++EXPORT_SYMBOL_GPL(d_exchange); + + /** + * d_ancestor - search for an ancestor +Index: debian-kernel/fs/exec.c +=================================================================== +--- debian-kernel.orig/fs/exec.c ++++ debian-kernel/fs/exec.c +@@ -111,6 +111,7 @@ bool path_noexec(const struct path *path + return (path->mnt->mnt_flags & MNT_NOEXEC) || + (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); + } ++EXPORT_SYMBOL_GPL(path_noexec); + + #ifdef CONFIG_USELIB + /* +Index: debian-kernel/fs/fcntl.c +=================================================================== +--- debian-kernel.orig/fs/fcntl.c ++++ debian-kernel/fs/fcntl.c +@@ -85,6 +85,7 @@ int setfl(int fd, struct file *filp, uns + out: + return error; + } ++EXPORT_SYMBOL_GPL(setfl); + + static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, + int force) +Index: debian-kernel/fs/file_table.c +=================================================================== +--- debian-kernel.orig/fs/file_table.c ++++ debian-kernel/fs/file_table.c +@@ -162,6 +162,7 @@ over: + } + return ERR_PTR(-ENFILE); + } ++EXPORT_SYMBOL_GPL(alloc_empty_file); + + /* + * Variant of alloc_empty_file() that doesn't check and modify nr_files. +@@ -376,6 +377,7 @@ void __fput_sync(struct file *file) + } + + EXPORT_SYMBOL(fput); ++EXPORT_SYMBOL_GPL(__fput_sync); + + void __init files_init(void) + { +Index: debian-kernel/fs/inode.c +=================================================================== +--- debian-kernel.orig/fs/inode.c ++++ debian-kernel/fs/inode.c +@@ -1774,6 +1774,7 @@ int update_time(struct inode *inode, str + return inode->i_op->update_time(inode, time, flags); + return generic_update_time(inode, time, flags); + } ++EXPORT_SYMBOL_GPL(update_time); + + /** + * touch_atime - update the access time +Index: debian-kernel/fs/namespace.c +=================================================================== +--- debian-kernel.orig/fs/namespace.c ++++ debian-kernel/fs/namespace.c +@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *m + mnt_dec_writers(real_mount(mnt)); + preempt_enable(); + } ++EXPORT_SYMBOL_GPL(__mnt_drop_write); + + /** + * mnt_drop_write - give up write access to a mount +@@ -797,6 +798,7 @@ int is_current_mnt_ns(struct vfsmount *m + { + return check_mnt(real_mount(mnt)); + } ++EXPORT_SYMBOL_GPL(is_current_mnt_ns); + + /* + * vfsmount lock must be held for write +@@ -1961,6 +1963,7 @@ int iterate_mounts(int (*f)(struct vfsmo + } + return 0; + } ++EXPORT_SYMBOL_GPL(iterate_mounts); + + static void lock_mnt_tree(struct mount *mnt) + { +Index: debian-kernel/fs/notify/group.c +=================================================================== +--- debian-kernel.orig/fs/notify/group.c ++++ debian-kernel/fs/notify/group.c +@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_ + { + refcount_inc(&group->refcnt); + } ++EXPORT_SYMBOL_GPL(fsnotify_get_group); + + /* + * Drop a reference to a group. Free it if it's through. +Index: debian-kernel/fs/open.c +=================================================================== +--- debian-kernel.orig/fs/open.c ++++ debian-kernel/fs/open.c +@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, l + inode_unlock(dentry->d_inode); + return ret; + } ++EXPORT_SYMBOL_GPL(do_truncate); + + long vfs_truncate(const struct path *path, loff_t length) + { +Index: debian-kernel/fs/read_write.c +=================================================================== +--- debian-kernel.orig/fs/read_write.c ++++ debian-kernel/fs/read_write.c +@@ -488,6 +488,7 @@ ssize_t vfs_read(struct file *file, char + inc_syscr(current); + return ret; + } ++EXPORT_SYMBOL_GPL(vfs_read); + + static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) + { +@@ -517,6 +518,7 @@ vfs_readf_t vfs_readf(struct file *file) + return new_sync_read; + return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */ + } ++EXPORT_SYMBOL_GPL(vfs_readf); + + vfs_writef_t vfs_writef(struct file *file) + { +@@ -528,6 +530,7 @@ vfs_writef_t vfs_writef(struct file *fil + return new_sync_write; + return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */ + } ++EXPORT_SYMBOL_GPL(vfs_writef); + + /* caller is responsible for file_start_write/file_end_write */ + ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) +@@ -608,6 +611,7 @@ ssize_t vfs_write(struct file *file, con + file_end_write(file); + return ret; + } ++EXPORT_SYMBOL_GPL(vfs_write); + + /* file_ppos returns &file->f_pos or NULL if file is stream */ + static inline loff_t *file_ppos(struct file *file) +Index: debian-kernel/fs/splice.c +=================================================================== +--- debian-kernel.orig/fs/splice.c ++++ debian-kernel/fs/splice.c +@@ -870,6 +870,7 @@ long do_splice_to(struct file *in, loff_ + return in->f_op->splice_read(in, ppos, pipe, len, flags); + return default_file_splice_read(in, ppos, pipe, len, flags); + } ++EXPORT_SYMBOL_GPL(do_splice_from); + + /** + * splice_direct_to_actor - splices data directly between two non-pipes +@@ -1016,6 +1017,7 @@ static int direct_splice_actor(struct pi + return do_splice_from(pipe, file, sd->opos, sd->total_len, + sd->flags); + } ++EXPORT_SYMBOL_GPL(do_splice_to); + + /** + * do_splice_direct - splices data directly between two files +Index: debian-kernel/fs/sync.c +=================================================================== +--- debian-kernel.orig/fs/sync.c ++++ debian-kernel/fs/sync.c +@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block + sb->s_op->sync_fs(sb, wait); + return __sync_blockdev(sb->s_bdev, wait); + } ++EXPORT_SYMBOL_GPL(__sync_filesystem); + + /* + * Write out and wait upon all dirty data associated with this +Index: debian-kernel/fs/xattr.c +=================================================================== +--- debian-kernel.orig/fs/xattr.c ++++ debian-kernel/fs/xattr.c +@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry + *xattr_value = value; + return error; + } ++EXPORT_SYMBOL_GPL(vfs_getxattr_alloc); + + ssize_t + __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, +Index: debian-kernel/kernel/locking/lockdep.c +=================================================================== +--- debian-kernel.orig/kernel/locking/lockdep.c ++++ debian-kernel/kernel/locking/lockdep.c +@@ -190,6 +190,7 @@ inline struct lock_class *lockdep_hlock_ + */ + return lock_classes + class_idx; + } ++EXPORT_SYMBOL_GPL(lockdep_hlock_class); + #define hlock_class(hlock) lockdep_hlock_class(hlock) + + #ifdef CONFIG_LOCK_STAT +Index: debian-kernel/kernel/task_work.c +=================================================================== +--- debian-kernel.orig/kernel/task_work.c ++++ debian-kernel/kernel/task_work.c +@@ -139,3 +139,4 @@ void task_work_run(void) + } while (work); + } + } ++EXPORT_SYMBOL_GPL(task_work_run); +Index: debian-kernel/security/security.c +=================================================================== +--- debian-kernel.orig/security/security.c ++++ debian-kernel/security/security.c +@@ -1096,6 +1096,7 @@ int security_path_rmdir(const struct pat + return 0; + return call_int_hook(path_rmdir, 0, dir, dentry); + } ++EXPORT_SYMBOL_GPL(security_path_rmdir); + + int security_path_unlink(const struct path *dir, struct dentry *dentry) + { +@@ -1112,6 +1113,7 @@ int security_path_symlink(const struct p + return 0; + return call_int_hook(path_symlink, 0, dir, dentry, old_name); + } ++EXPORT_SYMBOL_GPL(security_path_symlink); + + int security_path_link(struct dentry *old_dentry, const struct path *new_dir, + struct dentry *new_dentry) +@@ -1120,6 +1122,7 @@ int security_path_link(struct dentry *ol + return 0; + return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); + } ++EXPORT_SYMBOL_GPL(security_path_link); + + int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, + const struct path *new_dir, struct dentry *new_dentry, +@@ -1147,6 +1150,7 @@ int security_path_truncate(const struct + return 0; + return call_int_hook(path_truncate, 0, path); + } ++EXPORT_SYMBOL_GPL(security_path_truncate); + + int security_path_chmod(const struct path *path, umode_t mode) + { +@@ -1154,6 +1158,7 @@ int security_path_chmod(const struct pat + return 0; + return call_int_hook(path_chmod, 0, path, mode); + } ++EXPORT_SYMBOL_GPL(security_path_chmod); + + int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) + { +@@ -1161,6 +1166,7 @@ int security_path_chown(const struct pat + return 0; + return call_int_hook(path_chown, 0, path, uid, gid); + } ++EXPORT_SYMBOL_GPL(security_path_chown); + + int security_path_chroot(const struct path *path) + { +@@ -1261,6 +1267,7 @@ int security_inode_permission(struct ino + return 0; + return call_int_hook(inode_permission, 0, inode, mask); + } ++EXPORT_SYMBOL_GPL(security_inode_permission); + + int security_inode_setattr(struct dentry *dentry, struct iattr *attr) + { +@@ -1453,6 +1460,7 @@ int security_file_permission(struct file + + return fsnotify_perm(file, mask); + } ++EXPORT_SYMBOL_GPL(security_file_permission); + + int security_file_alloc(struct file *file) + { diff --git a/debian/patches/features/all/db-mok-keyring/0001-MODSIGN-do-not-load-mok-when-secure-boot-disabled.patch b/debian/patches/features/all/db-mok-keyring/0001-MODSIGN-do-not-load-mok-when-secure-boot-disabled.patch new file mode 100644 index 000000000..5d4ec82f0 --- /dev/null +++ b/debian/patches/features/all/db-mok-keyring/0001-MODSIGN-do-not-load-mok-when-secure-boot-disabled.patch @@ -0,0 +1,40 @@ +From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com> +Date: Tue, 13 Mar 2018 18:37:59 +0800 +Subject: [PATCH 1/5] MODSIGN: do not load mok when secure boot disabled +Origin: https://lore.kernel.org/patchwork/patch/933173/ + +The mok can not be trusted when the secure boot is disabled. Which +means that the kernel embedded certificate is the only trusted key. + +Due to db/dbx are authenticated variables, they needs manufacturer's +KEK for update. So db/dbx are secure when secureboot disabled. + +Cc: David Howells <dhowells@redhat.com> +Cc: Josh Boyer <jwboyer@fedoraproject.org> +Cc: James Bottomley <James.Bottomley@HansenPartnership.com> +Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com> +[Rebased by Luca Boccassi] +[bwh: Forward-ported to 5.5.9: + - get_cert_list() takes a pointer to status and returns the cert list + - Adjust filename] +[Salvatore Bonaccorso: Forward-ported to 5.10: Refresh for changes in +38a1f03aa240 ("integrity: Move import of MokListRT certs to a separate +routine"). Refresh in context for change in ebd9c2ae369a ("integrity: Load mokx +variables into the blacklist keyring")] +--- + security/integrity/platform_certs/load_uefi.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +--- a/security/integrity/platform_certs/load_uefi.c ++++ b/security/integrity/platform_certs/load_uefi.c +@@ -176,6 +176,10 @@ static int __init load_uefi_certs(void) + kfree(dbx); + } + ++ /* the MOK can not be trusted when secure boot is disabled */ ++ if (!efi_enabled(EFI_SECURE_BOOT)) ++ return 0; ++ + mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status); + if (!mokx) { + if (status == EFI_NOT_FOUND) diff --git a/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch b/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch new file mode 100644 index 000000000..a7ec5ccb5 --- /dev/null +++ b/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch @@ -0,0 +1,117 @@ +From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com> +Date: Tue, 13 Mar 2018 18:38:02 +0800 +Subject: [PATCH 3/4] MODSIGN: checking the blacklisted hash before loading a + kernel module +Origin: https://lore.kernel.org/patchwork/patch/933175/ + +This patch adds the logic for checking the kernel module's hash +base on blacklist. The hash must be generated by sha256 and enrolled +to dbx/mokx. + +For example: + sha256sum sample.ko + mokutil --mokx --import-hash $HASH_RESULT + +Whether the signature on ko file is stripped or not, the hash can be +compared by kernel. + +Cc: David Howells <dhowells@redhat.com> +Cc: Josh Boyer <jwboyer@fedoraproject.org> +Cc: James Bottomley <James.Bottomley@HansenPartnership.com> +Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com> +[Rebased by Luca Boccassi] +--- + kernel/module_signing.c | 59 +++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 57 insertions(+), 2 deletions(-) + +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -12,15 +12,62 @@ + #include <linux/string.h> + #include <linux/verification.h> + #include <crypto/public_key.h> ++#include <crypto/hash.h> ++#include <keys/system_keyring.h> + #include "module-internal.h" + ++static int mod_is_hash_blacklisted(const void *mod, size_t verifylen) ++{ ++ struct crypto_shash *tfm; ++ struct shash_desc *desc; ++ size_t digest_size, desc_size; ++ u8 *digest; ++ int ret = 0; ++ ++ tfm = crypto_alloc_shash("sha256", 0, 0); ++ if (IS_ERR(tfm)) ++ goto error_return; ++ ++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); ++ digest_size = crypto_shash_digestsize(tfm); ++ digest = kzalloc(digest_size + desc_size, GFP_KERNEL); ++ if (!digest) { ++ pr_err("digest memory buffer allocate fail\n"); ++ ret = -ENOMEM; ++ goto error_digest; ++ } ++ desc = (void *)digest + digest_size; ++ desc->tfm = tfm; ++ ret = crypto_shash_init(desc); ++ if (ret < 0) ++ goto error_shash; ++ ++ ret = crypto_shash_finup(desc, mod, verifylen, digest); ++ if (ret < 0) ++ goto error_shash; ++ ++ pr_debug("%ld digest: %*phN\n", verifylen, (int) digest_size, digest); ++ ++ ret = is_hash_blacklisted(digest, digest_size, "bin"); ++ if (ret == -EKEYREJECTED) ++ pr_err("Module hash %*phN is blacklisted\n", ++ (int) digest_size, digest); ++ ++error_shash: ++ kfree(digest); ++error_digest: ++ crypto_free_shash(tfm); ++error_return: ++ return ret; ++} ++ + /* + * Verify the signature on a module. + */ + int mod_verify_sig(const void *mod, struct load_info *info) + { + struct module_signature ms; +- size_t sig_len, modlen = info->len; ++ size_t sig_len, modlen = info->len, wholelen; + int ret; + + pr_devel("==>%s(,%zu)\n", __func__, modlen); +@@ -28,6 +75,7 @@ int mod_verify_sig(const void *mod, stru + if (modlen <= sizeof(ms)) + return -EBADMSG; + ++ wholelen = modlen + sizeof(MODULE_SIG_STRING) - 1; + memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); + + ret = mod_check_sig(&ms, modlen, "module"); +@@ -38,8 +86,15 @@ int mod_verify_sig(const void *mod, stru + modlen -= sig_len + sizeof(ms); + info->len = modlen; + +- return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, ++ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, + VERIFY_USE_SECONDARY_KEYRING, + VERIFYING_MODULE_SIGNATURE, + NULL, NULL); ++ pr_devel("verify_pkcs7_signature() = %d\n", ret); ++ ++ /* checking hash of module is in blacklist */ ++ if (!ret) ++ ret = mod_is_hash_blacklisted(mod, wholelen); ++ ++ return ret; + } diff --git a/debian/patches/features/all/db-mok-keyring/0004-MODSIGN-check-the-attributes-of-db-and-mok.patch b/debian/patches/features/all/db-mok-keyring/0004-MODSIGN-check-the-attributes-of-db-and-mok.patch new file mode 100644 index 000000000..530885944 --- /dev/null +++ b/debian/patches/features/all/db-mok-keyring/0004-MODSIGN-check-the-attributes-of-db-and-mok.patch @@ -0,0 +1,113 @@ +From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com> +Date: Tue, 13 Mar 2018 18:38:03 +0800 +Subject: [PATCH 4/4] MODSIGN: check the attributes of db and mok +Origin: https://lore.kernel.org/patchwork/patch/933176/ + +That's better for checking the attributes of db and mok variables +before loading certificates to kernel keyring. + +For db and dbx, both of them are authenticated variables. Which +means that they can only be modified by manufacturer's key. So +the kernel should checks EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS +attribute before we trust it. + +For mok-rt and mokx-rt, both of them are created by shim boot loader +to forward the mok/mokx content to runtime. They must be runtime-volatile +variables. So kernel should checks that the attributes map did not set +EFI_VARIABLE_NON_VOLATILE bit before we trust it. + +Cc: David Howells <dhowells@redhat.com> +Cc: Josh Boyer <jwboyer@fedoraproject.org> +Cc: James Bottomley <James.Bottomley@HansenPartnership.com> +Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com> +[Rebased by Luca Boccassi] +[bwh: Forward-ported to 5.5.9: + - get_cert_list() takes a pointer to status and returns the cert list + - Adjust filename, context] +[bwh: Forward-ported to 5.10: MokListRT and MokListXRT are now both + loaded through a single code path.] +--- + security/integrity/platform_certs/load_uefi.c | 27 ++++++++++++++----- + 1 file changed, 21 insertions(+), 6 deletions(-) + +--- a/security/integrity/platform_certs/load_uefi.c ++++ b/security/integrity/platform_certs/load_uefi.c +@@ -35,11 +35,13 @@ static __init bool uefi_check_ignore_db( + * Get a certificate list blob from the named EFI variable. + */ + static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid, +- unsigned long *size, efi_status_t *status) ++ unsigned long *size, efi_status_t *status, ++ u32 pos_attr, u32 neg_attr) + { + unsigned long lsize = 4; + unsigned long tmpdb[4]; + void *db; ++ u32 attr = 0; + + *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb); + if (*status == EFI_NOT_FOUND) +@@ -54,13 +56,22 @@ static __init void *get_cert_list(efi_ch + if (!db) + return NULL; + +- *status = efi.get_variable(name, guid, NULL, &lsize, db); ++ *status = efi.get_variable(name, guid, &attr, &lsize, db); + if (*status != EFI_SUCCESS) { + kfree(db); + pr_err("Error reading db var: 0x%lx\n", *status); + return NULL; + } + ++ /* must have positive attributes and no negative attributes */ ++ if ((pos_attr && !(attr & pos_attr)) || ++ (neg_attr && (attr & neg_attr))) { ++ kfree(db); ++ pr_err("Error reading db var attributes: 0x%016x\n", attr); ++ *status = EFI_SECURITY_VIOLATION; ++ return NULL; ++ } ++ + *size = lsize; + return db; + } +@@ -106,7 +117,8 @@ static int __init load_moklist_certs(voi + /* Get MokListRT. It might not exist, so it isn't an error + * if we can't get it. + */ +- mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status); ++ mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status, ++ 0, EFI_VARIABLE_NON_VOLATILE); + if (mok) { + rc = parse_efi_signature_list("UEFI:MokListRT", + mok, moksize, get_handler_for_db); +@@ -145,7 +157,8 @@ static int __init load_uefi_certs(void) + * if we can't get them. + */ + if (!uefi_check_ignore_db()) { +- db = get_cert_list(L"db", &secure_var, &dbsize, &status); ++ db = get_cert_list(L"db", &secure_var, &dbsize, &status, ++ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, 0); + if (!db) { + if (status == EFI_NOT_FOUND) + pr_debug("MODSIGN: db variable wasn't found\n"); +@@ -161,7 +174,8 @@ static int __init load_uefi_certs(void) + } + } + +- dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status); ++ dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status, ++ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, 0); + if (!dbx) { + if (status == EFI_NOT_FOUND) + pr_debug("dbx variable wasn't found\n"); +@@ -180,7 +194,8 @@ static int __init load_uefi_certs(void) + if (!efi_enabled(EFI_SECURE_BOOT)) + return 0; + +- mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status); ++ mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status, ++ 0, EFI_VARIABLE_NON_VOLATILE); + if (!mokx) { + if (status == EFI_NOT_FOUND) + pr_debug("mokx variable wasn't found\n"); diff --git a/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch b/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch new file mode 100644 index 000000000..f00bf3d24 --- /dev/null +++ b/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch @@ -0,0 +1,37 @@ +From: Robert Holmes <robeholmes@gmail.com> +Date: Tue, 23 Apr 2019 07:39:29 +0000 +Subject: [PATCH] KEYS: Make use of platform keyring for module signature + verify +Bug-Debian: https://bugs.debian.org/935945 +Origin: https://src.fedoraproject.org/rpms/kernel/raw/master/f/KEYS-Make-use-of-platform-keyring-for-module-signature.patch + +This patch completes commit 278311e417be ("kexec, KEYS: Make use of +platform keyring for signature verify") which, while adding the +platform keyring for bzImage verification, neglected to also add +this keyring for module verification. + +As such, kernel modules signed with keys from the MokList variable +were not successfully verified. + +Signed-off-by: Robert Holmes <robeholmes@gmail.com> +Signed-off-by: Jeremy Cline <jcline@redhat.com> +--- + kernel/module_signing.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -135,6 +135,13 @@ int mod_verify_sig(const void *mod, stru + VERIFYING_MODULE_SIGNATURE, + NULL, NULL); + pr_devel("verify_pkcs7_signature() = %d\n", ret); ++ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) { ++ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, ++ VERIFY_USE_PLATFORM_KEYRING, ++ VERIFYING_MODULE_SIGNATURE, ++ NULL, NULL); ++ pr_devel("verify_pkcs7_signature() = %d\n", ret); ++ } + + /* checking hash of module is in blacklist */ + if (!ret) diff --git a/debian/patches/features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch b/debian/patches/features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch new file mode 100644 index 000000000..2ae3ddde4 --- /dev/null +++ b/debian/patches/features/all/db-mok-keyring/modsign-make-shash-allocation-failure-fatal.patch @@ -0,0 +1,28 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Sun, 05 May 2019 13:45:06 +0100 +Subject: MODSIGN: Make shash allocation failure fatal + +mod_is_hash_blacklisted() currently returns 0 (suceess) if +crypto_alloc_shash() fails. This should instead be a fatal error, +so unwrap and pass up the error code. + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/kernel/module_signing.c ++++ b/kernel/module_signing.c +@@ -51,11 +51,13 @@ static int mod_is_hash_blacklisted(const + struct shash_desc *desc; + size_t digest_size, desc_size; + u8 *digest; +- int ret = 0; ++ int ret; + + tfm = crypto_alloc_shash("sha256", 0, 0); +- if (IS_ERR(tfm)) ++ if (IS_ERR(tfm)) { ++ ret = PTR_ERR(tfm); + goto error_return; ++ } + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + digest_size = crypto_shash_digestsize(tfm); diff --git a/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch new file mode 100644 index 000000000..a24ba17ef --- /dev/null +++ b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch @@ -0,0 +1,149 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Mon, 24 Aug 2009 23:19:58 +0100 +Subject: af9005: Use request_firmware() to load register init script +Forwarded: no + +Read the register init script from the Windows driver. This is sick +but should avoid the potential copyright infringement in distributing +a version of the script which is directly derived from the driver. +--- + drivers/media/dvb/dvb-usb/Kconfig | 2 +- + drivers/media/dvb/dvb-usb/af9005-fe.c | 66 ++++++++++++++++++++++++++------ + 2 files changed, 54 insertions(+), 14 deletions(-) + +Index: debian-kernel/drivers/media/usb/dvb-usb/Kconfig +=================================================================== +--- debian-kernel.orig/drivers/media/usb/dvb-usb/Kconfig ++++ debian-kernel/drivers/media/usb/dvb-usb/Kconfig +@@ -260,10 +260,10 @@ config DVB_USB_OPERA1 + + config DVB_USB_AF9005 + tristate "Afatech AF9005 DVB-T USB1.1 support" +- depends on BROKEN + depends on DVB_USB + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT ++ select FW_LOADER + help + Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver + and the TerraTec Cinergy T USB XE (Rev.1) +Index: debian-kernel/drivers/media/usb/dvb-usb/af9005-fe.c +=================================================================== +--- debian-kernel.orig/drivers/media/usb/dvb-usb/af9005-fe.c ++++ debian-kernel/drivers/media/usb/dvb-usb/af9005-fe.c +@@ -9,10 +9,26 @@ + * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information + */ + #include "af9005.h" +-#include "af9005-script.h" + #include "mt2060.h" + #include "qt1010.h" + #include <asm/div64.h> ++#include <linux/firmware.h> ++ ++/* Register initialisation script to be extracted from the Windows driver */ ++ ++typedef struct { ++ __le16 reg; ++ u8 pos; ++ u8 len; ++ u8 val; ++ u8 pad; ++} __packed RegDesc; ++ ++#define WIN_DRV_NAME "AF05BDA.sys" ++#define WIN_DRV_VERSION "6.3.2.1" ++#define WIN_DRV_SIZE 133504 ++#define WIN_DRV_SCRIPT_OFFSET 88316 ++#define WIN_DRV_SCRIPT_SIZE 1110 + + struct af9005_fe_state { + struct dvb_usb_device *d; +@@ -804,6 +820,8 @@ static int af9005_fe_init(struct dvb_fro + { + struct af9005_fe_state *state = fe->demodulator_priv; + struct dvb_usb_adapter *adap = fe->dvb->priv; ++ const struct firmware *fw; ++ const RegDesc *script; + int ret, i, scriptlen; + u8 temp, temp0 = 0, temp1 = 0, temp2 = 0; + u8 buf[2]; +@@ -956,37 +974,55 @@ static int af9005_fe_init(struct dvb_fro + if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01))) + return ret; + +- /* load init script */ +- deb_info("load init script\n"); +- scriptlen = sizeof(script) / sizeof(RegDesc); ++ /* load and validate init script */ ++ deb_info("load init script from Windows driver\n"); ++ ret = request_firmware(&fw, WIN_DRV_NAME, &state->d->udev->dev); ++ if (ret) ++ return ret; ++ BUILD_BUG_ON(sizeof(RegDesc) != 6); ++ if (fw->size != WIN_DRV_SIZE || ++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET, ++ "\x80\xa1\x00\x08\x0a\x00", 6) || ++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET + WIN_DRV_SCRIPT_SIZE - 6, ++ "\x49\xa3\x00\x06\x02\x00", 6)) { ++ err("%s is invalid - should be version %s, size %u bytes\n", ++ WIN_DRV_NAME, WIN_DRV_VERSION, WIN_DRV_SIZE); ++ ret = -EINVAL; ++ goto fail_release; ++ } ++ ++ script = (const RegDesc *)(fw->data + WIN_DRV_SCRIPT_OFFSET); ++ scriptlen = WIN_DRV_SCRIPT_SIZE / sizeof(RegDesc); + for (i = 0; i < scriptlen; i++) { ++ u16 reg = le16_to_cpu(script[i].reg); + if ((ret = +- af9005_write_register_bits(state->d, script[i].reg, ++ af9005_write_register_bits(state->d, reg, + script[i].pos, + script[i].len, script[i].val))) +- return ret; ++ goto fail_release; + /* save 3 bytes of original fcw */ +- if (script[i].reg == 0xae18) ++ if (reg == 0xae18) + temp2 = script[i].val; +- if (script[i].reg == 0xae19) ++ if (reg == 0xae19) + temp1 = script[i].val; +- if (script[i].reg == 0xae1a) ++ if (reg == 0xae1a) + temp0 = script[i].val; + + /* save original unplug threshold */ +- if (script[i].reg == xd_p_reg_unplug_th) ++ if (reg == xd_p_reg_unplug_th) + state->original_if_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_rf_gain_th) ++ if (reg == xd_p_reg_unplug_rf_gain_th) + state->original_rf_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th) ++ if (reg == xd_p_reg_unplug_dtop_if_gain_th) + state->original_dtop_if_unplug_th = script[i].val; +- if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th) ++ if (reg == xd_p_reg_unplug_dtop_rf_gain_th) + state->original_dtop_rf_unplug_th = script[i].val; + + } + state->original_fcw = + ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0; + ++ release_firmware(fw); + + /* save original TOPs */ + deb_info("save original TOPs\n"); +@@ -1066,6 +1102,10 @@ static int af9005_fe_init(struct dvb_fro + + deb_info("profit!\n"); + return 0; ++ ++fail_release: ++ release_firmware(fw); ++ return ret; + } + + static int af9005_fe_sleep(struct dvb_frontend *fe) diff --git a/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch b/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch new file mode 100644 index 000000000..7f9ee1cf9 --- /dev/null +++ b/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch @@ -0,0 +1,153 @@ +From: Linn Crosetto <linn@hpe.com> +Date: Tue, 30 Aug 2016 11:54:38 -0600 +Subject: arm64: add kernel config option to lock down when in Secure Boot mode +Bug-Debian: https://bugs.debian.org/831827 +Forwarded: no + +Add a kernel configuration option to lock down the kernel, to restrict +userspace's ability to modify the running kernel when UEFI Secure Boot is +enabled. Based on the x86 patch by Matthew Garrett. + +Determine the state of Secure Boot in the EFI stub and pass this to the +kernel using the FDT. + +Signed-off-by: Linn Crosetto <linn@hpe.com> +[bwh: Forward-ported to 4.10: adjust context] +[Lukas Wunner: Forward-ported to 4.11: drop parts applied upstream] +[bwh: Forward-ported to 4.15 and lockdown patch set: + - Pass result of efi_get_secureboot() in stub through to + efi_set_secure_boot() in main kernel + - Use lockdown API and naming] +[bwh: Forward-ported to 4.19.3: adjust context in update_fdt()] +[dannf: Moved init_lockdown() call after uefi_init(), fixing SB detection] +[bwh: Drop call to init_lockdown(), as efi_set_secure_boot() now calls this] +[bwh: Forward-ported to 5.6: efi_get_secureboot() no longer takes a + sys_table parameter] +[bwh: Forward-ported to 5.7: EFI initialisation from FDT was rewritten, so: + - Add Secure Boot mode to the parameter enumeration in fdtparams.c + - Add a parameter to efi_get_fdt_params() to return the Secure Boot mode + - Since Xen does not have a property name defined for Secure Boot mode, + change efi_get_fdt_prop() to handle a missing property name by clearing + the output variable] +[Salvatore Bonaccorso: Forward-ported to 5.10: f30f242fb131 ("efi: Rename +arm-init to efi-init common for all arch") renamed arm-init.c to efi-init.c] +--- + drivers/firmware/efi/efi-init.c | 5 ++++- + drivers/firmware/efi/fdtparams.c | 12 +++++++++++- + drivers/firmware/efi/libstub/fdt.c | 6 ++++++ + include/linux/efi.h | 3 ++- + 4 files changed, 23 insertions(+), 3 deletions(-) + +--- a/drivers/firmware/efi/efi-init.c ++++ b/drivers/firmware/efi/efi-init.c +@@ -210,9 +210,10 @@ void __init efi_init(void) + { + struct efi_memory_map_data data; + u64 efi_system_table; ++ u32 secure_boot; + + /* Grab UEFI information placed in FDT by stub */ +- efi_system_table = efi_get_fdt_params(&data); ++ efi_system_table = efi_get_fdt_params(&data, &secure_boot); + if (!efi_system_table) + return; + +@@ -234,6 +235,8 @@ void __init efi_init(void) + return; + } + ++ efi_set_secure_boot(secure_boot); ++ + reserve_regions(); + efi_esrt_init(); + efi_mokvar_table_init(); +--- a/drivers/firmware/efi/fdtparams.c ++++ b/drivers/firmware/efi/fdtparams.c +@@ -16,6 +16,7 @@ enum { + MMSIZE, + DCSIZE, + DCVERS, ++ SBMODE, + + PARAMCOUNT + }; +@@ -26,6 +27,7 @@ static __initconst const char name[][22] + [MMSIZE] = "MemMap Size ", + [DCSIZE] = "MemMap Desc. Size ", + [DCVERS] = "MemMap Desc. Version ", ++ [SBMODE] = "Secure Boot Enabled ", + }; + + static __initconst const struct { +@@ -41,6 +43,7 @@ static __initconst const struct { + [MMSIZE] = "xen,uefi-mmap-size", + [DCSIZE] = "xen,uefi-mmap-desc-size", + [DCVERS] = "xen,uefi-mmap-desc-ver", ++ [SBMODE] = "", + } + }, { + #endif +@@ -51,6 +54,7 @@ static __initconst const struct { + [MMSIZE] = "linux,uefi-mmap-size", + [DCSIZE] = "linux,uefi-mmap-desc-size", + [DCVERS] = "linux,uefi-mmap-desc-ver", ++ [SBMODE] = "linux,uefi-secure-boot", + } + } + }; +@@ -62,6 +66,11 @@ static int __init efi_get_fdt_prop(const + int len; + u64 val; + ++ if (!pname[0]) { ++ memset(var, 0, size); ++ return 0; ++ } ++ + prop = fdt_getprop(fdt, node, pname, &len); + if (!prop) + return 1; +@@ -79,7 +88,7 @@ static int __init efi_get_fdt_prop(const + return 0; + } + +-u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm) ++u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm, u32 *secure_boot) + { + const void *fdt = initial_boot_params; + unsigned long systab; +@@ -93,6 +102,7 @@ u64 __init efi_get_fdt_params(struct efi + [MMSIZE] = { &mm->size, sizeof(mm->size) }, + [DCSIZE] = { &mm->desc_size, sizeof(mm->desc_size) }, + [DCVERS] = { &mm->desc_version, sizeof(mm->desc_version) }, ++ [SBMODE] = { secure_boot, sizeof(*secure_boot) }, + }; + + BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name)); +--- a/drivers/firmware/efi/libstub/fdt.c ++++ b/drivers/firmware/efi/libstub/fdt.c +@@ -148,6 +148,12 @@ static efi_status_t update_fdt(void *ori + } + } + ++ fdt_val32 = cpu_to_fdt32(efi_get_secureboot()); ++ status = fdt_setprop(fdt, node, "linux,uefi-secure-boot", ++ &fdt_val32, sizeof(fdt_val32)); ++ if (status) ++ goto fdt_set_fail; ++ + /* Shrink the FDT back to its minimum size: */ + fdt_pack(fdt); + +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -665,7 +665,8 @@ extern void efi_mem_reserve(phys_addr_t + extern int efi_mem_reserve_persistent(phys_addr_t addr, u64 size); + extern void efi_initialize_iomem_resources(struct resource *code_resource, + struct resource *data_resource, struct resource *bss_resource); +-extern u64 efi_get_fdt_params(struct efi_memory_map_data *data); ++extern u64 efi_get_fdt_params(struct efi_memory_map_data *data, ++ u32 *secure_boot); + extern struct kobject *efi_kobj; + + extern int efi_reboot_quirk_mode; diff --git a/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch b/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch new file mode 100644 index 000000000..431281249 --- /dev/null +++ b/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch @@ -0,0 +1,152 @@ +From: David Howells <dhowells@redhat.com> +Date: Mon, 18 Feb 2019 12:45:03 +0000 +Subject: [28/30] efi: Add an EFI_SECURE_BOOT flag to indicate secure boot mode +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit?id=a5d70c55c603233c192b375f72116a395909da28 + +UEFI machines can be booted in Secure Boot mode. Add an EFI_SECURE_BOOT +flag that can be passed to efi_enabled() to find out whether secure boot is +enabled. + +Move the switch-statement in x86's setup_arch() that inteprets the +secure_boot boot parameter to generic code and set the bit there. + +Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> +Signed-off-by: David Howells <dhowells@redhat.com> +Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> +cc: linux-efi@vger.kernel.org +[rperier: Forward-ported to 5.5: + - Use pr_warn() + - Adjust context] +[bwh: Forward-ported to 5.6: adjust context] +[bwh: Forward-ported to 5.7: + - Use the next available bit in efi.flags + - Adjust context] +--- + arch/x86/kernel/setup.c | 14 +---------- + drivers/firmware/efi/Makefile | 1 + + drivers/firmware/efi/secureboot.c | 39 +++++++++++++++++++++++++++++++ + include/linux/efi.h | 16 ++++++++----- + 4 files changed, 51 insertions(+), 19 deletions(-) + create mode 100644 drivers/firmware/efi/secureboot.c + +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -1124,19 +1124,7 @@ void __init setup_arch(char **cmdline_p) + /* Allocate bigger log buffer */ + setup_log_buf(1); + +- if (efi_enabled(EFI_BOOT)) { +- switch (boot_params.secure_boot) { +- case efi_secureboot_mode_disabled: +- pr_info("Secure boot disabled\n"); +- break; +- case efi_secureboot_mode_enabled: +- pr_info("Secure boot enabled\n"); +- break; +- default: +- pr_info("Secure boot could not be determined\n"); +- break; +- } +- } ++ efi_set_secure_boot(boot_params.secure_boot); + + reserve_initrd(); + +--- a/drivers/firmware/efi/Makefile ++++ b/drivers/firmware/efi/Makefile +@@ -25,6 +25,7 @@ obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_m + obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o + obj-$(CONFIG_EFI_TEST) += test/ + obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o ++obj-$(CONFIG_EFI) += secureboot.o + obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o + obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o + obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o +--- /dev/null ++++ b/drivers/firmware/efi/secureboot.c +@@ -0,0 +1,39 @@ ++ ++/* Core kernel secure boot support. ++ * ++ * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include <linux/efi.h> ++#include <linux/kernel.h> ++#include <linux/printk.h> ++ ++/* ++ * Decide what to do when UEFI secure boot mode is enabled. ++ */ ++void __init efi_set_secure_boot(enum efi_secureboot_mode mode) ++{ ++ if (efi_enabled(EFI_BOOT)) { ++ switch (mode) { ++ case efi_secureboot_mode_disabled: ++ pr_info("Secure boot disabled\n"); ++ break; ++ case efi_secureboot_mode_enabled: ++ set_bit(EFI_SECURE_BOOT, &efi.flags); ++ pr_info("Secure boot enabled\n"); ++ break; ++ default: ++ pr_warn("Secure boot could not be determined (mode %u)\n", ++ mode); ++ break; ++ } ++ } ++} +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -776,6 +776,14 @@ extern int __init efi_setup_pcdp_console + #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */ + #define EFI_MEM_NO_SOFT_RESERVE 11 /* Is the kernel configured to ignore soft reservations? */ + #define EFI_PRESERVE_BS_REGIONS 12 /* Are EFI boot-services memory segments available? */ ++#define EFI_SECURE_BOOT 13 /* Are we in Secure Boot mode? */ ++ ++enum efi_secureboot_mode { ++ efi_secureboot_mode_unset, ++ efi_secureboot_mode_unknown, ++ efi_secureboot_mode_disabled, ++ efi_secureboot_mode_enabled, ++}; + + #ifdef CONFIG_EFI + /* +@@ -799,6 +807,7 @@ static inline bool efi_rt_services_suppo + { + return (efi.runtime_supported_mask & mask) == mask; + } ++extern void __init efi_set_secure_boot(enum efi_secureboot_mode mode); + #else + static inline bool efi_enabled(int feature) + { +@@ -822,6 +831,7 @@ static inline bool efi_rt_services_suppo + { + return false; + } ++static inline void efi_set_secure_boot(enum efi_secureboot_mode mode) {} + #endif + + extern int efi_status_to_err(efi_status_t status); +@@ -1083,12 +1093,6 @@ static inline bool efi_runtime_disabled( + extern void efi_call_virt_check_flags(unsigned long flags, const char *call); + extern unsigned long efi_call_virt_save_flags(void); + +-enum efi_secureboot_mode { +- efi_secureboot_mode_unset, +- efi_secureboot_mode_unknown, +- efi_secureboot_mode_disabled, +- efi_secureboot_mode_enabled, +-}; + enum efi_secureboot_mode efi_get_secureboot(void); + + #ifdef CONFIG_RESET_ATTACK_MITIGATION diff --git a/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch b/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch new file mode 100644 index 000000000..627e37154 --- /dev/null +++ b/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch @@ -0,0 +1,127 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Tue, 10 Sep 2019 11:54:28 +0100 +Subject: efi: Lock down the kernel if booted in secure boot mode + +Based on an earlier patch by David Howells, who wrote the following +description: + +> UEFI Secure Boot provides a mechanism for ensuring that the firmware will +> only load signed bootloaders and kernels. Certain use cases may also +> require that all kernel modules also be signed. Add a configuration option +> that to lock down the kernel - which includes requiring validly signed +> modules - if the kernel is secure-booted. + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kernel/setup.c | 4 ++-- + drivers/firmware/efi/secureboot.c | 3 +++ + include/linux/security.h | 6 ++++++ + security/lockdown/Kconfig | 15 +++++++++++++++ + security/lockdown/lockdown.c | 2 +- + 5 files changed, 27 insertions(+), 3 deletions(-) + +Index: debian-kernel/arch/x86/kernel/setup.c +=================================================================== +--- debian-kernel.orig/arch/x86/kernel/setup.c ++++ debian-kernel/arch/x86/kernel/setup.c +@@ -979,6 +979,8 @@ void __init setup_arch(char **cmdline_p) + if (efi_enabled(EFI_BOOT)) + efi_init(); + ++ efi_set_secure_boot(boot_params.secure_boot); ++ + dmi_setup(); + + /* +@@ -1130,8 +1132,6 @@ void __init setup_arch(char **cmdline_p) + /* Allocate bigger log buffer */ + setup_log_buf(1); + +- efi_set_secure_boot(boot_params.secure_boot); +- + reserve_initrd(); + + acpi_table_upgrade(); +Index: debian-kernel/drivers/firmware/efi/secureboot.c +=================================================================== +--- debian-kernel.orig/drivers/firmware/efi/secureboot.c ++++ debian-kernel/drivers/firmware/efi/secureboot.c +@@ -15,6 +15,7 @@ + #include <linux/efi.h> + #include <linux/kernel.h> + #include <linux/printk.h> ++#include <linux/security.h> + + /* + * Decide what to do when UEFI secure boot mode is enabled. +@@ -28,6 +29,10 @@ void __init efi_set_secure_boot(enum efi + break; + case efi_secureboot_mode_enabled: + set_bit(EFI_SECURE_BOOT, &efi.flags); ++#ifdef CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT ++ lock_kernel_down("EFI Secure Boot", ++ LOCKDOWN_INTEGRITY_MAX); ++#endif + pr_info("Secure boot enabled\n"); + break; + default: +Index: debian-kernel/include/linux/security.h +=================================================================== +--- debian-kernel.orig/include/linux/security.h ++++ debian-kernel/include/linux/security.h +@@ -451,6 +451,7 @@ int security_inode_notifysecctx(struct i + int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); + int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); + int security_locked_down(enum lockdown_reason what); ++int lock_kernel_down(const char *where, enum lockdown_reason level); + #else /* CONFIG_SECURITY */ + + static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data) +@@ -1291,6 +1292,11 @@ static inline int security_locked_down(e + { + return 0; + } ++static inline int ++lock_kernel_down(const char *where, enum lockdown_reason level) ++{ ++ return -EOPNOTSUPP; ++} + #endif /* CONFIG_SECURITY */ + + #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) +Index: debian-kernel/security/lockdown/Kconfig +=================================================================== +--- debian-kernel.orig/security/lockdown/Kconfig ++++ debian-kernel/security/lockdown/Kconfig +@@ -45,3 +45,18 @@ config LOCK_DOWN_KERNEL_FORCE_CONFIDENTI + disabled. + + endchoice ++ ++config LOCK_DOWN_IN_EFI_SECURE_BOOT ++ bool "Lock down the kernel in EFI Secure Boot mode" ++ default n ++ depends on SECURITY_LOCKDOWN_LSM ++ depends on EFI ++ select SECURITY_LOCKDOWN_LSM_EARLY ++ help ++ UEFI Secure Boot provides a mechanism for ensuring that the firmware ++ will only load signed bootloaders and kernels. Secure boot mode may ++ be determined from EFI variables provided by the system firmware if ++ not indicated by the boot parameters. ++ ++ Enabling this option results in kernel lockdown being ++ triggered in confidentiality mode if EFI Secure Boot is set. +Index: debian-kernel/security/lockdown/lockdown.c +=================================================================== +--- debian-kernel.orig/security/lockdown/lockdown.c ++++ debian-kernel/security/lockdown/lockdown.c +@@ -23,7 +23,7 @@ static const enum lockdown_reason lockdo + /* + * Put the kernel into lock-down mode. + */ +-static int lock_kernel_down(const char *where, enum lockdown_reason level) ++int lock_kernel_down(const char *where, enum lockdown_reason level) + { + if (kernel_locked_down >= level) + return -EPERM; diff --git a/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch b/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch new file mode 100644 index 000000000..5004e5dca --- /dev/null +++ b/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch @@ -0,0 +1,75 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Fri, 30 Aug 2019 15:54:24 +0100 +Subject: mtd: phram,slram: Disable when the kernel is locked down +Forwarded: https://lore.kernel.org/linux-security-module/20190830154720.eekfjt6c4jzvlbfz@decadent.org.uk/ + +These drivers allow mapping arbitrary memory ranges as MTD devices. +This should be disabled to preserve the kernel's integrity when it is +locked down. + +* Add the HWPARAM flag to the module parameters +* When slram is built-in, it uses __setup() to read kernel parameters, + so add an explicit check security_locked_down() check + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +Cc: Matthew Garrett <mjg59@google.com> +Cc: David Howells <dhowells@redhat.com> +Cc: Joern Engel <joern@lazybastard.org> +Cc: linux-mtd@lists.infradead.org +--- + drivers/mtd/devices/phram.c | 6 +++++- + drivers/mtd/devices/slram.c | 9 ++++++++- + 2 files changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/devices/phram.c ++++ b/drivers/mtd/devices/phram.c +@@ -294,7 +294,11 @@ static int phram_param_call(const char * + #endif + } + +-module_param_call(phram, phram_param_call, NULL, NULL, 0200); ++static const struct kernel_param_ops phram_param_ops = { ++ .set = phram_param_call ++}; ++__module_param_call(MODULE_PARAM_PREFIX, phram, &phram_param_ops, NULL, ++ 0200, -1, KERNEL_PARAM_FL_HWPARAM | hwparam_iomem); + MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\""); + + +--- a/drivers/mtd/devices/slram.c ++++ b/drivers/mtd/devices/slram.c +@@ -43,6 +43,7 @@ + #include <linux/ioctl.h> + #include <linux/init.h> + #include <linux/io.h> ++#include <linux/security.h> + + #include <linux/mtd/mtd.h> + +@@ -65,7 +66,7 @@ typedef struct slram_mtd_list { + #ifdef MODULE + static char *map[SLRAM_MAX_DEVICES_PARAMS]; + +-module_param_array(map, charp, NULL, 0); ++module_param_hw_array(map, charp, iomem, NULL, 0); + MODULE_PARM_DESC(map, "List of memory regions to map. \"map=<name>, <start>, <length / end>\""); + #else + static char *map; +@@ -281,11 +282,17 @@ static int __init init_slram(void) + #ifndef MODULE + char *devstart; + char *devlength; ++ int ret; + + if (!map) { + E("slram: not enough parameters.\n"); + return(-EINVAL); + } ++ ++ ret = security_locked_down(LOCKDOWN_MODULE_PARAMETERS); ++ if (ret) ++ return ret; ++ + while (map) { + devname = devstart = devlength = NULL; + diff --git a/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch b/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch new file mode 100644 index 000000000..33db1f765 --- /dev/null +++ b/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch @@ -0,0 +1,80 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Mon, 11 Jan 2016 15:23:55 +0000 +Subject: security,perf: Allow further restriction of perf_event_open +Forwarded: https://lkml.org/lkml/2016/1/11/587 + +When kernel.perf_event_open is set to 3 (or greater), disallow all +access to performance events by users without CAP_SYS_ADMIN. +Add a Kconfig symbol CONFIG_SECURITY_PERF_EVENTS_RESTRICT that +makes this value the default. + +This is based on a similar feature in grsecurity +(CONFIG_GRKERNSEC_PERF_HARDEN). This version doesn't include making +the variable read-only. It also allows enabling further restriction +at run-time regardless of whether the default is changed. + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/linux/perf_event.h | 5 +++++ + kernel/events/core.c | 8 ++++++++ + security/Kconfig | 9 +++++++++ + 3 files changed, 22 insertions(+) + +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -1305,6 +1305,11 @@ int perf_cpu_time_max_percent_handler(st + int perf_event_max_stack_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, loff_t *ppos); + ++static inline bool perf_paranoid_any(void) ++{ ++ return sysctl_perf_event_paranoid > 2; ++} ++ + /* Access to perf_event_open(2) syscall. */ + #define PERF_SECURITY_OPEN 0 + +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -408,8 +408,13 @@ static cpumask_var_t perf_online_mask; + * 0 - disallow raw tracepoint access for unpriv + * 1 - disallow cpu events for unpriv + * 2 - disallow kernel profiling for unpriv ++ * 3 - disallow all unpriv perf event use + */ ++#ifdef CONFIG_SECURITY_PERF_EVENTS_RESTRICT ++int sysctl_perf_event_paranoid __read_mostly = 3; ++#else + int sysctl_perf_event_paranoid __read_mostly = 2; ++#endif + + /* Minimum for 512 kiB + 1 user control page */ + int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */ +@@ -11785,6 +11790,9 @@ SYSCALL_DEFINE5(perf_event_open, + if (err) + return err; + ++ if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN)) ++ return -EACCES; ++ + /* Do we allow access to perf_event_open(2) ? */ + err = security_perf_event_open(&attr, PERF_SECURITY_OPEN); + if (err) +--- a/security/Kconfig ++++ b/security/Kconfig +@@ -19,6 +19,15 @@ config SECURITY_DMESG_RESTRICT + + If you are unsure how to answer this question, answer N. + ++config SECURITY_PERF_EVENTS_RESTRICT ++ bool "Restrict unprivileged use of performance events" ++ depends on PERF_EVENTS ++ help ++ If you say Y here, the kernel.perf_event_paranoid sysctl ++ will be set to 3 by default, and no unprivileged use of the ++ perf_event_open syscall will be permitted unless it is ++ changed. ++ + config SECURITY + bool "Enable different security models" + depends on SYSFS diff --git a/debian/patches/features/arm64/arm64-compat-Implement-misalignment-fixups-for-multi.patch b/debian/patches/features/arm64/arm64-compat-Implement-misalignment-fixups-for-multi.patch new file mode 100644 index 000000000..303e69f83 --- /dev/null +++ b/debian/patches/features/arm64/arm64-compat-Implement-misalignment-fixups-for-multi.patch @@ -0,0 +1,480 @@ +From: Ard Biesheuvel <ardb@kernel.org> +Date: Fri, 1 Jul 2022 15:53:22 +0200 +Subject: arm64: compat: Implement misalignment fixups for multiword loads +Origin: https://git.kernel.org/linus/3fc24ef32d3b9368f4c103dcd21d6a3f959b4870 + +The 32-bit ARM kernel implements fixups on behalf of user space when +using LDM/STM or LDRD/STRD instructions on addresses that are not 32-bit +aligned. This is not something that is supported by the architecture, +but was done anyway to increase compatibility with user space software, +which mostly targeted x86 at the time and did not care about aligned +accesses. + +This feature is one of the remaining impediments to being able to switch +to 64-bit kernels on 64-bit capable hardware running 32-bit user space, +so let's implement it for the arm64 compat layer as well. + +Note that the intent is to implement the exact same handling of +misaligned multi-word loads and stores as the 32-bit kernel does, +including what appears to be missing support for user space programs +that rely on SETEND to switch to a different byte order and back. Also, +like the 32-bit ARM version, we rely on the faulting address reported by +the CPU to infer the memory address, instead of decoding the instruction +fully to obtain this information. + +This implementation is taken from the 32-bit ARM tree, with all pieces +removed that deal with instructions other than LDRD/STRD and LDM/STM, or +that deal with alignment exceptions taken in kernel mode. + +Cc: debian-arm@lists.debian.org +Cc: Vagrant Cascadian <vagrant@debian.org> +Cc: Riku Voipio <riku.voipio@iki.fi> +Cc: Steve McIntyre <steve@einval.com> +Signed-off-by: Ard Biesheuvel <ardb@kernel.org> +Reviewed-by: Arnd Bergmann <arnd@arndb.de> +Link: https://lore.kernel.org/r/20220701135322.3025321-1-ardb@kernel.org +[catalin.marinas@arm.com: change the option to 'default n'] +Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> +--- + arch/arm64/Kconfig | 3 + + arch/arm64/include/asm/exception.h | 1 + + arch/arm64/kernel/Makefile | 1 + + arch/arm64/kernel/compat_alignment.c | 387 +++++++++++++++++++++++++++ + arch/arm64/mm/fault.c | 3 + + 5 files changed, 395 insertions(+) + create mode 100644 arch/arm64/kernel/compat_alignment.c + +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -1328,6 +1328,9 @@ config THUMB2_COMPAT_VDSO + Compile the compat vDSO with '-mthumb -fomit-frame-pointer' if y, + otherwise with '-marm'. + ++config COMPAT_ALIGNMENT_FIXUPS ++ bool "Fix up misaligned multi-word loads and stores in user space" ++ + menuconfig ARMV8_DEPRECATED + bool "Emulate deprecated/obsolete ARMv8 instructions" + depends on SYSCTL +--- a/arch/arm64/include/asm/exception.h ++++ b/arch/arm64/include/asm/exception.h +@@ -47,6 +47,7 @@ void do_el0_sys(unsigned long esr, struc + void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); + void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr); + void do_el0_cp15(unsigned long esr, struct pt_regs *regs); ++int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs); + void do_el0_svc(struct pt_regs *regs); + void do_el0_svc_compat(struct pt_regs *regs); + void do_el0_fpac(struct pt_regs *regs, unsigned long esr); +--- a/arch/arm64/kernel/Makefile ++++ b/arch/arm64/kernel/Makefile +@@ -28,6 +28,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE + obj-$(CONFIG_COMPAT) += sys32.o signal32.o \ + sys_compat.o + obj-$(CONFIG_COMPAT) += sigreturn32.o ++obj-$(CONFIG_COMPAT_ALIGNMENT_FIXUPS) += compat_alignment.o + obj-$(CONFIG_KUSER_HELPERS) += kuser32.o + obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o + obj-$(CONFIG_MODULES) += module.o +--- /dev/null ++++ b/arch/arm64/kernel/compat_alignment.c +@@ -0,0 +1,387 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// based on arch/arm/mm/alignment.c ++ ++#include <linux/compiler.h> ++#include <linux/errno.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/perf_event.h> ++#include <linux/uaccess.h> ++ ++#include <asm/exception.h> ++#include <asm/ptrace.h> ++#include <asm/traps.h> ++ ++/* ++ * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998 ++ * ++ * Speed optimisations and better fault handling by Russell King. ++ */ ++#define CODING_BITS(i) (i & 0x0e000000) ++ ++#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */ ++#define LDST_U_BIT(i) (i & (1 << 23)) /* Add offset */ ++#define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */ ++#define LDST_L_BIT(i) (i & (1 << 20)) /* Load */ ++ ++#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0) ++ ++#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */ ++ ++#define RN_BITS(i) ((i >> 16) & 15) /* Rn */ ++#define RD_BITS(i) ((i >> 12) & 15) /* Rd */ ++#define RM_BITS(i) (i & 15) /* Rm */ ++ ++#define REGMASK_BITS(i) (i & 0xffff) ++ ++#define BAD_INSTR 0xdeadc0de ++ ++/* Thumb-2 32 bit format per ARMv7 DDI0406A A6.3, either f800h,e800h,f800h */ ++#define IS_T32(hi16) \ ++ (((hi16) & 0xe000) == 0xe000 && ((hi16) & 0x1800)) ++ ++union offset_union { ++ unsigned long un; ++ signed long sn; ++}; ++ ++#define TYPE_ERROR 0 ++#define TYPE_FAULT 1 ++#define TYPE_LDST 2 ++#define TYPE_DONE 3 ++ ++static void ++do_alignment_finish_ldst(unsigned long addr, u32 instr, struct pt_regs *regs, ++ union offset_union offset) ++{ ++ if (!LDST_U_BIT(instr)) ++ offset.un = -offset.un; ++ ++ if (!LDST_P_BIT(instr)) ++ addr += offset.un; ++ ++ if (!LDST_P_BIT(instr) || LDST_W_BIT(instr)) ++ regs->regs[RN_BITS(instr)] = addr; ++} ++ ++static int ++do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs) ++{ ++ unsigned int rd = RD_BITS(instr); ++ unsigned int rd2; ++ int load; ++ ++ if ((instr & 0xfe000000) == 0xe8000000) { ++ /* ARMv7 Thumb-2 32-bit LDRD/STRD */ ++ rd2 = (instr >> 8) & 0xf; ++ load = !!(LDST_L_BIT(instr)); ++ } else if (((rd & 1) == 1) || (rd == 14)) { ++ return TYPE_ERROR; ++ } else { ++ load = ((instr & 0xf0) == 0xd0); ++ rd2 = rd + 1; ++ } ++ ++ if (load) { ++ unsigned int val, val2; ++ ++ if (get_user(val, (u32 __user *)addr) || ++ get_user(val2, (u32 __user *)(addr + 4))) ++ return TYPE_FAULT; ++ regs->regs[rd] = val; ++ regs->regs[rd2] = val2; ++ } else { ++ if (put_user(regs->regs[rd], (u32 __user *)addr) || ++ put_user(regs->regs[rd2], (u32 __user *)(addr + 4))) ++ return TYPE_FAULT; ++ } ++ return TYPE_LDST; ++} ++ ++/* ++ * LDM/STM alignment handler. ++ * ++ * There are 4 variants of this instruction: ++ * ++ * B = rn pointer before instruction, A = rn pointer after instruction ++ * ------ increasing address -----> ++ * | | r0 | r1 | ... | rx | | ++ * PU = 01 B A ++ * PU = 11 B A ++ * PU = 00 A B ++ * PU = 10 A B ++ */ ++static int ++do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) ++{ ++ unsigned int rd, rn, nr_regs, regbits; ++ unsigned long eaddr, newaddr; ++ unsigned int val; ++ ++ /* count the number of registers in the mask to be transferred */ ++ nr_regs = hweight16(REGMASK_BITS(instr)) * 4; ++ ++ rn = RN_BITS(instr); ++ newaddr = eaddr = regs->regs[rn]; ++ ++ if (!LDST_U_BIT(instr)) ++ nr_regs = -nr_regs; ++ newaddr += nr_regs; ++ if (!LDST_U_BIT(instr)) ++ eaddr = newaddr; ++ ++ if (LDST_P_EQ_U(instr)) /* U = P */ ++ eaddr += 4; ++ ++ for (regbits = REGMASK_BITS(instr), rd = 0; regbits; ++ regbits >>= 1, rd += 1) ++ if (regbits & 1) { ++ if (LDST_L_BIT(instr)) { ++ if (get_user(val, (u32 __user *)eaddr)) ++ return TYPE_FAULT; ++ if (rd < 15) ++ regs->regs[rd] = val; ++ else ++ regs->pc = val; ++ } else { ++ /* ++ * The PC register has a bias of +8 in ARM mode ++ * and +4 in Thumb mode. This means that a read ++ * of the value of PC should account for this. ++ * Since Thumb does not permit STM instructions ++ * to refer to PC, just add 8 here. ++ */ ++ val = (rd < 15) ? regs->regs[rd] : regs->pc + 8; ++ if (put_user(val, (u32 __user *)eaddr)) ++ return TYPE_FAULT; ++ } ++ eaddr += 4; ++ } ++ ++ if (LDST_W_BIT(instr)) ++ regs->regs[rn] = newaddr; ++ ++ return TYPE_DONE; ++} ++ ++/* ++ * Convert Thumb multi-word load/store instruction forms to equivalent ARM ++ * instructions so we can reuse ARM userland alignment fault fixups for Thumb. ++ * ++ * This implementation was initially based on the algorithm found in ++ * gdb/sim/arm/thumbemu.c. It is basically just a code reduction of same ++ * to convert only Thumb ld/st instruction forms to equivalent ARM forms. ++ * ++ * NOTES: ++ * 1. Comments below refer to ARM ARM DDI0100E Thumb Instruction sections. ++ * 2. If for some reason we're passed an non-ld/st Thumb instruction to ++ * decode, we return 0xdeadc0de. This should never happen under normal ++ * circumstances but if it does, we've got other problems to deal with ++ * elsewhere and we obviously can't fix those problems here. ++ */ ++ ++static unsigned long thumb2arm(u16 tinstr) ++{ ++ u32 L = (tinstr & (1<<11)) >> 11; ++ ++ switch ((tinstr & 0xf800) >> 11) { ++ /* 6.6.1 Format 1: */ ++ case 0xc000 >> 11: /* 7.1.51 STMIA */ ++ case 0xc800 >> 11: /* 7.1.25 LDMIA */ ++ { ++ u32 Rn = (tinstr & (7<<8)) >> 8; ++ u32 W = ((L<<Rn) & (tinstr&255)) ? 0 : 1<<21; ++ ++ return 0xe8800000 | W | (L<<20) | (Rn<<16) | ++ (tinstr&255); ++ } ++ ++ /* 6.6.1 Format 2: */ ++ case 0xb000 >> 11: /* 7.1.48 PUSH */ ++ case 0xb800 >> 11: /* 7.1.47 POP */ ++ if ((tinstr & (3 << 9)) == 0x0400) { ++ static const u32 subset[4] = { ++ 0xe92d0000, /* STMDB sp!,{registers} */ ++ 0xe92d4000, /* STMDB sp!,{registers,lr} */ ++ 0xe8bd0000, /* LDMIA sp!,{registers} */ ++ 0xe8bd8000 /* LDMIA sp!,{registers,pc} */ ++ }; ++ return subset[(L<<1) | ((tinstr & (1<<8)) >> 8)] | ++ (tinstr & 255); /* register_list */ ++ } ++ fallthrough; /* for illegal instruction case */ ++ ++ default: ++ return BAD_INSTR; ++ } ++} ++ ++/* ++ * Convert Thumb-2 32 bit LDM, STM, LDRD, STRD to equivalent instruction ++ * handlable by ARM alignment handler, also find the corresponding handler, ++ * so that we can reuse ARM userland alignment fault fixups for Thumb. ++ * ++ * @pinstr: original Thumb-2 instruction; returns new handlable instruction ++ * @regs: register context. ++ * @poffset: return offset from faulted addr for later writeback ++ * ++ * NOTES: ++ * 1. Comments below refer to ARMv7 DDI0406A Thumb Instruction sections. ++ * 2. Register name Rt from ARMv7 is same as Rd from ARMv6 (Rd is Rt) ++ */ ++static void * ++do_alignment_t32_to_handler(u32 *pinstr, struct pt_regs *regs, ++ union offset_union *poffset) ++{ ++ u32 instr = *pinstr; ++ u16 tinst1 = (instr >> 16) & 0xffff; ++ u16 tinst2 = instr & 0xffff; ++ ++ switch (tinst1 & 0xffe0) { ++ /* A6.3.5 Load/Store multiple */ ++ case 0xe880: /* STM/STMIA/STMEA,LDM/LDMIA, PUSH/POP T2 */ ++ case 0xe8a0: /* ...above writeback version */ ++ case 0xe900: /* STMDB/STMFD, LDMDB/LDMEA */ ++ case 0xe920: /* ...above writeback version */ ++ /* no need offset decision since handler calculates it */ ++ return do_alignment_ldmstm; ++ ++ case 0xf840: /* POP/PUSH T3 (single register) */ ++ if (RN_BITS(instr) == 13 && (tinst2 & 0x09ff) == 0x0904) { ++ u32 L = !!(LDST_L_BIT(instr)); ++ const u32 subset[2] = { ++ 0xe92d0000, /* STMDB sp!,{registers} */ ++ 0xe8bd0000, /* LDMIA sp!,{registers} */ ++ }; ++ *pinstr = subset[L] | (1<<RD_BITS(instr)); ++ return do_alignment_ldmstm; ++ } ++ /* Else fall through for illegal instruction case */ ++ break; ++ ++ /* A6.3.6 Load/store double, STRD/LDRD(immed, lit, reg) */ ++ case 0xe860: ++ case 0xe960: ++ case 0xe8e0: ++ case 0xe9e0: ++ poffset->un = (tinst2 & 0xff) << 2; ++ fallthrough; ++ ++ case 0xe940: ++ case 0xe9c0: ++ return do_alignment_ldrdstrd; ++ ++ /* ++ * No need to handle load/store instructions up to word size ++ * since ARMv6 and later CPUs can perform unaligned accesses. ++ */ ++ default: ++ break; ++ } ++ return NULL; ++} ++ ++static int alignment_get_arm(struct pt_regs *regs, __le32 __user *ip, u32 *inst) ++{ ++ __le32 instr = 0; ++ int fault; ++ ++ fault = get_user(instr, ip); ++ if (fault) ++ return fault; ++ ++ *inst = __le32_to_cpu(instr); ++ return 0; ++} ++ ++static int alignment_get_thumb(struct pt_regs *regs, __le16 __user *ip, u16 *inst) ++{ ++ __le16 instr = 0; ++ int fault; ++ ++ fault = get_user(instr, ip); ++ if (fault) ++ return fault; ++ ++ *inst = __le16_to_cpu(instr); ++ return 0; ++} ++ ++int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs) ++{ ++ union offset_union offset; ++ unsigned long instrptr; ++ int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs); ++ unsigned int type; ++ u32 instr = 0; ++ u16 tinstr = 0; ++ int isize = 4; ++ int thumb2_32b = 0; ++ int fault; ++ ++ instrptr = instruction_pointer(regs); ++ ++ if (compat_thumb_mode(regs)) { ++ __le16 __user *ptr = (__le16 __user *)(instrptr & ~1); ++ ++ fault = alignment_get_thumb(regs, ptr, &tinstr); ++ if (!fault) { ++ if (IS_T32(tinstr)) { ++ /* Thumb-2 32-bit */ ++ u16 tinst2; ++ fault = alignment_get_thumb(regs, ptr + 1, &tinst2); ++ instr = ((u32)tinstr << 16) | tinst2; ++ thumb2_32b = 1; ++ } else { ++ isize = 2; ++ instr = thumb2arm(tinstr); ++ } ++ } ++ } else { ++ fault = alignment_get_arm(regs, (__le32 __user *)instrptr, &instr); ++ } ++ ++ if (fault) ++ return 1; ++ ++ switch (CODING_BITS(instr)) { ++ case 0x00000000: /* 3.13.4 load/store instruction extensions */ ++ if (LDSTHD_I_BIT(instr)) ++ offset.un = (instr & 0xf00) >> 4 | (instr & 15); ++ else ++ offset.un = regs->regs[RM_BITS(instr)]; ++ ++ if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */ ++ (instr & 0x001000f0) == 0x000000f0) /* STRD */ ++ handler = do_alignment_ldrdstrd; ++ else ++ return 1; ++ break; ++ ++ case 0x08000000: /* ldm or stm, or thumb-2 32bit instruction */ ++ if (thumb2_32b) { ++ offset.un = 0; ++ handler = do_alignment_t32_to_handler(&instr, regs, &offset); ++ } else { ++ offset.un = 0; ++ handler = do_alignment_ldmstm; ++ } ++ break; ++ ++ default: ++ return 1; ++ } ++ ++ type = handler(addr, instr, regs); ++ ++ if (type == TYPE_ERROR || type == TYPE_FAULT) ++ return 1; ++ ++ if (type == TYPE_LDST) ++ do_alignment_finish_ldst(addr, instr, regs, offset); ++ ++ perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, regs->pc); ++ arm64_skip_faulting_instruction(regs, isize); ++ ++ return 0; ++} +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -610,6 +610,9 @@ static int __kprobes do_translation_faul + static int do_alignment_fault(unsigned long addr, unsigned int esr, + struct pt_regs *regs) + { ++ if (IS_ENABLED(CONFIG_COMPAT_ALIGNMENT_FIXUPS) && ++ compat_user_mode(regs)) ++ return do_compat_alignment_fixup(addr, regs); + do_bad_area(addr, esr, regs); + return 0; + } diff --git a/debian/patches/features/arm64/arm64-dts-raspberry-Add-support-for-the-CM4.patch b/debian/patches/features/arm64/arm64-dts-raspberry-Add-support-for-the-CM4.patch new file mode 100644 index 000000000..8619cfcdd --- /dev/null +++ b/debian/patches/features/arm64/arm64-dts-raspberry-Add-support-for-the-CM4.patch @@ -0,0 +1,423 @@ +From: Cyril Brulebois <cyril@debamax.com> +Date: Mon, 03 Jan 2022 21:59:36 +0100 +Subject: arm64: dts: Add support for Raspberry Pi Compute Module 4 IO Board + +It was introduced in mainline during the v5.16 release cycle. Since +many broadcom includes were reworked since v5.10, adding support would +involve more than cherry-picking a DTS addition that uses a few +includes. + +To avoid side effects on other models, introduce a DTS that leverages +some existing includes (bcm2711.dtsi and bcm283x-rpi-usb-host.dtsi) +and describes the rest without re-using parts of the Raspberry Pi 4 B +model. + +To avoid phandle rotation (0x16, 0x17, and 0x18) across 3 nodes +(dma@7e007000, i2c@7e205000, and interrupt-controller@7ef00100), and the +related changes in other nodes referencing them, hardcode 0x16 as the +phandle for interrupt-controller@7ef00100. This leads to an empty dtdiff +between this new DTB and the one produced by a v5.16-rc8 build. + +Authored-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> +Reviewed-by: Cyril Brulebois <cyril@debamax.com> + +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -1,5 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0 + dtb-$(CONFIG_ARCH_BCM2835) += bcm2711-rpi-4-b.dtb \ ++ bcm2711-rpi-cm4-io.dtb \ + bcm2837-rpi-3-a-plus.dtb \ + bcm2837-rpi-3-b.dtb \ + bcm2837-rpi-3-b-plus.dtb \ +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2711-rpi-cm4-io.dts +@@ -0,0 +1,2 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include "arm/bcm2711-rpi-cm4-io.dts" +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -93,6 +93,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2837-rpi-3-b-plus.dtb \ + bcm2837-rpi-cm3-io3.dtb \ + bcm2711-rpi-4-b.dtb \ ++ bcm2711-rpi-cm4-io.dtb \ + bcm2835-rpi-zero.dtb \ + bcm2835-rpi-zero-w.dtb + dtb-$(CONFIG_ARCH_BCM_5301X) += \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts +@@ -0,0 +1,373 @@ ++/dts-v1/; ++ ++#include "bcm2711.dtsi" ++#include "bcm283x-rpi-usb-host.dtsi" ++ ++/ { ++ model = "Raspberry Pi Compute Module 4 IO Board"; ++ compatible = "raspberrypi,4-compute-module\0brcm,bcm2711"; ++ ++ aliases { ++ emmc2bus = "/emmc2bus"; ++ ethernet0 = "/scb/ethernet@7d580000"; ++ pcie0 = "/scb/pcie@7d500000"; ++ blconfig = &blconfig; ++ }; ++ ++ chosen { ++ stdout-path = "serial1:115200n8"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-act { ++ label = "ACT"; ++ default-state = "keep"; ++ linux,default-trigger = "heartbeat"; ++ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ led-pwr { ++ label = "PWR"; ++ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>; ++ default-state = "keep"; ++ linux,default-trigger = "default-on"; ++ }; ++ }; ++ ++ soc { ++ aon_intr: interrupt-controller@7ef00100 { ++ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; ++ reg = <0x7ef00100 0x30>; ++ phandle = <0x16>; ++ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ firmware: firmware { ++ compatible = "raspberrypi,bcm2835-firmware\0simple-mfd"; ++ #address-cells = <0x01>; ++ #size-cells = <0x01>; ++ mboxes = <&mailbox>; ++ dma-ranges; ++ ++ firmware_clocks: clocks { ++ compatible = "raspberrypi,firmware-clocks"; ++ #clock-cells = <0x01>; ++ }; ++ ++ expgpio: gpio { ++ compatible = "raspberrypi,firmware-gpio"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ status = "okay"; ++ gpio-line-names = "BT_ON", "WL_ON", "PWR_LED_OFF", "ANT1", "VDD_SD_IO_SEL", "CAM_GPIO", "SD_PWR_ON", "ANT2"; ++ ant1-hog { ++ gpio-hog; ++ gpios = <0x03 0x00>; ++ output-high; ++ line-name = "ant1"; ++ }; ++ ++ ant2-hog { ++ gpio-hog; ++ gpios = <0x07 0x00>; ++ output-low; ++ line-name = "ant2"; ++ }; ++ }; ++ ++ reset { ++ compatible = "raspberrypi,firmware-reset"; ++ #reset-cells = <1>; ++ }; ++ }; ++ ++ power: power { ++ compatible = "raspberrypi,bcm2835-power"; ++ firmware = <&firmware>; ++ #power-domain-cells = <1>; ++ }; ++ ++ mailbox@7e00b840 { ++ compatible = "brcm,bcm2835-vchiq"; ++ reg = <0x7e00b840 0x3c>; ++ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; ++ }; ++ ++ vec@7ec13000 { ++ compatible = "brcm,bcm2711-vec"; ++ reg = <0x7ec13000 0x1000>; ++ clocks = <&clocks BCM2835_CLOCK_VEC>; ++ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>; ++ status = "disabled"; ++ power-domains = <&power /* RPI_POWER_DOMAIN_VEC = */ 7>; ++ }; ++ }; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x00 0x00 0x00>; ++ }; ++ ++ wifi_pwrseq: wifi-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ reset-gpios = <&expgpio 0x01 0x01>; ++ }; ++ ++ sd_io_1v8_reg: sd_io_1v8_reg { ++ compatible = "regulator-gpio"; ++ regulator-name = "vdd-sd-io"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-settling-time-us = <5000>; ++ gpios = <&expgpio 0x04 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x1>, ++ <3300000 0x0>; ++ status = "okay"; ++ }; ++ ++ sd_vcc_reg: sd_vcc_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ enable-active-high; ++ gpio = <&expgpio 6 GPIO_ACTIVE_HIGH>; ++ }; ++}; ++ ++&ddc0 { ++ status = "okay"; ++}; ++ ++&ddc1 { ++ status = "okay"; ++}; ++ ++&dsi0 { ++ power-domains = <&power 17>; ++}; ++ ++&dsi1 { ++ compatible = "brcm,bcm2711-dsi1"; ++ power-domains = <&power 18>; ++}; ++ ++&emmc2 { ++ status = "okay"; ++ bus-width = <8>; ++ vqmmc-supply = <&sd_io_1v8_reg>; ++ vmmc-supply = <&sd_vcc_reg>; ++ broken-cd; ++ mmc-hs200-1_8v; ++}; ++ ++&gpio { ++ pinctrl-names = "default"; ++ /* ++ * Parts taken from rpi_SCH_4b_4p0_reduced.pdf and ++ * the official GPU firmware DT blob. ++ * ++ * Legend: ++ * "FOO" = GPIO line named "FOO" on the schematic ++ * "FOO_N" = GPIO line named "FOO" on schematic, active low ++ */ ++ gpio-line-names = "ID_SDA", ++ "ID_SCL", ++ "SDA1", ++ "SCL1", ++ "GPIO_GCLK", ++ "GPIO5", ++ "GPIO6", ++ "SPI_CE1_N", ++ "SPI_CE0_N", ++ "SPI_MISO", ++ "SPI_MOSI", ++ "SPI_SCLK", ++ "GPIO12", ++ "GPIO13", ++ /* Serial port */ ++ "TXD1", ++ "RXD1", ++ "GPIO16", ++ "GPIO17", ++ "GPIO18", ++ "GPIO19", ++ "GPIO20", ++ "GPIO21", ++ "GPIO22", ++ "GPIO23", ++ "GPIO24", ++ "GPIO25", ++ "GPIO26", ++ "GPIO27", ++ "RGMII_MDIO", ++ "RGMIO_MDC", ++ /* Used by BT module */ ++ "CTS0", ++ "RTS0", ++ "TXD0", ++ "RXD0", ++ /* Used by Wifi */ ++ "SD1_CLK", ++ "SD1_CMD", ++ "SD1_DATA0", ++ "SD1_DATA1", ++ "SD1_DATA2", ++ "SD1_DATA3", ++ /* Shared with SPI flash */ ++ "PWM0_MISO", ++ "PWM1_MOSI", ++ "STATUS_LED_G_CLK", ++ "SPIFLASH_CE_N", ++ "SDA0", ++ "SCL0", ++ "RGMII_RXCLK", ++ "RGMII_RXCTL", ++ "RGMII_RXD0", ++ "RGMII_RXD1", ++ "RGMII_RXD2", ++ "RGMII_RXD3", ++ "RGMII_TXCLK", ++ "RGMII_TXCTL", ++ "RGMII_TXD0", ++ "RGMII_TXD1", ++ "RGMII_TXD2", ++ "RGMII_TXD3"; ++ ++ gpioout { ++ brcm,pins = <0x06>; ++ brcm,function = <0x01>; ++ }; ++ ++ alt0 { ++ brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; ++ brcm,function = <0x04>; ++ }; ++}; ++ ++&hdmi0 { ++ status = "okay"; ++ interrupt-parent = <&aon_intr>; ++ interrupts = <0>, <1>, <2>, <3>, <4>, <5>; ++ interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed"; ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; ++ wifi-2.4ghz-coexistence; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ interrupt-parent = <&aon_intr>; ++ interrupts = <8>, <7>, <6>, <9>, <10>, <11>; ++ interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed"; ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; ++ wifi-2.4ghz-coexistence; ++}; ++ ++&hvs { ++ clocks = <&firmware_clocks 4>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_gpio0>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_gpio2>; ++ clock-frequency = <100000>; ++}; ++ ++&genet { ++ status = "okay"; ++ phy-handle = <ðphy0>; ++ phy-mode = "rgmii-rxid"; ++}; ++ ++&genet_mdio { ++ ethphy0: ethernet-phy@0 { ++ reg = <0>; ++ }; ++}; ++ ++&pixelvalve0 { ++ status = "okay"; ++}; ++ ++&pixelvalve1 { ++ status = "okay"; ++}; ++ ++&pixelvalve2 { ++ status = "okay"; ++}; ++ ++&pixelvalve4 { ++ status = "okay"; ++}; ++ ++&rmem { ++ blconfig: nvram@0 { ++ compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; ++ #address-cells = <0x01>; ++ #size-cells = <0x01>; ++ reg = <0x00 0x00 0x00>; ++ no-map; ++ status = "disabled"; ++ }; ++}; ++ ++&sdhci { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_gpio34>; ++ bus-width = <4>; ++ non-removable; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ ++ wifi@1 { ++ reg = <0x01>; ++ compatible = "brcm,bcm4329-fmac"; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32>; ++ uart-has-rtscts; ++ ++ bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <0x1e8480>; ++ shutdown-gpios = <&expgpio 0x00 0x00>; ++ }; ++}; ++ ++&uart1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_gpio14>; ++}; ++ ++&usb { ++ power-domains = <&power 6>; ++}; ++ ++&vc4 { ++ status = "okay"; ++}; ++ ++/delete-node/ &vec; diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-basic-support-for-Kobol-s-Hel.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-basic-support-for-Kobol-s-Hel.patch new file mode 100644 index 000000000..deeed7034 --- /dev/null +++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-basic-support-for-Kobol-s-Hel.patch @@ -0,0 +1,419 @@ +From: Uwe Kleine-König <uwe@kleine-koenig.org> +Date: Wed, 14 Oct 2020 22:00:30 +0200 +Subject: arm64: dts: rockchip: Add basic support for Kobol's Helios64 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/?id=09e006cfb43e8ec38afe28278b210dab72e6cac8 + +The hardware is described in detail on Kobol's wiki at +https://wiki.kobol.io/helios64/intro/. + +Up to now the following peripherals are working: + + - UART + - Micro-SD card + - eMMC + - ethernet port 1 + - status LED + - temperature sensor on i2c bus 2 + +Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org> +Link: https://lore.kernel.org/r/20201014200030.845759-3-uwe@kleine-koenig.org +Signed-off-by: Heiko Stuebner <heiko@sntech.de> +--- + arch/arm64/boot/dts/rockchip/Makefile | 1 + + .../dts/rockchip/rk3399-kobol-helios64.dts | 372 ++++++++++++++++++ + 2 files changed, 373 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts + +diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile +index 26661c7b736b..28b26a874313 100644 +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -26,6 +26,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-hugsun-x99.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge-captain.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge-v.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-kobol-helios64.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-leez-p710.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopc-t4.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-m4.dtb +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +new file mode 100644 +index 000000000000..2a561be724b2 +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +@@ -0,0 +1,372 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 Aditya Prayoga <aditya@kobol.io> ++ */ ++ ++/* ++ * The Kobol Helios64 is a board designed to operate as a NAS and optionally ++ * ships with an enclosing that can host five 2.5" hard disks. ++ * ++ * See https://wiki.kobol.io/helios64/intro/ for further details. ++ */ ++ ++/dts-v1/; ++#include "rk3399.dtsi" ++#include "rk3399-opp.dtsi" ++ ++/ { ++ model = "Kobol Helios64"; ++ compatible = "kobol,helios64", "rockchip,rk3399"; ++ ++ avdd_1v8_s0: avdd-1v8-s0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "avdd_1v8_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc3v3_sys_s3>; ++ }; ++ ++ clkin_gmac: external-gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "clkin_gmac"; ++ #clock-cells = <0>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sys_grn_led_on &sys_red_led_on>; ++ ++ led-0 { ++ label = "helios64:green:status"; ++ gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led-1 { ++ label = "helios64:red:fault"; ++ gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>; ++ default-state = "keep"; ++ }; ++ }; ++ ++ vcc1v8_sys_s0: vcc1v8-sys-s0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8_sys_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&vcc1v8_sys_s3>; ++ }; ++ ++ vcc3v0_sd: vcc3v0-sd { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; ++ regulator-name = "vcc3v0_sd"; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc0_pwr_h>; ++ vin-supply = <&vcc3v3_sys_s3>; ++ }; ++ ++ vcc3v3_sys_s3: vcc_lan: vcc3v3-sys-s3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_sys_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin_bkup>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc12v_dcin: vcc12v-dcin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ }; ++ ++ vcc12v_dcin_bkup: vcc12v-dcin-bkup { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin_bkup"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++}; ++ ++/* ++ * The system doesn't run stable with cpu freq enabled, so disallow the lower ++ * frequencies until this problem is properly understood and resolved. ++ */ ++&cluster0_opp { ++ /delete-node/ opp00; ++ /delete-node/ opp01; ++ /delete-node/ opp02; ++ /delete-node/ opp03; ++ /delete-node/ opp04; ++}; ++ ++&cluster1_opp { ++ /delete-node/ opp00; ++ /delete-node/ opp01; ++ /delete-node/ opp02; ++ /delete-node/ opp03; ++ /delete-node/ opp04; ++ /delete-node/ opp05; ++ /delete-node/ opp06; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_b1 { ++ cpu-supply = <&vdd_cpu_b>; ++}; ++ ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l1 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l2 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&cpu_l3 { ++ cpu-supply = <&vdd_cpu_l>; ++}; ++ ++&emmc_phy { ++ status = "okay"; ++}; ++ ++&gmac { ++ assigned-clock-parents = <&clkin_gmac>; ++ assigned-clocks = <&cru SCLK_RMII_SRC>; ++ clock_in_out = "input"; ++ phy-mode = "rgmii"; ++ phy-supply = <&vcc_lan>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii_pins &gphy_reset>; ++ rx_delay = <0x20>; ++ tx_delay = <0x28>; ++ snps,reset-active-low; ++ snps,reset-delays-us = <0 10000 50000>; ++ snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ clock-frequency = <400000>; ++ i2c-scl-rising-time-ns = <168>; ++ i2c-scl-falling-time-ns = <4>; ++ status = "okay"; ++ ++ rk808: pmic@1b { ++ compatible = "rockchip,rk808"; ++ reg = <0x1b>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <10 IRQ_TYPE_LEVEL_LOW>; ++ clock-output-names = "xin32k", "rk808-clkout2"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_int_l>; ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc3v3_sys_s3>; ++ vcc9-supply = <&vcc5v0_sys>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc5v0_sys>; ++ vcc12-supply = <&vcc3v3_sys_s3>; ++ vddio-supply = <&vcc3v0_s3>; ++ wakeup-source; ++ #clock-cells = <1>; ++ ++ regulators { ++ vdd_cpu_l: DCDC_REG2 { ++ regulator-name = "vdd_cpu_l"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-ramp-delay = <6001>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc1v8_sys_s3: DCDC_REG4 { ++ regulator-name = "vcc1v8_sys_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc_sdio_s0: LDO_REG4 { ++ regulator-name = "vcc_sdio_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3000000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ ++ vcc3v0_s3: LDO_REG8 { ++ regulator-name = "vcc3v0_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3000000>; ++ regulator-max-microvolt = <3000000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3000000>; ++ }; ++ }; ++ }; ++ }; ++ ++ vdd_cpu_b: regulator@40 { ++ compatible = "silergy,syr827"; ++ reg = <0x40>; ++ fcs,suspend-voltage-selector = <1>; ++ regulator-name = "vdd_cpu_b"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1500000>; ++ regulator-ramp-delay = <1000>; ++ vin-supply = <&vcc5v0_sys>; ++ ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ i2c-scl-rising-time-ns = <160>; ++ i2c-scl-falling-time-ns = <30>; ++ status = "okay"; ++ ++ temp@4c { ++ compatible = "national,lm75"; ++ reg = <0x4c>; ++ }; ++}; ++ ++&io_domains { ++ audio-supply = <&vcc1v8_sys_s0>; ++ bt656-supply = <&vcc1v8_sys_s0>; ++ gpio1830-supply = <&vcc3v0_s3>; ++ sdmmc-supply = <&vcc_sdio_s0>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ gmac { ++ gphy_reset: gphy-reset { ++ rockchip,pins = <3 RK_PB7 RK_FUNC_GPIO &pcfg_output_low>; ++ }; ++ }; ++ ++ leds { ++ sys_grn_led_on: sys-grn-led-on { ++ rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ ++ sys_red_led_on: sys-red-led-on { ++ rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ vcc3v0-sd { ++ sdmmc0_pwr_h: sdmmc0-pwr-h { ++ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++}; ++ ++&pmu_io_domains { ++ pmu1830-supply = <&vcc3v0_s3>; ++ status = "okay"; ++}; ++ ++&sdhci { ++ bus-width = <8>; ++ mmc-hs200-1_8v; ++ non-removable; ++ vqmmc-supply = <&vcc1v8_sys_s0>; ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>; ++ disable-wp; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>; ++ vmmc-supply = <&vcc3v0_sd>; ++ vqmmc-supply = <&vcc_sdio_s0>; ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; +-- +2.28.0 + diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-PCIe-on-helios64.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-PCIe-on-helios64.patch new file mode 100644 index 000000000..6abebd080 --- /dev/null +++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-PCIe-on-helios64.patch @@ -0,0 +1,113 @@ +From: Uwe Kleine-König <uwe@kleine-koenig.org> +Date: Mon, 10 May 2021 11:09:32 +0200 +Subject: arm64: dts: rockchip: Add support for PCIe on helios64 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/patch/?id=5a65adfa2ad1542f856fc7de3999d51f3a35d2e2 + +This is enough to make the SATA controller visible: + +# lspci +00:00.0 PCI bridge: Fuzhou Rockchip Electronics Co., Ltd RK3399 PCI Express Root Port +01:00.0 SATA controller: JMicron Technology Corp. JMB58x AHCI SATA controller + +Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org> +Link: https://lore.kernel.org/r/20210510090932.970447-1-uwe@kleine-koenig.org +Signed-off-by: Heiko Stuebner <heiko@sntech.de> +--- + .../dts/rockchip/rk3399-kobol-helios64.dts | 53 +++++++++++++++++++ + 1 file changed, 53 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +index 9d4a0885fd12..037dc5cdc3f3 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +@@ -23,6 +23,16 @@ aliases { + mmc1 = &sdhci; + }; + ++ avdd_0v9_s0: avdd-0v9-s0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "avdd_0v9_s0"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ vin-supply = <&vcc1v8_sys_s3>; ++ }; ++ + avdd_1v8_s0: avdd-1v8-s0 { + compatible = "regulator-fixed"; + regulator-name = "avdd_1v8_s0"; +@@ -72,6 +82,18 @@ led-1 { + }; + }; + ++ pcie_power: pcie-power { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; ++ pinctrl-0 = <&pcie_pwr>; ++ pinctrl-names = "default"; ++ regulator-boot-on; ++ regulator-name = "pcie_power"; ++ startup-delay-us = <10000>; ++ vin-supply = <&vcc5v0_perdev>; ++ }; ++ + vcc1v8_sys_s0: vcc1v8-sys-s0 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_sys_s0"; +@@ -109,6 +131,16 @@ regulator-state-mem { + }; + }; + ++ vcc5v0_perdev: vcc5v0-perdev { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_perdev"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin_bkup>; ++ }; ++ + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; +@@ -331,6 +363,20 @@ &io_domains { + status = "okay"; + }; + ++&pcie_phy { ++ status = "okay"; ++}; ++ ++&pcie0 { ++ num-lanes = <2>; ++ status = "okay"; ++ ++ vpcie12v-supply = <&vcc12v_dcin>; ++ vpcie3v3-supply = <&pcie_power>; ++ vpcie1v8-supply = <&avdd_1v8_s0>; ++ vpcie0v9-supply = <&avdd_0v9_s0>; ++}; ++ + &pinctrl { + gmac { + gphy_reset: gphy-reset { +@@ -348,6 +394,13 @@ sys_red_led_on: sys-red-led-on { + }; + }; + ++ pcie { ++ pcie_pwr: pcie-pwr { ++ rockchip,pins = ++ <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; +-- +2.30.2 + diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-two-PWM-fans-on-h.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-two-PWM-fans-on-h.patch new file mode 100644 index 000000000..9755e0b8c --- /dev/null +++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-support-for-two-PWM-fans-on-h.patch @@ -0,0 +1,61 @@ +From: Uwe Kleine-König <uwe@kleine-koenig.org> +Date: Mon, 10 May 2021 11:06:07 +0200 +Subject: arm64: dts: rockchip: Add support for two PWM fans on + helios64 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git/patch/?id=271b66414df0b172c936b3cfd1894b7939f84165 + +On the helios64 board the two connectors P6 and P7 are supposed to +power two fans. Add the corresponding pwm-fan devices. + +Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org> +Link: https://lore.kernel.org/r/20210510090607.970145-1-uwe@kleine-koenig.org +Signed-off-by: Heiko Stuebner <heiko@sntech.de> +--- + .../dts/rockchip/rk3399-kobol-helios64.dts | 24 +++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +index 19485b552bc4..9d4a0885fd12 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +@@ -40,6 +40,20 @@ clkin_gmac: external-gmac-clock { + #clock-cells = <0>; + }; + ++ fan1 { ++ /* fan connected to P7 */ ++ compatible = "pwm-fan"; ++ pwms = <&pwm0 0 40000 0>; ++ cooling-levels = <0 80 170 255>; ++ }; ++ ++ fan2 { ++ /* fan connected to P6 */ ++ compatible = "pwm-fan"; ++ pwms = <&pwm1 0 40000 0>; ++ cooling-levels = <0 80 170 255>; ++ }; ++ + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +@@ -352,6 +366,16 @@ &pmu_io_domains { + status = "okay"; + }; + ++&pwm0 { ++ /* pwm-fan on P7 */ ++ status = "okay"; ++}; ++ ++&pwm1 { ++ /* pwm-fan on P6 */ ++ status = "okay"; ++}; ++ + &sdhci { + bus-width = <8>; + mmc-hs200-1_8v; +-- +2.30.2 + diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Rely-on-SoC-external-pull-up-on-p.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Rely-on-SoC-external-pull-up-on-p.patch new file mode 100644 index 000000000..ef6dab336 --- /dev/null +++ b/debian/patches/features/arm64/arm64-dts-rockchip-Rely-on-SoC-external-pull-up-on-p.patch @@ -0,0 +1,32 @@ +From: Uwe Kleine-König <uwe@kleine-koenig.org> +Date: Sun, 24 Jan 2021 22:03:28 +0100 +Subject: arm64: dts: rockchip: Rely on SoC external pull up on pmic-int-l on Helios64 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/?id=1e58ba111421375c5948c3e8145bdd84b06ac095 + +According to the schematic there is an external pull up, so there is no +need to enable the internal one additionally. Using no pull up matches +the vendor device tree. + +Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org> +Link: https://lore.kernel.org/r/20210124210328.611707-2-uwe@kleine-koenig.org +Signed-off-by: Heiko Stuebner <heiko@sntech.de> +--- + arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +index 2a561be724b2..66c725a34220 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +@@ -331,7 +331,7 @@ sys_red_led_on: sys-red-led-on { + + pmic { + pmic_int_l: pmic-int-l { +- rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; ++ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + +-- +2.30.2 + diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-kobol-helios64-Add-mmc-aliases.patch b/debian/patches/features/arm64/arm64-dts-rockchip-kobol-helios64-Add-mmc-aliases.patch new file mode 100644 index 000000000..ad4b53de9 --- /dev/null +++ b/debian/patches/features/arm64/arm64-dts-rockchip-kobol-helios64-Add-mmc-aliases.patch @@ -0,0 +1,30 @@ +From: Uwe Kleine-König <ukleinek@debian.org> +Date: Wed, 29 Mar 2021 09:45:58 +0100 +Subject: arm64: dts: rockchip: kobol-helios64: Add mmc aliases + +This patch is part of commit 5dcbe7e3862d ("arm64: dts: rockchip: move mmc +aliases to board dts on rk3399") upstream. It is applied here only for Kobol's +helios64 to simplify conflict resolution for some further patches. It currently +is a noop as the same aliases already exist in rk3399.dtsi. + +Link: https://lore.kernel.org/r/20210324122235.1059292-7-heiko@sntech.de +--- +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +index 66c725a34220..19485b552bc4 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +@@ -18,6 +18,11 @@ / { + model = "Kobol Helios64"; + compatible = "kobol,helios64", "rockchip,rk3399"; + ++ aliases { ++ mmc0 = &sdmmc; ++ mmc1 = &sdhci; ++ }; ++ + avdd_1v8_s0: avdd-1v8-s0 { + compatible = "regulator-fixed"; + regulator-name = "avdd_1v8_s0"; +-- +2.30.2 + diff --git a/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch b/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch new file mode 100644 index 000000000..1840fc4bd --- /dev/null +++ b/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch @@ -0,0 +1,85 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 21 Aug 2019 00:32:16 +0100 +Subject: intel-iommu: Add Kconfig option to exclude iGPU by default +Bug-Debian: https://bugs.debian.org/935270 +Bug-Kali: https://bugs.kali.org/view.php?id=5644 + +There is still laptop firmware that touches the integrated GPU behind +the operating system's back, and doesn't say so in the RMRR table. +Enabling the IOMMU for all devices causes breakage. + +Replace CONFIG_INTEL_IOMMU_DEFAULT_ON with a 3-way choice +corresponding to "on", "off", and "on,intgpu_off". + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/iommu/intel/Kconfig ++++ b/drivers/iommu/intel/Kconfig +@@ -45,14 +45,28 @@ config INTEL_IOMMU_SVM + to access DMA resources through process address space by + means of a Process Address Space ID (PASID). + +-config INTEL_IOMMU_DEFAULT_ON +- def_bool y +- prompt "Enable Intel DMA Remapping Devices by default" +- depends on INTEL_IOMMU ++if INTEL_IOMMU ++ ++choice ++ prompt "Default state of Intel DMA Remapping Devices" ++ default INTEL_IOMMU_DEFAULT_ON + help +- Selecting this option will enable a DMAR device at boot time if +- one is found. If this option is not selected, DMAR support can +- be enabled by passing intel_iommu=on to the kernel. ++ Choose whether Intel DMA Remapping Devices should be enabled ++ by default. This can be overridden at boot time using the ++ intel_iommu= kernel parameter. ++ ++config INTEL_IOMMU_DEFAULT_ON ++ bool "Enable" ++ ++config INTEL_IOMMU_DEFAULT_ON_INTGPU_OFF ++ bool "Enable, excluding integrated GPU" ++ ++config INTEL_IOMMU_DEFAULT_OFF ++ bool "Disable" ++ ++endchoice ++ ++endif + + config INTEL_IOMMU_BROKEN_GFX_WA + bool "Workaround broken graphics drivers (going away soon)" +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -338,11 +338,7 @@ static int intel_iommu_attach_device(str + static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, + dma_addr_t iova); + +-#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON +-int dmar_disabled = 0; +-#else +-int dmar_disabled = 1; +-#endif /* CONFIG_INTEL_IOMMU_DEFAULT_ON */ ++int dmar_disabled = IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_OFF); + + #ifdef CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON + int intel_iommu_sm = 1; +@@ -354,7 +350,7 @@ int intel_iommu_enabled = 0; + EXPORT_SYMBOL_GPL(intel_iommu_enabled); + + static int dmar_map_gfx = 1; +-static int dmar_map_intgpu = 1; ++static int dmar_map_intgpu = IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON); + static int dmar_forcedac; + static int intel_iommu_strict; + static int intel_iommu_superpage = 1; +@@ -442,6 +438,7 @@ static int __init intel_iommu_setup(char + while (*str) { + if (!strncmp(str, "on", 2)) { + dmar_disabled = 0; ++ dmar_map_intgpu = 1; + pr_info("IOMMU enabled\n"); + } else if (!strncmp(str, "off", 3)) { + dmar_disabled = 1; diff --git a/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch b/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch new file mode 100644 index 000000000..1717d8fe2 --- /dev/null +++ b/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch @@ -0,0 +1,91 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Wed, 21 Aug 2019 00:05:30 +0100 +Subject: intel-iommu: Add option to exclude integrated GPU only +Bug-Debian: https://bugs.debian.org/935270 +Bug-Kali: https://bugs.kali.org/view.php?id=5644 + +There is still laptop firmware that touches the integrated GPU behind +the operating system's back, and doesn't say so in the RMRR table. +Enabling the IOMMU for all devices causes breakage, but turning it off +for all graphics devices seems like a major weakness. + +Add an option, intel_iommu=igpu_off, to exclude only integrated GPUs +from remapping. This is a narrower exclusion than igfx_off: it only +affects Intel devices on the root bus. Devices attached through an +external port (Thunderbolt or ExpressCard) won't be on the root bus. + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + Documentation/admin-guide/kernel-parameters.txt | 2 ++ + drivers/iommu/intel/iommu.c | 14 ++++++++++++++ + 2 files changed, 16 insertions(+) + +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -1837,6 +1837,8 @@ + bypassed by not enabling DMAR with this option. In + this case, gfx device will use physical address for + DMA. ++ intgpu_off [Default Off] ++ Bypass the DMAR unit for an integrated GPU only. + forcedac [X86-64] + With this option iommu will not optimize to look + for io virtual address below 32-bit forcing dual +--- a/drivers/iommu/intel/iommu.c ++++ b/drivers/iommu/intel/iommu.c +@@ -54,6 +54,9 @@ + #define CONTEXT_SIZE VTD_PAGE_SIZE + + #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) ++#define IS_INTGPU_DEVICE(pdev) (IS_GFX_DEVICE(pdev) && \ ++ (pdev)->vendor == 0x8086 && \ ++ pci_is_root_bus((pdev)->bus)) + #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB) + #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) + #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e) +@@ -351,6 +354,7 @@ int intel_iommu_enabled = 0; + EXPORT_SYMBOL_GPL(intel_iommu_enabled); + + static int dmar_map_gfx = 1; ++static int dmar_map_intgpu = 1; + static int dmar_forcedac; + static int intel_iommu_strict; + static int intel_iommu_superpage = 1; +@@ -360,6 +364,7 @@ static int iommu_skip_te_disable; + + #define IDENTMAP_GFX 2 + #define IDENTMAP_AZALIA 4 ++#define IDENTMAP_INTGPU 8 + + int intel_iommu_gfx_mapped; + EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); +@@ -445,6 +450,9 @@ static int __init intel_iommu_setup(char + } else if (!strncmp(str, "igfx_off", 8)) { + dmar_map_gfx = 0; + pr_info("Disable GFX device mapping\n"); ++ } else if (!strncmp(str, "intgpu_off", 8)) { ++ dmar_map_intgpu = 0; ++ pr_info("Disable integrated GPU device mapping\n"); + } else if (!strncmp(str, "forcedac", 8)) { + pr_info("Forcing DAC for PCI devices\n"); + dmar_forcedac = 1; +@@ -2890,6 +2898,9 @@ static int device_def_domain_type(struct + + if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev)) + return IOMMU_DOMAIN_IDENTITY; ++ ++ if ((iommu_identity_mapping & IDENTMAP_INTGPU) && IS_INTGPU_DEVICE(pdev)) ++ return IOMMU_DOMAIN_IDENTITY; + } + + return 0; +@@ -3325,6 +3336,9 @@ static int __init init_dmars(void) + if (!dmar_map_gfx) + iommu_identity_mapping |= IDENTMAP_GFX; + ++ if (!dmar_map_intgpu) ++ iommu_identity_mapping |= IDENTMAP_INTGPU; ++ + check_tylersburg_isoch(); + + ret = si_domain_init(hw_pass_through); diff --git a/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch new file mode 100644 index 000000000..62731a997 --- /dev/null +++ b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch @@ -0,0 +1,193 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Mon, 12 Feb 2018 23:59:26 +0000 +Subject: x86: Make x32 syscall support conditional on a kernel parameter +Bug-Debian: https://bugs.debian.org/708070 +Forwarded: https://lore.kernel.org/lkml/1415245982.3398.53.camel@decadent.org.uk/T/#u + +Enabling x32 in the standard amd64 kernel would increase its attack +surface while provide no benefit to the vast majority of its users. +No-one seems interested in regularly checking for vulnerabilities +specific to x32 (at least no-one with a white hat). + +Still, adding another flavour just to turn on x32 seems wasteful. And +the only differences on syscall entry are a few instructions that mask +out the x32 flag and compare the syscall number. + +Use a static key to control whether x32 syscalls are really enabled, a +Kconfig parameter to set its default value and a kernel parameter +"syscall.x32" to change it at boot time. + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + .../admin-guide/kernel-parameters.txt | 4 ++ + arch/x86/Kconfig | 8 ++++ + arch/x86/entry/common.c | 3 +- + arch/x86/entry/syscall_64.c | 46 +++++++++++++++++++ + arch/x86/include/asm/elf.h | 6 ++- + arch/x86/include/asm/syscall.h | 13 ++++++ + 6 files changed, 78 insertions(+), 2 deletions(-) + +Index: debian-kernel/Documentation/admin-guide/kernel-parameters.txt +=================================================================== +--- debian-kernel.orig/Documentation/admin-guide/kernel-parameters.txt ++++ debian-kernel/Documentation/admin-guide/kernel-parameters.txt +@@ -5000,6 +5000,10 @@ + later by a loaded module cannot be set this way. + Example: sysctl.vm.swappiness=40 + ++ syscall.x32= [KNL,x86_64] Enable/disable use of x32 syscalls on ++ an x86_64 kernel where CONFIG_X86_X32 is enabled. ++ Default depends on CONFIG_X86_X32_DISABLED. ++ + sysfs.deprecated=0|1 [KNL] + Enable/disable old style sysfs layout for old udev + on older distributions. When this option is enabled +Index: debian-kernel/arch/x86/Kconfig +=================================================================== +--- debian-kernel.orig/arch/x86/Kconfig ++++ debian-kernel/arch/x86/Kconfig +@@ -2888,6 +2888,14 @@ config COMPAT_32 + select HAVE_UID16 + select OLD_SIGSUSPEND3 + ++config X86_X32_DISABLED ++ bool "x32 ABI disabled by default" ++ depends on X86_X32 ++ default n ++ help ++ Disable the x32 ABI unless explicitly enabled using the ++ kernel paramter "syscall.x32=y". ++ + config COMPAT + def_bool y + depends on IA32_EMULATION || X86_X32 +Index: debian-kernel/arch/x86/entry/common.c +=================================================================== +--- debian-kernel.orig/arch/x86/entry/common.c ++++ debian-kernel/arch/x86/entry/common.c +@@ -383,7 +383,8 @@ __visible noinstr void do_syscall_64(uns + nr = array_index_nospec(nr, NR_syscalls); + regs->ax = sys_call_table[nr](regs); + #ifdef CONFIG_X86_X32_ABI +- } else if (likely((nr & __X32_SYSCALL_BIT) && ++ } else if (x32_enabled && ++ likely((nr & __X32_SYSCALL_BIT) && + (nr & ~__X32_SYSCALL_BIT) < X32_NR_syscalls)) { + nr = array_index_nospec(nr & ~__X32_SYSCALL_BIT, + X32_NR_syscalls); +Index: debian-kernel/arch/x86/entry/syscall_x32.c +=================================================================== +--- debian-kernel.orig/arch/x86/entry/syscall_x32.c ++++ debian-kernel/arch/x86/entry/syscall_x32.c +@@ -4,6 +4,9 @@ + #include <linux/linkage.h> + #include <linux/sys.h> + #include <linux/cache.h> ++#include <linux/moduleparam.h> ++#undef MODULE_PARAM_PREFIX ++#define MODULE_PARAM_PREFIX "syscall." + #include <linux/syscalls.h> + #include <asm/unistd.h> + #include <asm/syscall.h> +@@ -27,3 +30,46 @@ asmlinkage const sys_call_ptr_t x32_sys_ + [0 ... __NR_x32_syscall_max] = &__x64_sys_ni_syscall, + #include <asm/syscalls_64.h> + }; ++ ++/* Maybe enable x32 syscalls */ ++ ++#if defined(CONFIG_X86_X32_DISABLED) ++DEFINE_STATIC_KEY_FALSE(x32_enabled_skey); ++#else ++DEFINE_STATIC_KEY_TRUE(x32_enabled_skey); ++#endif ++ ++static int __init x32_param_set(const char *val, const struct kernel_param *p) ++{ ++ bool enabled; ++ int ret; ++ ++ ret = kstrtobool(val, &enabled); ++ if (ret) ++ return ret; ++ if (IS_ENABLED(CONFIG_X86_X32_DISABLED)) { ++ if (enabled) { ++ static_key_enable(&x32_enabled_skey.key); ++ pr_info("Enabled x32 syscalls\n"); ++ } ++ } else { ++ if (!enabled) { ++ static_key_disable(&x32_enabled_skey.key); ++ pr_info("Disabled x32 syscalls\n"); ++ } ++ } ++ return 0; ++} ++ ++static int x32_param_get(char *buffer, const struct kernel_param *p) ++{ ++ return sprintf(buffer, "%c\n", ++ static_key_enabled(&x32_enabled_skey) ? 'Y' : 'N'); ++} ++ ++static const struct kernel_param_ops x32_param_ops = { ++ .set = x32_param_set, ++ .get = x32_param_get, ++}; ++ ++arch_param_cb(x32, &x32_param_ops, NULL, 0444); +Index: debian-kernel/arch/x86/include/asm/elf.h +=================================================================== +--- debian-kernel.orig/arch/x86/include/asm/elf.h ++++ debian-kernel/arch/x86/include/asm/elf.h +@@ -11,6 +11,9 @@ + #include <asm/user.h> + #include <asm/auxvec.h> + #include <asm/fsgsbase.h> ++#ifndef COMPILE_OFFSETS /* avoid a circular dependency on asm-offsets.h */ ++#include <asm/syscall.h> ++#endif + + typedef unsigned long elf_greg_t; + +@@ -163,7 +166,8 @@ do { \ + + #define compat_elf_check_arch(x) \ + (elf_check_arch_ia32(x) || \ +- (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64)) ++ (IS_ENABLED(CONFIG_X86_X32_ABI) && x32_enabled && \ ++ (x)->e_machine == EM_X86_64)) + + #if __USER32_DS != __USER_DS + # error "The following code assumes __USER32_DS == __USER_DS" +Index: debian-kernel/arch/x86/include/asm/syscall.h +=================================================================== +--- debian-kernel.orig/arch/x86/include/asm/syscall.h ++++ debian-kernel/arch/x86/include/asm/syscall.h +@@ -13,6 +13,7 @@ + #include <uapi/linux/audit.h> + #include <linux/sched.h> + #include <linux/err.h> ++#include <linux/jump_label.h> + #include <asm/thread_info.h> /* for TS_COMPAT */ + #include <asm/unistd.h> + +@@ -31,6 +32,18 @@ extern const sys_call_ptr_t ia32_sys_cal + extern const sys_call_ptr_t x32_sys_call_table[]; + #endif + ++#if defined(CONFIG_X86_X32_ABI) ++#if defined(CONFIG_X86_X32_DISABLED) ++DECLARE_STATIC_KEY_FALSE(x32_enabled_skey); ++#define x32_enabled static_branch_unlikely(&x32_enabled_skey) ++#else ++DECLARE_STATIC_KEY_TRUE(x32_enabled_skey); ++#define x32_enabled static_branch_likely(&x32_enabled_skey) ++#endif ++#else ++#define x32_enabled 0 ++#endif ++ + /* + * Only the low 32 bits of orig_ax are meaningful, so we return int. + * This importantly ignores the high bits on 64-bit, so comparisons diff --git a/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch b/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch new file mode 100644 index 000000000..7a7952003 --- /dev/null +++ b/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch @@ -0,0 +1,28 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Mon, 5 Dec 2011 04:00:58 +0000 +Subject: x86: memtest: WARN if bad RAM found +Bug-Debian: https://bugs.debian.org/613321 +Forwarded: http://thread.gmane.org/gmane.linux.kernel/1286471 + +Since this is not a particularly thorough test, if we find any bad +bits of RAM then there is a fair chance that there are other bad bits +we fail to detect. + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + mm/memtest.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +--- a/mm/memtest.c ++++ b/mm/memtest.c +@@ -26,6 +26,10 @@ static u64 patterns[] __initdata = { + + static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad) + { ++#ifdef CONFIG_X86 ++ WARN_ONCE(1, "Bad RAM detected. Use memtest86+ to perform a thorough test\n" ++ "and the memmap= parameter to reserve the bad areas."); ++#endif + pr_info(" %016llx bad mem addr %pa - %pa reserved\n", + cpu_to_be64(pattern), &start_bad, &end_bad); + memblock_reserve(start_bad, end_bad - start_bad); |