SYSCALL_DEFINE1(s390_runtime_instr, int, command) { struct runtime_instr_cb *cb; if (!test_facility(64)) return -EOPNOTSUPP; if (command == S390_RUNTIME_INSTR_STOP) { preempt_disable(); exit_thread_runtime_instr(); preempt_enable(); return 0; } if (command != S390_RUNTIME_INSTR_START) return -EINVAL; if (!current->thread.ri_cb) { cb = kzalloc(sizeof(*cb), GFP_KERNEL); if (!cb) return -ENOMEM; } else { cb = current->thread.ri_cb; memset(cb, 0, sizeof(*cb)); } init_runtime_instr_cb(cb); /* now load the control block to make it available */ preempt_disable(); current->thread.ri_cb = cb; load_runtime_instr_cb(cb); preempt_enable(); return 0; }
/* * Get time offsets with PTFF */ void __init ptff_init(void) { struct ptff_qto qto; struct ptff_qui qui; if (!test_facility(28)) return; ptff(&ptff_function_mask, sizeof(ptff_function_mask), PTFF_QAF); /* get LPAR offset */ if (ptff_query(PTFF_QTO) && ptff(&qto, sizeof(qto), PTFF_QTO) == 0) lpar_offset = qto.tod_epoch_difference; /* get initial leap seconds */ if (ptff_query(PTFF_QUI) && ptff(&qui, sizeof(qui), PTFF_QUI) == 0) initial_leap_seconds = (unsigned long) ((long) qui.old_leap * 4096000000L); }
static int vfio_ap_matrix_dev_create(void) { int ret; struct device *root_device; root_device = root_device_register(VFIO_AP_ROOT_NAME); if (IS_ERR(root_device)) return PTR_ERR(root_device); matrix_dev = kzalloc(sizeof(*matrix_dev), GFP_KERNEL); if (!matrix_dev) { ret = -ENOMEM; goto matrix_alloc_err; } /* Fill in config info via PQAP(QCI), if available */ if (test_facility(12)) { ret = ap_qci(&matrix_dev->info); if (ret) goto matrix_alloc_err; } mutex_init(&matrix_dev->lock); INIT_LIST_HEAD(&matrix_dev->mdev_list); matrix_dev->device.type = &vfio_ap_dev_type; dev_set_name(&matrix_dev->device, "%s", VFIO_AP_DEV_NAME); matrix_dev->device.parent = root_device; matrix_dev->device.release = vfio_ap_matrix_dev_release; matrix_dev->device.driver = &vfio_ap_drv.driver; ret = device_register(&matrix_dev->device); if (ret) goto matrix_reg_err; return 0; matrix_reg_err: put_device(&matrix_dev->device); matrix_alloc_err: root_device_unregister(root_device); return ret; }
/* Get the CPU speed, try sampling facility first and CPU attributes second. */ static void cf_diag_get_cpu_speed(void) { if (cpum_sf_avail()) { /* Sampling facility first */ struct hws_qsi_info_block si; memset(&si, 0, sizeof(si)); if (!qsi(&si)) { cf_diag_cpu_speed = si.cpu_speed; return; } } if (test_facility(34)) { /* CPU speed extract static part */ unsigned long mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0); if (mhz != -1UL) cf_diag_cpu_speed = mhz & 0xffffffff; } }
static int __init nobp_setup_early(char *str) { bool enabled; int rc; rc = kstrtobool(str, &enabled); if (rc) return rc; if (enabled && test_facility(82)) { /* * The user explicitely requested nobp=1, enable it and * disable the expoline support. */ __set_facility(82, S390_lowcore.alt_stfle_fac_list); if (IS_ENABLED(CONFIG_EXPOLINE)) nospec_disable = 1; } else { __clear_facility(82, S390_lowcore.alt_stfle_fac_list); } return 0; }
/* * Setup hardware capabilities. */ static void __init setup_hwcaps(void) { static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; struct cpuid cpu_id; int i; /* * The store facility list bits numbers as found in the principles * of operation are numbered with bit 1UL<<31 as number 0 to * bit 1UL<<0 as number 31. * Bit 0: instructions named N3, "backported" to esa-mode * Bit 2: z/Architecture mode is active * Bit 7: the store-facility-list-extended facility is installed * Bit 17: the message-security assist is installed * Bit 19: the long-displacement facility is installed * Bit 21: the extended-immediate facility is installed * Bit 22: extended-translation facility 3 is installed * Bit 30: extended-translation facility 3 enhancement facility * These get translated to: * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1, * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3, * HWCAP_S390_LDISP bit 4, HWCAP_S390_EIMM bit 5 and * HWCAP_S390_ETF3EH bit 8 (22 && 30). */ for (i = 0; i < 6; i++) if (test_facility(stfl_bits[i])) elf_hwcap |= 1UL << i; if (test_facility(22) && test_facility(30)) elf_hwcap |= HWCAP_S390_ETF3EH; /* * Check for additional facilities with store-facility-list-extended. * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0 * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information * as stored by stfl, bits 32-xxx contain additional facilities. * How many facility words are stored depends on the number of * doublewords passed to the instruction. The additional facilites * are: * Bit 42: decimal floating point facility is installed * Bit 44: perform floating point operation facility is installed * translated to: * HWCAP_S390_DFP bit 6 (42 && 44). */ if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) elf_hwcap |= HWCAP_S390_DFP; /* * Huge page support HWCAP_S390_HPAGE is bit 7. */ if (MACHINE_HAS_HPAGE) elf_hwcap |= HWCAP_S390_HPAGE; /* * 64-bit register support for 31-bit processes * HWCAP_S390_HIGH_GPRS is bit 9. */ elf_hwcap |= HWCAP_S390_HIGH_GPRS; get_cpu_id(&cpu_id); switch (cpu_id.machine) { case 0x9672: #if !defined(CONFIG_64BIT) default: /* Use "g5" as default for 31 bit kernels. */ #endif strcpy(elf_platform, "g5"); break; case 0x2064: case 0x2066: #if defined(CONFIG_64BIT) default: /* Use "z900" as default for 64 bit kernels. */ #endif strcpy(elf_platform, "z900"); break; case 0x2084: case 0x2086: strcpy(elf_platform, "z990"); break; case 0x2094: case 0x2096: strcpy(elf_platform, "z9-109"); break; case 0x2097: case 0x2098: strcpy(elf_platform, "z10"); break; case 0x2817: strcpy(elf_platform, "z196"); break; } }
void fault_init(void) { if (test_facility(2) && test_facility(75)) store_indication = 0xc00; }
static int __init fault_init(void) { if (test_facility(75)) store_indication = 0xc00; return 0; }
static int handle_pfmf(struct kvm_vcpu *vcpu) { int reg1, reg2; unsigned long start, end; vcpu->stat.instruction_pfmf++; kvm_s390_get_regs_rre(vcpu, ®1, ®2); if (!MACHINE_HAS_PFMF) return kvm_s390_inject_program_int(vcpu, PGM_OPERATION); if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); if (vcpu->run->s.regs.gprs[reg1] & PFMF_RESERVED) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); /* Only provide non-quiescing support if the host supports it */ if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && !test_facility(14)) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); /* No support for conditional-SSKE */ if (vcpu->run->s.regs.gprs[reg1] & (PFMF_MR | PFMF_MC)) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); start = vcpu->run->s.regs.gprs[reg2] & PAGE_MASK; switch (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) { case 0x00000000: end = (start + (1UL << 12)) & ~((1UL << 12) - 1); break; case 0x00001000: end = (start + (1UL << 20)) & ~((1UL << 20) - 1); break; /* We dont support EDAT2 case 0x00002000: end = (start + (1UL << 31)) & ~((1UL << 31) - 1); break;*/ default: return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); } while (start < end) { unsigned long useraddr; useraddr = gmap_translate(start, vcpu->arch.gmap); if (IS_ERR((void *)useraddr)) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); if (vcpu->run->s.regs.gprs[reg1] & PFMF_CF) { if (clear_user((void __user *)useraddr, PAGE_SIZE)) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); } if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) { if (set_guest_storage_key(current->mm, useraddr, vcpu->run->s.regs.gprs[reg1] & PFMF_KEY, vcpu->run->s.regs.gprs[reg1] & PFMF_NQ)) return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); } start += PAGE_SIZE; } if (vcpu->run->s.regs.gprs[reg1] & PFMF_FSC) vcpu->run->s.regs.gprs[reg2] = end; return 0; }
void __init cpu_detect_mhz_feature(void) { if (test_facility(34) && __ecag(ECAG_CPU_ATTRIBUTE, 0) != -1UL) machine_has_cpu_mhz = 1; }