1ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian/* -*- mode: C; c-basic-offset: 3; -*- */ 2ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#include <setjmp.h> 402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#include <signal.h> 502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#include <stdio.h> 602b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#include <stdlib.h> 702b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#include <string.h> 8a066ccdcfd4e6f20fada0e772e279dc2035cb930florian#include <assert.h> 9ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian#include <ctype.h> // isspace 10ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian#include <fcntl.h> // open 11ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian#include <unistd.h> // lseek 12ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian#include <sys/stat.h> // S_IRUSR 1302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 1402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj// This file determines s390x features a processor supports. 1502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj// 1602b89e887521d3f4e0cb0d3408eb3f462142f932sewardj// We return: 17ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// - 0 if the machine provides the asked-for feature and the cpu 18ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// model, if specified, matches the machine 19ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// - 1 the machine does not provide the asked-for feature or the 20ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// cpu model, if specified, does not match the machine 219dd35e05acd69b52ed4d59295f70826edef77c92cborntra// - 1 for an unknown cpu model in /proc/cpu_info 2202b89e887521d3f4e0cb0d3408eb3f462142f932sewardj// - 2 if the asked-for feature isn't recognised (this will be the case for 2302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj// any feature if run on a non-s390x machine). 2402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj// - 3 if there was a usage error (it also prints an error message). 25ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// 26ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// USAGE: 27ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// 28ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// s390x_features <feature> [<machine-model>] 29ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// 30ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// The machine_model is optional and it can be something like: 31ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// 32ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// z9 -- Host needs to be a z9 (and nothing else) 33ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// z9: -- Host needs to be a z9 or any later model 34ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// :z9 -- Host needs to be a model up to and including z9 35ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// z900:z9 -- Host needs to be at least a z900 and at most a z9. 36ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian// Any model in between is OK, too. 3702b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 3802b89e887521d3f4e0cb0d3408eb3f462142f932sewardjjmp_buf env; 3902b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 4002b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#if defined(VGA_s390x) 4102b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 4202b89e887521d3f4e0cb0d3408eb3f462142f932sewardjvoid handle_sigill(int signum) 4302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj{ 4402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj longjmp(env, 1); 4502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj} 4602b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 4702b89e887521d3f4e0cb0d3408eb3f462142f932sewardjunsigned long long stfle(void) 4802b89e887521d3f4e0cb0d3408eb3f462142f932sewardj{ 4902b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 5002b89e887521d3f4e0cb0d3408eb3f462142f932sewardj unsigned long long ret; 5102b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 5202b89e887521d3f4e0cb0d3408eb3f462142f932sewardj signal(SIGILL, handle_sigill); 5302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj if (setjmp(env)) { 5402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj /* stfle not available: assume no facilities */ 5502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj return 0; 5602b89e887521d3f4e0cb0d3408eb3f462142f932sewardj } else { 5702b89e887521d3f4e0cb0d3408eb3f462142f932sewardj asm volatile("lghi 0, 0\n" 5802b89e887521d3f4e0cb0d3408eb3f462142f932sewardj ".insn s,0xb2b00000,%0\n" /* stfle */ 5902b89e887521d3f4e0cb0d3408eb3f462142f932sewardj : "=Q" (ret)::"0", "cc"); 6002b89e887521d3f4e0cb0d3408eb3f462142f932sewardj return ret; 6102b89e887521d3f4e0cb0d3408eb3f462142f932sewardj } 6202b89e887521d3f4e0cb0d3408eb3f462142f932sewardj} 6302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 64ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 65ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian/* Read /proc/cpuinfo. Look for lines like these 66ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 67ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian processor 0: version = FF, identification = 0117C9, machine = 2064 68ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 69ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian and return the machine model or NULL on error. 70ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian Adapted from function VG_(get_machine_model) in coregrind/m_machine.c */ 71ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 72ec82dd9de08eaf9d6d5c6b1ebaec53039e371903floriantypedef struct { 73ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian const char *cpuinfo_name; 74ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian const char *real_name; 75ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian} model_info; 76ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 77ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian/* Array needs to be sorted chronologically. Oldest to newest */ 78ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florianmodel_info models[] = { 79ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian { "2064", "z900" }, 80ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian { "2066", "z800" }, 81ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian { "2084", "z990" }, 82ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian { "2086", "z890" }, 8387a25cf59352617f8876b8bdc8d437d4aafe5ae3florian { "2094", "z9-EC" }, 8487a25cf59352617f8876b8bdc8d437d4aafe5ae3florian { "2096", "z9-BC" }, 8587a25cf59352617f8876b8bdc8d437d4aafe5ae3florian { "2097", "z10-EC" }, 8687a25cf59352617f8876b8bdc8d437d4aafe5ae3florian { "2098", "z10-BC" }, 87ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian { "2817", "z196" }, 889dd35e05acd69b52ed4d59295f70826edef77c92cborntra { "2818", "z114" }, 8987a25cf59352617f8876b8bdc8d437d4aafe5ae3florian { "2827", "zEC12" }, 903b411c169c685099c2fc26d816d4eac29fca6573florian { "2828", "zBC12" }, 91dd1d372ee14d89793942cea99296853253a664edflorian { "2964", "z13" }, 92a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes { "2965", "z13s" }, 93ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian}; 94ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 95ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 96ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian/* Locate a machine model by name. Name can be either the cpuinfo 97ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian name or the external name. */ 98ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florianstatic model_info *locate_model(const char *name) 99ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian{ 100ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian model_info *p; 101ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 102ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Try cpuinfo name first */ 103ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian for (p = models; p != models + sizeof models / sizeof models[0]; ++p) { 104ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (strcmp(p->cpuinfo_name, name) == 0) return p; // found it 105ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 106ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 107ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Now try external name */ 108ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian for (p = models; p != models + sizeof models / sizeof models[0]; ++p) { 109ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (strcmp(p->real_name, name) == 0) return p; // found it 110ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 111ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 112ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian return NULL; 113ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian} 114ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 115ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 116ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florianstatic model_info *get_host(void) 117ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian{ 118ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian int n, fh; 119ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian size_t num_bytes, file_buf_size; 120ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian char *p, *m, *model_name, *file_buf; 121ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian model_info *model; 122ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 123ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Slurp contents of /proc/cpuinfo into FILE_BUF */ 124ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian fh = open("/proc/cpuinfo", O_RDONLY, S_IRUSR); 125ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (fh < 0) return NULL; 126ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 127ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Determine the size of /proc/cpuinfo. 128ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian Work around broken-ness in /proc file system implementation. 129ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian fstat returns a zero size for /proc/cpuinfo although it is 130ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian claimed to be a regular file. */ 131ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian num_bytes = 0; 132ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian file_buf_size = 1000; 133ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian file_buf = malloc(file_buf_size + 1); 134ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 135ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian while (42) { 136ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian n = read(fh, file_buf, file_buf_size); 137ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (n < 0) break; 138ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 139ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian num_bytes += n; 140ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (n < file_buf_size) break; /* reached EOF */ 141ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 142ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 143ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (n < 0) num_bytes = 0; /* read error; ignore contents */ 144ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 145ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (num_bytes > file_buf_size) { 146ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian free(file_buf); 147ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian lseek(fh, 0, SEEK_SET); 148ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian file_buf = malloc(num_bytes + 1); 149ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian n = read(fh, file_buf, num_bytes); 150ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (n < 0) num_bytes = 0; 151ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 152ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 153ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian file_buf[num_bytes] = '\0'; 154ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian close(fh); 155ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 156ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Parse file */ 157ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian model = models + sizeof models / sizeof models[0]; 158ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian for (p = file_buf; *p; ++p) { 159ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Beginning of line */ 160ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (strncmp(p, "processor", sizeof "processor" - 1 ) != 0) continue; 161ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 162ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian m = strstr(p, "machine"); 163ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (m == NULL) continue; 164ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 165ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian p = m + sizeof "machine" - 1; 166ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian while (isspace(*p) || *p == '=') { 167ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (*p == '\n') goto next_line; 168ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian ++p; 169ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 170ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 171ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian model_name = p; 172ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian for (n = 0; n < sizeof models / sizeof models[0]; ++n) { 173ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian model_info *mm = models + n; 174ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian size_t len = strlen(mm->cpuinfo_name); 175ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (strncmp(mm->cpuinfo_name, model_name, len) == 0 && 176ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian isspace(model_name[len])) { 177ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* In case there are different CPUs in this cluster return the 178ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian one with the dewest capabilities ("oldest" model). */ 179ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (mm < model) model = mm; 180ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian p = model_name + len; 181ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian break; 182ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 183ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 184ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Skip until end-of-line */ 185ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian while (*p != '\n') 186ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian ++p; 187ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian next_line: ; 188ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 189ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 190ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian free(file_buf); 191ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 192ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (model == models + sizeof models / sizeof models[0]) return NULL; 193ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 194ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian return model; 195ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian} 196ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 1974bc35a8615523bd9f23d6104aacb9662ca72f316florian 1984bc35a8615523bd9f23d6104aacb9662ca72f316florian/* Convenience macro that maps the facility bit number as given in the 1994bc35a8615523bd9f23d6104aacb9662ca72f316florian Principles of Ops "facility indications" section to a bit mask */ 2004bc35a8615523bd9f23d6104aacb9662ca72f316florian#define FAC_BIT(x) (1ULL << (63 - (x))) 2014bc35a8615523bd9f23d6104aacb9662ca72f316florian 202ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florianstatic int go(char *feature, char *cpu) 20302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj{ 20402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj unsigned long long facilities; 20502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj unsigned long long match; 206ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian model_info *host, *from, *to, *p; 207ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian char *colon; 20802b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 20902b89e887521d3f4e0cb0d3408eb3f462142f932sewardj facilities = stfle(); 21002b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 211ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (strcmp(feature, "s390x-zarch") == 0 ) { 2124bc35a8615523bd9f23d6104aacb9662ca72f316florian match = (facilities & FAC_BIT(1)) && (facilities & FAC_BIT(2)); 213ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (strcmp(feature, "s390x-n3") == 0 ) { 2144bc35a8615523bd9f23d6104aacb9662ca72f316florian match = facilities & FAC_BIT(0); 215ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (strcmp(feature, "s390x-stfle") == 0 ) { 2164bc35a8615523bd9f23d6104aacb9662ca72f316florian match = facilities & FAC_BIT(7); 217ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (strcmp(feature, "s390x-ldisp") == 0 ) { 2184bc35a8615523bd9f23d6104aacb9662ca72f316florian match = (facilities & FAC_BIT(18)) && (facilities & FAC_BIT(19)); 219ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (strcmp(feature, "s390x-eimm") == 0 ) { 2204bc35a8615523bd9f23d6104aacb9662ca72f316florian match = facilities & FAC_BIT(21); 221ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (strcmp(feature, "s390x-stckf") == 0 ) { 2224bc35a8615523bd9f23d6104aacb9662ca72f316florian match = facilities & FAC_BIT(25); 223ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (strcmp(feature, "s390x-genins") == 0 ) { 2244bc35a8615523bd9f23d6104aacb9662ca72f316florian match = facilities & FAC_BIT(34); 225ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (strcmp(feature, "s390x-exrl") == 0 ) { 2264bc35a8615523bd9f23d6104aacb9662ca72f316florian match = facilities & FAC_BIT(35); 2274b345f3cf237441639360de238837127edd72c0bflorian } else if (strcmp(feature, "s390x-etf3") == 0 ) { 2284bc35a8615523bd9f23d6104aacb9662ca72f316florian match = facilities & FAC_BIT(30); 229370bc773b6b0c0c4977634f6614947a448a5aa48florian } else if (strcmp(feature, "s390x-fpext") == 0 ) { 230370bc773b6b0c0c4977634f6614947a448a5aa48florian match = facilities & FAC_BIT(37); 23146825980db94de9a1fb0bb3398eb10862fcf2aa7florian } else if (strcmp(feature, "s390x-dfp") == 0 ) { 23246825980db94de9a1fb0bb3398eb10862fcf2aa7florian match = facilities & FAC_BIT(42); 2331106692158e71bade4e00a2d21548e74b2ea334eflorian } else if (strcmp(feature, "s390x-pfpo") == 0 ) { 2341106692158e71bade4e00a2d21548e74b2ea334eflorian match = facilities & FAC_BIT(44); 235a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes } else if (strcmp(feature, "s390x-highw") == 0 ) { 236a0664b9ca67b594bd6f570a61d3301167a24750cElliott Hughes match = facilities & FAC_BIT(45); 23702b89e887521d3f4e0cb0d3408eb3f462142f932sewardj } else { 2384bc35a8615523bd9f23d6104aacb9662ca72f316florian return 2; // Unrecognised feature. 23902b89e887521d3f4e0cb0d3408eb3f462142f932sewardj } 24002b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 241ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (match == 0) return 1; // facility not provided 242ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 243ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Host provides facility. If no CPU was specified, we're done. */ 244ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (cpu == NULL) return 0; 245ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 246ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian host = get_host(); 2479dd35e05acd69b52ed4d59295f70826edef77c92cborntra if (host == NULL) return 1; // unknown model 248ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 249ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian // printf("host = %s (%s)\n", host->cpuinfo_name, host->real_name); 250ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 251ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Determine interval of models in which to search for HOST. */ 252ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian from = to = NULL; 253ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian colon = strchr(cpu, ':'); 254ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 255ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (colon == NULL) { 256ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian // match exact 257ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian from = to = locate_model(cpu); 258ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (colon == cpu) { 259ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian // :NAME match machines up to and including CPU 260ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian from = models; 261ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian to = locate_model(cpu + 1); 262ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else if (colon[1] == '\0') { 263ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian // NAME: match machines beginning with CPU or later 264ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian *colon = '\0'; 265ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian from = locate_model(cpu); 266ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian to = models + sizeof models / sizeof models[0] - 1; 267ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian *colon = ':'; 268ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } else { 269ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian // NAME:NAME match machines in interval 270ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian *colon = '\0'; 271ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian from = locate_model(cpu); 272ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian to = locate_model(colon + 1); 273ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian *colon = ':'; 274ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 275ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 276ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (from == NULL || to == NULL || from > to) { 277ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian fprintf(stderr, "invalid cpu specification '%s'\n", cpu); 278ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian return 3; 279ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 280ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 281ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian#if 0 282ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian printf("from %s (%s) to %s (%s)\n", from->cpuinfo_name, from->real_name, 283ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian to->cpuinfo_name, to->real_name); 284ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian#endif 285ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 286ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian /* Search for HOST. */ 287ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian for (p = from; p <= to; ++p) { 288ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (p == host) return 0; 289ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian } 290ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 291ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian return 1; // host does not match CPU specification 29202b89e887521d3f4e0cb0d3408eb3f462142f932sewardj} 29302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 29402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#else 29502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 296ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florianstatic int go(char *feature, char *cpu) 29702b89e887521d3f4e0cb0d3408eb3f462142f932sewardj{ 29802b89e887521d3f4e0cb0d3408eb3f462142f932sewardj return 2; // Feature not recognised (non-s390x machine!) 29902b89e887521d3f4e0cb0d3408eb3f462142f932sewardj} 30002b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 30102b89e887521d3f4e0cb0d3408eb3f462142f932sewardj#endif 30202b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 30302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj 30402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj//--------------------------------------------------------------------------- 30502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj// main 30602b89e887521d3f4e0cb0d3408eb3f462142f932sewardj//--------------------------------------------------------------------------- 30702b89e887521d3f4e0cb0d3408eb3f462142f932sewardjint main(int argc, char **argv) 30802b89e887521d3f4e0cb0d3408eb3f462142f932sewardj{ 309a066ccdcfd4e6f20fada0e772e279dc2035cb930florian int rc, inverted = 0; 310ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 311ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian if (argc < 2 || argc > 3) { 312ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian fprintf( stderr, "usage: s390x_features <feature> [<machine-model>]\n" ); 31302b89e887521d3f4e0cb0d3408eb3f462142f932sewardj exit(3); // Usage error. 31402b89e887521d3f4e0cb0d3408eb3f462142f932sewardj } 315ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 316a066ccdcfd4e6f20fada0e772e279dc2035cb930florian if (argv[1][0] == '!') { 317a066ccdcfd4e6f20fada0e772e279dc2035cb930florian assert(argv[2] == NULL); // not allowed 318a066ccdcfd4e6f20fada0e772e279dc2035cb930florian inverted = 1; 319a066ccdcfd4e6f20fada0e772e279dc2035cb930florian ++argv[1]; 320a066ccdcfd4e6f20fada0e772e279dc2035cb930florian } 321a066ccdcfd4e6f20fada0e772e279dc2035cb930florian 322ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian rc = go(argv[1], argv[2]); 323a066ccdcfd4e6f20fada0e772e279dc2035cb930florian 324a066ccdcfd4e6f20fada0e772e279dc2035cb930florian if (inverted) { 325a066ccdcfd4e6f20fada0e772e279dc2035cb930florian switch (rc) { 326a066ccdcfd4e6f20fada0e772e279dc2035cb930florian case 0: rc = 1; break; 327a066ccdcfd4e6f20fada0e772e279dc2035cb930florian case 1: rc = 0; break; 328a066ccdcfd4e6f20fada0e772e279dc2035cb930florian case 2: rc = 2; break; 329a066ccdcfd4e6f20fada0e772e279dc2035cb930florian } 330a066ccdcfd4e6f20fada0e772e279dc2035cb930florian } 331ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 332ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian // printf("rc = %d\n", rc); 333ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian 334ec82dd9de08eaf9d6d5c6b1ebaec53039e371903florian return rc; 33502b89e887521d3f4e0cb0d3408eb3f462142f932sewardj} 336