1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* -*- mode: C; c-basic-offset: 3; -*- */ 2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <setjmp.h> 4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <signal.h> 5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdio.h> 6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdlib.h> 7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <string.h> 8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <assert.h> 9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <ctype.h> // isspace 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <fcntl.h> // open 11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <unistd.h> // lseek 12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <sys/stat.h> // S_IRUSR 13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// This file determines s390x features a processor supports. 15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// 16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// We return: 17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// - 0 if the machine provides the asked-for feature and the cpu 18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// model, if specified, matches the machine 19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// - 1 the machine does not provide the asked-for feature or the 20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// cpu model, if specified, does not match the machine 21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// - 1 for an unknown cpu model in /proc/cpu_info 22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// - 2 if the asked-for feature isn't recognised (this will be the case for 23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// any feature if run on a non-s390x machine). 24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// - 3 if there was a usage error (it also prints an error message). 25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// 26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// USAGE: 27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// 28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// s390x_features <feature> [<machine-model>] 29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// 30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// The machine_model is optional and it can be something like: 31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// 32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// z9 -- Host needs to be a z9 (and nothing else) 33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// z9: -- Host needs to be a z9 or any later model 34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// :z9 -- Host needs to be a model up to and including z9 35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// z900:z9 -- Host needs to be at least a z900 and at most a z9. 36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Any model in between is OK, too. 37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovjmp_buf env; 39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGA_s390x) 41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid handle_sigill(int signum) 43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov longjmp(env, 1); 45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovunsigned long long stfle(void) 48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unsigned long long ret; 51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov signal(SIGILL, handle_sigill); 53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (setjmp(env)) { 54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* stfle not available: assume no facilities */ 55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return 0; 56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov asm volatile("lghi 0, 0\n" 58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ".insn s,0xb2b00000,%0\n" /* stfle */ 59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov : "=Q" (ret)::"0", "cc"); 60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return ret; 61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Read /proc/cpuinfo. Look for lines like these 66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov processor 0: version = FF, identification = 0117C9, machine = 2064 68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov and return the machine model or NULL on error. 70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Adapted from function VG_(get_machine_model) in coregrind/m_machine.c */ 71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef struct { 73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const char *cpuinfo_name; 74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const char *real_name; 75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} model_info; 76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Array needs to be sorted chronologically. Oldest to newest */ 78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovmodel_info models[] = { 79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { "2064", "z900" }, 80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { "2066", "z800" }, 81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { "2084", "z990" }, 82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { "2086", "z890" }, 83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { "2094", "z9-EC" }, 84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { "2096", "z9-BC" }, 85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { "2097", "z10-EC" }, 86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { "2098", "z10-BC" }, 87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov { "2817", "z196" }, 88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { "2818", "z114" }, 89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { "2827", "zEC12" }, 90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov { "2828", "zBC12" }, 91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}; 92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Locate a machine model by name. Name can be either the cpuinfo 95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov name or the external name. */ 96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic model_info *locate_model(const char *name) 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov model_info *p; 99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Try cpuinfo name first */ 101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (p = models; p != models + sizeof models / sizeof models[0]; ++p) { 102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (strcmp(p->cpuinfo_name, name) == 0) return p; // found it 103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Now try external name */ 106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (p = models; p != models + sizeof models / sizeof models[0]; ++p) { 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (strcmp(p->real_name, name) == 0) return p; // found it 108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return NULL; 111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic model_info *get_host(void) 115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int n, fh; 117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov size_t num_bytes, file_buf_size; 118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char *p, *m, *model_name, *file_buf; 119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov model_info *model; 120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Slurp contents of /proc/cpuinfo into FILE_BUF */ 122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fh = open("/proc/cpuinfo", O_RDONLY, S_IRUSR); 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (fh < 0) return NULL; 124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Determine the size of /proc/cpuinfo. 126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Work around broken-ness in /proc file system implementation. 127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fstat returns a zero size for /proc/cpuinfo although it is 128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov claimed to be a regular file. */ 129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov num_bytes = 0; 130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov file_buf_size = 1000; 131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov file_buf = malloc(file_buf_size + 1); 132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (42) { 134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov n = read(fh, file_buf, file_buf_size); 135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (n < 0) break; 136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov num_bytes += n; 138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (n < file_buf_size) break; /* reached EOF */ 139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (n < 0) num_bytes = 0; /* read error; ignore contents */ 142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (num_bytes > file_buf_size) { 144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free(file_buf); 145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov lseek(fh, 0, SEEK_SET); 146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov file_buf = malloc(num_bytes + 1); 147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov n = read(fh, file_buf, num_bytes); 148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (n < 0) num_bytes = 0; 149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov file_buf[num_bytes] = '\0'; 152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov close(fh); 153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Parse file */ 155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov model = models + sizeof models / sizeof models[0]; 156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (p = file_buf; *p; ++p) { 157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Beginning of line */ 158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (strncmp(p, "processor", sizeof "processor" - 1 ) != 0) continue; 159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov m = strstr(p, "machine"); 161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (m == NULL) continue; 162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p = m + sizeof "machine" - 1; 164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (isspace(*p) || *p == '=') { 165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (*p == '\n') goto next_line; 166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ++p; 167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov model_name = p; 170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (n = 0; n < sizeof models / sizeof models[0]; ++n) { 171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov model_info *mm = models + n; 172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov size_t len = strlen(mm->cpuinfo_name); 173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (strncmp(mm->cpuinfo_name, model_name, len) == 0 && 174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov isspace(model_name[len])) { 175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* In case there are different CPUs in this cluster return the 176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov one with the dewest capabilities ("oldest" model). */ 177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (mm < model) model = mm; 178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p = model_name + len; 179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Skip until end-of-line */ 183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (*p != '\n') 184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ++p; 185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov next_line: ; 186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free(file_buf); 189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (model == models + sizeof models / sizeof models[0]) return NULL; 191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return model; 193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Convenience macro that maps the facility bit number as given in the 197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Principles of Ops "facility indications" section to a bit mask */ 198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define FAC_BIT(x) (1ULL << (63 - (x))) 199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int go(char *feature, char *cpu) 201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unsigned long long facilities; 203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov unsigned long long match; 204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov model_info *host, *from, *to, *p; 205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char *colon; 206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov facilities = stfle(); 208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (strcmp(feature, "s390x-zarch") == 0 ) { 210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = (facilities & FAC_BIT(1)) && (facilities & FAC_BIT(2)); 211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (strcmp(feature, "s390x-n3") == 0 ) { 212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(0); 213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (strcmp(feature, "s390x-stfle") == 0 ) { 214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(7); 215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (strcmp(feature, "s390x-ldisp") == 0 ) { 216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = (facilities & FAC_BIT(18)) && (facilities & FAC_BIT(19)); 217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (strcmp(feature, "s390x-eimm") == 0 ) { 218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(21); 219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (strcmp(feature, "s390x-stckf") == 0 ) { 220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(25); 221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (strcmp(feature, "s390x-genins") == 0 ) { 222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(34); 223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (strcmp(feature, "s390x-exrl") == 0 ) { 224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(35); 225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else if (strcmp(feature, "s390x-etf3") == 0 ) { 226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(30); 227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else if (strcmp(feature, "s390x-fpext") == 0 ) { 228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(37); 229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else if (strcmp(feature, "s390x-dfp") == 0 ) { 230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(42); 231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else if (strcmp(feature, "s390x-pfpo") == 0 ) { 232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov match = facilities & FAC_BIT(44); 233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return 2; // Unrecognised feature. 235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (match == 0) return 1; // facility not provided 238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Host provides facility. If no CPU was specified, we're done. */ 240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (cpu == NULL) return 0; 241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov host = get_host(); 243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (host == NULL) return 1; // unknown model 244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // printf("host = %s (%s)\n", host->cpuinfo_name, host->real_name); 246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Determine interval of models in which to search for HOST. */ 248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov from = to = NULL; 249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov colon = strchr(cpu, ':'); 250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (colon == NULL) { 252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // match exact 253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov from = to = locate_model(cpu); 254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (colon == cpu) { 255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // :NAME match machines up to and including CPU 256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov from = models; 257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to = locate_model(cpu + 1); 258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else if (colon[1] == '\0') { 259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // NAME: match machines beginning with CPU or later 260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *colon = '\0'; 261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov from = locate_model(cpu); 262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to = models + sizeof models / sizeof models[0] - 1; 263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *colon = ':'; 264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // NAME:NAME match machines in interval 266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *colon = '\0'; 267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov from = locate_model(cpu); 268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to = locate_model(colon + 1); 269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *colon = ':'; 270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (from == NULL || to == NULL || from > to) { 273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, "invalid cpu specification '%s'\n", cpu); 274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return 3; 275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if 0 278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov printf("from %s (%s) to %s (%s)\n", from->cpuinfo_name, from->real_name, 279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to->cpuinfo_name, to->real_name); 280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Search for HOST. */ 283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (p = from; p <= to; ++p) { 284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (p == host) return 0; 285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return 1; // host does not match CPU specification 288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#else 291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic int go(char *feature, char *cpu) 293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return 2; // Feature not recognised (non-s390x machine!) 295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//--------------------------------------------------------------------------- 301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// main 302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//--------------------------------------------------------------------------- 303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint main(int argc, char **argv) 304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov int rc, inverted = 0; 306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (argc < 2 || argc > 3) { 308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf( stderr, "usage: s390x_features <feature> [<machine-model>]\n" ); 309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov exit(3); // Usage error. 310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (argv[1][0] == '!') { 313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(argv[2] == NULL); // not allowed 314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inverted = 1; 315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ++argv[1]; 316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov rc = go(argv[1], argv[2]); 319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (inverted) { 321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (rc) { 322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 0: rc = 1; break; 323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 1: rc = 0; break; 324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case 2: rc = 2; break; 325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // printf("rc = %d\n", rc); 329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return rc; 331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 332