162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Hypervisor filesystem for Linux on s390. z/VM implementation. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright IBM Corp. 2006 662306a36Sopenharmony_ci * Author(s): Michael Holzheu <holzheu@de.ibm.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <linux/errno.h> 1162306a36Sopenharmony_ci#include <linux/string.h> 1262306a36Sopenharmony_ci#include <linux/vmalloc.h> 1362306a36Sopenharmony_ci#include <asm/extable.h> 1462306a36Sopenharmony_ci#include <asm/diag.h> 1562306a36Sopenharmony_ci#include <asm/ebcdic.h> 1662306a36Sopenharmony_ci#include <asm/timex.h> 1762306a36Sopenharmony_ci#include "hypfs_vm.h" 1862306a36Sopenharmony_ci#include "hypfs.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define ATTRIBUTE(dir, name, member) \ 2162306a36Sopenharmony_cido { \ 2262306a36Sopenharmony_ci void *rc; \ 2362306a36Sopenharmony_ci rc = hypfs_create_u64(dir, name, member); \ 2462306a36Sopenharmony_ci if (IS_ERR(rc)) \ 2562306a36Sopenharmony_ci return PTR_ERR(rc); \ 2662306a36Sopenharmony_ci} while (0) 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic int hypfs_vm_create_guest(struct dentry *systems_dir, 2962306a36Sopenharmony_ci struct diag2fc_data *data) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci char guest_name[DIAG2FC_NAME_LEN + 1] = {}; 3262306a36Sopenharmony_ci struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir; 3362306a36Sopenharmony_ci int dedicated_flag, capped_value; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci capped_value = (data->flags & 0x00000006) >> 1; 3662306a36Sopenharmony_ci dedicated_flag = (data->flags & 0x00000008) >> 3; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* guest dir */ 3962306a36Sopenharmony_ci memcpy(guest_name, data->guest_name, DIAG2FC_NAME_LEN); 4062306a36Sopenharmony_ci EBCASC(guest_name, DIAG2FC_NAME_LEN); 4162306a36Sopenharmony_ci strim(guest_name); 4262306a36Sopenharmony_ci guest_dir = hypfs_mkdir(systems_dir, guest_name); 4362306a36Sopenharmony_ci if (IS_ERR(guest_dir)) 4462306a36Sopenharmony_ci return PTR_ERR(guest_dir); 4562306a36Sopenharmony_ci ATTRIBUTE(guest_dir, "onlinetime_us", data->el_time); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /* logical cpu information */ 4862306a36Sopenharmony_ci cpus_dir = hypfs_mkdir(guest_dir, "cpus"); 4962306a36Sopenharmony_ci if (IS_ERR(cpus_dir)) 5062306a36Sopenharmony_ci return PTR_ERR(cpus_dir); 5162306a36Sopenharmony_ci ATTRIBUTE(cpus_dir, "cputime_us", data->used_cpu); 5262306a36Sopenharmony_ci ATTRIBUTE(cpus_dir, "capped", capped_value); 5362306a36Sopenharmony_ci ATTRIBUTE(cpus_dir, "dedicated", dedicated_flag); 5462306a36Sopenharmony_ci ATTRIBUTE(cpus_dir, "count", data->vcpus); 5562306a36Sopenharmony_ci /* 5662306a36Sopenharmony_ci * Note: The "weight_min" attribute got the wrong name. 5762306a36Sopenharmony_ci * The value represents the number of non-stopped (operating) 5862306a36Sopenharmony_ci * CPUS. 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ci ATTRIBUTE(cpus_dir, "weight_min", data->ocpus); 6162306a36Sopenharmony_ci ATTRIBUTE(cpus_dir, "weight_max", data->cpu_max); 6262306a36Sopenharmony_ci ATTRIBUTE(cpus_dir, "weight_cur", data->cpu_shares); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* memory information */ 6562306a36Sopenharmony_ci mem_dir = hypfs_mkdir(guest_dir, "mem"); 6662306a36Sopenharmony_ci if (IS_ERR(mem_dir)) 6762306a36Sopenharmony_ci return PTR_ERR(mem_dir); 6862306a36Sopenharmony_ci ATTRIBUTE(mem_dir, "min_KiB", data->mem_min_kb); 6962306a36Sopenharmony_ci ATTRIBUTE(mem_dir, "max_KiB", data->mem_max_kb); 7062306a36Sopenharmony_ci ATTRIBUTE(mem_dir, "used_KiB", data->mem_used_kb); 7162306a36Sopenharmony_ci ATTRIBUTE(mem_dir, "share_KiB", data->mem_share_kb); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* samples */ 7462306a36Sopenharmony_ci samples_dir = hypfs_mkdir(guest_dir, "samples"); 7562306a36Sopenharmony_ci if (IS_ERR(samples_dir)) 7662306a36Sopenharmony_ci return PTR_ERR(samples_dir); 7762306a36Sopenharmony_ci ATTRIBUTE(samples_dir, "cpu_using", data->cpu_use_samp); 7862306a36Sopenharmony_ci ATTRIBUTE(samples_dir, "cpu_delay", data->cpu_delay_samp); 7962306a36Sopenharmony_ci ATTRIBUTE(samples_dir, "mem_delay", data->page_wait_samp); 8062306a36Sopenharmony_ci ATTRIBUTE(samples_dir, "idle", data->idle_samp); 8162306a36Sopenharmony_ci ATTRIBUTE(samples_dir, "other", data->other_samp); 8262306a36Sopenharmony_ci ATTRIBUTE(samples_dir, "total", data->total_samp); 8362306a36Sopenharmony_ci return 0; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciint hypfs_vm_create_files(struct dentry *root) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci struct dentry *dir, *file; 8962306a36Sopenharmony_ci struct diag2fc_data *data; 9062306a36Sopenharmony_ci unsigned int count = 0; 9162306a36Sopenharmony_ci int rc, i; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci data = diag2fc_store(diag2fc_guest_query, &count, 0); 9462306a36Sopenharmony_ci if (IS_ERR(data)) 9562306a36Sopenharmony_ci return PTR_ERR(data); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* Hypervisor Info */ 9862306a36Sopenharmony_ci dir = hypfs_mkdir(root, "hyp"); 9962306a36Sopenharmony_ci if (IS_ERR(dir)) { 10062306a36Sopenharmony_ci rc = PTR_ERR(dir); 10162306a36Sopenharmony_ci goto failed; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci file = hypfs_create_str(dir, "type", "z/VM Hypervisor"); 10462306a36Sopenharmony_ci if (IS_ERR(file)) { 10562306a36Sopenharmony_ci rc = PTR_ERR(file); 10662306a36Sopenharmony_ci goto failed; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* physical cpus */ 11062306a36Sopenharmony_ci dir = hypfs_mkdir(root, "cpus"); 11162306a36Sopenharmony_ci if (IS_ERR(dir)) { 11262306a36Sopenharmony_ci rc = PTR_ERR(dir); 11362306a36Sopenharmony_ci goto failed; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci file = hypfs_create_u64(dir, "count", data->lcpus); 11662306a36Sopenharmony_ci if (IS_ERR(file)) { 11762306a36Sopenharmony_ci rc = PTR_ERR(file); 11862306a36Sopenharmony_ci goto failed; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* guests */ 12262306a36Sopenharmony_ci dir = hypfs_mkdir(root, "systems"); 12362306a36Sopenharmony_ci if (IS_ERR(dir)) { 12462306a36Sopenharmony_ci rc = PTR_ERR(dir); 12562306a36Sopenharmony_ci goto failed; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci for (i = 0; i < count; i++) { 12962306a36Sopenharmony_ci rc = hypfs_vm_create_guest(dir, &data[i]); 13062306a36Sopenharmony_ci if (rc) 13162306a36Sopenharmony_ci goto failed; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci diag2fc_free(data); 13462306a36Sopenharmony_ci return 0; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cifailed: 13762306a36Sopenharmony_ci diag2fc_free(data); 13862306a36Sopenharmony_ci return rc; 13962306a36Sopenharmony_ci} 140