Linux Audio

Check our new training course

Buildroot integration, development and maintenance

Need a Buildroot system for your embedded project?
Loading...
v6.2
  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.h"
 18
 19#define NAME_LEN 8
 20#define DBFS_D2FC_HDR_VERSION 0
 21
 22static char local_guest[] = "        ";
 23static char all_guests[] = "*       ";
 24static char *all_groups = all_guests;
 25static char *guest_query;
 26
 27struct diag2fc_data {
 28	__u32 version;
 29	__u32 flags;
 30	__u64 used_cpu;
 31	__u64 el_time;
 32	__u64 mem_min_kb;
 33	__u64 mem_max_kb;
 34	__u64 mem_share_kb;
 35	__u64 mem_used_kb;
 36	__u32 pcpus;
 37	__u32 lcpus;
 38	__u32 vcpus;
 39	__u32 ocpus;
 40	__u32 cpu_max;
 41	__u32 cpu_shares;
 42	__u32 cpu_use_samp;
 43	__u32 cpu_delay_samp;
 44	__u32 page_wait_samp;
 45	__u32 idle_samp;
 46	__u32 other_samp;
 47	__u32 total_samp;
 48	char  guest_name[NAME_LEN];
 49};
 50
 51struct diag2fc_parm_list {
 52	char userid[NAME_LEN];
 53	char aci_grp[NAME_LEN];
 54	__u64 addr;
 55	__u32 size;
 56	__u32 fmt;
 57};
 58
 59static int diag2fc(int size, char* query, void *addr)
 60{
 61	unsigned long residual_cnt;
 62	unsigned long rc;
 63	struct diag2fc_parm_list parm_list;
 64
 65	memcpy(parm_list.userid, query, NAME_LEN);
 66	ASCEBC(parm_list.userid, NAME_LEN);
 67	memcpy(parm_list.aci_grp, all_groups, NAME_LEN);
 68	ASCEBC(parm_list.aci_grp, NAME_LEN);
 69	parm_list.addr = (unsigned long)addr;
 70	parm_list.size = size;
 71	parm_list.fmt = 0x02;
 
 72	rc = -1;
 73
 74	diag_stat_inc(DIAG_STAT_X2FC);
 75	asm volatile(
 76		"	diag    %0,%1,0x2fc\n"
 77		"0:	nopr	%%r7\n"
 78		EX_TABLE(0b,0b)
 79		: "=d" (residual_cnt), "+d" (rc) : "0" (&parm_list) : "memory");
 80
 81	if ((rc != 0 ) && (rc != -2))
 82		return rc;
 83	else
 84		return -residual_cnt;
 85}
 86
 87/*
 88 * Allocate buffer for "query" and store diag 2fc at "offset"
 89 */
 90static void *diag2fc_store(char *query, unsigned int *count, int offset)
 91{
 92	void *data;
 93	int size;
 94
 95	do {
 96		size = diag2fc(0, query, NULL);
 97		if (size < 0)
 98			return ERR_PTR(-EACCES);
 99		data = vmalloc(size + offset);
100		if (!data)
101			return ERR_PTR(-ENOMEM);
102		if (diag2fc(size, query, data + offset) == 0)
103			break;
104		vfree(data);
105	} while (1);
106	*count = (size / sizeof(struct diag2fc_data));
107
108	return data;
109}
110
111static void diag2fc_free(const void *data)
112{
113	vfree(data);
114}
115
116#define ATTRIBUTE(dir, name, member) \
117do { \
118	void *rc; \
119	rc = hypfs_create_u64(dir, name, member); \
120	if (IS_ERR(rc)) \
121		return PTR_ERR(rc); \
122} while(0)
123
124static int hypfs_vm_create_guest(struct dentry *systems_dir,
 
125				 struct diag2fc_data *data)
126{
127	char guest_name[NAME_LEN + 1] = {};
128	struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir;
129	int dedicated_flag, capped_value;
130
131	capped_value = (data->flags & 0x00000006) >> 1;
132	dedicated_flag = (data->flags & 0x00000008) >> 3;
133
134	/* guest dir */
135	memcpy(guest_name, data->guest_name, NAME_LEN);
136	EBCASC(guest_name, NAME_LEN);
137	strim(guest_name);
138	guest_dir = hypfs_mkdir(systems_dir, guest_name);
139	if (IS_ERR(guest_dir))
140		return PTR_ERR(guest_dir);
141	ATTRIBUTE(guest_dir, "onlinetime_us", data->el_time);
142
143	/* logical cpu information */
144	cpus_dir = hypfs_mkdir(guest_dir, "cpus");
145	if (IS_ERR(cpus_dir))
146		return PTR_ERR(cpus_dir);
147	ATTRIBUTE(cpus_dir, "cputime_us", data->used_cpu);
148	ATTRIBUTE(cpus_dir, "capped", capped_value);
149	ATTRIBUTE(cpus_dir, "dedicated", dedicated_flag);
150	ATTRIBUTE(cpus_dir, "count", data->vcpus);
151	/*
152	 * Note: The "weight_min" attribute got the wrong name.
153	 * The value represents the number of non-stopped (operating)
154	 * CPUS.
155	 */
156	ATTRIBUTE(cpus_dir, "weight_min", data->ocpus);
157	ATTRIBUTE(cpus_dir, "weight_max", data->cpu_max);
158	ATTRIBUTE(cpus_dir, "weight_cur", data->cpu_shares);
159
160	/* memory information */
161	mem_dir = hypfs_mkdir(guest_dir, "mem");
162	if (IS_ERR(mem_dir))
163		return PTR_ERR(mem_dir);
164	ATTRIBUTE(mem_dir, "min_KiB", data->mem_min_kb);
165	ATTRIBUTE(mem_dir, "max_KiB", data->mem_max_kb);
166	ATTRIBUTE(mem_dir, "used_KiB", data->mem_used_kb);
167	ATTRIBUTE(mem_dir, "share_KiB", data->mem_share_kb);
168
169	/* samples */
170	samples_dir = hypfs_mkdir(guest_dir, "samples");
171	if (IS_ERR(samples_dir))
172		return PTR_ERR(samples_dir);
173	ATTRIBUTE(samples_dir, "cpu_using", data->cpu_use_samp);
174	ATTRIBUTE(samples_dir, "cpu_delay", data->cpu_delay_samp);
175	ATTRIBUTE(samples_dir, "mem_delay", data->page_wait_samp);
176	ATTRIBUTE(samples_dir, "idle", data->idle_samp);
177	ATTRIBUTE(samples_dir, "other", data->other_samp);
178	ATTRIBUTE(samples_dir, "total", data->total_samp);
179	return 0;
180}
181
182int hypfs_vm_create_files(struct dentry *root)
183{
184	struct dentry *dir, *file;
185	struct diag2fc_data *data;
186	unsigned int count = 0;
187	int rc, i;
188
189	data = diag2fc_store(guest_query, &count, 0);
190	if (IS_ERR(data))
191		return PTR_ERR(data);
192
193	/* Hypervisor Info */
194	dir = hypfs_mkdir(root, "hyp");
195	if (IS_ERR(dir)) {
196		rc = PTR_ERR(dir);
197		goto failed;
198	}
199	file = hypfs_create_str(dir, "type", "z/VM Hypervisor");
200	if (IS_ERR(file)) {
201		rc = PTR_ERR(file);
202		goto failed;
203	}
204
205	/* physical cpus */
206	dir = hypfs_mkdir(root, "cpus");
207	if (IS_ERR(dir)) {
208		rc = PTR_ERR(dir);
209		goto failed;
210	}
211	file = hypfs_create_u64(dir, "count", data->lcpus);
212	if (IS_ERR(file)) {
213		rc = PTR_ERR(file);
214		goto failed;
215	}
216
217	/* guests */
218	dir = hypfs_mkdir(root, "systems");
219	if (IS_ERR(dir)) {
220		rc = PTR_ERR(dir);
221		goto failed;
222	}
223
224	for (i = 0; i < count; i++) {
225		rc = hypfs_vm_create_guest(dir, &(data[i]));
226		if (rc)
227			goto failed;
228	}
229	diag2fc_free(data);
230	return 0;
231
232failed:
233	diag2fc_free(data);
234	return rc;
235}
236
237struct dbfs_d2fc_hdr {
238	u64	len;		/* Length of d2fc buffer without header */
239	u16	version;	/* Version of header */
240	union tod_clock tod_ext; /* TOD clock for d2fc */
241	u64	count;		/* Number of VM guests in d2fc buffer */
242	char	reserved[30];
243} __attribute__ ((packed));
244
245struct dbfs_d2fc {
246	struct dbfs_d2fc_hdr	hdr;	/* 64 byte header */
247	char			buf[];	/* d2fc buffer */
248} __attribute__ ((packed));
249
250static int dbfs_diag2fc_create(void **data, void **data_free_ptr, size_t *size)
251{
252	struct dbfs_d2fc *d2fc;
253	unsigned int count;
254
255	d2fc = diag2fc_store(guest_query, &count, sizeof(d2fc->hdr));
256	if (IS_ERR(d2fc))
257		return PTR_ERR(d2fc);
258	store_tod_clock_ext(&d2fc->hdr.tod_ext);
259	d2fc->hdr.len = count * sizeof(struct diag2fc_data);
260	d2fc->hdr.version = DBFS_D2FC_HDR_VERSION;
261	d2fc->hdr.count = count;
262	memset(&d2fc->hdr.reserved, 0, sizeof(d2fc->hdr.reserved));
263	*data = d2fc;
264	*data_free_ptr = d2fc;
265	*size = d2fc->hdr.len + sizeof(struct dbfs_d2fc_hdr);
266	return 0;
267}
268
269static struct hypfs_dbfs_file dbfs_file_2fc = {
270	.name		= "diag_2fc",
271	.data_create	= dbfs_diag2fc_create,
272	.data_free	= diag2fc_free,
273};
274
275int hypfs_vm_init(void)
276{
277	if (!MACHINE_IS_VM)
278		return 0;
279	if (diag2fc(0, all_guests, NULL) > 0)
280		guest_query = all_guests;
281	else if (diag2fc(0, local_guest, NULL) > 0)
282		guest_query = local_guest;
283	else
284		return -EACCES;
285	hypfs_dbfs_create_file(&dbfs_file_2fc);
286	return 0;
287}
288
289void hypfs_vm_exit(void)
290{
291	if (!MACHINE_IS_VM)
292		return;
293	hypfs_dbfs_remove_file(&dbfs_file_2fc);
294}
v3.5.6
 
  1/*
  2 *    Hypervisor filesystem for Linux on s390. z/VM implementation.
  3 *
  4 *    Copyright (C) IBM Corp. 2006
  5 *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
  6 */
  7
  8#include <linux/types.h>
  9#include <linux/errno.h>
 10#include <linux/string.h>
 11#include <linux/vmalloc.h>
 
 
 12#include <asm/ebcdic.h>
 13#include <asm/timex.h>
 14#include "hypfs.h"
 15
 16#define NAME_LEN 8
 17#define DBFS_D2FC_HDR_VERSION 0
 18
 19static char local_guest[] = "        ";
 20static char all_guests[] = "*       ";
 
 21static char *guest_query;
 22
 23struct diag2fc_data {
 24	__u32 version;
 25	__u32 flags;
 26	__u64 used_cpu;
 27	__u64 el_time;
 28	__u64 mem_min_kb;
 29	__u64 mem_max_kb;
 30	__u64 mem_share_kb;
 31	__u64 mem_used_kb;
 32	__u32 pcpus;
 33	__u32 lcpus;
 34	__u32 vcpus;
 35	__u32 cpu_min;
 36	__u32 cpu_max;
 37	__u32 cpu_shares;
 38	__u32 cpu_use_samp;
 39	__u32 cpu_delay_samp;
 40	__u32 page_wait_samp;
 41	__u32 idle_samp;
 42	__u32 other_samp;
 43	__u32 total_samp;
 44	char  guest_name[NAME_LEN];
 45};
 46
 47struct diag2fc_parm_list {
 48	char userid[NAME_LEN];
 49	char aci_grp[NAME_LEN];
 50	__u64 addr;
 51	__u32 size;
 52	__u32 fmt;
 53};
 54
 55static int diag2fc(int size, char* query, void *addr)
 56{
 57	unsigned long residual_cnt;
 58	unsigned long rc;
 59	struct diag2fc_parm_list parm_list;
 60
 61	memcpy(parm_list.userid, query, NAME_LEN);
 62	ASCEBC(parm_list.userid, NAME_LEN);
 63	parm_list.addr = (unsigned long) addr ;
 
 
 64	parm_list.size = size;
 65	parm_list.fmt = 0x02;
 66	memset(parm_list.aci_grp, 0x40, NAME_LEN);
 67	rc = -1;
 68
 
 69	asm volatile(
 70		"	diag    %0,%1,0x2fc\n"
 71		"0:\n"
 72		EX_TABLE(0b,0b)
 73		: "=d" (residual_cnt), "+d" (rc) : "0" (&parm_list) : "memory");
 74
 75	if ((rc != 0 ) && (rc != -2))
 76		return rc;
 77	else
 78		return -residual_cnt;
 79}
 80
 81/*
 82 * Allocate buffer for "query" and store diag 2fc at "offset"
 83 */
 84static void *diag2fc_store(char *query, unsigned int *count, int offset)
 85{
 86	void *data;
 87	int size;
 88
 89	do {
 90		size = diag2fc(0, query, NULL);
 91		if (size < 0)
 92			return ERR_PTR(-EACCES);
 93		data = vmalloc(size + offset);
 94		if (!data)
 95			return ERR_PTR(-ENOMEM);
 96		if (diag2fc(size, query, data + offset) == 0)
 97			break;
 98		vfree(data);
 99	} while (1);
100	*count = (size / sizeof(struct diag2fc_data));
101
102	return data;
103}
104
105static void diag2fc_free(const void *data)
106{
107	vfree(data);
108}
109
110#define ATTRIBUTE(sb, dir, name, member) \
111do { \
112	void *rc; \
113	rc = hypfs_create_u64(sb, dir, name, member); \
114	if (IS_ERR(rc)) \
115		return PTR_ERR(rc); \
116} while(0)
117
118static int hpyfs_vm_create_guest(struct super_block *sb,
119				 struct dentry *systems_dir,
120				 struct diag2fc_data *data)
121{
122	char guest_name[NAME_LEN + 1] = {};
123	struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir;
124	int dedicated_flag, capped_value;
125
126	capped_value = (data->flags & 0x00000006) >> 1;
127	dedicated_flag = (data->flags & 0x00000008) >> 3;
128
129	/* guest dir */
130	memcpy(guest_name, data->guest_name, NAME_LEN);
131	EBCASC(guest_name, NAME_LEN);
132	strim(guest_name);
133	guest_dir = hypfs_mkdir(sb, systems_dir, guest_name);
134	if (IS_ERR(guest_dir))
135		return PTR_ERR(guest_dir);
136	ATTRIBUTE(sb, guest_dir, "onlinetime_us", data->el_time);
137
138	/* logical cpu information */
139	cpus_dir = hypfs_mkdir(sb, guest_dir, "cpus");
140	if (IS_ERR(cpus_dir))
141		return PTR_ERR(cpus_dir);
142	ATTRIBUTE(sb, cpus_dir, "cputime_us", data->used_cpu);
143	ATTRIBUTE(sb, cpus_dir, "capped", capped_value);
144	ATTRIBUTE(sb, cpus_dir, "dedicated", dedicated_flag);
145	ATTRIBUTE(sb, cpus_dir, "count", data->vcpus);
146	ATTRIBUTE(sb, cpus_dir, "weight_min", data->cpu_min);
147	ATTRIBUTE(sb, cpus_dir, "weight_max", data->cpu_max);
148	ATTRIBUTE(sb, cpus_dir, "weight_cur", data->cpu_shares);
 
 
 
 
 
149
150	/* memory information */
151	mem_dir = hypfs_mkdir(sb, guest_dir, "mem");
152	if (IS_ERR(mem_dir))
153		return PTR_ERR(mem_dir);
154	ATTRIBUTE(sb, mem_dir, "min_KiB", data->mem_min_kb);
155	ATTRIBUTE(sb, mem_dir, "max_KiB", data->mem_max_kb);
156	ATTRIBUTE(sb, mem_dir, "used_KiB", data->mem_used_kb);
157	ATTRIBUTE(sb, mem_dir, "share_KiB", data->mem_share_kb);
158
159	/* samples */
160	samples_dir = hypfs_mkdir(sb, guest_dir, "samples");
161	if (IS_ERR(samples_dir))
162		return PTR_ERR(samples_dir);
163	ATTRIBUTE(sb, samples_dir, "cpu_using", data->cpu_use_samp);
164	ATTRIBUTE(sb, samples_dir, "cpu_delay", data->cpu_delay_samp);
165	ATTRIBUTE(sb, samples_dir, "mem_delay", data->page_wait_samp);
166	ATTRIBUTE(sb, samples_dir, "idle", data->idle_samp);
167	ATTRIBUTE(sb, samples_dir, "other", data->other_samp);
168	ATTRIBUTE(sb, samples_dir, "total", data->total_samp);
169	return 0;
170}
171
172int hypfs_vm_create_files(struct super_block *sb, struct dentry *root)
173{
174	struct dentry *dir, *file;
175	struct diag2fc_data *data;
176	unsigned int count = 0;
177	int rc, i;
178
179	data = diag2fc_store(guest_query, &count, 0);
180	if (IS_ERR(data))
181		return PTR_ERR(data);
182
183	/* Hpervisor Info */
184	dir = hypfs_mkdir(sb, root, "hyp");
185	if (IS_ERR(dir)) {
186		rc = PTR_ERR(dir);
187		goto failed;
188	}
189	file = hypfs_create_str(sb, dir, "type", "z/VM Hypervisor");
190	if (IS_ERR(file)) {
191		rc = PTR_ERR(file);
192		goto failed;
193	}
194
195	/* physical cpus */
196	dir = hypfs_mkdir(sb, root, "cpus");
197	if (IS_ERR(dir)) {
198		rc = PTR_ERR(dir);
199		goto failed;
200	}
201	file = hypfs_create_u64(sb, dir, "count", data->lcpus);
202	if (IS_ERR(file)) {
203		rc = PTR_ERR(file);
204		goto failed;
205	}
206
207	/* guests */
208	dir = hypfs_mkdir(sb, root, "systems");
209	if (IS_ERR(dir)) {
210		rc = PTR_ERR(dir);
211		goto failed;
212	}
213
214	for (i = 0; i < count; i++) {
215		rc = hpyfs_vm_create_guest(sb, dir, &(data[i]));
216		if (rc)
217			goto failed;
218	}
219	diag2fc_free(data);
220	return 0;
221
222failed:
223	diag2fc_free(data);
224	return rc;
225}
226
227struct dbfs_d2fc_hdr {
228	u64	len;		/* Length of d2fc buffer without header */
229	u16	version;	/* Version of header */
230	char	tod_ext[16];	/* TOD clock for d2fc */
231	u64	count;		/* Number of VM guests in d2fc buffer */
232	char	reserved[30];
233} __attribute__ ((packed));
234
235struct dbfs_d2fc {
236	struct dbfs_d2fc_hdr	hdr;	/* 64 byte header */
237	char			buf[];	/* d2fc buffer */
238} __attribute__ ((packed));
239
240static int dbfs_diag2fc_create(void **data, void **data_free_ptr, size_t *size)
241{
242	struct dbfs_d2fc *d2fc;
243	unsigned int count;
244
245	d2fc = diag2fc_store(guest_query, &count, sizeof(d2fc->hdr));
246	if (IS_ERR(d2fc))
247		return PTR_ERR(d2fc);
248	get_clock_ext(d2fc->hdr.tod_ext);
249	d2fc->hdr.len = count * sizeof(struct diag2fc_data);
250	d2fc->hdr.version = DBFS_D2FC_HDR_VERSION;
251	d2fc->hdr.count = count;
252	memset(&d2fc->hdr.reserved, 0, sizeof(d2fc->hdr.reserved));
253	*data = d2fc;
254	*data_free_ptr = d2fc;
255	*size = d2fc->hdr.len + sizeof(struct dbfs_d2fc_hdr);
256	return 0;
257}
258
259static struct hypfs_dbfs_file dbfs_file_2fc = {
260	.name		= "diag_2fc",
261	.data_create	= dbfs_diag2fc_create,
262	.data_free	= diag2fc_free,
263};
264
265int hypfs_vm_init(void)
266{
267	if (!MACHINE_IS_VM)
268		return 0;
269	if (diag2fc(0, all_guests, NULL) > 0)
270		guest_query = all_guests;
271	else if (diag2fc(0, local_guest, NULL) > 0)
272		guest_query = local_guest;
273	else
274		return -EACCES;
275	return hypfs_dbfs_create_file(&dbfs_file_2fc);
 
276}
277
278void hypfs_vm_exit(void)
279{
280	if (!MACHINE_IS_VM)
281		return;
282	hypfs_dbfs_remove_file(&dbfs_file_2fc);
283}