aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-10 16:16:35 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-10 16:16:35 -0500
commit15303ba5d1cd9b28d03a980456c0978c0ea3b208 (patch)
treeb9200d5b7474661cf36468038529a5269ee83238 /drivers
parent9a61df9e5f7471fe5be3e02bd0bed726b2761a54 (diff)
parent1ab03c072feb579c9fd116de25be2b211e6bff6a (diff)
Merge tag 'kvm-4.16-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM updates from Radim Krčmář: "ARM: - icache invalidation optimizations, improving VM startup time - support for forwarded level-triggered interrupts, improving performance for timers and passthrough platform devices - a small fix for power-management notifiers, and some cosmetic changes PPC: - add MMIO emulation for vector loads and stores - allow HPT guests to run on a radix host on POWER9 v2.2 CPUs without requiring the complex thread synchronization of older CPU versions - improve the handling of escalation interrupts with the XIVE interrupt controller - support decrement register migration - various cleanups and bugfixes. s390: - Cornelia Huck passed maintainership to Janosch Frank - exitless interrupts for emulated devices - cleanup of cpuflag handling - kvm_stat counter improvements - VSIE improvements - mm cleanup x86: - hypervisor part of SEV - UMIP, RDPID, and MSR_SMI_COUNT emulation - paravirtualized TLB shootdown using the new KVM_VCPU_PREEMPTED bit - allow guests to see TOPOEXT, GFNI, VAES, VPCLMULQDQ, and more AVX512 features - show vcpu id in its anonymous inode name - many fixes and cleanups - per-VCPU MSR bitmaps (already merged through x86/pti branch) - stable KVM clock when nesting on Hyper-V (merged through x86/hyperv)" * tag 'kvm-4.16-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (197 commits) KVM: PPC: Book3S: Add MMIO emulation for VMX instructions KVM: PPC: Book3S HV: Branch inside feature section KVM: PPC: Book3S HV: Make HPT resizing work on POWER9 KVM: PPC: Book3S HV: Fix handling of secondary HPTEG in HPT resizing code KVM: PPC: Book3S PR: Fix broken select due to misspelling KVM: x86: don't forget vcpu_put() in kvm_arch_vcpu_ioctl_set_sregs() KVM: PPC: Book3S PR: Fix svcpu copying with preemption enabled KVM: PPC: Book3S HV: Drop locks before reading guest memory kvm: x86: remove efer_reload entry in kvm_vcpu_stat KVM: x86: AMD Processor Topology Information x86/kvm/vmx: do not use vm-exit instruction length for fast MMIO when running nested kvm: embed vcpu id to dentry of vcpu anon inode kvm: Map PFN-type memory regions as writable (if possible) x86/kvm: Make it compile on 32bit and with HYPYERVISOR_GUEST=n KVM: arm/arm64: Fixup userspace irqchip static key optimization KVM: arm/arm64: Fix userspace_irqchip_in_use counting KVM: arm/arm64: Fix incorrect timer_is_pending logic MAINTAINERS: update KVM/s390 maintainers MAINTAINERS: add Halil as additional vfio-ccw maintainer MAINTAINERS: add David as a reviewer for KVM/s390 ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/crypto/ccp/Kconfig12
-rw-r--r--drivers/crypto/ccp/Makefile1
-rw-r--r--drivers/crypto/ccp/psp-dev.c805
-rw-r--r--drivers/crypto/ccp/psp-dev.h83
-rw-r--r--drivers/crypto/ccp/sp-dev.c35
-rw-r--r--drivers/crypto/ccp/sp-dev.h28
-rw-r--r--drivers/crypto/ccp/sp-pci.c52
-rw-r--r--drivers/s390/char/sclp_early.c3
8 files changed, 1017 insertions, 2 deletions
diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig
index 6d626606b9c5..b9dfae47aefd 100644
--- a/drivers/crypto/ccp/Kconfig
+++ b/drivers/crypto/ccp/Kconfig
@@ -1,5 +1,6 @@
1config CRYPTO_DEV_CCP_DD 1config CRYPTO_DEV_CCP_DD
2 tristate "Secure Processor device driver" 2 tristate "Secure Processor device driver"
3 depends on CPU_SUP_AMD || ARM64
3 default m 4 default m
4 help 5 help
5 Provides AMD Secure Processor device driver. 6 Provides AMD Secure Processor device driver.
@@ -32,3 +33,14 @@ config CRYPTO_DEV_CCP_CRYPTO
32 Support for using the cryptographic API with the AMD Cryptographic 33 Support for using the cryptographic API with the AMD Cryptographic
33 Coprocessor. This module supports offload of SHA and AES algorithms. 34 Coprocessor. This module supports offload of SHA and AES algorithms.
34 If you choose 'M' here, this module will be called ccp_crypto. 35 If you choose 'M' here, this module will be called ccp_crypto.
36
37config CRYPTO_DEV_SP_PSP
38 bool "Platform Security Processor (PSP) device"
39 default y
40 depends on CRYPTO_DEV_CCP_DD && X86_64
41 help
42 Provide support for the AMD Platform Security Processor (PSP).
43 The PSP is a dedicated processor that provides support for key
44 management commands in Secure Encrypted Virtualization (SEV) mode,
45 along with software-based Trusted Execution Environment (TEE) to
46 enable third-party trusted applications.
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index c4ce726b931e..51d1c0cf66c7 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -8,6 +8,7 @@ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
8 ccp-dmaengine.o \ 8 ccp-dmaengine.o \
9 ccp-debugfs.o 9 ccp-debugfs.o
10ccp-$(CONFIG_PCI) += sp-pci.o 10ccp-$(CONFIG_PCI) += sp-pci.o
11ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o
11 12
12obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o 13obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
13ccp-crypto-objs := ccp-crypto-main.o \ 14ccp-crypto-objs := ccp-crypto-main.o \
diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
new file mode 100644
index 000000000000..fcfa5b1eae61
--- /dev/null
+++ b/drivers/crypto/ccp/psp-dev.c
@@ -0,0 +1,805 @@
1/*
2 * AMD Platform Security Processor (PSP) interface
3 *
4 * Copyright (C) 2016-2017 Advanced Micro Devices, Inc.
5 *
6 * Author: Brijesh Singh <brijesh.singh@amd.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/kthread.h>
16#include <linux/sched.h>
17#include <linux/interrupt.h>
18#include <linux/spinlock.h>
19#include <linux/spinlock_types.h>
20#include <linux/types.h>
21#include <linux/mutex.h>
22#include <linux/delay.h>
23#include <linux/hw_random.h>
24#include <linux/ccp.h>
25
26#include "sp-dev.h"
27#include "psp-dev.h"
28
29#define DEVICE_NAME "sev"
30
31static DEFINE_MUTEX(sev_cmd_mutex);
32static struct sev_misc_dev *misc_dev;
33static struct psp_device *psp_master;
34
35static struct psp_device *psp_alloc_struct(struct sp_device *sp)
36{
37 struct device *dev = sp->dev;
38 struct psp_device *psp;
39
40 psp = devm_kzalloc(dev, sizeof(*psp), GFP_KERNEL);
41 if (!psp)
42 return NULL;
43
44 psp->dev = dev;
45 psp->sp = sp;
46
47 snprintf(psp->name, sizeof(psp->name), "psp-%u", sp->ord);
48
49 return psp;
50}
51
52static irqreturn_t psp_irq_handler(int irq, void *data)
53{
54 struct psp_device *psp = data;
55 unsigned int status;
56 int reg;
57
58 /* Read the interrupt status: */
59 status = ioread32(psp->io_regs + PSP_P2CMSG_INTSTS);
60
61 /* Check if it is command completion: */
62 if (!(status & BIT(PSP_CMD_COMPLETE_REG)))
63 goto done;
64
65 /* Check if it is SEV command completion: */
66 reg = ioread32(psp->io_regs + PSP_CMDRESP);
67 if (reg & PSP_CMDRESP_RESP) {
68 psp->sev_int_rcvd = 1;
69 wake_up(&psp->sev_int_queue);
70 }
71
72done:
73 /* Clear the interrupt status by writing the same value we read. */
74 iowrite32(status, psp->io_regs + PSP_P2CMSG_INTSTS);
75
76 return IRQ_HANDLED;
77}
78
79static void sev_wait_cmd_ioc(struct psp_device *psp, unsigned int *reg)
80{
81 psp->sev_int_rcvd = 0;
82
83 wait_event(psp->sev_int_queue, psp->sev_int_rcvd);
84 *reg = ioread32(psp->io_regs + PSP_CMDRESP);
85}
86
87static int sev_cmd_buffer_len(int cmd)
88{
89 switch (cmd) {
90 case SEV_CMD_INIT: return sizeof(struct sev_data_init);
91 case SEV_CMD_PLATFORM_STATUS: return sizeof(struct sev_user_data_status);
92 case SEV_CMD_PEK_CSR: return sizeof(struct sev_data_pek_csr);
93 case SEV_CMD_PEK_CERT_IMPORT: return sizeof(struct sev_data_pek_cert_import);
94 case SEV_CMD_PDH_CERT_EXPORT: return sizeof(struct sev_data_pdh_cert_export);
95 case SEV_CMD_LAUNCH_START: return sizeof(struct sev_data_launch_start);
96 case SEV_CMD_LAUNCH_UPDATE_DATA: return sizeof(struct sev_data_launch_update_data);
97 case SEV_CMD_LAUNCH_UPDATE_VMSA: return sizeof(struct sev_data_launch_update_vmsa);
98 case SEV_CMD_LAUNCH_FINISH: return sizeof(struct sev_data_launch_finish);
99 case SEV_CMD_LAUNCH_MEASURE: return sizeof(struct sev_data_launch_measure);
100 case SEV_CMD_ACTIVATE: return sizeof(struct sev_data_activate);
101 case SEV_CMD_DEACTIVATE: return sizeof(struct sev_data_deactivate);
102 case SEV_CMD_DECOMMISSION: return sizeof(struct sev_data_decommission);
103 case SEV_CMD_GUEST_STATUS: return sizeof(struct sev_data_guest_status);
104 case SEV_CMD_DBG_DECRYPT: return sizeof(struct sev_data_dbg);
105 case SEV_CMD_DBG_ENCRYPT: return sizeof(struct sev_data_dbg);
106 case SEV_CMD_SEND_START: return sizeof(struct sev_data_send_start);
107 case SEV_CMD_SEND_UPDATE_DATA: return sizeof(struct sev_data_send_update_data);
108 case SEV_CMD_SEND_UPDATE_VMSA: return sizeof(struct sev_data_send_update_vmsa);
109 case SEV_CMD_SEND_FINISH: return sizeof(struct sev_data_send_finish);
110 case SEV_CMD_RECEIVE_START: return sizeof(struct sev_data_receive_start);
111 case SEV_CMD_RECEIVE_FINISH: return sizeof(struct sev_data_receive_finish);
112 case SEV_CMD_RECEIVE_UPDATE_DATA: return sizeof(struct sev_data_receive_update_data);
113 case SEV_CMD_RECEIVE_UPDATE_VMSA: return sizeof(struct sev_data_receive_update_vmsa);
114 case SEV_CMD_LAUNCH_UPDATE_SECRET: return sizeof(struct sev_data_launch_secret);
115 default: return 0;
116 }
117
118 return 0;
119}
120
121static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
122{
123 struct psp_device *psp = psp_master;
124 unsigned int phys_lsb, phys_msb;
125 unsigned int reg, ret = 0;
126
127 if (!psp)
128 return -ENODEV;
129
130 /* Get the physical address of the command buffer */
131 phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0;
132 phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0;
133
134 dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x\n",
135 cmd, phys_msb, phys_lsb);
136
137 print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
138 sev_cmd_buffer_len(cmd), false);
139
140 iowrite32(phys_lsb, psp->io_regs + PSP_CMDBUFF_ADDR_LO);
141 iowrite32(phys_msb, psp->io_regs + PSP_CMDBUFF_ADDR_HI);
142
143 reg = cmd;
144 reg <<= PSP_CMDRESP_CMD_SHIFT;
145 reg |= PSP_CMDRESP_IOC;
146 iowrite32(reg, psp->io_regs + PSP_CMDRESP);
147
148 /* wait for command completion */
149 sev_wait_cmd_ioc(psp, &reg);
150
151 if (psp_ret)
152 *psp_ret = reg & PSP_CMDRESP_ERR_MASK;
153
154 if (reg & PSP_CMDRESP_ERR_MASK) {
155 dev_dbg(psp->dev, "sev command %#x failed (%#010x)\n",
156 cmd, reg & PSP_CMDRESP_ERR_MASK);
157 ret = -EIO;
158 }
159
160 print_hex_dump_debug("(out): ", DUMP_PREFIX_OFFSET, 16, 2, data,
161 sev_cmd_buffer_len(cmd), false);
162
163 return ret;
164}
165
166static int sev_do_cmd(int cmd, void *data, int *psp_ret)
167{
168 int rc;
169
170 mutex_lock(&sev_cmd_mutex);
171 rc = __sev_do_cmd_locked(cmd, data, psp_ret);
172 mutex_unlock(&sev_cmd_mutex);
173
174 return rc;
175}
176
177static int __sev_platform_init_locked(int *error)
178{
179 struct psp_device *psp = psp_master;
180 int rc = 0;
181
182 if (!psp)
183 return -ENODEV;
184
185 if (psp->sev_state == SEV_STATE_INIT)
186 return 0;
187
188 rc = __sev_do_cmd_locked(SEV_CMD_INIT, &psp->init_cmd_buf, error);
189 if (rc)
190 return rc;
191
192 psp->sev_state = SEV_STATE_INIT;
193 dev_dbg(psp->dev, "SEV firmware initialized\n");
194
195 return rc;
196}
197
198int sev_platform_init(int *error)
199{
200 int rc;
201
202 mutex_lock(&sev_cmd_mutex);
203 rc = __sev_platform_init_locked(error);
204 mutex_unlock(&sev_cmd_mutex);
205
206 return rc;
207}
208EXPORT_SYMBOL_GPL(sev_platform_init);
209
210static int __sev_platform_shutdown_locked(int *error)
211{
212 int ret;
213
214 ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, 0, error);
215 if (ret)
216 return ret;
217
218 psp_master->sev_state = SEV_STATE_UNINIT;
219 dev_dbg(psp_master->dev, "SEV firmware shutdown\n");
220
221 return ret;
222}
223
224static int sev_platform_shutdown(int *error)
225{
226 int rc;
227
228 mutex_lock(&sev_cmd_mutex);
229 rc = __sev_platform_shutdown_locked(NULL);
230 mutex_unlock(&sev_cmd_mutex);
231
232 return rc;
233}
234
235static int sev_get_platform_state(int *state, int *error)
236{
237 int rc;
238
239 rc = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS,
240 &psp_master->status_cmd_buf, error);
241 if (rc)
242 return rc;
243
244 *state = psp_master->status_cmd_buf.state;
245 return rc;
246}
247
248static int sev_ioctl_do_reset(struct sev_issue_cmd *argp)
249{
250 int state, rc;
251
252 /*
253 * The SEV spec requires that FACTORY_RESET must be issued in
254 * UNINIT state. Before we go further lets check if any guest is
255 * active.
256 *
257 * If FW is in WORKING state then deny the request otherwise issue
258 * SHUTDOWN command do INIT -> UNINIT before issuing the FACTORY_RESET.
259 *
260 */
261 rc = sev_get_platform_state(&state, &argp->error);
262 if (rc)
263 return rc;
264
265 if (state == SEV_STATE_WORKING)
266 return -EBUSY;
267
268 if (state == SEV_STATE_INIT) {
269 rc = __sev_platform_shutdown_locked(&argp->error);
270 if (rc)
271 return rc;
272 }
273
274 return __sev_do_cmd_locked(SEV_CMD_FACTORY_RESET, 0, &argp->error);
275}
276
277static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp)
278{
279 struct sev_user_data_status *data = &psp_master->status_cmd_buf;
280 int ret;
281
282 ret = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, data, &argp->error);
283 if (ret)
284 return ret;
285
286 if (copy_to_user((void __user *)argp->data, data, sizeof(*data)))
287 ret = -EFAULT;
288
289 return ret;
290}
291
292static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp)
293{
294 int rc;
295
296 if (psp_master->sev_state == SEV_STATE_UNINIT) {
297 rc = __sev_platform_init_locked(&argp->error);
298 if (rc)
299 return rc;
300 }
301
302 return __sev_do_cmd_locked(cmd, 0, &argp->error);
303}
304
305static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp)
306{
307 struct sev_user_data_pek_csr input;
308 struct sev_data_pek_csr *data;
309 void *blob = NULL;
310 int ret;
311
312 if (copy_from_user(&input, (void __user *)argp->data, sizeof(input)))
313 return -EFAULT;
314
315 data = kzalloc(sizeof(*data), GFP_KERNEL);
316 if (!data)
317 return -ENOMEM;
318
319 /* userspace wants to query CSR length */
320 if (!input.address || !input.length)
321 goto cmd;
322
323 /* allocate a physically contiguous buffer to store the CSR blob */
324 if (!access_ok(VERIFY_WRITE, input.address, input.length) ||
325 input.length > SEV_FW_BLOB_MAX_SIZE) {
326 ret = -EFAULT;
327 goto e_free;
328 }
329
330 blob = kmalloc(input.length, GFP_KERNEL);
331 if (!blob) {
332 ret = -ENOMEM;
333 goto e_free;
334 }
335
336 data->address = __psp_pa(blob);
337 data->len = input.length;
338
339cmd:
340 if (psp_master->sev_state == SEV_STATE_UNINIT) {
341 ret = __sev_platform_init_locked(&argp->error);
342 if (ret)
343 goto e_free_blob;
344 }
345
346 ret = __sev_do_cmd_locked(SEV_CMD_PEK_CSR, data, &argp->error);
347
348 /* If we query the CSR length, FW responded with expected data. */
349 input.length = data->len;
350
351 if (copy_to_user((void __user *)argp->data, &input, sizeof(input))) {
352 ret = -EFAULT;
353 goto e_free_blob;
354 }
355
356 if (blob) {
357 if (copy_to_user((void __user *)input.address, blob, input.length))
358 ret = -EFAULT;
359 }
360
361e_free_blob:
362 kfree(blob);
363e_free:
364 kfree(data);
365 return ret;
366}
367
368void *psp_copy_user_blob(u64 __user uaddr, u32 len)
369{
370 void *data;
371
372 if (!uaddr || !len)
373 return ERR_PTR(-EINVAL);
374
375 /* verify that blob length does not exceed our limit */
376 if (len > SEV_FW_BLOB_MAX_SIZE)
377 return ERR_PTR(-EINVAL);
378
379 data = kmalloc(len, GFP_KERNEL);
380 if (!data)
381 return ERR_PTR(-ENOMEM);
382
383 if (copy_from_user(data, (void __user *)(uintptr_t)uaddr, len))
384 goto e_free;
385
386 return data;
387
388e_free:
389 kfree(data);
390 return ERR_PTR(-EFAULT);
391}
392EXPORT_SYMBOL_GPL(psp_copy_user_blob);
393
394static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp)
395{
396 struct sev_user_data_pek_cert_import input;
397 struct sev_data_pek_cert_import *data;
398 void *pek_blob, *oca_blob;
399 int ret;
400
401 if (copy_from_user(&input, (void __user *)argp->data, sizeof(input)))
402 return -EFAULT;
403
404 data = kzalloc(sizeof(*data), GFP_KERNEL);
405 if (!data)
406 return -ENOMEM;
407
408 /* copy PEK certificate blobs from userspace */
409 pek_blob = psp_copy_user_blob(input.pek_cert_address, input.pek_cert_len);
410 if (IS_ERR(pek_blob)) {
411 ret = PTR_ERR(pek_blob);
412 goto e_free;
413 }
414
415 data->pek_cert_address = __psp_pa(pek_blob);
416 data->pek_cert_len = input.pek_cert_len;
417
418 /* copy PEK certificate blobs from userspace */
419 oca_blob = psp_copy_user_blob(input.oca_cert_address, input.oca_cert_len);
420 if (IS_ERR(oca_blob)) {
421 ret = PTR_ERR(oca_blob);
422 goto e_free_pek;
423 }
424
425 data->oca_cert_address = __psp_pa(oca_blob);
426 data->oca_cert_len = input.oca_cert_len;
427
428 /* If platform is not in INIT state then transition it to INIT */
429 if (psp_master->sev_state != SEV_STATE_INIT) {
430 ret = __sev_platform_init_locked(&argp->error);
431 if (ret)
432 goto e_free_oca;
433 }
434
435 ret = __sev_do_cmd_locked(SEV_CMD_PEK_CERT_IMPORT, data, &argp->error);
436
437e_free_oca:
438 kfree(oca_blob);
439e_free_pek:
440 kfree(pek_blob);
441e_free:
442 kfree(data);
443 return ret;
444}
445
446static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp)
447{
448 struct sev_user_data_pdh_cert_export input;
449 void *pdh_blob = NULL, *cert_blob = NULL;
450 struct sev_data_pdh_cert_export *data;
451 int ret;
452
453 if (copy_from_user(&input, (void __user *)argp->data, sizeof(input)))
454 return -EFAULT;
455
456 data = kzalloc(sizeof(*data), GFP_KERNEL);
457 if (!data)
458 return -ENOMEM;
459
460 /* Userspace wants to query the certificate length. */
461 if (!input.pdh_cert_address ||
462 !input.pdh_cert_len ||
463 !input.cert_chain_address)
464 goto cmd;
465
466 /* Allocate a physically contiguous buffer to store the PDH blob. */
467 if ((input.pdh_cert_len > SEV_FW_BLOB_MAX_SIZE) ||
468 !access_ok(VERIFY_WRITE, input.pdh_cert_address, input.pdh_cert_len)) {
469 ret = -EFAULT;
470 goto e_free;
471 }
472
473 /* Allocate a physically contiguous buffer to store the cert chain blob. */
474 if ((input.cert_chain_len > SEV_FW_BLOB_MAX_SIZE) ||
475 !access_ok(VERIFY_WRITE, input.cert_chain_address, input.cert_chain_len)) {
476 ret = -EFAULT;
477 goto e_free;
478 }
479
480 pdh_blob = kmalloc(input.pdh_cert_len, GFP_KERNEL);
481 if (!pdh_blob) {
482 ret = -ENOMEM;
483 goto e_free;
484 }
485
486 data->pdh_cert_address = __psp_pa(pdh_blob);
487 data->pdh_cert_len = input.pdh_cert_len;
488
489 cert_blob = kmalloc(input.cert_chain_len, GFP_KERNEL);
490 if (!cert_blob) {
491 ret = -ENOMEM;
492 goto e_free_pdh;
493 }
494
495 data->cert_chain_address = __psp_pa(cert_blob);
496 data->cert_chain_len = input.cert_chain_len;
497
498cmd:
499 /* If platform is not in INIT state then transition it to INIT. */
500 if (psp_master->sev_state != SEV_STATE_INIT) {
501 ret = __sev_platform_init_locked(&argp->error);
502 if (ret)
503 goto e_free_cert;
504 }
505
506 ret = __sev_do_cmd_locked(SEV_CMD_PDH_CERT_EXPORT, data, &argp->error);
507
508 /* If we query the length, FW responded with expected data. */
509 input.cert_chain_len = data->cert_chain_len;
510 input.pdh_cert_len = data->pdh_cert_len;
511
512 if (copy_to_user((void __user *)argp->data, &input, sizeof(input))) {
513 ret = -EFAULT;
514 goto e_free_cert;
515 }
516
517 if (pdh_blob) {
518 if (copy_to_user((void __user *)input.pdh_cert_address,
519 pdh_blob, input.pdh_cert_len)) {
520 ret = -EFAULT;
521 goto e_free_cert;
522 }
523 }
524
525 if (cert_blob) {
526 if (copy_to_user((void __user *)input.cert_chain_address,
527 cert_blob, input.cert_chain_len))
528 ret = -EFAULT;
529 }
530
531e_free_cert:
532 kfree(cert_blob);
533e_free_pdh:
534 kfree(pdh_blob);
535e_free:
536 kfree(data);
537 return ret;
538}
539
540static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
541{
542 void __user *argp = (void __user *)arg;
543 struct sev_issue_cmd input;
544 int ret = -EFAULT;
545
546 if (!psp_master)
547 return -ENODEV;
548
549 if (ioctl != SEV_ISSUE_CMD)
550 return -EINVAL;
551
552 if (copy_from_user(&input, argp, sizeof(struct sev_issue_cmd)))
553 return -EFAULT;
554
555 if (input.cmd > SEV_MAX)
556 return -EINVAL;
557
558 mutex_lock(&sev_cmd_mutex);
559
560 switch (input.cmd) {
561
562 case SEV_FACTORY_RESET:
563 ret = sev_ioctl_do_reset(&input);
564 break;
565 case SEV_PLATFORM_STATUS:
566 ret = sev_ioctl_do_platform_status(&input);
567 break;
568 case SEV_PEK_GEN:
569 ret = sev_ioctl_do_pek_pdh_gen(SEV_CMD_PEK_GEN, &input);
570 break;
571 case SEV_PDH_GEN:
572 ret = sev_ioctl_do_pek_pdh_gen(SEV_CMD_PDH_GEN, &input);
573 break;
574 case SEV_PEK_CSR:
575 ret = sev_ioctl_do_pek_csr(&input);
576 break;
577 case SEV_PEK_CERT_IMPORT:
578 ret = sev_ioctl_do_pek_import(&input);
579 break;
580 case SEV_PDH_CERT_EXPORT:
581 ret = sev_ioctl_do_pdh_export(&input);
582 break;
583 default:
584 ret = -EINVAL;
585 goto out;
586 }
587
588 if (copy_to_user(argp, &input, sizeof(struct sev_issue_cmd)))
589 ret = -EFAULT;
590out:
591 mutex_unlock(&sev_cmd_mutex);
592
593 return ret;
594}
595
596static const struct file_operations sev_fops = {
597 .owner = THIS_MODULE,
598 .unlocked_ioctl = sev_ioctl,
599};
600
601int sev_platform_status(struct sev_user_data_status *data, int *error)
602{
603 return sev_do_cmd(SEV_CMD_PLATFORM_STATUS, data, error);
604}
605EXPORT_SYMBOL_GPL(sev_platform_status);
606
607int sev_guest_deactivate(struct sev_data_deactivate *data, int *error)
608{
609 return sev_do_cmd(SEV_CMD_DEACTIVATE, data, error);
610}
611EXPORT_SYMBOL_GPL(sev_guest_deactivate);
612
613int sev_guest_activate(struct sev_data_activate *data, int *error)
614{
615 return sev_do_cmd(SEV_CMD_ACTIVATE, data, error);
616}
617EXPORT_SYMBOL_GPL(sev_guest_activate);
618
619int sev_guest_decommission(struct sev_data_decommission *data, int *error)
620{
621 return sev_do_cmd(SEV_CMD_DECOMMISSION, data, error);
622}
623EXPORT_SYMBOL_GPL(sev_guest_decommission);
624
625int sev_guest_df_flush(int *error)
626{
627 return sev_do_cmd(SEV_CMD_DF_FLUSH, 0, error);
628}
629EXPORT_SYMBOL_GPL(sev_guest_df_flush);
630
631static void sev_exit(struct kref *ref)
632{
633 struct sev_misc_dev *misc_dev = container_of(ref, struct sev_misc_dev, refcount);
634
635 misc_deregister(&misc_dev->misc);
636}
637
638static int sev_misc_init(struct psp_device *psp)
639{
640 struct device *dev = psp->dev;
641 int ret;
642
643 /*
644 * SEV feature support can be detected on multiple devices but the SEV
645 * FW commands must be issued on the master. During probe, we do not
646 * know the master hence we create /dev/sev on the first device probe.
647 * sev_do_cmd() finds the right master device to which to issue the
648 * command to the firmware.
649 */
650 if (!misc_dev) {
651 struct miscdevice *misc;
652
653 misc_dev = devm_kzalloc(dev, sizeof(*misc_dev), GFP_KERNEL);
654 if (!misc_dev)
655 return -ENOMEM;
656
657 misc = &misc_dev->misc;
658 misc->minor = MISC_DYNAMIC_MINOR;
659 misc->name = DEVICE_NAME;
660 misc->fops = &sev_fops;
661
662 ret = misc_register(misc);
663 if (ret)
664 return ret;
665
666 kref_init(&misc_dev->refcount);
667 } else {
668 kref_get(&misc_dev->refcount);
669 }
670
671 init_waitqueue_head(&psp->sev_int_queue);
672 psp->sev_misc = misc_dev;
673 dev_dbg(dev, "registered SEV device\n");
674
675 return 0;
676}
677
678static int sev_init(struct psp_device *psp)
679{
680 /* Check if device supports SEV feature */
681 if (!(ioread32(psp->io_regs + PSP_FEATURE_REG) & 1)) {
682 dev_dbg(psp->dev, "device does not support SEV\n");
683 return 1;
684 }
685
686 return sev_misc_init(psp);
687}
688
689int psp_dev_init(struct sp_device *sp)
690{
691 struct device *dev = sp->dev;
692 struct psp_device *psp;
693 int ret;
694
695 ret = -ENOMEM;
696 psp = psp_alloc_struct(sp);
697 if (!psp)
698 goto e_err;
699
700 sp->psp_data = psp;
701
702 psp->vdata = (struct psp_vdata *)sp->dev_vdata->psp_vdata;
703 if (!psp->vdata) {
704 ret = -ENODEV;
705 dev_err(dev, "missing driver data\n");
706 goto e_err;
707 }
708
709 psp->io_regs = sp->io_map + psp->vdata->offset;
710
711 /* Disable and clear interrupts until ready */
712 iowrite32(0, psp->io_regs + PSP_P2CMSG_INTEN);
713 iowrite32(-1, psp->io_regs + PSP_P2CMSG_INTSTS);
714
715 /* Request an irq */
716 ret = sp_request_psp_irq(psp->sp, psp_irq_handler, psp->name, psp);
717 if (ret) {
718 dev_err(dev, "psp: unable to allocate an IRQ\n");
719 goto e_err;
720 }
721
722 ret = sev_init(psp);
723 if (ret)
724 goto e_irq;
725
726 if (sp->set_psp_master_device)
727 sp->set_psp_master_device(sp);
728
729 /* Enable interrupt */
730 iowrite32(-1, psp->io_regs + PSP_P2CMSG_INTEN);
731
732 return 0;
733
734e_irq:
735 sp_free_psp_irq(psp->sp, psp);
736e_err:
737 sp->psp_data = NULL;
738
739 dev_notice(dev, "psp initialization failed\n");
740
741 return ret;
742}
743
744void psp_dev_destroy(struct sp_device *sp)
745{
746 struct psp_device *psp = sp->psp_data;
747
748 if (psp->sev_misc)
749 kref_put(&misc_dev->refcount, sev_exit);
750
751 sp_free_psp_irq(sp, psp);
752}
753
754int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd,
755 void *data, int *error)
756{
757 if (!filep || filep->f_op != &sev_fops)
758 return -EBADF;
759
760 return sev_do_cmd(cmd, data, error);
761}
762EXPORT_SYMBOL_GPL(sev_issue_cmd_external_user);
763
764void psp_pci_init(void)
765{
766 struct sev_user_data_status *status;
767 struct sp_device *sp;
768 int error, rc;
769
770 sp = sp_get_psp_master_device();
771 if (!sp)
772 return;
773
774 psp_master = sp->psp_data;
775
776 /* Initialize the platform */
777 rc = sev_platform_init(&error);
778 if (rc) {
779 dev_err(sp->dev, "SEV: failed to INIT error %#x\n", error);
780 goto err;
781 }
782
783 /* Display SEV firmware version */
784 status = &psp_master->status_cmd_buf;
785 rc = sev_platform_status(status, &error);
786 if (rc) {
787 dev_err(sp->dev, "SEV: failed to get status error %#x\n", error);
788 goto err;
789 }
790
791 dev_info(sp->dev, "SEV API:%d.%d build:%d\n", status->api_major,
792 status->api_minor, status->build);
793 return;
794
795err:
796 psp_master = NULL;
797}
798
799void psp_pci_exit(void)
800{
801 if (!psp_master)
802 return;
803
804 sev_platform_shutdown(NULL);
805}
diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h
new file mode 100644
index 000000000000..c81f0b11287a
--- /dev/null
+++ b/drivers/crypto/ccp/psp-dev.h
@@ -0,0 +1,83 @@
1/*
2 * AMD Platform Security Processor (PSP) interface driver
3 *
4 * Copyright (C) 2017 Advanced Micro Devices, Inc.
5 *
6 * Author: Brijesh Singh <brijesh.singh@amd.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __PSP_DEV_H__
14#define __PSP_DEV_H__
15
16#include <linux/device.h>
17#include <linux/pci.h>
18#include <linux/spinlock.h>
19#include <linux/mutex.h>
20#include <linux/list.h>
21#include <linux/wait.h>
22#include <linux/dmapool.h>
23#include <linux/hw_random.h>
24#include <linux/bitops.h>
25#include <linux/interrupt.h>
26#include <linux/irqreturn.h>
27#include <linux/dmaengine.h>
28#include <linux/psp-sev.h>
29#include <linux/miscdevice.h>
30
31#include "sp-dev.h"
32
33#define PSP_C2PMSG(_num) ((_num) << 2)
34#define PSP_CMDRESP PSP_C2PMSG(32)
35#define PSP_CMDBUFF_ADDR_LO PSP_C2PMSG(56)
36#define PSP_CMDBUFF_ADDR_HI PSP_C2PMSG(57)
37#define PSP_FEATURE_REG PSP_C2PMSG(63)
38
39#define PSP_P2CMSG(_num) ((_num) << 2)
40#define PSP_CMD_COMPLETE_REG 1
41#define PSP_CMD_COMPLETE PSP_P2CMSG(PSP_CMD_COMPLETE_REG)
42
43#define PSP_P2CMSG_INTEN 0x0110
44#define PSP_P2CMSG_INTSTS 0x0114
45
46#define PSP_C2PMSG_ATTR_0 0x0118
47#define PSP_C2PMSG_ATTR_1 0x011c
48#define PSP_C2PMSG_ATTR_2 0x0120
49#define PSP_C2PMSG_ATTR_3 0x0124
50#define PSP_P2CMSG_ATTR_0 0x0128
51
52#define PSP_CMDRESP_CMD_SHIFT 16
53#define PSP_CMDRESP_IOC BIT(0)
54#define PSP_CMDRESP_RESP BIT(31)
55#define PSP_CMDRESP_ERR_MASK 0xffff
56
57#define MAX_PSP_NAME_LEN 16
58
59struct sev_misc_dev {
60 struct kref refcount;
61 struct miscdevice misc;
62};
63
64struct psp_device {
65 struct list_head entry;
66
67 struct psp_vdata *vdata;
68 char name[MAX_PSP_NAME_LEN];
69
70 struct device *dev;
71 struct sp_device *sp;
72
73 void __iomem *io_regs;
74
75 int sev_state;
76 unsigned int sev_int_rcvd;
77 wait_queue_head_t sev_int_queue;
78 struct sev_misc_dev *sev_misc;
79 struct sev_user_data_status status_cmd_buf;
80 struct sev_data_init init_cmd_buf;
81};
82
83#endif /* __PSP_DEV_H */
diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c
index bef387c8abfd..eb0da6572720 100644
--- a/drivers/crypto/ccp/sp-dev.c
+++ b/drivers/crypto/ccp/sp-dev.c
@@ -198,6 +198,8 @@ int sp_init(struct sp_device *sp)
198 if (sp->dev_vdata->ccp_vdata) 198 if (sp->dev_vdata->ccp_vdata)
199 ccp_dev_init(sp); 199 ccp_dev_init(sp);
200 200
201 if (sp->dev_vdata->psp_vdata)
202 psp_dev_init(sp);
201 return 0; 203 return 0;
202} 204}
203 205
@@ -206,6 +208,9 @@ void sp_destroy(struct sp_device *sp)
206 if (sp->dev_vdata->ccp_vdata) 208 if (sp->dev_vdata->ccp_vdata)
207 ccp_dev_destroy(sp); 209 ccp_dev_destroy(sp);
208 210
211 if (sp->dev_vdata->psp_vdata)
212 psp_dev_destroy(sp);
213
209 sp_del_device(sp); 214 sp_del_device(sp);
210} 215}
211 216
@@ -237,6 +242,27 @@ int sp_resume(struct sp_device *sp)
237} 242}
238#endif 243#endif
239 244
245struct sp_device *sp_get_psp_master_device(void)
246{
247 struct sp_device *i, *ret = NULL;
248 unsigned long flags;
249
250 write_lock_irqsave(&sp_unit_lock, flags);
251 if (list_empty(&sp_units))
252 goto unlock;
253
254 list_for_each_entry(i, &sp_units, entry) {
255 if (i->psp_data)
256 break;
257 }
258
259 if (i->get_psp_master_device)
260 ret = i->get_psp_master_device();
261unlock:
262 write_unlock_irqrestore(&sp_unit_lock, flags);
263 return ret;
264}
265
240static int __init sp_mod_init(void) 266static int __init sp_mod_init(void)
241{ 267{
242#ifdef CONFIG_X86 268#ifdef CONFIG_X86
@@ -246,6 +272,10 @@ static int __init sp_mod_init(void)
246 if (ret) 272 if (ret)
247 return ret; 273 return ret;
248 274
275#ifdef CONFIG_CRYPTO_DEV_SP_PSP
276 psp_pci_init();
277#endif
278
249 return 0; 279 return 0;
250#endif 280#endif
251 281
@@ -265,6 +295,11 @@ static int __init sp_mod_init(void)
265static void __exit sp_mod_exit(void) 295static void __exit sp_mod_exit(void)
266{ 296{
267#ifdef CONFIG_X86 297#ifdef CONFIG_X86
298
299#ifdef CONFIG_CRYPTO_DEV_SP_PSP
300 psp_pci_exit();
301#endif
302
268 sp_pci_exit(); 303 sp_pci_exit();
269#endif 304#endif
270 305
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
index 5ab486ade1ad..acb197b66ced 100644
--- a/drivers/crypto/ccp/sp-dev.h
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -42,12 +42,17 @@ struct ccp_vdata {
42 const unsigned int offset; 42 const unsigned int offset;
43 const unsigned int rsamax; 43 const unsigned int rsamax;
44}; 44};
45
46struct psp_vdata {
47 const unsigned int offset;
48};
49
45/* Structure to hold SP device data */ 50/* Structure to hold SP device data */
46struct sp_dev_vdata { 51struct sp_dev_vdata {
47 const unsigned int bar; 52 const unsigned int bar;
48 53
49 const struct ccp_vdata *ccp_vdata; 54 const struct ccp_vdata *ccp_vdata;
50 void *psp_vdata; 55 const struct psp_vdata *psp_vdata;
51}; 56};
52 57
53struct sp_device { 58struct sp_device {
@@ -68,6 +73,10 @@ struct sp_device {
68 /* DMA caching attribute support */ 73 /* DMA caching attribute support */
69 unsigned int axcache; 74 unsigned int axcache;
70 75
76 /* get and set master device */
77 struct sp_device*(*get_psp_master_device)(void);
78 void (*set_psp_master_device)(struct sp_device *);
79
71 bool irq_registered; 80 bool irq_registered;
72 bool use_tasklet; 81 bool use_tasklet;
73 82
@@ -103,6 +112,7 @@ void sp_free_ccp_irq(struct sp_device *sp, void *data);
103int sp_request_psp_irq(struct sp_device *sp, irq_handler_t handler, 112int sp_request_psp_irq(struct sp_device *sp, irq_handler_t handler,
104 const char *name, void *data); 113 const char *name, void *data);
105void sp_free_psp_irq(struct sp_device *sp, void *data); 114void sp_free_psp_irq(struct sp_device *sp, void *data);
115struct sp_device *sp_get_psp_master_device(void);
106 116
107#ifdef CONFIG_CRYPTO_DEV_SP_CCP 117#ifdef CONFIG_CRYPTO_DEV_SP_CCP
108 118
@@ -130,4 +140,20 @@ static inline int ccp_dev_resume(struct sp_device *sp)
130} 140}
131#endif /* CONFIG_CRYPTO_DEV_SP_CCP */ 141#endif /* CONFIG_CRYPTO_DEV_SP_CCP */
132 142
143#ifdef CONFIG_CRYPTO_DEV_SP_PSP
144
145int psp_dev_init(struct sp_device *sp);
146void psp_pci_init(void);
147void psp_dev_destroy(struct sp_device *sp);
148void psp_pci_exit(void);
149
150#else /* !CONFIG_CRYPTO_DEV_SP_PSP */
151
152static inline int psp_dev_init(struct sp_device *sp) { return 0; }
153static inline void psp_pci_init(void) { }
154static inline void psp_dev_destroy(struct sp_device *sp) { }
155static inline void psp_pci_exit(void) { }
156
157#endif /* CONFIG_CRYPTO_DEV_SP_PSP */
158
133#endif 159#endif
diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c
index 9859aa683a28..f5f43c50698a 100644
--- a/drivers/crypto/ccp/sp-pci.c
+++ b/drivers/crypto/ccp/sp-pci.c
@@ -25,6 +25,7 @@
25#include <linux/ccp.h> 25#include <linux/ccp.h>
26 26
27#include "ccp-dev.h" 27#include "ccp-dev.h"
28#include "psp-dev.h"
28 29
29#define MSIX_VECTORS 2 30#define MSIX_VECTORS 2
30 31
@@ -32,6 +33,7 @@ struct sp_pci {
32 int msix_count; 33 int msix_count;
33 struct msix_entry msix_entry[MSIX_VECTORS]; 34 struct msix_entry msix_entry[MSIX_VECTORS];
34}; 35};
36static struct sp_device *sp_dev_master;
35 37
36static int sp_get_msix_irqs(struct sp_device *sp) 38static int sp_get_msix_irqs(struct sp_device *sp)
37{ 39{
@@ -108,6 +110,45 @@ static void sp_free_irqs(struct sp_device *sp)
108 sp->psp_irq = 0; 110 sp->psp_irq = 0;
109} 111}
110 112
113static bool sp_pci_is_master(struct sp_device *sp)
114{
115 struct device *dev_cur, *dev_new;
116 struct pci_dev *pdev_cur, *pdev_new;
117
118 dev_new = sp->dev;
119 dev_cur = sp_dev_master->dev;
120
121 pdev_new = to_pci_dev(dev_new);
122 pdev_cur = to_pci_dev(dev_cur);
123
124 if (pdev_new->bus->number < pdev_cur->bus->number)
125 return true;
126
127 if (PCI_SLOT(pdev_new->devfn) < PCI_SLOT(pdev_cur->devfn))
128 return true;
129
130 if (PCI_FUNC(pdev_new->devfn) < PCI_FUNC(pdev_cur->devfn))
131 return true;
132
133 return false;
134}
135
136static void psp_set_master(struct sp_device *sp)
137{
138 if (!sp_dev_master) {
139 sp_dev_master = sp;
140 return;
141 }
142
143 if (sp_pci_is_master(sp))
144 sp_dev_master = sp;
145}
146
147static struct sp_device *psp_get_master(void)
148{
149 return sp_dev_master;
150}
151
111static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 152static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
112{ 153{
113 struct sp_device *sp; 154 struct sp_device *sp;
@@ -166,6 +207,8 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
166 goto e_err; 207 goto e_err;
167 208
168 pci_set_master(pdev); 209 pci_set_master(pdev);
210 sp->set_psp_master_device = psp_set_master;
211 sp->get_psp_master_device = psp_get_master;
169 212
170 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48)); 213 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
171 if (ret) { 214 if (ret) {
@@ -225,6 +268,12 @@ static int sp_pci_resume(struct pci_dev *pdev)
225} 268}
226#endif 269#endif
227 270
271#ifdef CONFIG_CRYPTO_DEV_SP_PSP
272static const struct psp_vdata psp_entry = {
273 .offset = 0x10500,
274};
275#endif
276
228static const struct sp_dev_vdata dev_vdata[] = { 277static const struct sp_dev_vdata dev_vdata[] = {
229 { 278 {
230 .bar = 2, 279 .bar = 2,
@@ -237,6 +286,9 @@ static const struct sp_dev_vdata dev_vdata[] = {
237#ifdef CONFIG_CRYPTO_DEV_SP_CCP 286#ifdef CONFIG_CRYPTO_DEV_SP_CCP
238 .ccp_vdata = &ccpv5a, 287 .ccp_vdata = &ccpv5a,
239#endif 288#endif
289#ifdef CONFIG_CRYPTO_DEV_SP_PSP
290 .psp_vdata = &psp_entry
291#endif
240 }, 292 },
241 { 293 {
242 .bar = 2, 294 .bar = 2,
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index d06bc5674e5f..6b1891539c84 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -49,7 +49,7 @@ struct read_info_sccb {
49 u8 _pad_112[116 - 112]; /* 112-115 */ 49 u8 _pad_112[116 - 112]; /* 112-115 */
50 u8 fac116; /* 116 */ 50 u8 fac116; /* 116 */
51 u8 fac117; /* 117 */ 51 u8 fac117; /* 117 */
52 u8 _pad_118; /* 118 */ 52 u8 fac118; /* 118 */
53 u8 fac119; /* 119 */ 53 u8 fac119; /* 119 */
54 u16 hcpua; /* 120-121 */ 54 u16 hcpua; /* 120-121 */
55 u8 _pad_122[124 - 122]; /* 122-123 */ 55 u8 _pad_122[124 - 122]; /* 122-123 */
@@ -100,6 +100,7 @@ static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb)
100 sclp.has_esca = !!(sccb->fac116 & 0x08); 100 sclp.has_esca = !!(sccb->fac116 & 0x08);
101 sclp.has_pfmfi = !!(sccb->fac117 & 0x40); 101 sclp.has_pfmfi = !!(sccb->fac117 & 0x40);
102 sclp.has_ibs = !!(sccb->fac117 & 0x20); 102 sclp.has_ibs = !!(sccb->fac117 & 0x20);
103 sclp.has_gisaf = !!(sccb->fac118 & 0x08);
103 sclp.has_hvs = !!(sccb->fac119 & 0x80); 104 sclp.has_hvs = !!(sccb->fac119 & 0x80);
104 sclp.has_kss = !!(sccb->fac98 & 0x01); 105 sclp.has_kss = !!(sccb->fac98 & 0x01);
105 if (sccb->fac85 & 0x02) 106 if (sccb->fac85 & 0x02)