^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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Diag 0C implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright IBM Corp. 2014
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/diag.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/hypfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "hypfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define DBFS_D0C_HDR_VERSION 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Get hypfs_diag0c_entry from CPU vector and store diag0c data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static void diag0c_fn(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) diag_stat_inc(DIAG_STAT_X00C);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) diag_dma_ops.diag0c(((void **) data)[smp_processor_id()]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * Allocate buffer and store diag 0c data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static void *diag0c_store(unsigned int *count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct hypfs_diag0c_data *diag0c_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned int cpu_count, cpu, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void **cpu_vec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) get_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) cpu_count = num_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) cpu_vec = kmalloc_array(num_possible_cpus(), sizeof(*cpu_vec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (!cpu_vec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) goto fail_put_online_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* Note: Diag 0c needs 8 byte alignment and real storage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) diag0c_data = kzalloc(struct_size(diag0c_data, entry, cpu_count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (!diag0c_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) goto fail_kfree_cpu_vec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* Fill CPU vector for each online CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) for_each_online_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) diag0c_data->entry[i].cpu = cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) cpu_vec[cpu] = &diag0c_data->entry[i++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Collect data all CPUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) on_each_cpu(diag0c_fn, cpu_vec, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) *count = cpu_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) kfree(cpu_vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return diag0c_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) fail_kfree_cpu_vec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) kfree(cpu_vec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) fail_put_online_cpus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) put_online_cpus();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Hypfs DBFS callback: Free diag 0c data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void dbfs_diag0c_free(const void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * Hypfs DBFS callback: Create diag 0c data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int dbfs_diag0c_create(void **data, void **data_free_ptr, size_t *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct hypfs_diag0c_data *diag0c_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) diag0c_data = diag0c_store(&count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (IS_ERR(diag0c_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return PTR_ERR(diag0c_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) memset(&diag0c_data->hdr, 0, sizeof(diag0c_data->hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) get_tod_clock_ext(diag0c_data->hdr.tod_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) diag0c_data->hdr.len = count * sizeof(struct hypfs_diag0c_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) diag0c_data->hdr.version = DBFS_D0C_HDR_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) diag0c_data->hdr.count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *data = diag0c_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *data_free_ptr = diag0c_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *size = diag0c_data->hdr.len + sizeof(struct hypfs_diag0c_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Hypfs DBFS file structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct hypfs_dbfs_file dbfs_file_0c = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .name = "diag_0c",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .data_create = dbfs_diag0c_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .data_free = dbfs_diag0c_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * Initialize diag 0c interface for z/VM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int __init hypfs_diag0c_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!MACHINE_IS_VM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) hypfs_dbfs_create_file(&dbfs_file_0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * Shutdown diag 0c interface for z/VM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) void hypfs_diag0c_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!MACHINE_IS_VM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) hypfs_dbfs_remove_file(&dbfs_file_0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }