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 void *rc; \ 23 rc = hypfs_create_u64(dir, name, member); \ 24 if (IS_ERR(rc)) \ 25 return PTR_ERR(rc); \ 26 } while (0) 27 28 static int hypfs_vm_create_guest(struct dentry *systems_dir, 29 struct diag2fc_data *data) 30 { 31 char guest_name[DIAG2FC_NAME_LEN + 1] = {}; 32 struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir; 33 int dedicated_flag, capped_value; 34 35 capped_value = (data->flags & 0x00000006) >> 1; 36 dedicated_flag = (data->flags & 0x00000008) >> 3; 37 38 /* guest dir */ 39 memcpy(guest_name, data->guest_name, DIAG2FC_NAME_LEN); 40 EBCASC(guest_name, DIAG2FC_NAME_LEN); 41 strim(guest_name); 42 guest_dir = hypfs_mkdir(systems_dir, guest_name); 43 if (IS_ERR(guest_dir)) 44 return PTR_ERR(guest_dir); 45 ATTRIBUTE(guest_dir, "onlinetime_us", data->el_time); 46 47 /* logical cpu information */ 48 cpus_dir = hypfs_mkdir(guest_dir, "cpus"); 49 if (IS_ERR(cpus_dir)) 50 return PTR_ERR(cpus_dir); 51 ATTRIBUTE(cpus_dir, "cputime_us", data->used_cpu); 52 ATTRIBUTE(cpus_dir, "capped", capped_value); 53 ATTRIBUTE(cpus_dir, "dedicated", dedicated_flag); 54 ATTRIBUTE(cpus_dir, "count", data->vcpus); 55 /* 56 * Note: The "weight_min" attribute got the wrong name. 57 * The value represents the number of non-stopped (operating) 58 * CPUS. 59 */ 60 ATTRIBUTE(cpus_dir, "weight_min", data->ocpus); 61 ATTRIBUTE(cpus_dir, "weight_max", data->cpu_max); 62 ATTRIBUTE(cpus_dir, "weight_cur", data->cpu_shares); 63 64 /* memory information */ 65 mem_dir = hypfs_mkdir(guest_dir, "mem"); 66 if (IS_ERR(mem_dir)) 67 return PTR_ERR(mem_dir); 68 ATTRIBUTE(mem_dir, "min_KiB", data->mem_min_kb); 69 ATTRIBUTE(mem_dir, "max_KiB", data->mem_max_kb); 70 ATTRIBUTE(mem_dir, "used_KiB", data->mem_used_kb); 71 ATTRIBUTE(mem_dir, "share_KiB", data->mem_share_kb); 72 73 /* samples */ 74 samples_dir = hypfs_mkdir(guest_dir, "samples"); 75 if (IS_ERR(samples_dir)) 76 return PTR_ERR(samples_dir); 77 ATTRIBUTE(samples_dir, "cpu_using", data->cpu_use_samp); 78 ATTRIBUTE(samples_dir, "cpu_delay", data->cpu_delay_samp); 79 ATTRIBUTE(samples_dir, "mem_delay", data->page_wait_samp); 80 ATTRIBUTE(samples_dir, "idle", data->idle_samp); 81 ATTRIBUTE(samples_dir, "other", data->other_samp); 82 ATTRIBUTE(samples_dir, "total", data->total_samp); 83 return 0; 84 } 85 86 int hypfs_vm_create_files(struct dentry *root) 87 { 88 struct dentry *dir, *file; 89 struct diag2fc_data *data; 90 unsigned int count = 0; 91 int rc, i; 92 93 data = diag2fc_store(diag2fc_guest_query, &count, 0); 94 if (IS_ERR(data)) 95 return PTR_ERR(data); 96 97 /* Hypervisor Info */ 98 dir = hypfs_mkdir(root, "hyp"); 99 if (IS_ERR(dir)) { 100 rc = PTR_ERR(dir); 101 goto failed; 102 } 103 file = hypfs_create_str(dir, "type", "z/VM Hypervisor"); 104 if (IS_ERR(file)) { 105 rc = PTR_ERR(file); 106 goto failed; 107 } 108 109 /* physical cpus */ 110 dir = hypfs_mkdir(root, "cpus"); 111 if (IS_ERR(dir)) { 112 rc = PTR_ERR(dir); 113 goto failed; 114 } 115 file = hypfs_create_u64(dir, "count", data->lcpus); 116 if (IS_ERR(file)) { 117 rc = PTR_ERR(file); 118 goto failed; 119 } 120 121 /* guests */ 122 dir = hypfs_mkdir(root, "systems"); 123 if (IS_ERR(dir)) { 124 rc = PTR_ERR(dir); 125 goto failed; 126 } 127 128 for (i = 0; i < count; i++) { 129 rc = hypfs_vm_create_guest(dir, &data[i]); 130 if (rc) 131 goto failed; 132 } 133 diag2fc_free(data); 134 return 0; 135 136 failed: 137 diag2fc_free(data); 138 return rc; 139 } 140