xref: /openbmc/linux/drivers/xen/sys-hypervisor.c (revision cff7e81b3dd7c25cd2248cd7a04c5764552d5d55)
1*cff7e81bSJeremy Fitzhardinge /*
2*cff7e81bSJeremy Fitzhardinge  *  copyright (c) 2006 IBM Corporation
3*cff7e81bSJeremy Fitzhardinge  *  Authored by: Mike D. Day <ncmike@us.ibm.com>
4*cff7e81bSJeremy Fitzhardinge  *
5*cff7e81bSJeremy Fitzhardinge  *  This program is free software; you can redistribute it and/or modify
6*cff7e81bSJeremy Fitzhardinge  *  it under the terms of the GNU General Public License version 2 as
7*cff7e81bSJeremy Fitzhardinge  *  published by the Free Software Foundation.
8*cff7e81bSJeremy Fitzhardinge  */
9*cff7e81bSJeremy Fitzhardinge 
10*cff7e81bSJeremy Fitzhardinge #include <linux/kernel.h>
11*cff7e81bSJeremy Fitzhardinge #include <linux/module.h>
12*cff7e81bSJeremy Fitzhardinge #include <linux/kobject.h>
13*cff7e81bSJeremy Fitzhardinge 
14*cff7e81bSJeremy Fitzhardinge #include <asm/xen/hypervisor.h>
15*cff7e81bSJeremy Fitzhardinge #include <asm/xen/hypercall.h>
16*cff7e81bSJeremy Fitzhardinge 
17*cff7e81bSJeremy Fitzhardinge #include <xen/xenbus.h>
18*cff7e81bSJeremy Fitzhardinge #include <xen/interface/xen.h>
19*cff7e81bSJeremy Fitzhardinge #include <xen/interface/version.h>
20*cff7e81bSJeremy Fitzhardinge 
21*cff7e81bSJeremy Fitzhardinge #define HYPERVISOR_ATTR_RO(_name) \
22*cff7e81bSJeremy Fitzhardinge static struct hyp_sysfs_attr  _name##_attr = __ATTR_RO(_name)
23*cff7e81bSJeremy Fitzhardinge 
24*cff7e81bSJeremy Fitzhardinge #define HYPERVISOR_ATTR_RW(_name) \
25*cff7e81bSJeremy Fitzhardinge static struct hyp_sysfs_attr _name##_attr = \
26*cff7e81bSJeremy Fitzhardinge 	__ATTR(_name, 0644, _name##_show, _name##_store)
27*cff7e81bSJeremy Fitzhardinge 
28*cff7e81bSJeremy Fitzhardinge struct hyp_sysfs_attr {
29*cff7e81bSJeremy Fitzhardinge 	struct attribute attr;
30*cff7e81bSJeremy Fitzhardinge 	ssize_t (*show)(struct hyp_sysfs_attr *, char *);
31*cff7e81bSJeremy Fitzhardinge 	ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
32*cff7e81bSJeremy Fitzhardinge 	void *hyp_attr_data;
33*cff7e81bSJeremy Fitzhardinge };
34*cff7e81bSJeremy Fitzhardinge 
35*cff7e81bSJeremy Fitzhardinge static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
36*cff7e81bSJeremy Fitzhardinge {
37*cff7e81bSJeremy Fitzhardinge 	return sprintf(buffer, "xen\n");
38*cff7e81bSJeremy Fitzhardinge }
39*cff7e81bSJeremy Fitzhardinge 
40*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(type);
41*cff7e81bSJeremy Fitzhardinge 
42*cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_type_init(void)
43*cff7e81bSJeremy Fitzhardinge {
44*cff7e81bSJeremy Fitzhardinge 	return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
45*cff7e81bSJeremy Fitzhardinge }
46*cff7e81bSJeremy Fitzhardinge 
47*cff7e81bSJeremy Fitzhardinge static void xen_sysfs_type_destroy(void)
48*cff7e81bSJeremy Fitzhardinge {
49*cff7e81bSJeremy Fitzhardinge 	sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
50*cff7e81bSJeremy Fitzhardinge }
51*cff7e81bSJeremy Fitzhardinge 
52*cff7e81bSJeremy Fitzhardinge /* xen version attributes */
53*cff7e81bSJeremy Fitzhardinge static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
54*cff7e81bSJeremy Fitzhardinge {
55*cff7e81bSJeremy Fitzhardinge 	int version = HYPERVISOR_xen_version(XENVER_version, NULL);
56*cff7e81bSJeremy Fitzhardinge 	if (version)
57*cff7e81bSJeremy Fitzhardinge 		return sprintf(buffer, "%d\n", version >> 16);
58*cff7e81bSJeremy Fitzhardinge 	return -ENODEV;
59*cff7e81bSJeremy Fitzhardinge }
60*cff7e81bSJeremy Fitzhardinge 
61*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(major);
62*cff7e81bSJeremy Fitzhardinge 
63*cff7e81bSJeremy Fitzhardinge static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer)
64*cff7e81bSJeremy Fitzhardinge {
65*cff7e81bSJeremy Fitzhardinge 	int version = HYPERVISOR_xen_version(XENVER_version, NULL);
66*cff7e81bSJeremy Fitzhardinge 	if (version)
67*cff7e81bSJeremy Fitzhardinge 		return sprintf(buffer, "%d\n", version & 0xff);
68*cff7e81bSJeremy Fitzhardinge 	return -ENODEV;
69*cff7e81bSJeremy Fitzhardinge }
70*cff7e81bSJeremy Fitzhardinge 
71*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(minor);
72*cff7e81bSJeremy Fitzhardinge 
73*cff7e81bSJeremy Fitzhardinge static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer)
74*cff7e81bSJeremy Fitzhardinge {
75*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
76*cff7e81bSJeremy Fitzhardinge 	char *extra;
77*cff7e81bSJeremy Fitzhardinge 
78*cff7e81bSJeremy Fitzhardinge 	extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL);
79*cff7e81bSJeremy Fitzhardinge 	if (extra) {
80*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_extraversion, extra);
81*cff7e81bSJeremy Fitzhardinge 		if (!ret)
82*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%s\n", extra);
83*cff7e81bSJeremy Fitzhardinge 		kfree(extra);
84*cff7e81bSJeremy Fitzhardinge 	}
85*cff7e81bSJeremy Fitzhardinge 
86*cff7e81bSJeremy Fitzhardinge 	return ret;
87*cff7e81bSJeremy Fitzhardinge }
88*cff7e81bSJeremy Fitzhardinge 
89*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(extra);
90*cff7e81bSJeremy Fitzhardinge 
91*cff7e81bSJeremy Fitzhardinge static struct attribute *version_attrs[] = {
92*cff7e81bSJeremy Fitzhardinge 	&major_attr.attr,
93*cff7e81bSJeremy Fitzhardinge 	&minor_attr.attr,
94*cff7e81bSJeremy Fitzhardinge 	&extra_attr.attr,
95*cff7e81bSJeremy Fitzhardinge 	NULL
96*cff7e81bSJeremy Fitzhardinge };
97*cff7e81bSJeremy Fitzhardinge 
98*cff7e81bSJeremy Fitzhardinge static struct attribute_group version_group = {
99*cff7e81bSJeremy Fitzhardinge 	.name = "version",
100*cff7e81bSJeremy Fitzhardinge 	.attrs = version_attrs,
101*cff7e81bSJeremy Fitzhardinge };
102*cff7e81bSJeremy Fitzhardinge 
103*cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_version_init(void)
104*cff7e81bSJeremy Fitzhardinge {
105*cff7e81bSJeremy Fitzhardinge 	return sysfs_create_group(hypervisor_kobj, &version_group);
106*cff7e81bSJeremy Fitzhardinge }
107*cff7e81bSJeremy Fitzhardinge 
108*cff7e81bSJeremy Fitzhardinge static void xen_sysfs_version_destroy(void)
109*cff7e81bSJeremy Fitzhardinge {
110*cff7e81bSJeremy Fitzhardinge 	sysfs_remove_group(hypervisor_kobj, &version_group);
111*cff7e81bSJeremy Fitzhardinge }
112*cff7e81bSJeremy Fitzhardinge 
113*cff7e81bSJeremy Fitzhardinge /* UUID */
114*cff7e81bSJeremy Fitzhardinge 
115*cff7e81bSJeremy Fitzhardinge static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer)
116*cff7e81bSJeremy Fitzhardinge {
117*cff7e81bSJeremy Fitzhardinge 	char *vm, *val;
118*cff7e81bSJeremy Fitzhardinge 	int ret;
119*cff7e81bSJeremy Fitzhardinge 	extern int xenstored_ready;
120*cff7e81bSJeremy Fitzhardinge 
121*cff7e81bSJeremy Fitzhardinge 	if (!xenstored_ready)
122*cff7e81bSJeremy Fitzhardinge 		return -EBUSY;
123*cff7e81bSJeremy Fitzhardinge 
124*cff7e81bSJeremy Fitzhardinge 	vm = xenbus_read(XBT_NIL, "vm", "", NULL);
125*cff7e81bSJeremy Fitzhardinge 	if (IS_ERR(vm))
126*cff7e81bSJeremy Fitzhardinge 		return PTR_ERR(vm);
127*cff7e81bSJeremy Fitzhardinge 	val = xenbus_read(XBT_NIL, vm, "uuid", NULL);
128*cff7e81bSJeremy Fitzhardinge 	kfree(vm);
129*cff7e81bSJeremy Fitzhardinge 	if (IS_ERR(val))
130*cff7e81bSJeremy Fitzhardinge 		return PTR_ERR(val);
131*cff7e81bSJeremy Fitzhardinge 	ret = sprintf(buffer, "%s\n", val);
132*cff7e81bSJeremy Fitzhardinge 	kfree(val);
133*cff7e81bSJeremy Fitzhardinge 	return ret;
134*cff7e81bSJeremy Fitzhardinge }
135*cff7e81bSJeremy Fitzhardinge 
136*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(uuid);
137*cff7e81bSJeremy Fitzhardinge 
138*cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_uuid_init(void)
139*cff7e81bSJeremy Fitzhardinge {
140*cff7e81bSJeremy Fitzhardinge 	return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr);
141*cff7e81bSJeremy Fitzhardinge }
142*cff7e81bSJeremy Fitzhardinge 
143*cff7e81bSJeremy Fitzhardinge static void xen_sysfs_uuid_destroy(void)
144*cff7e81bSJeremy Fitzhardinge {
145*cff7e81bSJeremy Fitzhardinge 	sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
146*cff7e81bSJeremy Fitzhardinge }
147*cff7e81bSJeremy Fitzhardinge 
148*cff7e81bSJeremy Fitzhardinge /* xen compilation attributes */
149*cff7e81bSJeremy Fitzhardinge 
150*cff7e81bSJeremy Fitzhardinge static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
151*cff7e81bSJeremy Fitzhardinge {
152*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
153*cff7e81bSJeremy Fitzhardinge 	struct xen_compile_info *info;
154*cff7e81bSJeremy Fitzhardinge 
155*cff7e81bSJeremy Fitzhardinge 	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
156*cff7e81bSJeremy Fitzhardinge 	if (info) {
157*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
158*cff7e81bSJeremy Fitzhardinge 		if (!ret)
159*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%s\n", info->compiler);
160*cff7e81bSJeremy Fitzhardinge 		kfree(info);
161*cff7e81bSJeremy Fitzhardinge 	}
162*cff7e81bSJeremy Fitzhardinge 
163*cff7e81bSJeremy Fitzhardinge 	return ret;
164*cff7e81bSJeremy Fitzhardinge }
165*cff7e81bSJeremy Fitzhardinge 
166*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compiler);
167*cff7e81bSJeremy Fitzhardinge 
168*cff7e81bSJeremy Fitzhardinge static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer)
169*cff7e81bSJeremy Fitzhardinge {
170*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
171*cff7e81bSJeremy Fitzhardinge 	struct xen_compile_info *info;
172*cff7e81bSJeremy Fitzhardinge 
173*cff7e81bSJeremy Fitzhardinge 	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
174*cff7e81bSJeremy Fitzhardinge 	if (info) {
175*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
176*cff7e81bSJeremy Fitzhardinge 		if (!ret)
177*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%s\n", info->compile_by);
178*cff7e81bSJeremy Fitzhardinge 		kfree(info);
179*cff7e81bSJeremy Fitzhardinge 	}
180*cff7e81bSJeremy Fitzhardinge 
181*cff7e81bSJeremy Fitzhardinge 	return ret;
182*cff7e81bSJeremy Fitzhardinge }
183*cff7e81bSJeremy Fitzhardinge 
184*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compiled_by);
185*cff7e81bSJeremy Fitzhardinge 
186*cff7e81bSJeremy Fitzhardinge static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer)
187*cff7e81bSJeremy Fitzhardinge {
188*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
189*cff7e81bSJeremy Fitzhardinge 	struct xen_compile_info *info;
190*cff7e81bSJeremy Fitzhardinge 
191*cff7e81bSJeremy Fitzhardinge 	info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
192*cff7e81bSJeremy Fitzhardinge 	if (info) {
193*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
194*cff7e81bSJeremy Fitzhardinge 		if (!ret)
195*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%s\n", info->compile_date);
196*cff7e81bSJeremy Fitzhardinge 		kfree(info);
197*cff7e81bSJeremy Fitzhardinge 	}
198*cff7e81bSJeremy Fitzhardinge 
199*cff7e81bSJeremy Fitzhardinge 	return ret;
200*cff7e81bSJeremy Fitzhardinge }
201*cff7e81bSJeremy Fitzhardinge 
202*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compile_date);
203*cff7e81bSJeremy Fitzhardinge 
204*cff7e81bSJeremy Fitzhardinge static struct attribute *xen_compile_attrs[] = {
205*cff7e81bSJeremy Fitzhardinge 	&compiler_attr.attr,
206*cff7e81bSJeremy Fitzhardinge 	&compiled_by_attr.attr,
207*cff7e81bSJeremy Fitzhardinge 	&compile_date_attr.attr,
208*cff7e81bSJeremy Fitzhardinge 	NULL
209*cff7e81bSJeremy Fitzhardinge };
210*cff7e81bSJeremy Fitzhardinge 
211*cff7e81bSJeremy Fitzhardinge static struct attribute_group xen_compilation_group = {
212*cff7e81bSJeremy Fitzhardinge 	.name = "compilation",
213*cff7e81bSJeremy Fitzhardinge 	.attrs = xen_compile_attrs,
214*cff7e81bSJeremy Fitzhardinge };
215*cff7e81bSJeremy Fitzhardinge 
216*cff7e81bSJeremy Fitzhardinge int __init static xen_compilation_init(void)
217*cff7e81bSJeremy Fitzhardinge {
218*cff7e81bSJeremy Fitzhardinge 	return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
219*cff7e81bSJeremy Fitzhardinge }
220*cff7e81bSJeremy Fitzhardinge 
221*cff7e81bSJeremy Fitzhardinge static void xen_compilation_destroy(void)
222*cff7e81bSJeremy Fitzhardinge {
223*cff7e81bSJeremy Fitzhardinge 	sysfs_remove_group(hypervisor_kobj, &xen_compilation_group);
224*cff7e81bSJeremy Fitzhardinge }
225*cff7e81bSJeremy Fitzhardinge 
226*cff7e81bSJeremy Fitzhardinge /* xen properties info */
227*cff7e81bSJeremy Fitzhardinge 
228*cff7e81bSJeremy Fitzhardinge static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer)
229*cff7e81bSJeremy Fitzhardinge {
230*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
231*cff7e81bSJeremy Fitzhardinge 	char *caps;
232*cff7e81bSJeremy Fitzhardinge 
233*cff7e81bSJeremy Fitzhardinge 	caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL);
234*cff7e81bSJeremy Fitzhardinge 	if (caps) {
235*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_capabilities, caps);
236*cff7e81bSJeremy Fitzhardinge 		if (!ret)
237*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%s\n", caps);
238*cff7e81bSJeremy Fitzhardinge 		kfree(caps);
239*cff7e81bSJeremy Fitzhardinge 	}
240*cff7e81bSJeremy Fitzhardinge 
241*cff7e81bSJeremy Fitzhardinge 	return ret;
242*cff7e81bSJeremy Fitzhardinge }
243*cff7e81bSJeremy Fitzhardinge 
244*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(capabilities);
245*cff7e81bSJeremy Fitzhardinge 
246*cff7e81bSJeremy Fitzhardinge static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer)
247*cff7e81bSJeremy Fitzhardinge {
248*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
249*cff7e81bSJeremy Fitzhardinge 	char *cset;
250*cff7e81bSJeremy Fitzhardinge 
251*cff7e81bSJeremy Fitzhardinge 	cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL);
252*cff7e81bSJeremy Fitzhardinge 	if (cset) {
253*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_changeset, cset);
254*cff7e81bSJeremy Fitzhardinge 		if (!ret)
255*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%s\n", cset);
256*cff7e81bSJeremy Fitzhardinge 		kfree(cset);
257*cff7e81bSJeremy Fitzhardinge 	}
258*cff7e81bSJeremy Fitzhardinge 
259*cff7e81bSJeremy Fitzhardinge 	return ret;
260*cff7e81bSJeremy Fitzhardinge }
261*cff7e81bSJeremy Fitzhardinge 
262*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(changeset);
263*cff7e81bSJeremy Fitzhardinge 
264*cff7e81bSJeremy Fitzhardinge static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
265*cff7e81bSJeremy Fitzhardinge {
266*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
267*cff7e81bSJeremy Fitzhardinge 	struct xen_platform_parameters *parms;
268*cff7e81bSJeremy Fitzhardinge 
269*cff7e81bSJeremy Fitzhardinge 	parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL);
270*cff7e81bSJeremy Fitzhardinge 	if (parms) {
271*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
272*cff7e81bSJeremy Fitzhardinge 					     parms);
273*cff7e81bSJeremy Fitzhardinge 		if (!ret)
274*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%lx\n", parms->virt_start);
275*cff7e81bSJeremy Fitzhardinge 		kfree(parms);
276*cff7e81bSJeremy Fitzhardinge 	}
277*cff7e81bSJeremy Fitzhardinge 
278*cff7e81bSJeremy Fitzhardinge 	return ret;
279*cff7e81bSJeremy Fitzhardinge }
280*cff7e81bSJeremy Fitzhardinge 
281*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(virtual_start);
282*cff7e81bSJeremy Fitzhardinge 
283*cff7e81bSJeremy Fitzhardinge static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer)
284*cff7e81bSJeremy Fitzhardinge {
285*cff7e81bSJeremy Fitzhardinge 	int ret;
286*cff7e81bSJeremy Fitzhardinge 
287*cff7e81bSJeremy Fitzhardinge 	ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL);
288*cff7e81bSJeremy Fitzhardinge 	if (ret > 0)
289*cff7e81bSJeremy Fitzhardinge 		ret = sprintf(buffer, "%x\n", ret);
290*cff7e81bSJeremy Fitzhardinge 
291*cff7e81bSJeremy Fitzhardinge 	return ret;
292*cff7e81bSJeremy Fitzhardinge }
293*cff7e81bSJeremy Fitzhardinge 
294*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(pagesize);
295*cff7e81bSJeremy Fitzhardinge 
296*cff7e81bSJeremy Fitzhardinge /* eventually there will be several more features to export */
297*cff7e81bSJeremy Fitzhardinge static ssize_t xen_feature_show(int index, char *buffer)
298*cff7e81bSJeremy Fitzhardinge {
299*cff7e81bSJeremy Fitzhardinge 	int ret = -ENOMEM;
300*cff7e81bSJeremy Fitzhardinge 	struct xen_feature_info *info;
301*cff7e81bSJeremy Fitzhardinge 
302*cff7e81bSJeremy Fitzhardinge 	info = kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL);
303*cff7e81bSJeremy Fitzhardinge 	if (info) {
304*cff7e81bSJeremy Fitzhardinge 		info->submap_idx = index;
305*cff7e81bSJeremy Fitzhardinge 		ret = HYPERVISOR_xen_version(XENVER_get_features, info);
306*cff7e81bSJeremy Fitzhardinge 		if (!ret)
307*cff7e81bSJeremy Fitzhardinge 			ret = sprintf(buffer, "%d\n", info->submap);
308*cff7e81bSJeremy Fitzhardinge 		kfree(info);
309*cff7e81bSJeremy Fitzhardinge 	}
310*cff7e81bSJeremy Fitzhardinge 
311*cff7e81bSJeremy Fitzhardinge 	return ret;
312*cff7e81bSJeremy Fitzhardinge }
313*cff7e81bSJeremy Fitzhardinge 
314*cff7e81bSJeremy Fitzhardinge static ssize_t writable_pt_show(struct hyp_sysfs_attr *attr, char *buffer)
315*cff7e81bSJeremy Fitzhardinge {
316*cff7e81bSJeremy Fitzhardinge 	return xen_feature_show(XENFEAT_writable_page_tables, buffer);
317*cff7e81bSJeremy Fitzhardinge }
318*cff7e81bSJeremy Fitzhardinge 
319*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(writable_pt);
320*cff7e81bSJeremy Fitzhardinge 
321*cff7e81bSJeremy Fitzhardinge static struct attribute *xen_properties_attrs[] = {
322*cff7e81bSJeremy Fitzhardinge 	&capabilities_attr.attr,
323*cff7e81bSJeremy Fitzhardinge 	&changeset_attr.attr,
324*cff7e81bSJeremy Fitzhardinge 	&virtual_start_attr.attr,
325*cff7e81bSJeremy Fitzhardinge 	&pagesize_attr.attr,
326*cff7e81bSJeremy Fitzhardinge 	&writable_pt_attr.attr,
327*cff7e81bSJeremy Fitzhardinge 	NULL
328*cff7e81bSJeremy Fitzhardinge };
329*cff7e81bSJeremy Fitzhardinge 
330*cff7e81bSJeremy Fitzhardinge static struct attribute_group xen_properties_group = {
331*cff7e81bSJeremy Fitzhardinge 	.name = "properties",
332*cff7e81bSJeremy Fitzhardinge 	.attrs = xen_properties_attrs,
333*cff7e81bSJeremy Fitzhardinge };
334*cff7e81bSJeremy Fitzhardinge 
335*cff7e81bSJeremy Fitzhardinge static int __init xen_properties_init(void)
336*cff7e81bSJeremy Fitzhardinge {
337*cff7e81bSJeremy Fitzhardinge 	return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
338*cff7e81bSJeremy Fitzhardinge }
339*cff7e81bSJeremy Fitzhardinge 
340*cff7e81bSJeremy Fitzhardinge static void xen_properties_destroy(void)
341*cff7e81bSJeremy Fitzhardinge {
342*cff7e81bSJeremy Fitzhardinge 	sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
343*cff7e81bSJeremy Fitzhardinge }
344*cff7e81bSJeremy Fitzhardinge 
345*cff7e81bSJeremy Fitzhardinge #ifdef CONFIG_KEXEC
346*cff7e81bSJeremy Fitzhardinge 
347*cff7e81bSJeremy Fitzhardinge extern size_t vmcoreinfo_size_xen;
348*cff7e81bSJeremy Fitzhardinge extern unsigned long paddr_vmcoreinfo_xen;
349*cff7e81bSJeremy Fitzhardinge 
350*cff7e81bSJeremy Fitzhardinge static ssize_t vmcoreinfo_show(struct hyp_sysfs_attr *attr, char *page)
351*cff7e81bSJeremy Fitzhardinge {
352*cff7e81bSJeremy Fitzhardinge 	return sprintf(page, "%lx %zx\n",
353*cff7e81bSJeremy Fitzhardinge 		paddr_vmcoreinfo_xen, vmcoreinfo_size_xen);
354*cff7e81bSJeremy Fitzhardinge }
355*cff7e81bSJeremy Fitzhardinge 
356*cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(vmcoreinfo);
357*cff7e81bSJeremy Fitzhardinge 
358*cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_vmcoreinfo_init(void)
359*cff7e81bSJeremy Fitzhardinge {
360*cff7e81bSJeremy Fitzhardinge 	return sysfs_create_file(hypervisor_kobj,
361*cff7e81bSJeremy Fitzhardinge 				 &vmcoreinfo_attr.attr);
362*cff7e81bSJeremy Fitzhardinge }
363*cff7e81bSJeremy Fitzhardinge 
364*cff7e81bSJeremy Fitzhardinge static void xen_sysfs_vmcoreinfo_destroy(void)
365*cff7e81bSJeremy Fitzhardinge {
366*cff7e81bSJeremy Fitzhardinge 	sysfs_remove_file(hypervisor_kobj, &vmcoreinfo_attr.attr);
367*cff7e81bSJeremy Fitzhardinge }
368*cff7e81bSJeremy Fitzhardinge 
369*cff7e81bSJeremy Fitzhardinge #endif
370*cff7e81bSJeremy Fitzhardinge 
371*cff7e81bSJeremy Fitzhardinge static int __init hyper_sysfs_init(void)
372*cff7e81bSJeremy Fitzhardinge {
373*cff7e81bSJeremy Fitzhardinge 	int ret;
374*cff7e81bSJeremy Fitzhardinge 
375*cff7e81bSJeremy Fitzhardinge 	if (!xen_domain())
376*cff7e81bSJeremy Fitzhardinge 		return -ENODEV;
377*cff7e81bSJeremy Fitzhardinge 
378*cff7e81bSJeremy Fitzhardinge 	ret = xen_sysfs_type_init();
379*cff7e81bSJeremy Fitzhardinge 	if (ret)
380*cff7e81bSJeremy Fitzhardinge 		goto out;
381*cff7e81bSJeremy Fitzhardinge 	ret = xen_sysfs_version_init();
382*cff7e81bSJeremy Fitzhardinge 	if (ret)
383*cff7e81bSJeremy Fitzhardinge 		goto version_out;
384*cff7e81bSJeremy Fitzhardinge 	ret = xen_compilation_init();
385*cff7e81bSJeremy Fitzhardinge 	if (ret)
386*cff7e81bSJeremy Fitzhardinge 		goto comp_out;
387*cff7e81bSJeremy Fitzhardinge 	ret = xen_sysfs_uuid_init();
388*cff7e81bSJeremy Fitzhardinge 	if (ret)
389*cff7e81bSJeremy Fitzhardinge 		goto uuid_out;
390*cff7e81bSJeremy Fitzhardinge 	ret = xen_properties_init();
391*cff7e81bSJeremy Fitzhardinge 	if (ret)
392*cff7e81bSJeremy Fitzhardinge 		goto prop_out;
393*cff7e81bSJeremy Fitzhardinge #ifdef CONFIG_KEXEC
394*cff7e81bSJeremy Fitzhardinge 	if (vmcoreinfo_size_xen != 0) {
395*cff7e81bSJeremy Fitzhardinge 		ret = xen_sysfs_vmcoreinfo_init();
396*cff7e81bSJeremy Fitzhardinge 		if (ret)
397*cff7e81bSJeremy Fitzhardinge 			goto vmcoreinfo_out;
398*cff7e81bSJeremy Fitzhardinge 	}
399*cff7e81bSJeremy Fitzhardinge #endif
400*cff7e81bSJeremy Fitzhardinge 
401*cff7e81bSJeremy Fitzhardinge 	goto out;
402*cff7e81bSJeremy Fitzhardinge 
403*cff7e81bSJeremy Fitzhardinge #ifdef CONFIG_KEXEC
404*cff7e81bSJeremy Fitzhardinge vmcoreinfo_out:
405*cff7e81bSJeremy Fitzhardinge #endif
406*cff7e81bSJeremy Fitzhardinge 	xen_properties_destroy();
407*cff7e81bSJeremy Fitzhardinge prop_out:
408*cff7e81bSJeremy Fitzhardinge 	xen_sysfs_uuid_destroy();
409*cff7e81bSJeremy Fitzhardinge uuid_out:
410*cff7e81bSJeremy Fitzhardinge 	xen_compilation_destroy();
411*cff7e81bSJeremy Fitzhardinge comp_out:
412*cff7e81bSJeremy Fitzhardinge 	xen_sysfs_version_destroy();
413*cff7e81bSJeremy Fitzhardinge version_out:
414*cff7e81bSJeremy Fitzhardinge 	xen_sysfs_type_destroy();
415*cff7e81bSJeremy Fitzhardinge out:
416*cff7e81bSJeremy Fitzhardinge 	return ret;
417*cff7e81bSJeremy Fitzhardinge }
418*cff7e81bSJeremy Fitzhardinge 
419*cff7e81bSJeremy Fitzhardinge static void __exit hyper_sysfs_exit(void)
420*cff7e81bSJeremy Fitzhardinge {
421*cff7e81bSJeremy Fitzhardinge #ifdef CONFIG_KEXEC
422*cff7e81bSJeremy Fitzhardinge 	if (vmcoreinfo_size_xen != 0)
423*cff7e81bSJeremy Fitzhardinge 		xen_sysfs_vmcoreinfo_destroy();
424*cff7e81bSJeremy Fitzhardinge #endif
425*cff7e81bSJeremy Fitzhardinge 	xen_properties_destroy();
426*cff7e81bSJeremy Fitzhardinge 	xen_compilation_destroy();
427*cff7e81bSJeremy Fitzhardinge 	xen_sysfs_uuid_destroy();
428*cff7e81bSJeremy Fitzhardinge 	xen_sysfs_version_destroy();
429*cff7e81bSJeremy Fitzhardinge 	xen_sysfs_type_destroy();
430*cff7e81bSJeremy Fitzhardinge 
431*cff7e81bSJeremy Fitzhardinge }
432*cff7e81bSJeremy Fitzhardinge module_init(hyper_sysfs_init);
433*cff7e81bSJeremy Fitzhardinge module_exit(hyper_sysfs_exit);
434*cff7e81bSJeremy Fitzhardinge 
435*cff7e81bSJeremy Fitzhardinge static ssize_t hyp_sysfs_show(struct kobject *kobj,
436*cff7e81bSJeremy Fitzhardinge 			      struct attribute *attr,
437*cff7e81bSJeremy Fitzhardinge 			      char *buffer)
438*cff7e81bSJeremy Fitzhardinge {
439*cff7e81bSJeremy Fitzhardinge 	struct hyp_sysfs_attr *hyp_attr;
440*cff7e81bSJeremy Fitzhardinge 	hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
441*cff7e81bSJeremy Fitzhardinge 	if (hyp_attr->show)
442*cff7e81bSJeremy Fitzhardinge 		return hyp_attr->show(hyp_attr, buffer);
443*cff7e81bSJeremy Fitzhardinge 	return 0;
444*cff7e81bSJeremy Fitzhardinge }
445*cff7e81bSJeremy Fitzhardinge 
446*cff7e81bSJeremy Fitzhardinge static ssize_t hyp_sysfs_store(struct kobject *kobj,
447*cff7e81bSJeremy Fitzhardinge 			       struct attribute *attr,
448*cff7e81bSJeremy Fitzhardinge 			       const char *buffer,
449*cff7e81bSJeremy Fitzhardinge 			       size_t len)
450*cff7e81bSJeremy Fitzhardinge {
451*cff7e81bSJeremy Fitzhardinge 	struct hyp_sysfs_attr *hyp_attr;
452*cff7e81bSJeremy Fitzhardinge 	hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
453*cff7e81bSJeremy Fitzhardinge 	if (hyp_attr->store)
454*cff7e81bSJeremy Fitzhardinge 		return hyp_attr->store(hyp_attr, buffer, len);
455*cff7e81bSJeremy Fitzhardinge 	return 0;
456*cff7e81bSJeremy Fitzhardinge }
457*cff7e81bSJeremy Fitzhardinge 
458*cff7e81bSJeremy Fitzhardinge static struct sysfs_ops hyp_sysfs_ops = {
459*cff7e81bSJeremy Fitzhardinge 	.show = hyp_sysfs_show,
460*cff7e81bSJeremy Fitzhardinge 	.store = hyp_sysfs_store,
461*cff7e81bSJeremy Fitzhardinge };
462*cff7e81bSJeremy Fitzhardinge 
463*cff7e81bSJeremy Fitzhardinge static struct kobj_type hyp_sysfs_kobj_type = {
464*cff7e81bSJeremy Fitzhardinge 	.sysfs_ops = &hyp_sysfs_ops,
465*cff7e81bSJeremy Fitzhardinge };
466*cff7e81bSJeremy Fitzhardinge 
467*cff7e81bSJeremy Fitzhardinge static int __init hypervisor_subsys_init(void)
468*cff7e81bSJeremy Fitzhardinge {
469*cff7e81bSJeremy Fitzhardinge 	if (!xen_domain())
470*cff7e81bSJeremy Fitzhardinge 		return -ENODEV;
471*cff7e81bSJeremy Fitzhardinge 
472*cff7e81bSJeremy Fitzhardinge 	hypervisor_kobj->ktype = &hyp_sysfs_kobj_type;
473*cff7e81bSJeremy Fitzhardinge 	return 0;
474*cff7e81bSJeremy Fitzhardinge }
475*cff7e81bSJeremy Fitzhardinge device_initcall(hypervisor_subsys_init);
476