📄 hypfs_diag.c
字号:
/* * arch/s390/hypfs/hypfs_diag.c * Hypervisor filesystem for Linux on s390. Diag 204 and 224 * implementation. * * Copyright (C) IBM Corp. 2006 * Author(s): Michael Holzheu <holzheu@de.ibm.com> */#include <linux/types.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/vmalloc.h>#include <asm/ebcdic.h>#include "hypfs.h"#define LPAR_NAME_LEN 8 /* lpar name len in diag 204 data */#define CPU_NAME_LEN 16 /* type name len of cpus in diag224 name table */#define TMP_SIZE 64 /* size of temporary buffers *//* diag 204 subcodes */enum diag204_sc { SUBC_STIB4 = 4, SUBC_RSI = 5, SUBC_STIB6 = 6, SUBC_STIB7 = 7};/* The two available diag 204 data formats */enum diag204_format { INFO_SIMPLE = 0, INFO_EXT = 0x00010000};/* bit is set in flags, when physical cpu info is included in diag 204 data */#define LPAR_PHYS_FLG 0x80static char *diag224_cpu_names; /* diag 224 name table */static enum diag204_sc diag204_store_sc; /* used subcode for store */static enum diag204_format diag204_info_type; /* used diag 204 data format */static void *diag204_buf; /* 4K aligned buffer for diag204 data */static void *diag204_buf_vmalloc; /* vmalloc pointer for diag204 data */static int diag204_buf_pages; /* number of pages for diag204 data *//* * DIAG 204 data structures and member access functions. * * Since we have two different diag 204 data formats for old and new s390 * machines, we do not access the structs directly, but use getter functions for * each struct member instead. This should make the code more readable. *//* Time information block */struct info_blk_hdr { __u8 npar; __u8 flags; __u16 tslice; __u16 phys_cpus; __u16 this_part; __u64 curtod;} __attribute__ ((packed));struct x_info_blk_hdr { __u8 npar; __u8 flags; __u16 tslice; __u16 phys_cpus; __u16 this_part; __u64 curtod1; __u64 curtod2; char reserved[40];} __attribute__ ((packed));static inline int info_blk_hdr__size(enum diag204_format type){ if (type == INFO_SIMPLE) return sizeof(struct info_blk_hdr); else /* INFO_EXT */ return sizeof(struct x_info_blk_hdr);}static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct info_blk_hdr *)hdr)->npar; else /* INFO_EXT */ return ((struct x_info_blk_hdr *)hdr)->npar;}static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct info_blk_hdr *)hdr)->flags; else /* INFO_EXT */ return ((struct x_info_blk_hdr *)hdr)->flags;}static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct info_blk_hdr *)hdr)->phys_cpus; else /* INFO_EXT */ return ((struct x_info_blk_hdr *)hdr)->phys_cpus;}/* Partition header */struct part_hdr { __u8 pn; __u8 cpus; char reserved[6]; char part_name[LPAR_NAME_LEN];} __attribute__ ((packed));struct x_part_hdr { __u8 pn; __u8 cpus; __u8 rcpus; __u8 pflag; __u32 mlu; char part_name[LPAR_NAME_LEN]; char lpc_name[8]; char os_name[8]; __u64 online_cs; __u64 online_es; __u8 upid; char reserved1[3]; __u32 group_mlu; char group_name[8]; char reserved2[32];} __attribute__ ((packed));static inline int part_hdr__size(enum diag204_format type){ if (type == INFO_SIMPLE) return sizeof(struct part_hdr); else /* INFO_EXT */ return sizeof(struct x_part_hdr);}static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct part_hdr *)hdr)->cpus; else /* INFO_EXT */ return ((struct x_part_hdr *)hdr)->rcpus;}static inline void part_hdr__part_name(enum diag204_format type, void *hdr, char *name){ if (type == INFO_SIMPLE) memcpy(name, ((struct part_hdr *)hdr)->part_name, LPAR_NAME_LEN); else /* INFO_EXT */ memcpy(name, ((struct x_part_hdr *)hdr)->part_name, LPAR_NAME_LEN); EBCASC(name, LPAR_NAME_LEN); name[LPAR_NAME_LEN] = 0; strstrip(name);}struct cpu_info { __u16 cpu_addr; char reserved1[2]; __u8 ctidx; __u8 cflag; __u16 weight; __u64 acc_time; __u64 lp_time;} __attribute__ ((packed));struct x_cpu_info { __u16 cpu_addr; char reserved1[2]; __u8 ctidx; __u8 cflag; __u16 weight; __u64 acc_time; __u64 lp_time; __u16 min_weight; __u16 cur_weight; __u16 max_weight; char reseved2[2]; __u64 online_time; __u64 wait_time; __u32 pma_weight; __u32 polar_weight; char reserved3[40];} __attribute__ ((packed));/* CPU info block */static inline int cpu_info__size(enum diag204_format type){ if (type == INFO_SIMPLE) return sizeof(struct cpu_info); else /* INFO_EXT */ return sizeof(struct x_cpu_info);}static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct cpu_info *)hdr)->ctidx; else /* INFO_EXT */ return ((struct x_cpu_info *)hdr)->ctidx;}static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct cpu_info *)hdr)->cpu_addr; else /* INFO_EXT */ return ((struct x_cpu_info *)hdr)->cpu_addr;}static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct cpu_info *)hdr)->acc_time; else /* INFO_EXT */ return ((struct x_cpu_info *)hdr)->acc_time;}static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct cpu_info *)hdr)->lp_time; else /* INFO_EXT */ return ((struct x_cpu_info *)hdr)->lp_time;}static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return 0; /* online_time not available in simple info */ else /* INFO_EXT */ return ((struct x_cpu_info *)hdr)->online_time;}/* Physical header */struct phys_hdr { char reserved1[1]; __u8 cpus; char reserved2[6]; char mgm_name[8];} __attribute__ ((packed));struct x_phys_hdr { char reserved1[1]; __u8 cpus; char reserved2[6]; char mgm_name[8]; char reserved3[80];} __attribute__ ((packed));static inline int phys_hdr__size(enum diag204_format type){ if (type == INFO_SIMPLE) return sizeof(struct phys_hdr); else /* INFO_EXT */ return sizeof(struct x_phys_hdr);}static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct phys_hdr *)hdr)->cpus; else /* INFO_EXT */ return ((struct x_phys_hdr *)hdr)->cpus;}/* Physical CPU info block */struct phys_cpu { __u16 cpu_addr; char reserved1[2]; __u8 ctidx; char reserved2[3]; __u64 mgm_time; char reserved3[8];} __attribute__ ((packed));struct x_phys_cpu { __u16 cpu_addr; char reserved1[2]; __u8 ctidx; char reserved2[3]; __u64 mgm_time; char reserved3[80];} __attribute__ ((packed));static inline int phys_cpu__size(enum diag204_format type){ if (type == INFO_SIMPLE) return sizeof(struct phys_cpu); else /* INFO_EXT */ return sizeof(struct x_phys_cpu);}static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct phys_cpu *)hdr)->cpu_addr; else /* INFO_EXT */ return ((struct x_phys_cpu *)hdr)->cpu_addr;}static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct phys_cpu *)hdr)->mgm_time; else /* INFO_EXT */ return ((struct x_phys_cpu *)hdr)->mgm_time;}static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr){ if (type == INFO_SIMPLE) return ((struct phys_cpu *)hdr)->ctidx; else /* INFO_EXT */ return ((struct x_phys_cpu *)hdr)->ctidx;}/* Diagnose 204 functions */static int diag204(unsigned long subcode, unsigned long size, void *addr){ register unsigned long _subcode asm("0") = subcode; register unsigned long _size asm("1") = size; asm volatile( " diag %2,%0,0x204\n" "0:\n" EX_TABLE(0b,0b) : "+d" (_subcode), "+d" (_size) : "d" (addr) : "memory"); if (_subcode) return -1; return _size;}/* * For the old diag subcode 4 with simple data format we have to use real * memory. If we use subcode 6 or 7 with extended data format, we can (and * should) use vmalloc, since we need a lot of memory in that case. Currently * up to 93 pages! */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -