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