1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Hypervisor filesystem for Linux on s390. z/VM implementation. 4 * 5 * Copyright IBM Corp. 2006 6 * Author(s): Michael Holzheu <holzheu@de.ibm.com> 7 */ 8 9 #include <linux/types.h> 10 #include <linux/errno.h> 11 #include <linux/string.h> 12 #include <linux/vmalloc.h> 13 #include <asm/extable.h> 14 #include <asm/diag.h> 15 #include <asm/ebcdic.h> 16 #include <asm/timex.h> 17 #include "hypfs_vm.h" 18 #include "hypfs.h" 19 20 #define ATTRIBUTE(dir, name, member) \ 21 do { \ 22 int rc = hypfs_create_u64(dir, name, member); \ 23 if (rc) \ 24 return rc; \ 25 } while (0) 26 27 static int hypfs_vm_create_guest(struct dentry *systems_dir, 28 struct diag2fc_data *data) 29 { 30 char guest_name[DIAG2FC_NAME_LEN + 1] = {}; 31 struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir; 32 int dedicated_flag, capped_value; 33 34 capped_value = (data->flags & 0x00000006) >> 1; 35 dedicated_flag = (data->flags & 0x00000008) >> 3; 36 37 /* guest dir */ 38 memcpy(guest_name, data->guest_name, DIAG2FC_NAME_LEN); 39 EBCASC(guest_name, DIAG2FC_NAME_LEN); 40 strim(guest_name); 41 guest_dir = hypfs_mkdir(systems_dir, guest_name); 42 if (IS_ERR(guest_dir)) 43 return PTR_ERR(guest_dir); 44 ATTRIBUTE(guest_dir, "onlinetime_us", data->el_time); 45 46 /* logical cpu information */ 47 cpus_dir = hypfs_mkdir(guest_dir, "cpus"); 48 if (IS_ERR(cpus_dir)) 49 return PTR_ERR(cpus_dir); 50 ATTRIBUTE(cpus_dir, "cputime_us", data->used_cpu); 51 ATTRIBUTE(cpus_dir, "capped", capped_value); 52 ATTRIBUTE(cpus_dir, "dedicated", dedicated_flag); 53 ATTRIBUTE(cpus_dir, "count", data->vcpus); 54 /* 55 * Note: The "weight_min" attribute got the wrong name. 56 * The value represents the number of non-stopped (operating) 57 * CPUS. 58 */ 59 ATTRIBUTE(cpus_dir, "weight_min", data->ocpus); 60 ATTRIBUTE(cpus_dir, "weight_max", data->cpu_max); 61 ATTRIBUTE(cpus_dir, "weight_cur", data->cpu_shares); 62 63 /* memory information */ 64 mem_dir = hypfs_mkdir(guest_dir, "mem"); 65 if (IS_ERR(mem_dir)) 66 return PTR_ERR(mem_dir); 67 ATTRIBUTE(mem_dir, "min_KiB", data->mem_min_kb); 68 ATTRIBUTE(mem_dir, "max_KiB", data->mem_max_kb); 69 ATTRIBUTE(mem_dir, "used_KiB", data->mem_used_kb); 70 ATTRIBUTE(mem_dir, "share_KiB", data->mem_share_kb); 71 72 /* samples */ 73 samples_dir = hypfs_mkdir(guest_dir, "samples"); 74 if (IS_ERR(samples_dir)) 75 return PTR_ERR(samples_dir); 76 ATTRIBUTE(samples_dir, "cpu_using", data->cpu_use_samp); 77 ATTRIBUTE(samples_dir, "cpu_delay", data->cpu_delay_samp); 78 ATTRIBUTE(samples_dir, "mem_delay", data->page_wait_samp); 79 ATTRIBUTE(samples_dir, "idle", data->idle_samp); 80 ATTRIBUTE(samples_dir, "other", data->other_samp); 81 ATTRIBUTE(samples_dir, "total", data->total_samp); 82 return 0; 83 } 84 85 int hypfs_vm_create_files(struct dentry *root) 86 { 87 struct dentry *dir; 88 struct diag2fc_data *data; 89 unsigned int count = 0; 90 int rc, i; 91 92 data = diag2fc_store(diag2fc_guest_query, &count, 0); 93 if (IS_ERR(data)) 94 return PTR_ERR(data); 95 96 /* Hypervisor Info */ 97 dir = hypfs_mkdir(root, "hyp"); 98 if (IS_ERR(dir)) { 99 rc = PTR_ERR(dir); 100 goto failed; 101 } 102 rc = hypfs_create_str(dir, "type", "z/VM Hypervisor"); 103 if (rc) 104 goto failed; 105 106 /* physical cpus */ 107 dir = hypfs_mkdir(root, "cpus"); 108 if (IS_ERR(dir)) { 109 rc = PTR_ERR(dir); 110 goto failed; 111 } 112 rc = hypfs_create_u64(dir, "count", data->lcpus); 113 if (rc) 114 goto failed; 115 116 /* guests */ 117 dir = hypfs_mkdir(root, "systems"); 118 if (IS_ERR(dir)) { 119 rc = PTR_ERR(dir); 120 goto failed; 121 } 122 123 for (i = 0; i < count; i++) { 124 rc = hypfs_vm_create_guest(dir, &data[i]); 125 if (rc) 126 goto failed; 127 } 128 diag2fc_free(data); 129 return 0; 130 131 failed: 132 diag2fc_free(data); 133 return rc; 134 } 135