mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into 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>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -24,3 +24,8 @@ or vfio-ap is also available.
|
||||
.. toctree::
|
||||
s390x/vfio-ap
|
||||
|
||||
Architectural features
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
s390x/protvirt
|
||||
|
||||
+2
-2
@@ -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)
|
||||
{
|
||||
@@ -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)},
|
||||
|
||||
@@ -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
|
||||
|
||||
+56
-3
@@ -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.
|
||||
@@ -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"
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
|
||||
+102
-1
@@ -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
|
||||
@@ -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;
|
||||
@@ -71,6 +91,7 @@ union IplParameterBlock {
|
||||
union {
|
||||
IplBlockCcw ccw;
|
||||
IplBlockFcp fcp;
|
||||
IPLBlockPV pv;
|
||||
IplBlockQemuScsi scsi;
|
||||
};
|
||||
} QEMU_PACKED;
|
||||
@@ -85,8 +106,11 @@ 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 */
|
||||
@@ -94,6 +118,7 @@ enum s390_reset {
|
||||
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);
|
||||
@@ -133,6 +158,7 @@ struct S390IPLState {
|
||||
/*< private >*/
|
||||
DeviceState parent_obj;
|
||||
IplParameterBlock iplb;
|
||||
IplParameterBlock iplb_pv;
|
||||
QemuIplParameters qipl;
|
||||
uint64_t start_addr;
|
||||
uint64_t compat_start_addr;
|
||||
@@ -140,6 +166,7 @@ struct S390IPLState {
|
||||
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;
|
||||
@@ -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
|
||||
@@ -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) {
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Protected Virtualization functions
|
||||
*
|
||||
* Copyright IBM Corp. 2020
|
||||
* Author(s):
|
||||
* 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.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <linux/kvm.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "hw/s390x/ipl.h"
|
||||
#include "hw/s390x/pv.h"
|
||||
|
||||
static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
|
||||
{
|
||||
struct kvm_pv_cmd pv_cmd = {
|
||||
.cmd = cmd,
|
||||
.data = (uint64_t)data,
|
||||
};
|
||||
int rc;
|
||||
|
||||
do {
|
||||
rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd);
|
||||
} while (rc == -EINTR);
|
||||
|
||||
if (rc) {
|
||||
error_report("KVM PV command %d (%s) failed: header rc %x rrc %x "
|
||||
"IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc,
|
||||
rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* This macro lets us pass the command as a string to the function so
|
||||
* we can print it on an error.
|
||||
*/
|
||||
#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data);
|
||||
#define s390_pv_cmd_exit(cmd, data) \
|
||||
{ \
|
||||
int rc; \
|
||||
\
|
||||
rc = __s390_pv_cmd(cmd, #cmd, data);\
|
||||
if (rc) { \
|
||||
exit(1); \
|
||||
} \
|
||||
}
|
||||
|
||||
int s390_pv_vm_enable(void)
|
||||
{
|
||||
return s390_pv_cmd(KVM_PV_ENABLE, NULL);
|
||||
}
|
||||
|
||||
void s390_pv_vm_disable(void)
|
||||
{
|
||||
s390_pv_cmd_exit(KVM_PV_DISABLE, NULL);
|
||||
}
|
||||
|
||||
int s390_pv_set_sec_parms(uint64_t origin, uint64_t length)
|
||||
{
|
||||
struct kvm_s390_pv_sec_parm args = {
|
||||
.origin = origin,
|
||||
.length = length,
|
||||
};
|
||||
|
||||
return s390_pv_cmd(KVM_PV_SET_SEC_PARMS, &args);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called for each component in the SE type IPL parameter block 0.
|
||||
*/
|
||||
int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak)
|
||||
{
|
||||
struct kvm_s390_pv_unp args = {
|
||||
.addr = addr,
|
||||
.size = size,
|
||||
.tweak = tweak,
|
||||
};
|
||||
|
||||
return s390_pv_cmd(KVM_PV_UNPACK, &args);
|
||||
}
|
||||
|
||||
void s390_pv_perf_clear_reset(void)
|
||||
{
|
||||
s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL);
|
||||
}
|
||||
|
||||
int s390_pv_verify(void)
|
||||
{
|
||||
return s390_pv_cmd(KVM_PV_VERIFY, NULL);
|
||||
}
|
||||
|
||||
void s390_pv_unshare(void)
|
||||
{
|
||||
s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL);
|
||||
}
|
||||
|
||||
void s390_pv_inject_reset_error(CPUState *cs)
|
||||
{
|
||||
int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4;
|
||||
CPUS390XState *env = &S390_CPU(cs)->env;
|
||||
|
||||
/* Report that we are unable to enter protected mode */
|
||||
env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV;
|
||||
}
|
||||
+133
-4
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* virtio ccw machine
|
||||
*
|
||||
* Copyright 2012 IBM Corp.
|
||||
* Copyright 2012, 2020 IBM Corp.
|
||||
* Copyright (c) 2009 Alexander Graf <agraf@suse.de>
|
||||
* Author(s): Cornelia Huck <cornelia.huck@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
|
||||
@@ -42,6 +43,11 @@
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/s390x/tod.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/balloon.h"
|
||||
#include "hw/s390x/pv.h"
|
||||
#include "migration/blocker.h"
|
||||
|
||||
static Error *pv_mig_blocker;
|
||||
|
||||
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
|
||||
{
|
||||
@@ -317,10 +323,93 @@ static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg)
|
||||
s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
|
||||
}
|
||||
|
||||
static void s390_machine_unprotect(S390CcwMachineState *ms)
|
||||
{
|
||||
s390_pv_vm_disable();
|
||||
ms->pv = false;
|
||||
migrate_del_blocker(pv_mig_blocker);
|
||||
error_free_or_abort(&pv_mig_blocker);
|
||||
qemu_balloon_inhibit(false);
|
||||
}
|
||||
|
||||
static int s390_machine_protect(S390CcwMachineState *ms)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Ballooning on protected VMs needs support in the guest for
|
||||
* sharing and unsharing balloon pages. Block ballooning for
|
||||
* now, until we have a solution to make at least Linux guests
|
||||
* either support it or fail gracefully.
|
||||
*/
|
||||
qemu_balloon_inhibit(true);
|
||||
error_setg(&pv_mig_blocker,
|
||||
"protected VMs are currently not migrateable.");
|
||||
rc = migrate_add_blocker(pv_mig_blocker, &local_err);
|
||||
if (rc) {
|
||||
qemu_balloon_inhibit(false);
|
||||
error_report_err(local_err);
|
||||
error_free_or_abort(&pv_mig_blocker);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Create SE VM */
|
||||
rc = s390_pv_vm_enable();
|
||||
if (rc) {
|
||||
qemu_balloon_inhibit(false);
|
||||
migrate_del_blocker(pv_mig_blocker);
|
||||
error_free_or_abort(&pv_mig_blocker);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ms->pv = true;
|
||||
|
||||
/* Set SE header and unpack */
|
||||
rc = s390_ipl_prepare_pv_header();
|
||||
if (rc) {
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* Decrypt image */
|
||||
rc = s390_ipl_pv_unpack();
|
||||
if (rc) {
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* Verify integrity */
|
||||
rc = s390_pv_verify();
|
||||
if (rc) {
|
||||
goto out_err;
|
||||
}
|
||||
return rc;
|
||||
|
||||
out_err:
|
||||
s390_machine_unprotect(ms);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void s390_pv_prepare_reset(S390CcwMachineState *ms)
|
||||
{
|
||||
CPUState *cs;
|
||||
|
||||
if (!s390_is_pv()) {
|
||||
return;
|
||||
}
|
||||
/* Unsharing requires all cpus to be stopped */
|
||||
CPU_FOREACH(cs) {
|
||||
s390_cpu_set_state(S390_CPU_STATE_STOPPED, S390_CPU(cs));
|
||||
}
|
||||
s390_pv_unshare();
|
||||
s390_pv_perf_clear_reset();
|
||||
}
|
||||
|
||||
static void s390_machine_reset(MachineState *machine)
|
||||
{
|
||||
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
|
||||
enum s390_reset reset_type;
|
||||
CPUState *cs, *t;
|
||||
S390CPU *cpu;
|
||||
|
||||
/* get the reset parameters, reset them once done */
|
||||
s390_ipl_get_reset_request(&cs, &reset_type);
|
||||
@@ -328,9 +417,15 @@ static void s390_machine_reset(MachineState *machine)
|
||||
/* all CPUs are paused and synchronized at this point */
|
||||
s390_cmma_reset();
|
||||
|
||||
cpu = S390_CPU(cs);
|
||||
|
||||
switch (reset_type) {
|
||||
case S390_RESET_EXTERNAL:
|
||||
case S390_RESET_REIPL:
|
||||
if (s390_is_pv()) {
|
||||
s390_machine_unprotect(ms);
|
||||
}
|
||||
|
||||
qemu_devices_reset();
|
||||
s390_crypto_reset();
|
||||
|
||||
@@ -338,22 +433,56 @@ static void s390_machine_reset(MachineState *machine)
|
||||
run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL);
|
||||
break;
|
||||
case S390_RESET_MODIFIED_CLEAR:
|
||||
/*
|
||||
* Susbsystem reset needs to be done before we unshare memory
|
||||
* and lose access to VIRTIO structures in guest memory.
|
||||
*/
|
||||
subsystem_reset();
|
||||
s390_crypto_reset();
|
||||
s390_pv_prepare_reset(ms);
|
||||
CPU_FOREACH(t) {
|
||||
run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
|
||||
}
|
||||
subsystem_reset();
|
||||
s390_crypto_reset();
|
||||
run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
|
||||
break;
|
||||
case S390_RESET_LOAD_NORMAL:
|
||||
/*
|
||||
* Susbsystem reset needs to be done before we unshare memory
|
||||
* and lose access to VIRTIO structures in guest memory.
|
||||
*/
|
||||
subsystem_reset();
|
||||
s390_pv_prepare_reset(ms);
|
||||
CPU_FOREACH(t) {
|
||||
if (t == cs) {
|
||||
continue;
|
||||
}
|
||||
run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL);
|
||||
}
|
||||
subsystem_reset();
|
||||
run_on_cpu(cs, s390_do_cpu_initial_reset, RUN_ON_CPU_NULL);
|
||||
run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
|
||||
break;
|
||||
case S390_RESET_PV: /* Subcode 10 */
|
||||
subsystem_reset();
|
||||
s390_crypto_reset();
|
||||
|
||||
CPU_FOREACH(t) {
|
||||
if (t == cs) {
|
||||
continue;
|
||||
}
|
||||
run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
|
||||
}
|
||||
run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL);
|
||||
|
||||
if (s390_machine_protect(ms)) {
|
||||
s390_pv_inject_reset_error(cs);
|
||||
/*
|
||||
* Continue after the diag308 so the guest knows something
|
||||
* went wrong.
|
||||
*/
|
||||
s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
|
||||
return;
|
||||
}
|
||||
|
||||
run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL);
|
||||
break;
|
||||
default:
|
||||
|
||||
+45
-11
@@ -33,6 +33,22 @@ static inline SCLPDevice *get_sclp_device(void)
|
||||
return sclp;
|
||||
}
|
||||
|
||||
static inline bool sclp_command_code_valid(uint32_t code)
|
||||
{
|
||||
switch (code & SCLP_CMD_CODE_MASK) {
|
||||
case SCLP_CMDW_READ_SCP_INFO:
|
||||
case SCLP_CMDW_READ_SCP_INFO_FORCED:
|
||||
case SCLP_CMDW_READ_CPU_INFO:
|
||||
case SCLP_CMDW_CONFIGURE_IOA:
|
||||
case SCLP_CMDW_DECONFIGURE_IOA:
|
||||
case SCLP_CMD_READ_EVENT_DATA:
|
||||
case SCLP_CMD_WRITE_EVENT_DATA:
|
||||
case SCLP_CMD_WRITE_EVENT_MASK:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
@@ -193,6 +209,34 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We only need the address to have something valid for the
|
||||
* service_interrupt call.
|
||||
*/
|
||||
#define SCLP_PV_DUMMY_ADDR 0x4000
|
||||
int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
|
||||
uint32_t code)
|
||||
{
|
||||
SCLPDevice *sclp = get_sclp_device();
|
||||
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
|
||||
SCCB work_sccb;
|
||||
hwaddr sccb_len = sizeof(SCCB);
|
||||
|
||||
s390_cpu_pv_mem_read(env_archcpu(env), 0, &work_sccb, sccb_len);
|
||||
|
||||
if (!sclp_command_code_valid(code)) {
|
||||
work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
|
||||
goto out_write;
|
||||
}
|
||||
|
||||
sclp_c->execute(sclp, &work_sccb, code);
|
||||
out_write:
|
||||
s390_cpu_pv_mem_write(env_archcpu(env), 0, &work_sccb,
|
||||
be16_to_cpu(work_sccb.h.length));
|
||||
sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
|
||||
{
|
||||
SCLPDevice *sclp = get_sclp_device();
|
||||
@@ -225,17 +269,7 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
|
||||
return -PGM_SPECIFICATION;
|
||||
}
|
||||
|
||||
switch (code & SCLP_CMD_CODE_MASK) {
|
||||
case SCLP_CMDW_READ_SCP_INFO:
|
||||
case SCLP_CMDW_READ_SCP_INFO_FORCED:
|
||||
case SCLP_CMDW_READ_CPU_INFO:
|
||||
case SCLP_CMDW_CONFIGURE_IOA:
|
||||
case SCLP_CMDW_DECONFIGURE_IOA:
|
||||
case SCLP_CMD_READ_EVENT_DATA:
|
||||
case SCLP_CMD_WRITE_EVENT_DATA:
|
||||
case SCLP_CMD_WRITE_EVENT_MASK:
|
||||
break;
|
||||
default:
|
||||
if (!sclp_command_code_valid(code)) {
|
||||
work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
|
||||
goto out_write;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Protected Virtualization header
|
||||
*
|
||||
* Copyright IBM Corp. 2020
|
||||
* Author(s):
|
||||
* 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.
|
||||
*/
|
||||
#ifndef HW_S390_PV_H
|
||||
#define HW_S390_PV_H
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
#include "cpu.h"
|
||||
#include "hw/s390x/s390-virtio-ccw.h"
|
||||
|
||||
static inline bool s390_is_pv(void)
|
||||
{
|
||||
static S390CcwMachineState *ccw;
|
||||
Object *obj;
|
||||
|
||||
if (ccw) {
|
||||
return ccw->pv;
|
||||
}
|
||||
|
||||
/* we have to bail out for the "none" machine */
|
||||
obj = object_dynamic_cast(qdev_get_machine(),
|
||||
TYPE_S390_CCW_MACHINE);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
ccw = S390_CCW_MACHINE(obj);
|
||||
return ccw->pv;
|
||||
}
|
||||
|
||||
int s390_pv_vm_enable(void);
|
||||
void s390_pv_vm_disable(void);
|
||||
int s390_pv_set_sec_parms(uint64_t origin, uint64_t length);
|
||||
int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak);
|
||||
void s390_pv_perf_clear_reset(void);
|
||||
int s390_pv_verify(void);
|
||||
void s390_pv_unshare(void);
|
||||
void s390_pv_inject_reset_error(CPUState *cs);
|
||||
#else /* CONFIG_KVM */
|
||||
static inline bool s390_is_pv(void) { return false; }
|
||||
static inline int s390_pv_vm_enable(void) { return 0; }
|
||||
static inline void s390_pv_vm_disable(void) {}
|
||||
static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; }
|
||||
static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; }
|
||||
static inline void s390_pv_perf_clear_reset(void) {}
|
||||
static inline int s390_pv_verify(void) { return 0; }
|
||||
static inline void s390_pv_unshare(void) {}
|
||||
static inline void s390_pv_inject_reset_error(CPUState *cs) {};
|
||||
#endif /* CONFIG_KVM */
|
||||
|
||||
#endif /* HW_S390_PV_H */
|
||||
@@ -28,6 +28,7 @@ typedef struct S390CcwMachineState {
|
||||
/*< public >*/
|
||||
bool aes_key_wrap;
|
||||
bool dea_key_wrap;
|
||||
bool pv;
|
||||
uint8_t loadparm[8];
|
||||
} S390CcwMachineState;
|
||||
|
||||
|
||||
@@ -217,5 +217,7 @@ void s390_sclp_init(void);
|
||||
void sclp_service_interrupt(uint32_t sccb);
|
||||
void raise_irq_cpu_hotplug(void);
|
||||
int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
|
||||
int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
|
||||
uint32_t code);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -596,6 +596,9 @@ struct ethtool_pauseparam {
|
||||
* @ETH_SS_LINK_MODES: link mode names
|
||||
* @ETH_SS_MSG_CLASSES: debug message class names
|
||||
* @ETH_SS_WOL_MODES: wake-on-lan modes
|
||||
* @ETH_SS_SOF_TIMESTAMPING: SOF_TIMESTAMPING_* flags
|
||||
* @ETH_SS_TS_TX_TYPES: timestamping Tx types
|
||||
* @ETH_SS_TS_RX_FILTERS: timestamping Rx filters
|
||||
*/
|
||||
enum ethtool_stringset {
|
||||
ETH_SS_TEST = 0,
|
||||
@@ -610,6 +613,9 @@ enum ethtool_stringset {
|
||||
ETH_SS_LINK_MODES,
|
||||
ETH_SS_MSG_CLASSES,
|
||||
ETH_SS_WOL_MODES,
|
||||
ETH_SS_SOF_TIMESTAMPING,
|
||||
ETH_SS_TS_TX_TYPES,
|
||||
ETH_SS_TS_RX_FILTERS,
|
||||
|
||||
/* add new constants above here */
|
||||
ETH_SS_COUNT
|
||||
@@ -1330,6 +1336,7 @@ enum ethtool_fec_config_bits {
|
||||
ETHTOOL_FEC_OFF_BIT,
|
||||
ETHTOOL_FEC_RS_BIT,
|
||||
ETHTOOL_FEC_BASER_BIT,
|
||||
ETHTOOL_FEC_LLRS_BIT,
|
||||
};
|
||||
|
||||
#define ETHTOOL_FEC_NONE (1 << ETHTOOL_FEC_NONE_BIT)
|
||||
@@ -1337,6 +1344,7 @@ enum ethtool_fec_config_bits {
|
||||
#define ETHTOOL_FEC_OFF (1 << ETHTOOL_FEC_OFF_BIT)
|
||||
#define ETHTOOL_FEC_RS (1 << ETHTOOL_FEC_RS_BIT)
|
||||
#define ETHTOOL_FEC_BASER (1 << ETHTOOL_FEC_BASER_BIT)
|
||||
#define ETHTOOL_FEC_LLRS (1 << ETHTOOL_FEC_LLRS_BIT)
|
||||
|
||||
/* CMDs currently supported */
|
||||
#define ETHTOOL_GSET 0x00000001 /* DEPRECATED, Get settings.
|
||||
@@ -1521,7 +1529,7 @@ enum ethtool_link_mode_bit_indices {
|
||||
ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 71,
|
||||
ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT = 72,
|
||||
ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT = 73,
|
||||
|
||||
ETHTOOL_LINK_MODE_FEC_LLRS_BIT = 74,
|
||||
/* must be last entry */
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Input event codes
|
||||
*
|
||||
@@ -652,6 +652,9 @@
|
||||
/* Electronic privacy screen control */
|
||||
#define KEY_PRIVACY_SCREEN_TOGGLE 0x279
|
||||
|
||||
/* Select an area of screen to be copied */
|
||||
#define KEY_SELECTIVE_SCREENSHOT 0x27a
|
||||
|
||||
/*
|
||||
* Some keyboards have keys which do not have a defined meaning, these keys
|
||||
* are intended to be programmed / bound to macros by the user. For most
|
||||
|
||||
@@ -605,6 +605,7 @@
|
||||
#define PCI_EXP_SLTCTL_PWR_OFF 0x0400 /* Power Off */
|
||||
#define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */
|
||||
#define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */
|
||||
#define PCI_EXP_SLTCTL_IBPD_DISABLE 0x4000 /* In-band PD disable */
|
||||
#define PCI_EXP_SLTSTA 26 /* Slot Status */
|
||||
#define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */
|
||||
#define PCI_EXP_SLTSTA_PFD 0x0002 /* Power Fault Detected */
|
||||
@@ -680,6 +681,7 @@
|
||||
#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
|
||||
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52 /* v2 endpoints with link end here */
|
||||
#define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */
|
||||
#define PCI_EXP_SLTCAP2_IBPD 0x00000001 /* In-band PD Disable Supported */
|
||||
#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
|
||||
#define PCI_EXP_SLTSTA2 58 /* Slot Status 2 */
|
||||
|
||||
|
||||
@@ -119,6 +119,14 @@ struct vhost_scsi_target {
|
||||
unsigned short reserved;
|
||||
};
|
||||
|
||||
/* VHOST_VDPA specific definitions */
|
||||
|
||||
struct vhost_vdpa_config {
|
||||
uint32_t off;
|
||||
uint32_t len;
|
||||
uint8_t buf[0];
|
||||
};
|
||||
|
||||
/* Feature bits */
|
||||
/* Log all write descriptors. Can be changed while device is active. */
|
||||
#define VHOST_F_LOG_ALL 26
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* Deflate balloon on OOM */
|
||||
#define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */
|
||||
#define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */
|
||||
#define VIRTIO_BALLOON_F_REPORTING 5 /* Page reporting virtqueue */
|
||||
|
||||
/* Size of a PFN in the balloon interface. */
|
||||
#define VIRTIO_BALLOON_PFN_SHIFT 12
|
||||
@@ -47,8 +48,15 @@ struct virtio_balloon_config {
|
||||
uint32_t num_pages;
|
||||
/* Number of pages we've actually got in balloon. */
|
||||
uint32_t actual;
|
||||
/* Free page report command id, readonly by guest */
|
||||
uint32_t free_page_report_cmd_id;
|
||||
/*
|
||||
* Free page hint command id, readonly by guest.
|
||||
* Was previously named free_page_report_cmd_id so we
|
||||
* need to carry that name for legacy support.
|
||||
*/
|
||||
union {
|
||||
uint32_t free_page_hint_cmd_id;
|
||||
uint32_t free_page_report_cmd_id; /* deprecated */
|
||||
};
|
||||
/* Stores PAGE_POISON if page poisoning is in use */
|
||||
uint32_t poison_val;
|
||||
};
|
||||
|
||||
@@ -46,5 +46,6 @@
|
||||
#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */
|
||||
#define VIRTIO_ID_FS 26 /* virtio filesystem */
|
||||
#define VIRTIO_ID_PMEM 27 /* virtio pmem */
|
||||
#define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */
|
||||
|
||||
#endif /* _LINUX_VIRTIO_IDS_H */
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
* Steering */
|
||||
#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
|
||||
|
||||
#define VIRTIO_NET_F_HASH_REPORT 57 /* Supports hash report */
|
||||
#define VIRTIO_NET_F_RSS 60 /* Supports RSS RX steering */
|
||||
#define VIRTIO_NET_F_RSC_EXT 61 /* extended coalescing info */
|
||||
#define VIRTIO_NET_F_STANDBY 62 /* Act as standby for another device
|
||||
* with the same MAC.
|
||||
*/
|
||||
@@ -69,6 +72,17 @@
|
||||
#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
|
||||
#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */
|
||||
|
||||
/* supported/enabled hash types */
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_IPv4 (1 << 0)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_TCPv4 (1 << 1)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_UDPv4 (1 << 2)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_IPv6 (1 << 3)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_TCPv6 (1 << 4)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_UDPv6 (1 << 5)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_IP_EX (1 << 6)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_TCP_EX (1 << 7)
|
||||
#define VIRTIO_NET_RSS_HASH_TYPE_UDP_EX (1 << 8)
|
||||
|
||||
struct virtio_net_config {
|
||||
/* The config defining mac address (if VIRTIO_NET_F_MAC) */
|
||||
uint8_t mac[ETH_ALEN];
|
||||
@@ -92,6 +106,12 @@ struct virtio_net_config {
|
||||
* Any other value stands for unknown.
|
||||
*/
|
||||
uint8_t duplex;
|
||||
/* maximum size of RSS key */
|
||||
uint8_t rss_max_key_size;
|
||||
/* maximum number of indirection table entries */
|
||||
uint16_t rss_max_indirection_table_length;
|
||||
/* bitmask of supported VIRTIO_NET_RSS_HASH_ types */
|
||||
uint32_t supported_hash_types;
|
||||
} QEMU_PACKED;
|
||||
|
||||
/*
|
||||
@@ -104,6 +124,7 @@ struct virtio_net_config {
|
||||
struct virtio_net_hdr_v1 {
|
||||
#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* Use csum_start, csum_offset */
|
||||
#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */
|
||||
#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc info in csum_ fields */
|
||||
uint8_t flags;
|
||||
#define VIRTIO_NET_HDR_GSO_NONE 0 /* Not a GSO frame */
|
||||
#define VIRTIO_NET_HDR_GSO_TCPV4 1 /* GSO frame, IPv4 TCP (TSO) */
|
||||
@@ -113,11 +134,46 @@ struct virtio_net_hdr_v1 {
|
||||
uint8_t gso_type;
|
||||
__virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
|
||||
__virtio16 gso_size; /* Bytes to append to hdr_len per frame */
|
||||
__virtio16 csum_start; /* Position to start checksumming from */
|
||||
__virtio16 csum_offset; /* Offset after that to place checksum */
|
||||
union {
|
||||
struct {
|
||||
__virtio16 csum_start;
|
||||
__virtio16 csum_offset;
|
||||
};
|
||||
/* Checksum calculation */
|
||||
struct {
|
||||
/* Position to start checksumming from */
|
||||
__virtio16 start;
|
||||
/* Offset after that to place checksum */
|
||||
__virtio16 offset;
|
||||
} csum;
|
||||
/* Receive Segment Coalescing */
|
||||
struct {
|
||||
/* Number of coalesced segments */
|
||||
uint16_t segments;
|
||||
/* Number of duplicated acks */
|
||||
uint16_t dup_acks;
|
||||
} rsc;
|
||||
};
|
||||
__virtio16 num_buffers; /* Number of merged rx buffers */
|
||||
};
|
||||
|
||||
struct virtio_net_hdr_v1_hash {
|
||||
struct virtio_net_hdr_v1 hdr;
|
||||
uint32_t hash_value;
|
||||
#define VIRTIO_NET_HASH_REPORT_NONE 0
|
||||
#define VIRTIO_NET_HASH_REPORT_IPv4 1
|
||||
#define VIRTIO_NET_HASH_REPORT_TCPv4 2
|
||||
#define VIRTIO_NET_HASH_REPORT_UDPv4 3
|
||||
#define VIRTIO_NET_HASH_REPORT_IPv6 4
|
||||
#define VIRTIO_NET_HASH_REPORT_TCPv6 5
|
||||
#define VIRTIO_NET_HASH_REPORT_UDPv6 6
|
||||
#define VIRTIO_NET_HASH_REPORT_IPv6_EX 7
|
||||
#define VIRTIO_NET_HASH_REPORT_TCPv6_EX 8
|
||||
#define VIRTIO_NET_HASH_REPORT_UDPv6_EX 9
|
||||
uint16_t hash_report;
|
||||
uint16_t padding;
|
||||
};
|
||||
|
||||
#ifndef VIRTIO_NET_NO_LEGACY
|
||||
/* This header comes first in the scatter-gather list.
|
||||
* For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must
|
||||
@@ -228,7 +284,9 @@ struct virtio_net_ctrl_mac {
|
||||
|
||||
/*
|
||||
* Control Receive Flow Steering
|
||||
*
|
||||
*/
|
||||
#define VIRTIO_NET_CTRL_MQ 4
|
||||
/*
|
||||
* The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
|
||||
* enables Receive Flow Steering, specifying the number of the transmit and
|
||||
* receive queues that will be used. After the command is consumed and acked by
|
||||
@@ -241,11 +299,47 @@ struct virtio_net_ctrl_mq {
|
||||
__virtio16 virtqueue_pairs;
|
||||
};
|
||||
|
||||
#define VIRTIO_NET_CTRL_MQ 4
|
||||
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0
|
||||
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1
|
||||
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000
|
||||
|
||||
/*
|
||||
* The command VIRTIO_NET_CTRL_MQ_RSS_CONFIG has the same effect as
|
||||
* VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET does and additionally configures
|
||||
* the receive steering to use a hash calculated for incoming packet
|
||||
* to decide on receive virtqueue to place the packet. The command
|
||||
* also provides parameters to calculate a hash and receive virtqueue.
|
||||
*/
|
||||
struct virtio_net_rss_config {
|
||||
uint32_t hash_types;
|
||||
uint16_t indirection_table_mask;
|
||||
uint16_t unclassified_queue;
|
||||
uint16_t indirection_table[1/* + indirection_table_mask */];
|
||||
uint16_t max_tx_vq;
|
||||
uint8_t hash_key_length;
|
||||
uint8_t hash_key_data[/* hash_key_length */];
|
||||
};
|
||||
|
||||
#define VIRTIO_NET_CTRL_MQ_RSS_CONFIG 1
|
||||
|
||||
/*
|
||||
* The command VIRTIO_NET_CTRL_MQ_HASH_CONFIG requests the device
|
||||
* to include in the virtio header of the packet the value of the
|
||||
* calculated hash and the report type of hash. It also provides
|
||||
* parameters for hash calculation. The command requires feature
|
||||
* VIRTIO_NET_F_HASH_REPORT to be negotiated to extend the
|
||||
* layout of virtio header as defined in virtio_net_hdr_v1_hash.
|
||||
*/
|
||||
struct virtio_net_hash_config {
|
||||
uint32_t hash_types;
|
||||
/* for compatibility with virtio_net_rss_config */
|
||||
uint16_t reserved[4];
|
||||
uint8_t hash_key_length;
|
||||
uint8_t hash_key_data[/* hash_key_length */];
|
||||
};
|
||||
|
||||
#define VIRTIO_NET_CTRL_MQ_HASH_CONFIG 2
|
||||
|
||||
/*
|
||||
* Control network offloads
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user