162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * xenfs.c - a filesystem for passing info between the a domain and 462306a36Sopenharmony_ci * the hypervisor. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * 2008-10-07 Alex Zeffertt Replaced /proc/xen/xenbus with xenfs filesystem 762306a36Sopenharmony_ci * and /proc/xen compatibility mount point. 862306a36Sopenharmony_ci * Turned xenfs into a loadable module. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/errno.h> 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/fs.h> 1762306a36Sopenharmony_ci#include <linux/fs_context.h> 1862306a36Sopenharmony_ci#include <linux/magic.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <xen/xen.h> 2162306a36Sopenharmony_ci#include <xen/xenbus.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "xenfs.h" 2462306a36Sopenharmony_ci#include "../privcmd.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <asm/xen/hypervisor.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciMODULE_DESCRIPTION("Xen filesystem"); 2962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic ssize_t capabilities_read(struct file *file, char __user *buf, 3262306a36Sopenharmony_ci size_t size, loff_t *off) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci char *tmp = ""; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci if (xen_initial_domain()) 3762306a36Sopenharmony_ci tmp = "control_d\n"; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci return simple_read_from_buffer(buf, size, off, tmp, strlen(tmp)); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic const struct file_operations capabilities_file_ops = { 4362306a36Sopenharmony_ci .read = capabilities_read, 4462306a36Sopenharmony_ci .llseek = default_llseek, 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic int xenfs_fill_super(struct super_block *sb, struct fs_context *fc) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci static const struct tree_descr xenfs_files[] = { 5062306a36Sopenharmony_ci [2] = { "xenbus", &xen_xenbus_fops, S_IRUSR|S_IWUSR }, 5162306a36Sopenharmony_ci { "capabilities", &capabilities_file_ops, S_IRUGO }, 5262306a36Sopenharmony_ci { "privcmd", &xen_privcmd_fops, S_IRUSR|S_IWUSR }, 5362306a36Sopenharmony_ci {""}, 5462306a36Sopenharmony_ci }; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci static const struct tree_descr xenfs_init_files[] = { 5762306a36Sopenharmony_ci [2] = { "xenbus", &xen_xenbus_fops, S_IRUSR|S_IWUSR }, 5862306a36Sopenharmony_ci { "capabilities", &capabilities_file_ops, S_IRUGO }, 5962306a36Sopenharmony_ci { "privcmd", &xen_privcmd_fops, S_IRUSR|S_IWUSR }, 6062306a36Sopenharmony_ci { "xsd_kva", &xsd_kva_file_ops, S_IRUSR|S_IWUSR}, 6162306a36Sopenharmony_ci { "xsd_port", &xsd_port_file_ops, S_IRUSR|S_IWUSR}, 6262306a36Sopenharmony_ci#ifdef CONFIG_XEN_SYMS 6362306a36Sopenharmony_ci { "xensyms", &xensyms_ops, S_IRUSR}, 6462306a36Sopenharmony_ci#endif 6562306a36Sopenharmony_ci {""}, 6662306a36Sopenharmony_ci }; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return simple_fill_super(sb, XENFS_SUPER_MAGIC, 6962306a36Sopenharmony_ci xen_initial_domain() ? xenfs_init_files : xenfs_files); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic int xenfs_get_tree(struct fs_context *fc) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci return get_tree_single(fc, xenfs_fill_super); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic const struct fs_context_operations xenfs_context_ops = { 7862306a36Sopenharmony_ci .get_tree = xenfs_get_tree, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic int xenfs_init_fs_context(struct fs_context *fc) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci fc->ops = &xenfs_context_ops; 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic struct file_system_type xenfs_type = { 8862306a36Sopenharmony_ci .owner = THIS_MODULE, 8962306a36Sopenharmony_ci .name = "xenfs", 9062306a36Sopenharmony_ci .init_fs_context = xenfs_init_fs_context, 9162306a36Sopenharmony_ci .kill_sb = kill_litter_super, 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ciMODULE_ALIAS_FS("xenfs"); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int __init xenfs_init(void) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci if (xen_domain()) 9862306a36Sopenharmony_ci return register_filesystem(&xenfs_type); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return 0; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void __exit xenfs_exit(void) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci if (xen_domain()) 10662306a36Sopenharmony_ci unregister_filesystem(&xenfs_type); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cimodule_init(xenfs_init); 11062306a36Sopenharmony_cimodule_exit(xenfs_exit); 11162306a36Sopenharmony_ci 112