Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' int…
Browse files Browse the repository at this point in the history
…o staging

- update Linux headers to 5.7-rc3 (and virtio-net fixup)
- support for protected virtualization aka secure execution

# gpg: Signature made Thu 30 Apr 2020 10:41:31 BST
# gpg:                using RSA key C3D0D66DC3624FF6A8C018CEDECF6B93C6F02FAF
# gpg:                issuer "cohuck@redhat.com"
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" [marginal]
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>" [full]
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>" [marginal]
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>" [marginal]
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20200430:
  s390x/s390-virtio-ccw: Fix build on systems without KVM
  s390x/pv: Retry ioctls on -EINTR
  s390x: protvirt: Fix stray error_report_err in s390_machine_protect
  s390x: Add unpack facility feature to GA1
  docs: system: Add protvirt docs
  s390x: protvirt: Handle SIGP store status correctly
  s390x: protvirt: Move IO control structures over SIDA
  s390x: protvirt: Disable address checks for PV guest IO emulation
  s390x: protvirt: Move diag 308 data over SIDA
  s390x: protvirt: Set guest IPL PSW
  s390x: protvirt: SCLP interpretation
  s390x: protvirt: Move STSI data over SIDAD
  s390x: Add SIDA memory ops
  s390x: protvirt: KVM intercept changes
  s390x: protvirt: Inhibit balloon when switching to protected mode
  s390x: protvirt: Add migration blocker
  s390x: protvirt: Support unpack facility
  s390x: Move diagnose 308 subcodes and rcs into ipl.h
  linux-headers: update against Linux 5.7-rc3
  virtio-net: fix rsc_ext compat handling

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Apr 30, 2020
2 parents 68bfd7d + fbc1384 commit 16aaacb
Show file tree
Hide file tree
Showing 41 changed files with 1,116 additions and 98 deletions.
2 changes: 2 additions & 0 deletions MAINTAINERS
Expand Up @@ -396,6 +396,8 @@ F: target/s390x/machine.c
F: target/s390x/sigp.c
F: target/s390x/cpu_features*.[ch]
F: target/s390x/cpu_models.[ch]
F: hw/s390x/pv.c
F: include/hw/s390x/pv.h
F: hw/intc/s390_flic.c
F: hw/intc/s390_flic_kvm.c
F: include/hw/s390x/s390_flic.h
Expand Down
60 changes: 60 additions & 0 deletions docs/system/s390x/protvirt.rst
@@ -0,0 +1,60 @@
Protected Virtualization on s390x
=================================

The memory and most of the registers of Protected Virtual Machines
(PVMs) are encrypted or inaccessible to the hypervisor, effectively
prohibiting VM introspection when the VM is running. At rest, PVMs are
encrypted and can only be decrypted by the firmware, represented by an
entity called Ultravisor, of specific IBM Z machines.


Prerequisites
-------------

To run PVMs, a machine with the Protected Virtualization feature, as
indicated by the Ultravisor Call facility (stfle bit 158), is
required. The Ultravisor needs to be initialized at boot by setting
`prot_virt=1` on the host's kernel command line.

Running PVMs requires using the KVM hypervisor.

If those requirements are met, the capability `KVM_CAP_S390_PROTECTED`
will indicate that KVM can support PVMs on that LPAR.


QEMU Settings
-------------

To indicate to the VM that it can transition into protected mode, the
`Unpack facility` (stfle bit 161 represented by the feature
`unpack`/`S390_FEAT_UNPACK`) needs to be part of the cpu model of
the VM.

All I/O devices need to use the IOMMU.
Passthrough (vfio) devices are currently not supported.

Host huge page backings are not supported. However guests can use huge
pages as indicated by its facilities.


Boot Process
------------

A secure guest image can either be loaded from disk or supplied on the
QEMU command line. Booting from disk is done by the unmodified
s390-ccw BIOS. I.e., the bootmap is interpreted, multiple components
are read into memory and control is transferred to one of the
components (zipl stage3). Stage3 does some fixups and then transfers
control to some program residing in guest memory, which is normally
the OS kernel. The secure image has another component prepended
(stage3a) that uses the new diag308 subcodes 8 and 10 to trigger the
transition into secure mode.

Booting from the image supplied on the QEMU command line requires that
the file passed via -kernel has the same memory layout as would result
from the disk boot. This memory layout includes the encrypted
components (kernel, initrd, cmdline), the stage3a loader and
metadata. In case this boot method is used, the command line
options -initrd and -cmdline are ineffective. The preparation of a PVM
image is done via the `genprotimg` tool from the s390-tools
collection.
5 changes: 5 additions & 0 deletions docs/system/target-s390x.rst
Expand Up @@ -24,3 +24,8 @@ or vfio-ap is also available.
.. toctree::
s390x/vfio-ap

Architectural features
======================

.. toctree::
s390x/protvirt
4 changes: 2 additions & 2 deletions hw/net/virtio-net.c
Expand Up @@ -83,6 +83,8 @@
#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc_ext data in csum_ fields */
#define VIRTIO_NET_F_RSC_EXT 61

#endif

static inline __virtio16 *virtio_net_rsc_ext_num_packets(
struct virtio_net_hdr *hdr)
{
Expand All @@ -95,8 +97,6 @@ static inline __virtio16 *virtio_net_rsc_ext_num_dupacks(
return &hdr->csum_offset;
}

#endif

static VirtIOFeature feature_sizes[] = {
{.flags = 1ULL << VIRTIO_NET_F_MAC,
.end = endof(struct virtio_net_config, mac)},
Expand Down
1 change: 1 addition & 0 deletions hw/s390x/Makefile.objs
Expand Up @@ -31,6 +31,7 @@ obj-y += tod-qemu.o
obj-$(CONFIG_KVM) += tod-kvm.o
obj-$(CONFIG_KVM) += s390-skeys-kvm.o
obj-$(CONFIG_KVM) += s390-stattrib-kvm.o
obj-$(CONFIG_KVM) += pv.o
obj-y += s390-ccw.o
obj-y += ap-device.o
obj-y += ap-bridge.o
59 changes: 56 additions & 3 deletions hw/s390x/ipl.c
@@ -1,10 +1,11 @@
/*
* bootloader support
*
* Copyright IBM, Corp. 2012
* Copyright IBM, Corp. 2012, 2020
*
* Authors:
* Christian Borntraeger <borntraeger@de.ibm.com>
* Janosch Frank <frankja@linux.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at your
* option) any later version. See the COPYING file in the top-level directory.
Expand All @@ -27,6 +28,7 @@
#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
#include "hw/s390x/pv.h"
#include "ipl.h"
#include "qemu/error-report.h"
#include "qemu/config-file.h"
Expand Down Expand Up @@ -566,12 +568,31 @@ void s390_ipl_update_diag308(IplParameterBlock *iplb)
{
S390IPLState *ipl = get_ipl_device();

ipl->iplb = *iplb;
ipl->iplb_valid = true;
/*
* The IPLB set and retrieved by subcodes 8/9 is completely
* separate from the one managed via subcodes 5/6.
*/
if (iplb->pbt == S390_IPL_TYPE_PV) {
ipl->iplb_pv = *iplb;
ipl->iplb_valid_pv = true;
} else {
ipl->iplb = *iplb;
ipl->iplb_valid = true;
}
ipl->netboot = is_virtio_net_device(iplb);
update_machine_ipl_properties(iplb);
}

IplParameterBlock *s390_ipl_get_iplb_pv(void)
{
S390IPLState *ipl = get_ipl_device();

if (!ipl->iplb_valid_pv) {
return NULL;
}
return &ipl->iplb_pv;
}

IplParameterBlock *s390_ipl_get_iplb(void)
{
S390IPLState *ipl = get_ipl_device();
Expand Down Expand Up @@ -660,6 +681,38 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu)
cpu_physical_memory_unmap(addr, len, 1, len);
}

int s390_ipl_prepare_pv_header(void)
{
IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
IPLBlockPV *ipib_pv = &ipib->pv;
void *hdr = g_malloc(ipib_pv->pv_header_len);
int rc;

cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr,
ipib_pv->pv_header_len);
rc = s390_pv_set_sec_parms((uintptr_t)hdr,
ipib_pv->pv_header_len);
g_free(hdr);
return rc;
}

int s390_ipl_pv_unpack(void)
{
IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
IPLBlockPV *ipib_pv = &ipib->pv;
int i, rc = 0;

for (i = 0; i < ipib_pv->num_comp; i++) {
rc = s390_pv_unpack(ipib_pv->components[i].addr,
TARGET_PAGE_ALIGN(ipib_pv->components[i].size),
ipib_pv->components[i].tweak_pref);
if (rc) {
break;
}
}
return rc;
}

void s390_ipl_prepare_cpu(S390CPU *cpu)
{
S390IPLState *ipl = get_ipl_device();
Expand Down
103 changes: 102 additions & 1 deletion hw/s390x/ipl.h
@@ -1,8 +1,9 @@
/*
* s390 IPL device
*
* Copyright 2015 IBM Corp.
* Copyright 2015, 2020 IBM Corp.
* Author(s): Zhang Fan <bjfanzh@cn.ibm.com>
* Janosch Frank <frankja@linux.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or (at
* your option) any later version. See the COPYING file in the top-level
Expand All @@ -13,8 +14,27 @@
#define HW_S390_IPL_H

#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/qdev-core.h"

struct IPLBlockPVComp {
uint64_t tweak_pref;
uint64_t addr;
uint64_t size;
} QEMU_PACKED;
typedef struct IPLBlockPVComp IPLBlockPVComp;

struct IPLBlockPV {
uint8_t reserved18[87]; /* 0x18 */
uint8_t version; /* 0x6f */
uint32_t reserved70; /* 0x70 */
uint32_t num_comp; /* 0x74 */
uint64_t pv_header_addr; /* 0x78 */
uint64_t pv_header_len; /* 0x80 */
struct IPLBlockPVComp components[];
} QEMU_PACKED;
typedef struct IPLBlockPV IPLBlockPV;

struct IplBlockCcw {
uint8_t reserved0[85];
uint8_t ssid;
Expand Down Expand Up @@ -71,6 +91,7 @@ union IplParameterBlock {
union {
IplBlockCcw ccw;
IplBlockFcp fcp;
IPLBlockPV pv;
IplBlockQemuScsi scsi;
};
} QEMU_PACKED;
Expand All @@ -85,15 +106,19 @@ typedef union IplParameterBlock IplParameterBlock;

int s390_ipl_set_loadparm(uint8_t *loadparm);
void s390_ipl_update_diag308(IplParameterBlock *iplb);
int s390_ipl_prepare_pv_header(void);
int s390_ipl_pv_unpack(void);
void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);
IplParameterBlock *s390_ipl_get_iplb_pv(void);

enum s390_reset {
/* default is a reset not triggered by a CPU e.g. issued by QMP */
S390_RESET_EXTERNAL = 0,
S390_RESET_REIPL,
S390_RESET_MODIFIED_CLEAR,
S390_RESET_LOAD_NORMAL,
S390_RESET_PV,
};
void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type);
void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type);
Expand Down Expand Up @@ -133,13 +158,15 @@ struct S390IPLState {
/*< private >*/
DeviceState parent_obj;
IplParameterBlock iplb;
IplParameterBlock iplb_pv;
QemuIplParameters qipl;
uint64_t start_addr;
uint64_t compat_start_addr;
uint64_t bios_start_addr;
uint64_t compat_bios_start_addr;
bool enforce_bios;
bool iplb_valid;
bool iplb_valid_pv;
bool netboot;
/* reset related properties don't have to be migrated or reset */
enum s390_reset reset_type;
Expand All @@ -159,11 +186,29 @@ struct S390IPLState {
typedef struct S390IPLState S390IPLState;
QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong");

#define DIAG_308_RC_OK 0x0001
#define DIAG_308_RC_NO_CONF 0x0102
#define DIAG_308_RC_INVALID 0x0402
#define DIAG_308_RC_NO_PV_CONF 0x0902
#define DIAG_308_RC_INVAL_FOR_PV 0x0a02

#define DIAG308_RESET_MOD_CLR 0
#define DIAG308_RESET_LOAD_NORM 1
#define DIAG308_LOAD_CLEAR 3
#define DIAG308_LOAD_NORMAL_DUMP 4
#define DIAG308_SET 5
#define DIAG308_STORE 6
#define DIAG308_PV_SET 8
#define DIAG308_PV_STORE 9
#define DIAG308_PV_START 10

#define S390_IPL_TYPE_FCP 0x00
#define S390_IPL_TYPE_CCW 0x02
#define S390_IPL_TYPE_PV 0x05
#define S390_IPL_TYPE_QEMU_SCSI 0xff

#define S390_IPLB_HEADER_LEN 8
#define S390_IPLB_MIN_PV_LEN 148
#define S390_IPLB_MIN_CCW_LEN 200
#define S390_IPLB_MIN_FCP_LEN 384
#define S390_IPLB_MIN_QEMU_SCSI_LEN 200
Expand All @@ -173,6 +218,62 @@ static inline bool iplb_valid_len(IplParameterBlock *iplb)
return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock);
}

static inline bool ipl_valid_pv_components(IplParameterBlock *iplb)
{
IPLBlockPV *ipib_pv = &iplb->pv;
int i;

if (ipib_pv->num_comp == 0) {
return false;
}

for (i = 0; i < ipib_pv->num_comp; i++) {
/* Addr must be 4k aligned */
if (ipib_pv->components[i].addr & ~TARGET_PAGE_MASK) {
return false;
}

/* Tweak prefix is monotonically increasing with each component */
if (i < ipib_pv->num_comp - 1 &&
ipib_pv->components[i].tweak_pref >=
ipib_pv->components[i + 1].tweak_pref) {
return false;
}
}
return true;
}

static inline bool ipl_valid_pv_header(IplParameterBlock *iplb)
{
IPLBlockPV *ipib_pv = &iplb->pv;

if (ipib_pv->pv_header_len > 2 * TARGET_PAGE_SIZE) {
return false;
}

if (!address_space_access_valid(&address_space_memory,
ipib_pv->pv_header_addr,
ipib_pv->pv_header_len,
false,
MEMTXATTRS_UNSPECIFIED)) {
return false;
}

return true;
}

static inline bool iplb_valid_pv(IplParameterBlock *iplb)
{
if (iplb->pbt != S390_IPL_TYPE_PV ||
be32_to_cpu(iplb->len) < S390_IPLB_MIN_PV_LEN) {
return false;
}
if (!ipl_valid_pv_header(iplb)) {
return false;
}
return ipl_valid_pv_components(iplb);
}

static inline bool iplb_valid(IplParameterBlock *iplb)
{
switch (iplb->pbt) {
Expand Down

0 comments on commit 16aaacb

Please sign in to comment.