diff options
46 files changed, 2653 insertions, 420 deletions
diff --git a/accel/Makefile.objs b/accel/Makefile.objs index 10666eda71..c3718a10c5 100644 --- a/accel/Makefile.objs +++ b/accel/Makefile.objs @@ -1,4 +1,4 @@ obj-$(CONFIG_SOFTMMU) += accel.o -obj-y += kvm/ +obj-$(CONFIG_KVM) += kvm/ obj-$(CONFIG_TCG) += tcg/ obj-y += stubs/ diff --git a/accel/kvm/Makefile.objs b/accel/kvm/Makefile.objs index 85351e7de7..fdfa481578 100644 --- a/accel/kvm/Makefile.objs +++ b/accel/kvm/Makefile.objs @@ -1 +1,2 @@ -obj-$(CONFIG_KVM) += kvm-all.o +obj-y += kvm-all.o +obj-$(call lnot,$(CONFIG_SEV)) += sev-stub.o diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index b91fcb7160..ffee68e603 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -38,6 +38,7 @@ #include "qemu/event_notifier.h" #include "trace.h" #include "hw/irq.h" +#include "sysemu/sev.h" #include "hw/boards.h" @@ -103,6 +104,10 @@ struct KVMState #endif KVMMemoryListener memory_listener; QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus; + + /* memory encryption */ + void *memcrypt_handle; + int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len); }; KVMState *kvm_state; @@ -138,6 +143,26 @@ int kvm_get_max_memslots(void) return s->nr_slots; } +bool kvm_memcrypt_enabled(void) +{ + if (kvm_state && kvm_state->memcrypt_handle) { + return true; + } + + return false; +} + +int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len) +{ + if (kvm_state->memcrypt_handle && + kvm_state->memcrypt_encrypt_data) { + return kvm_state->memcrypt_encrypt_data(kvm_state->memcrypt_handle, + ptr, len); + } + + return 1; +} + static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml) { KVMState *s = kvm_state; @@ -1636,6 +1661,20 @@ static int kvm_init(MachineState *ms) kvm_state = s; + /* + * if memory encryption object is specified then initialize the memory + * encryption context. + */ + if (ms->memory_encryption) { + kvm_state->memcrypt_handle = sev_guest_init(ms->memory_encryption); + if (!kvm_state->memcrypt_handle) { + ret = -1; + goto err; + } + + kvm_state->memcrypt_encrypt_data = sev_encrypt_data; + } + ret = kvm_arch_init(ms, s); if (ret < 0) { goto err; diff --git a/accel/kvm/sev-stub.c b/accel/kvm/sev-stub.c new file mode 100644 index 0000000000..4f97452585 --- /dev/null +++ b/accel/kvm/sev-stub.c @@ -0,0 +1,26 @@ +/* + * QEMU SEV stub + * + * Copyright Advanced Micro Devices 2018 + * + * Authors: + * Brijesh Singh <brijesh.singh@amd.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "sysemu/sev.h" + +int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) +{ + abort(); +} + +void *sev_guest_init(const char *id) +{ + return NULL; +} diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index c964af3e1c..02d5170031 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -105,6 +105,16 @@ int kvm_on_sigbus(int code, void *addr) return 1; } +bool kvm_memcrypt_enabled(void) +{ + return false; +} + +int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len) +{ + return 1; +} + #ifndef CONFIG_USER_ONLY int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev) { diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index 3326e3e0bb..8973579bd0 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -63,3 +63,4 @@ CONFIG_PXB=y CONFIG_ACPI_VMGENID=y CONFIG_FW_CFG_DMA=y CONFIG_I2C=y +CONFIG_SEV=$(CONFIG_KVM) diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 1c6cda1d9a..5e27a7a4f4 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -63,3 +63,4 @@ CONFIG_PXB=y CONFIG_ACPI_VMGENID=y CONFIG_FW_CFG_DMA=y CONFIG_I2C=y +CONFIG_SEV=$(CONFIG_KVM) diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt new file mode 100644 index 0000000000..f483795eaa --- /dev/null +++ b/docs/amd-memory-encryption.txt @@ -0,0 +1,109 @@ +Secure Encrypted Virtualization (SEV) is a feature found on AMD processors. + +SEV is an extension to the AMD-V architecture which supports running encrypted +virtual machine (VMs) under the control of KVM. Encrypted VMs have their pages +(code and data) secured such that only the guest itself has access to the +unencrypted version. Each encrypted VM is associated with a unique encryption +key; if its data is accessed to a different entity using a different key the +encrypted guests data will be incorrectly decrypted, leading to unintelligible +data. + +The key management of this feature is handled by separate processor known as +AMD secure processor (AMD-SP) which is present in AMD SOCs. Firmware running +inside the AMD-SP provide commands to support common VM lifecycle. This +includes commands for launching, snapshotting, migrating and debugging the +encrypted guest. Those SEV command can be issued via KVM_MEMORY_ENCRYPT_OP +ioctls. + +Launching +--------- +Boot images (such as bios) must be encrypted before guest can be booted. +MEMORY_ENCRYPT_OP ioctl provides commands to encrypt the images :LAUNCH_START, +LAUNCH_UPDATE_DATA, LAUNCH_MEASURE and LAUNCH_FINISH. These four commands +together generate a fresh memory encryption key for the VM, encrypt the boot +images and provide a measurement than can be used as an attestation of the +successful launch. + +LAUNCH_START is called first to create a cryptographic launch context within +the firmware. To create this context, guest owner must provides guest policy, +its public Diffie-Hellman key (PDH) and session parameters. These inputs +should be treated as binary blob and must be passed as-is to the SEV firmware. + +The guest policy is passed as plaintext and hypervisor may able to read it +but should not modify it (any modification of the policy bits will result +in bad measurement). The guest policy is a 4-byte data structure containing +several flags that restricts what can be done on running SEV guest. +See KM Spec section 3 and 6.2 for more details. + +The guest policy can be provided via the 'policy' property (see below) + +# ${QEMU} \ + sev-guest,id=sev0,policy=0x1...\ + +Guest owners provided DH certificate and session parameters will be used to +establish a cryptographic session with the guest owner to negotiate keys used +for the attestation. + +The DH certificate and session blob can be provided via 'dh-cert-file' and +'session-file' property (see below + +# ${QEMU} \ + sev-guest,id=sev0,dh-cert-file=<file1>,session-file=<file2> + +LAUNCH_UPDATE_DATA encrypts the memory region using the cryptographic context +created via LAUNCH_START command. If required, this command can be called +multiple times to encrypt different memory regions. The command also calculates +the measurement of the memory contents as it encrypts. + +LAUNCH_MEASURE command can be used to retrieve the measurement of encrypted +memory. This measurement is a signature of the memory contents that can be +sent to the guest owner as an attestation that the memory was encrypted +correctly by the firmware. The guest owner may wait to provide the guest +confidential information until it can verify the attestation measurement. +Since the guest owner knows the initial contents of the guest at boot, the +attestation measurement can be verified by comparing it to what the guest owner +expects. + +LAUNCH_FINISH command finalizes the guest launch and destroy's the cryptographic +context. + +See SEV KM API Spec [1] 'Launching a guest' usage flow (Appendix A) for the +complete flow chart. + +To launch a SEV guest + +# ${QEMU} \ + -machine ...,memory-encryption=sev0 \ + -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1 + +Debugging +----------- +Since memory contents of SEV guest is encrypted hence hypervisor access to the +guest memory will get a cipher text. If guest policy allows debugging, then +hypervisor can use DEBUG_DECRYPT and DEBUG_ENCRYPT commands access the guest +memory region for debug purposes. This is not supported in QEMU yet. + +Snapshot/Restore +----------------- +TODO + +Live Migration +---------------- +TODO + +References +----------------- + +AMD Memory Encryption whitepaper: +http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf + +Secure Encrypted Virutualization Key Management: +[1] http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf + +KVM Forum slides: +http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf + +AMD64 Architecture Programmer's Manual: + http://support.amd.com/TechDocs/24593.pdf + SME is section 7.10 + SEV is section 15.34 diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index ad590a4ffb..ddfcd5adcc 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -867,6 +867,22 @@ Display the amount of initially allocated and present hotpluggable (if enabled) memory in bytes. ETEXI +#if defined(TARGET_I386) + { + .name = "sev", + .args_type = "", + .params = "", + .help = "show SEV information", + .cmd = hmp_info_sev, + }, +#endif + +STEXI +@item info sev +@findex info sev +Show SEV information. +ETEXI + STEXI @end table ETEXI @@ -143,5 +143,6 @@ void hmp_info_ramblock(Monitor *mon, const QDict *qdict); void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict); void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict); void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict); +void hmp_info_sev(Monitor *mon, const QDict *qdict); #endif diff --git a/hw/core/machine.c b/hw/core/machine.c index 5e2bbcdace..2040177664 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -334,6 +334,22 @@ static bool machine_get_enforce_config_section(Object *obj, Error **errp) return ms->enforce_config_section; } +static char *machine_get_memory_encryption(Object *obj, Error **errp) +{ + MachineState *ms = MACHINE(obj); + + return g_strdup(ms->memory_encryption); +} + +static void machine_set_memory_encryption(Object *obj, const char *value, + Error **errp) +{ + MachineState *ms = MACHINE(obj); + + g_free(ms->memory_encryption); + ms->memory_encryption = g_strdup(value); +} + void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type) { strList *item = g_new0(strList, 1); @@ -612,6 +628,12 @@ static void machine_class_init(ObjectClass *oc, void *data) &error_abort); object_class_property_set_description(oc, "enforce-config-section", "Set on to enforce configuration section migration", &error_abort); + + object_class_property_add_str(oc, "memory-encryption", + machine_get_memory_encryption, machine_set_memory_encryption, + &error_abort); + object_class_property_set_description(oc, "memory-encryption", + "Set memory encyption object to use", &error_abort); } static void machine_class_base_init(ObjectClass *oc, void *data) diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 4325575e7d..73ac783f20 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -113,6 +113,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory) pflash_t *system_flash; MemoryRegion *flash_mem; char name[64]; + void *flash_ptr; + int ret, flash_size; sector_bits = 12; sector_size = 1 << sector_bits; @@ -169,6 +171,17 @@ static void pc_system_flash_init(MemoryRegion *rom_memory) if (unit == 0) { flash_mem = pflash_cfi01_get_memory(system_flash); pc_isa_bios_init(rom_memory, flash_mem, size); + + /* Encrypt the pflash boot ROM */ + if (kvm_memcrypt_enabled()) { + flash_ptr = memory_region_get_ram_ptr(flash_mem); + flash_size = memory_region_size(flash_mem); + ret = kvm_memcrypt_encrypt_data(flash_ptr, flash_size); + if (ret) { + error_report("failed to encrypt pflash rom"); + exit(1); + } + } } } } diff --git a/include/hw/boards.h b/include/hw/boards.h index efb0a9edfd..8ce9a7a21d 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -243,6 +243,7 @@ struct MachineState { bool suppress_vmdesc; bool enforce_config_section; bool enable_graphics; + char *memory_encryption; ram_addr_t ram_size; ram_addr_t maxram_size; diff --git a/include/standard-headers/linux/input-event-codes.h b/include/standard-headers/linux/input-event-codes.h index 79841b543f..9e6a8ba4ce 100644 --- a/include/standard-headers/linux/input-event-codes.h +++ b/include/standard-headers/linux/input-event-codes.h @@ -594,6 +594,7 @@ #define BTN_DPAD_RIGHT 0x223 #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ +#define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */ #define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */ #define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */ diff --git a/include/standard-headers/linux/input.h b/include/standard-headers/linux/input.h index bc3e6d3d5b..939b62775c 100644 --- a/include/standard-headers/linux/input.h +++ b/include/standard-headers/linux/input.h @@ -18,10 +18,21 @@ /* * The event structure itself + * Note that __USE_TIME_BITS64 is defined by libc based on + * application's request to use 64 bit time_t. */ struct input_event { +#if (HOST_LONG_BITS != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL) struct timeval time; +#define input_event_sec time.tv_sec +#define input_event_usec time.tv_usec +#else + __kernel_ulong_t __sec; + __kernel_ulong_t __usec; +#define input_event_sec __sec +#define input_event_usec __usec +#endif uint16_t type; uint16_t code; int32_t value; diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index 70c2b2ade0..0c79eac5e9 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -622,15 +622,19 @@ * safely. */ #define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */ +#define PCI_EXP_DEVCAP2_COMP_TMOUT_DIS 0x00000010 /* Completion Timeout Disable supported */ #define PCI_EXP_DEVCAP2_ARI 0x00000020 /* Alternative Routing-ID */ #define PCI_EXP_DEVCAP2_ATOMIC_ROUTE 0x00000040 /* Atomic Op routing */ -#define PCI_EXP_DEVCAP2_ATOMIC_COMP64 0x00000100 /* Atomic 64-bit compare */ +#define PCI_EXP_DEVCAP2_ATOMIC_COMP32 0x00000080 /* 32b AtomicOp completion */ +#define PCI_EXP_DEVCAP2_ATOMIC_COMP64 0x00000100 /* 64b AtomicOp completion */ +#define PCI_EXP_DEVCAP2_ATOMIC_COMP128 0x00000200 /* 128b AtomicOp completion */ #define PCI_EXP_DEVCAP2_LTR 0x00000800 /* Latency tolerance reporting */ #define PCI_EXP_DEVCAP2_OBFF_MASK 0x000c0000 /* OBFF support mechanism */ #define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */ #define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */ #define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ #define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */ +#define PCI_EXP_DEVCTL2_COMP_TMOUT_DIS 0x0010 /* Completion Timeout Disable */ #define PCI_EXP_DEVCTL2_ARI 0x0020 /* Alternative Routing-ID */ #define PCI_EXP_DEVCTL2_ATOMIC_REQ 0x0040 /* Set Atomic requests */ #define PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK 0x0080 /* Block atomic egress */ @@ -966,26 +970,28 @@ /* Downstream Port Containment */ #define PCI_EXP_DPC_CAP 4 /* DPC Capability */ -#define PCI_EXP_DPC_IRQ 0x1f /* DPC Interrupt Message Number */ -#define PCI_EXP_DPC_CAP_RP_EXT 0x20 /* Root Port Extensions for DPC */ -#define PCI_EXP_DPC_CAP_POISONED_TLP 0x40 /* Poisoned TLP Egress Blocking Supported */ -#define PCI_EXP_DPC_CAP_SW_TRIGGER 0x80 /* Software Triggering Supported */ -#define PCI_EXP_DPC_RP_PIO_LOG_SIZE 0xF00 /* RP PIO log size */ +#define PCI_EXP_DPC_IRQ 0x001F /* Interrupt Message Number */ +#define PCI_EXP_DPC_CAP_RP_EXT 0x0020 /* Root Port Extensions */ +#define PCI_EXP_DPC_CAP_POISONED_TLP 0x0040 /* Poisoned TLP Egress Blocking Supported */ +#define PCI_EXP_DPC_CAP_SW_TRIGGER 0x0080 /* Software Triggering Supported */ +#define PCI_EXP_DPC_RP_PIO_LOG_SIZE 0x0F00 /* RP PIO Log Size */ #define PCI_EXP_DPC_CAP_DL_ACTIVE 0x1000 /* ERR_COR signal on DL_Active supported */ #define PCI_EXP_DPC_CTL 6 /* DPC control */ -#define PCI_EXP_DPC_CTL_EN_NONFATAL 0x02 /* Enable trigger on ERR_NONFATAL message */ -#define PCI_EXP_DPC_CTL_INT_EN 0x08 /* DPC Interrupt Enable */ +#define PCI_EXP_DPC_CTL_EN_NONFATAL 0x0002 /* Enable trigger on ERR_NONFATAL message */ +#define PCI_EXP_DPC_CTL_INT_EN 0x0008 /* DPC Interrupt Enable */ #define PCI_EXP_DPC_STATUS 8 /* DPC Status */ -#define PCI_EXP_DPC_STATUS_TRIGGER 0x01 /* Trigger Status */ -#define PCI_EXP_DPC_STATUS_INTERRUPT 0x08 /* Interrupt Status */ -#define PCI_EXP_DPC_RP_BUSY 0x10 /* Root Port Busy */ +#define PCI_EXP_DPC_STATUS_TRIGGER 0x0001 /* Trigger Status */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN 0x0006 /* Trigger Reason */ +#define PCI_EXP_DPC_STATUS_INTERRUPT 0x0008 /* Interrupt Status */ +#define PCI_EXP_DPC_RP_BUSY 0x0010 /* Root Port Busy */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT 0x0060 /* Trig Reason Extension */ #define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ #define PCI_EXP_DPC_RP_PIO_STATUS 0x0C /* RP PIO Status */ -#define PCI_EXP_DPC_RP_PIO_MASK 0x10 /* RP PIO MASK */ +#define PCI_EXP_DPC_RP_PIO_MASK 0x10 /* RP PIO Mask */ #define PCI_EXP_DPC_RP_PIO_SEVERITY 0x14 /* RP PIO Severity */ #define PCI_EXP_DPC_RP_PIO_SYSERROR 0x18 /* RP PIO SysError */ #define PCI_EXP_DPC_RP_PIO_EXCEPTION 0x1C /* RP PIO Exception */ diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h index 30ff24940d..e9f255ea3f 100644 --- a/include/standard-headers/linux/virtio_net.h +++ b/include/standard-headers/linux/virtio_net.h @@ -57,6 +57,8 @@ * Steering */ #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ +#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */ + #ifndef VIRTIO_NET_NO_LEGACY #define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ #endif /* VIRTIO_NET_NO_LEGACY */ @@ -76,6 +78,17 @@ struct virtio_net_config { uint16_t max_virtqueue_pairs; /* Default maximum transmit unit advice */ uint16_t mtu; + /* + * speed, in units of 1Mb. All values 0 to INT_MAX are legal. + * Any other value stands for unknown. + */ + uint32_t speed; + /* + * 0x00 - half duplex + * 0x01 - full duplex + * Any other value stands for unknown. + */ + uint8_t duplex; } QEMU_PACKED; /* diff --git a/include/standard-headers/linux/virtio_ring.h b/include/standard-headers/linux/virtio_ring.h index f1dc05df25..d26e72bc6b 100644 --- a/include/standard-headers/linux/virtio_ring.h +++ b/include/standard-headers/linux/virtio_ring.h @@ -78,7 +78,7 @@ struct vring_avail { __virtio16 ring[]; }; -/* u32 is used here for ids for padding reasons. */ +/* uint32_t is used here for ids for padding reasons. */ struct vring_used_elem { /* Index of start of used descriptor chain. */ __virtio32 id; diff --git a/include/standard-headers/rdma/vmw_pvrdma-abi.h b/include/standard-headers/rdma/vmw_pvrdma-abi.h index 0d0f7a8aca..07a820d337 100644 --- a/include/standard-headers/rdma/vmw_pvrdma-abi.h +++ b/include/standard-headers/rdma/vmw_pvrdma-abi.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */ /* * Copyright (c) 2012-2016 VMware, Inc. All rights reserved. * @@ -51,12 +52,14 @@ #define PVRDMA_UVERBS_ABI_VERSION 3 /* ABI Version. */ #define PVRDMA_UAR_HANDLE_MASK 0x00FFFFFF /* Bottom 24 bits. */ #define PVRDMA_UAR_QP_OFFSET 0 /* QP doorbell. */ -#define PVRDMA_UAR_QP_SEND BIT(30) /* Send bit. */ -#define PVRDMA_UAR_QP_RECV BIT(31) /* Recv bit. */ +#define PVRDMA_UAR_QP_SEND (1 << 30) /* Send bit. */ +#define PVRDMA_UAR_QP_RECV (1 << 31) /* Recv bit. */ #define PVRDMA_UAR_CQ_OFFSET 4 /* CQ doorbell. */ -#define PVRDMA_UAR_CQ_ARM_SOL BIT(29) /* Arm solicited bit. */ -#define PVRDMA_UAR_CQ_ARM BIT(30) /* Arm bit. */ -#define PVRDMA_UAR_CQ_POLL BIT(31) /* Poll bit. */ +#define PVRDMA_UAR_CQ_ARM_SOL (1 << 29) /* Arm solicited bit. */ +#define PVRDMA_UAR_CQ_ARM (1 << 30) /* Arm bit. */ +#define PVRDMA_UAR_CQ_POLL (1 << 31) /* Poll bit. */ +#define PVRDMA_UAR_SRQ_OFFSET 8 /* SRQ doorbell. */ +#define PVRDMA_UAR_SRQ_RECV (1 << 30) /* Recv bit. */ enum pvrdma_wr_opcode { PVRDMA_WR_RDMA_WRITE, diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 85002ac49a..23669c4d5a 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -231,6 +231,23 @@ int kvm_destroy_vcpu(CPUState *cpu); */ bool kvm_arm_supports_user_irq(void); +/** + * kvm_memcrypt_enabled - return boolean indicating whether memory encryption + * is enabled + * Returns: 1 memory encryption is enabled + * 0 memory encryption is disabled + */ +bool kvm_memcrypt_enabled(void); + +/** + * kvm_memcrypt_encrypt_data: encrypt the memory range + * + * Return: 1 failed to encrypt the range + * 0 succesfully encrypted memory region + */ +int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len); + + #ifdef NEED_CPU_H #include "cpu.h" diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h new file mode 100644 index 0000000000..98c1ec8d38 --- /dev/null +++ b/include/sysemu/sev.h @@ -0,0 +1,21 @@ +/* + * QEMU Secure Encrypted Virutualization (SEV) support + * + * Copyright: Advanced Micro Devices, 2016-2018 + * + * Authors: + * Brijesh Singh <brijesh.singh@amd.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_SEV_H +#define QEMU_SEV_H + +#include "sysemu/kvm.h" + +void *sev_guest_init(const char *id); +int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len); +#endif diff --git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h index 637b7263cb..833ed9a16a 100644 --- a/linux-headers/asm-powerpc/kvm.h +++ b/linux-headers/asm-powerpc/kvm.h @@ -632,6 +632,8 @@ struct kvm_ppc_cpu_char { #define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc) #define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd) +#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe) + /* Transactional Memory checkpointed state: * This is all GPRs, all VSX regs and a subset of SPRs */ diff --git a/linux-headers/asm-powerpc/unistd.h b/linux-headers/asm-powerpc/unistd.h index 36abf58582..0c08edcfcd 100644 --- a/linux-headers/asm-powerpc/unistd.h +++ b/linux-headers/asm-powerpc/unistd.h @@ -395,5 +395,8 @@ #define __NR_pwritev2 381 #define __NR_kexec_file_load 382 #define __NR_statx 383 +#define __NR_pkey_alloc 384 +#define __NR_pkey_free 385 +#define __NR_pkey_mprotect 386 #endif /* _ASM_POWERPC_UNISTD_H_ */ diff --git a/linux-headers/asm-s390/unistd.h b/linux-headers/asm-s390/unistd.h index 99223b874a..27b8b211c8 100644 --- a/linux-headers/asm-s390/unistd.h +++ b/linux-headers/asm-s390/unistd.h @@ -8,405 +8,10 @@ #ifndef _ASM_S390_UNISTD_H_ #define _ASM_S390_UNISTD_H_ -/* - * This file contains the system call numbers. - */ - -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_restart_syscall 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_pause 29 -#define __NR_utime 30 -#define __NR_access 33 -#define __NR_nice 34 -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -#define __NR_brk 45 -#define __NR_signal 48 -#define __NR_acct 51 -#define __NR_umount2 52 -#define __NR_ioctl 54 -#define __NR_fcntl 55 -#define __NR_setpgid 57 -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_symlink 83 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -#define __NR_lookup_dcookie 110 -#define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ -#define __NR_getdents 141 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 -#define __NR_query_module 167 -#define __NR_poll 168 -#define __NR_nfsservctl 169 -#define __NR_prctl 172 -#define __NR_rt_sigreturn 173 -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#define __NR_rt_sigpending 176 -#define __NR_rt_sigtimedwait 177 -#define __NR_rt_sigqueueinfo 178 -#define __NR_rt_sigsuspend 179 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_getcwd 183 -#define __NR_capget 184 -#define __NR_capset 185 -#define __NR_sigaltstack 186 -#define __NR_sendfile 187 -#define __NR_getpmsg 188 -#define __NR_putpmsg 189 -#define __NR_vfork 190 -#define __NR_pivot_root 217 -#define __NR_mincore 218 -#define __NR_madvise 219 -#define __NR_getdents64 220 -#define __NR_readahead 222 -#define __NR_setxattr 224 -#define __NR_lsetxattr 225 -#define __NR_fsetxattr 226 -#define __NR_getxattr 227 -#define __NR_lgetxattr 228 -#define __NR_fgetxattr 229 -#define __NR_listxattr 230 -#define __NR_llistxattr 231 -#define __NR_flistxattr 232 -#define __NR_removexattr 233 -#define __NR_lremovexattr 234 -#define __NR_fremovexattr 235 -#define __NR_gettid 236 -#define __NR_tkill 237 -#define __NR_futex 238 -#define __NR_sched_setaffinity 239 -#define __NR_sched_getaffinity 240 -#define __NR_tgkill 241 -/* Number 242 is reserved for tux */ -#define __NR_io_setup 243 -#define __NR_io_destroy 244 -#define __NR_io_getevents 245 -#define __NR_io_submit 246 -#define __NR_io_cancel 247 -#define __NR_exit_group 248 -#define __NR_epoll_create 249 -#define __NR_epoll_ctl 250 -#define __NR_epoll_wait 251 -#define __NR_set_tid_address 252 -#define __NR_fadvise64 253 -#define __NR_timer_create 254 -#define __NR_timer_settime 255 -#define __NR_timer_gettime 256 -#define __NR_timer_getoverrun 257 -#define __NR_timer_delete 258 -#define __NR_clock_settime 259 -#define __NR_clock_gettime 260 -#define __NR_clock_getres 261 -#define __NR_clock_nanosleep 262 -/* Number 263 is reserved for vserver */ -#define __NR_statfs64 265 -#define __NR_fstatfs64 266 -#define __NR_remap_file_pages 267 -#define __NR_mbind 268 -#define __NR_get_mempolicy 269 -#define __NR_set_mempolicy 270 -#define __NR_mq_open 271 -#define __NR_mq_unlink 272 -#define __NR_mq_timedsend 273 -#define __NR_mq_timedreceive 274 -#define __NR_mq_notify 275 -#define __NR_mq_getsetattr 276 -#define __NR_kexec_load 277 -#define __NR_add_key 278 -#define __NR_request_key 279 -#define __NR_keyctl 280 -#define __NR_waitid 281 -#define __NR_ioprio_set 282 -#define __NR_ioprio_get 283 -#define __NR_inotify_init 284 -#define __NR_inotify_add_watch 285 -#define __NR_inotify_rm_watch 286 -#define __NR_migrate_pages 287 -#define __NR_openat 288 -#define __NR_mkdirat 289 -#define __NR_mknodat 290 -#define __NR_fchownat 291 -#define __NR_futimesat 292 -#define __NR_unlinkat 294 -#define __NR_renameat 295 -#define __NR_linkat 296 -#define __NR_symlinkat 297 -#define __NR_readlinkat 298 -#define __NR_fchmodat 299 -#define __NR_faccessat 300 -#define __NR_pselect6 301 -#define __NR_ppoll 302 -#define __NR_unshare 303 -#define __NR_set_robust_list 304 -#define __NR_get_robust_list 305 -#define __NR_splice 306 -#define __NR_sync_file_range 307 -#define __NR_tee 308 -#define __NR_vmsplice 309 -#define __NR_move_pages 310 -#define __NR_getcpu 311 -#define __NR_epoll_pwait 312 -#define __NR_utimes 313 -#define __NR_fallocate 314 -#define __NR_utimensat 315 -#define __NR_signalfd 316 -#define __NR_timerfd 317 -#define __NR_eventfd 318 -#define __NR_timerfd_create 319 -#define __NR_timerfd_settime 320 -#define __NR_timerfd_gettime 321 -#define __NR_signalfd4 322 -#define __NR_eventfd2 323 -#define __NR_inotify_init1 324 -#define __NR_pipe2 325 -#define __NR_dup3 326 -#define __NR_epoll_create1 327 -#define __NR_preadv 328 -#define __NR_pwritev 329 -#define __NR_rt_tgsigqueueinfo 330 -#define __NR_perf_event_open 331 -#define __NR_fanotify_init 332 -#define __NR_fanotify_mark 333 -#define __NR_prlimit64 334 -#define __NR_name_to_handle_at 335 -#define __NR_open_by_handle_at 336 -#define __NR_clock_adjtime 337 -#define __NR_syncfs 338 -#define __NR_setns 339 -#define __NR_process_vm_readv 340 -#define __NR_process_vm_writev 341 -#define __NR_s390_runtime_instr 342 -#define __NR_kcmp 343 -#define __NR_finit_module 344 -#define __NR_sched_setattr 345 -#define __NR_sched_getattr 346 -#define __NR_renameat2 347 -#define __NR_seccomp 348 -#define __NR_getrandom 349 -#define __NR_memfd_create 350 -#define __NR_bpf 351 -#define __NR_s390_pci_mmio_write 352 -#define __NR_s390_pci_mmio_read 353 -#define __NR_execveat 354 -#define __NR_userfaultfd 355 -#define __NR_membarrier 356 -#define __NR_recvmmsg 357 -#define __NR_sendmmsg 358 -#define __NR_socket 359 -#define __NR_socketpair 360 -#define __NR_bind 361 -#define __NR_connect 362 -#define __NR_listen 363 -#define __NR_accept4 364 -#define __NR_getsockopt 365 -#define __NR_setsockopt 366 -#define __NR_getsockname 367 -#define __NR_getpeername 368 -#define __NR_sendto 369 -#define __NR_sendmsg 370 -#define __NR_recvfrom 371 -#define __NR_recvmsg 372 -#define __NR_shutdown 373 -#define __NR_mlock2 374 -#define __NR_copy_file_range 375 -#define __NR_preadv2 376 -#define __NR_pwritev2 377 -#define __NR_s390_guarded_storage 378 -#define __NR_statx 379 -#define __NR_s390_sthyi 380 -#define NR_syscalls 381 - -/* - * There are some system calls that are not present on 64 bit, some - * have a different name although they do the same (e.g. __NR_chown32 - * is __NR_chown on 64 bit). - */ -#ifndef __s390x__ - -#define __NR_time 13 -#define __NR_lchown 16 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_getrlimit 76 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_fchown 95 -#define __NR_ioperm 101 -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR__newselect 142 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_chown 182 -#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_lchown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_chown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_fcntl64 221 -#define __NR_sendfile64 223 -#define __NR_fadvise64_64 264 -#define __NR_fstatat64 293 - +#ifdef __s390x__ +#include <asm/unistd_64.h> #else - -#define __NR_select 142 -#define __NR_getrlimit 191 /* SuS compliant getrlimit */ -#define __NR_lchown 198 -#define __NR_getuid 199 -#define __NR_getgid 200 -#define __NR_geteuid 201 -#define __NR_getegid 202 -#define __NR_setreuid 203 -#define __NR_setregid 204 -#define __NR_getgroups 205 -#define __NR_setgroups 206 -#define __NR_fchown 207 -#define __NR_setresuid 208 -#define __NR_getresuid 209 -#define __NR_setresgid 210 -#define __NR_getresgid 211 -#define __NR_chown 212 -#define __NR_setuid 213 -#define __NR_setgid 214 -#define __NR_setfsuid 215 -#define __NR_setfsgid 216 -#define __NR_newfstatat 293 - +#include <asm/unistd_32.h> #endif #endif /* _ASM_S390_UNISTD_H_ */ diff --git a/linux-headers/asm-s390/unistd_32.h b/linux-headers/asm-s390/unistd_32.h new file mode 100644 index 0000000000..1ae66a263b --- /dev/null +++ b/linux-headers/asm-s390/unistd_32.h @@ -0,0 +1,364 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_S390_UNISTD_32_H +#define _ASM_S390_UNISTD_32_H + +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_restart_syscall 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_lchown 16 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_umount2 52 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_setpgid 57 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_symlink 83 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_lookup_dcookie 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_chown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_getpmsg 188 +#define __NR_putpmsg 189 +#define __NR_vfork 190 +#define __NR_ugetrlimit 191 +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_lchown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_setgroups32 206 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_chown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_setfsuid32 215 +#define __NR_setfsgid32 216 +#define __NR_pivot_root 217 +#define __NR_mincore 218 +#define __NR_madvise 219 +#define __NR_getdents64 220 +#define __NR_fcntl64 221 +#define __NR_readahead 222 +#define __NR_sendfile64 223 +#define __NR_setxattr 224 +#define __NR_lsetxattr 225 +#define __NR_fsetxattr 226 +#define __NR_getxattr 227 +#define __NR_lgetxattr 228 +#define __NR_fgetxattr 229 +#define __NR_listxattr 230 +#define __NR_llistxattr 231 +#define __NR_flistxattr 232 +#define __NR_removexattr 233 +#define __NR_lremovexattr 234 +#define __NR_fremovexattr 235 +#define __NR_gettid 236 +#define __NR_tkill 237 +#define __NR_futex 238 +#define __NR_sched_setaffinity 239 +#define __NR_sched_getaffinity 240 +#define __NR_tgkill 241 +#define __NR_io_setup 243 +#define __NR_io_destroy 244 +#define __NR_io_getevents 245 +#define __NR_io_submit 246 +#define __NR_io_cancel 247 +#define __NR_exit_group 248 +#define __NR_epoll_create 249 +#define __NR_epoll_ctl 250 +#define __NR_epoll_wait 251 +#define __NR_set_tid_address 252 +#define __NR_fadvise64 253 +#define __NR_timer_create 254 +#define __NR_timer_settime 255 +#define __NR_timer_gettime 256 +#define __NR_timer_getoverrun 257 +#define __NR_timer_delete 258 +#define __NR_clock_settime 259 +#define __NR_clock_gettime 260 +#define __NR_clock_getres 261 +#define __NR_clock_nanosleep 262 +#define __NR_fadvise64_64 264 +#define __NR_statfs64 265 +#define __NR_fstatfs64 266 +#define __NR_remap_file_pages 267 +#define __NR_mbind 268 +#define __NR_get_mempolicy 269 +#define __NR_set_mempolicy 270 +#define __NR_mq_open 271 +#define __NR_mq_unlink 272 +#define __NR_mq_timedsend 273 +#define __NR_mq_timedreceive 274 +#define __NR_mq_notify 275 +#define __NR_mq_getsetattr 276 +#define __NR_kexec_load 277 +#define __NR_add_key 278 +#define __NR_request_key 279 +#define __NR_keyctl 280 +#define __NR_waitid 281 +#define __NR_ioprio_set 282 +#define __NR_ioprio_get 283 +#define __NR_inotify_init 284 +#define __NR_inotify_add_watch 285 +#define __NR_inotify_rm_watch 286 +#define __NR_migrate_pages 287 +#define __NR_openat 288 +#define __NR_mkdirat 289 +#define __NR_mknodat 290 +#define __NR_fchownat 291 +#define __NR_futimesat 292 +#define __NR_fstatat64 293 +#define __NR_unlinkat 294 +#define __NR_renameat 295 +#define __NR_linkat 296 +#define __NR_symlinkat 297 +#define __NR_readlinkat 298 +#define __NR_fchmodat 299 +#define __NR_faccessat 300 +#define __NR_pselect6 301 +#define __NR_ppoll 302 +#define __NR_unshare 303 +#define __NR_set_robust_list 304 +#define __NR_get_robust_list 305 +#define __NR_splice 306 +#define __NR_sync_file_range 307 +#define __NR_tee 308 +#define __NR_vmsplice 309 +#define __NR_move_pages 310 +#define __NR_getcpu 311 +#define __NR_epoll_pwait 312 +#define __NR_utimes 313 +#define __NR_fallocate 314 +#define __NR_utimensat 315 +#define __NR_signalfd 316 +#define __NR_timerfd 317 +#define __NR_eventfd 318 +#define __NR_timerfd_create 319 +#define __NR_timerfd_settime 320 +#define __NR_timerfd_gettime 321 +#define __NR_signalfd4 322 +#define __NR_eventfd2 323 +#define __NR_inotify_init1 324 +#define __NR_pipe2 325 +#define __NR_dup3 326 +#define __NR_epoll_create1 327 +#define __NR_preadv 328 +#define __NR_pwritev 329 +#define __NR_rt_tgsigqueueinfo 330 +#define __NR_perf_event_open 331 +#define __NR_fanotify_init 332 +#define __NR_fanotify_mark 333 +#define __NR_prlimit64 334 +#define __NR_name_to_handle_at 335 +#define __NR_open_by_handle_at 336 +#define __NR_clock_adjtime 337 +#define __NR_syncfs 338 +#define __NR_setns 339 +#define __NR_process_vm_readv 340 +#define __NR_process_vm_writev 341 +#define __NR_s390_runtime_instr 342 +#define __NR_kcmp 343 +#define __NR_finit_module 344 +#define __NR_sched_setattr 345 +#define __NR_sched_getattr 346 +#define __NR_renameat2 347 +#define __NR_seccomp 348 +#define __NR_getrandom 349 +#define __NR_memfd_create 350 +#define __NR_bpf 351 +#define __NR_s390_pci_mmio_write 352 +#define __NR_s390_pci_mmio_read 353 +#define __NR_execveat 354 +#define __NR_userfaultfd 355 +#define __NR_membarrier 356 +#define __NR_recvmmsg 357 +#define __NR_sendmmsg 358 +#define __NR_socket 359 +#define __NR_socketpair 360 +#define __NR_bind 361 +#define __NR_connect 362 +#define __NR_listen 363 +#define __NR_accept4 364 +#define __NR_getsockopt 365 +#define __NR_setsockopt 366 +#define __NR_getsockname 367 +#define __NR_getpeername 368 +#define __NR_sendto 369 +#define __NR_sendmsg 370 +#define __NR_recvfrom 371 +#define __NR_recvmsg 372 +#define __NR_shutdown 373 +#define __NR_mlock2 374 +#define __NR_copy_file_range 375 +#define __NR_preadv2 376 +#define __NR_pwritev2 377 +#define __NR_s390_guarded_storage 378 +#define __NR_statx 379 +#define __NR_s390_sthyi 380 + +#endif /* _ASM_S390_UNISTD_32_H */ diff --git a/linux-headers/asm-s390/unistd_64.h b/linux-headers/asm-s390/unistd_64.h new file mode 100644 index 0000000000..8aa9d046a9 --- /dev/null +++ b/linux-headers/asm-s390/unistd_64.h @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_S390_UNISTD_64_H +#define _ASM_S390_UNISTD_64_H + +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_restart_syscall 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_brk 45 +#define __NR_signal 48 +#define __NR_acct 51 +#define __NR_umount2 52 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_setpgid 57 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_symlink 83 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_lookup_dcookie 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 +#define __NR_getdents 141 +#define __NR_select 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_getpmsg 188 +#define __NR_putpmsg 189 +#define __NR_vfork 190 +#define __NR_getrlimit 191 +#define __NR_lchown 198 +#define __NR_getuid 199 +#define __NR_getgid 200 +#define __NR_geteuid 201 +#define __NR_getegid 202 +#define __NR_setreuid 203 +#define __NR_setregid 204 +#define __NR_getgroups 205 +#define __NR_setgroups 206 +#define __NR_fchown 207 +#define __NR_setresuid 208 +#define __NR_getresuid 209 +#define __NR_setresgid 210 +#define __NR_getresgid 211 +#define __NR_chown 212 +#define __NR_setuid 213 +#define __NR_setgid 214 +#define __NR_setfsuid 215 +#define __NR_setfsgid 216 +#define __NR_pivot_root 217 +#define __NR_mincore 218 +#define __NR_madvise 219 +#define __NR_getdents64 220 +#define __NR_readahead 222 +#define __NR_setxattr 224 +#define __NR_lsetxattr 225 +#define __NR_fsetxattr 226 +#define __NR_getxattr 227 +#define __NR_lgetxattr 228 +#define __NR_fgetxattr 229 +#define __NR_listxattr 230 +#define __NR_llistxattr 231 +#define __NR_flistxattr 232 +#define __NR_removexattr 233 +#define __NR_lremovexattr 234 +#define __NR_fremovexattr 235 +#define __NR_gettid 236 +#define __NR_tkill 237 +#define __NR_futex 238 +#define __NR_sched_setaffinity 239 +#define __NR_sched_getaffinity 240 +#define __NR_tgkill 241 +#define __NR_io_setup 243 +#define __NR_io_destroy 244 +#define __NR_io_getevents 245 +#define __NR_io_submit 246 +#define __NR_io_cancel 247 +#define __NR_exit_group 248 +#define __NR_epoll_create 249 +#define __NR_epoll_ctl 250 +#define __NR_epoll_wait 251 +#define __NR_set_tid_address 252 +#define __NR_fadvise64 253 +#define __NR_timer_create 254 +#define __NR_timer_settime 255 +#define __NR_timer_gettime 256 +#define __NR_timer_getoverrun 257 +#define __NR_timer_delete 258 +#define __NR_clock_settime 259 +#define __NR_clock_gettime 260 +#define __NR_clock_getres 261 +#define __NR_clock_nanosleep 262 +#define __NR_statfs64 265 +#define __NR_fstatfs64 266 +#define __NR_remap_file_pages 267 +#define __NR_mbind 268 +#define __NR_get_mempolicy 269 +#define __NR_set_mempolicy 270 +#define __NR_mq_open 271 +#define __NR_mq_unlink 272 +#define __NR_mq_timedsend 273 +#define __NR_mq_timedreceive 274 +#define __NR_mq_notify 275 +#define __NR_mq_getsetattr 276 +#define __NR_kexec_load 277 +#define __NR_add_key 278 +#define __NR_request_key 279 +#define __NR_keyctl 280 +#define __NR_waitid 281 +#define __NR_ioprio_set 282 +#define __NR_ioprio_get 283 +#define __NR_inotify_init 284 +#define __NR_inotify_add_watch 285 +#define __NR_inotify_rm_watch 286 +#define __NR_migrate_pages 287 +#define __NR_openat 288 +#define __NR_mkdirat 289 +#define __NR_mknodat 290 +#define __NR_fchownat 291 +#define __NR_futimesat 292 +#define __NR_newfstatat 293 +#define __NR_unlinkat 294 +#define __NR_renameat 295 +#define __NR_linkat 296 +#define __NR_symlinkat 297 +#define __NR_readlinkat 298 +#define __NR_fchmodat 299 +#define __NR_faccessat 300 +#define __NR_pselect6 301 +#define __NR_ppoll 302 +#define __NR_unshare 303 +#define __NR_set_robust_list 304 +#define __NR_get_robust_list 305 +#define __NR_splice 306 +#define __NR_sync_file_range 307 +#define __NR_tee 308 +#define __NR_vmsplice 309 +#define __NR_move_pages 310 +#define __NR_getcpu 311 +#define __NR_epoll_pwait 312 +#define __NR_utimes 313 +#define __NR_fallocate 314 +#define __NR_utimensat 315 +#define __NR_signalfd 316 +#define __NR_timerfd 317 +#define __NR_eventfd 318 +#define __NR_timerfd_create 319 +#define __NR_timerfd_settime 320 +#define __NR_timerfd_gettime 321 +#define __NR_signalfd4 322 +#define __NR_eventfd2 323 +#define __NR_inotify_init1 324 +#define __NR_pipe2 325 +#define __NR_dup3 326 +#define __NR_epoll_create1 327 +#define __NR_preadv 328 +#define __NR_pwritev 329 +#define __NR_rt_tgsigqueueinfo 330 +#define __NR_perf_event_open 331 +#define __NR_fanotify_init 332 +#define __NR_fanotify_mark 333 +#define __NR_prlimit64 334 +#define __NR_name_to_handle_at 335 +#define __NR_open_by_handle_at 336 +#define __NR_clock_adjtime 337 +#define __NR_syncfs 338 +#define __NR_setns 339 +#define __NR_process_vm_readv 340 +#define __NR_process_vm_writev 341 +#define __NR_s390_runtime_instr 342 +#define __NR_kcmp 343 +#define __NR_finit_module 344 +#define __NR_sched_setattr 345 +#define __NR_sched_getattr 346 +#define __NR_renameat2 347 +#define __NR_seccomp 348 +#define __NR_getrandom 349 +#define __NR_memfd_create 350 +#define __NR_bpf 351 +#define __NR_s390_pci_mmio_write 352 +#define __NR_s390_pci_mmio_read 353 +#define __NR_execveat 354 +#define __NR_userfaultfd 355 +#define __NR_membarrier 356 +#define __NR_recvmmsg 357 +#define __NR_sendmmsg 358 +#define __NR_socket 359 +#define __NR_socketpair 360 +#define __NR_bind 361 +#define __NR_connect 362 +#define __NR_listen 363 +#define __NR_accept4 364 +#define __NR_getsockopt 365 +#define __NR_setsockopt 366 +#define __NR_getsockname 367 +#define __NR_getpeername 368 +#define __NR_sendto 369 +#define __NR_sendmsg 370 +#define __NR_recvfrom 371 +#define __NR_recvmsg 372 +#define __NR_shutdown 373 +#define __NR_mlock2 374 +#define __NR_copy_file_range 375 +#define __NR_preadv2 376 +#define __NR_pwritev2 377 +#define __NR_s390_guarded_storage 378 +#define __NR_statx 379 +#define __NR_s390_sthyi 380 + +#endif /* _ASM_S390_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/kvm_para.h b/linux-headers/asm-x86/kvm_para.h index 4c300f6aaa..4c58184395 100644 --- a/linux-headers/asm-x86/kvm_para.h +++ b/linux-headers/asm-x86/kvm_para.h @@ -25,6 +25,8 @@ #define KVM_FEATURE_STEAL_TIME 5 #define KVM_FEATURE_PV_EOI 6 #define KVM_FEATURE_PV_UNHALT 7 +#define KVM_FEATURE_PV_TLB_FLUSH 9 +#define KVM_FEATURE_ASYNC_PF_VMEXIT 10 /* The last 8 bits are used to indicate how to interpret the flags field * in pvclock structure. If no bits are set, all flags are ignored. @@ -51,6 +53,9 @@ struct kvm_steal_time { __u32 pad[11]; }; +#define KVM_VCPU_PREEMPTED (1 << 0) +#define KVM_VCPU_FLUSH_TLB (1 << 1) + #define KVM_CLOCK_PAIRING_WALLCLOCK 0 struct kvm_clock_pairing { __s64 sec; diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index d92c9b2f0e..a167be89d1 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -761,6 +761,7 @@ struct kvm_ppc_resize_hpt { #define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07 #define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08 #define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) +#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list) /* * Extension capability list. @@ -934,6 +935,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_S390_AIS_MIGRATION 150 #define KVM_CAP_PPC_GET_CPU_CHAR 151 #define KVM_CAP_S390_BPB 152 +#define KVM_CAP_GET_MSR_FEATURES 153 #ifdef KVM_CAP_IRQ_ROUTING @@ -1362,6 +1364,96 @@ struct kvm_s390_ucas_mapping { /* Available with KVM_CAP_S390_CMMA_MIGRATION */ #define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log) #define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log) +/* Memory Encryption Commands */ +#define KVM_MEMORY_ENCRYPT_OP _IOWR(KVMIO, 0xba, unsigned long) + +struct kvm_enc_region { + __u64 addr; + __u64 size; +}; + +#define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region) +#define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region) + +/* Secure Encrypted Virtualization command */ +enum sev_cmd_id { + /* Guest initialization commands */ + KVM_SEV_INIT = 0, + KVM_SEV_ES_INIT, + /* Guest launch commands */ + KVM_SEV_LAUNCH_START, + KVM_SEV_LAUNCH_UPDATE_DATA, + KVM_SEV_LAUNCH_UPDATE_VMSA, + KVM_SEV_LAUNCH_SECRET, + KVM_SEV_LAUNCH_MEASURE, + KVM_SEV_LAUNCH_FINISH, + /* Guest migration commands (outgoing) */ + KVM_SEV_SEND_START, + KVM_SEV_SEND_UPDATE_DATA, + KVM_SEV_SEND_UPDATE_VMSA, + KVM_SEV_SEND_FINISH, + /* Guest migration commands (incoming) */ + KVM_SEV_RECEIVE_START, + KVM_SEV_RECEIVE_UPDATE_DATA, + KVM_SEV_RECEIVE_UPDATE_VMSA, + KVM_SEV_RECEIVE_FINISH, + /* Guest status and debug commands */ + KVM_SEV_GUEST_STATUS, + KVM_SEV_DBG_DECRYPT, + KVM_SEV_DBG_ENCRYPT, + /* Guest certificates commands */ + KVM_SEV_CERT_EXPORT, + + KVM_SEV_NR_MAX, +}; + +struct kvm_sev_cmd { + __u32 id; + __u64 data; + __u32 error; + __u32 sev_fd; +}; + +struct kvm_sev_launch_start { + __u32 handle; + __u32 policy; + __u64 dh_uaddr; + __u32 dh_len; + __u64 session_uaddr; + __u32 session_len; +}; + +struct kvm_sev_launch_update_data { + __u64 uaddr; + __u32 len; +}; + + +struct kvm_sev_launch_secret { + __u64 hdr_uaddr; + __u32 hdr_len; + __u64 guest_uaddr; + __u32 guest_len; + __u64 trans_uaddr; + __u32 trans_len; +}; + +struct kvm_sev_launch_measure { + __u64 uaddr; + __u32 len; +}; + +struct kvm_sev_guest_status { + __u32 handle; + __u32 policy; + __u32 state; +}; + +struct kvm_sev_dbg { + __u64 src_uaddr; + __u64 dst_uaddr; + __u32 len; +}; #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) diff --git a/linux-headers/linux/psci.h b/linux-headers/linux/psci.h index ccd17731c6..3905492d18 100644 --- a/linux-headers/linux/psci.h +++ b/linux-headers/linux/psci.h @@ -88,6 +88,9 @@ (((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT) #define PSCI_VERSION_MINOR(ver) \ ((ver) & PSCI_VERSION_MINOR_MASK) +#define PSCI_VERSION(maj, min) \ + ((((maj) << PSCI_VERSION_MAJOR_SHIFT) & PSCI_VERSION_MAJOR_MASK) | \ + ((min) & PSCI_VERSION_MINOR_MASK)) /* PSCI features decoding (>=1.0) */ #define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1 diff --git a/linux-headers/linux/psp-sev.h b/linux-headers/linux/psp-sev.h new file mode 100644 index 0000000000..33e247471a --- /dev/null +++ b/linux-headers/linux/psp-sev.h @@ -0,0 +1,142 @@ +/* + * Userspace interface for AMD Secure Encrypted Virtualization (SEV) + * platform management commands. + * + * Copyright (C) 2016-2017 Advanced Micro Devices, Inc. + * + * Author: Brijesh Singh <brijesh.singh@amd.com> + * + * SEV spec 0.14 is available at: + * http://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __PSP_SEV_USER_H__ +#define __PSP_SEV_USER_H__ + +#include <linux/types.h> + +/** + * SEV platform commands + */ +enum { + SEV_FACTORY_RESET = 0, + SEV_PLATFORM_STATUS, + SEV_PEK_GEN, + SEV_PEK_CSR, + SEV_PDH_GEN, + SEV_PDH_CERT_EXPORT, + SEV_PEK_CERT_IMPORT, + + SEV_MAX, +}; + +/** + * SEV Firmware status code + */ +typedef enum { + SEV_RET_SUCCESS = 0, + SEV_RET_INVALID_PLATFORM_STATE, + SEV_RET_INVALID_GUEST_STATE, + SEV_RET_INAVLID_CONFIG, + SEV_RET_INVALID_LEN, + SEV_RET_ALREADY_OWNED, + SEV_RET_INVALID_CERTIFICATE, + SEV_RET_POLICY_FAILURE, + SEV_RET_INACTIVE, + SEV_RET_INVALID_ADDRESS, + SEV_RET_BAD_SIGNATURE, + SEV_RET_BAD_MEASUREMENT, + SEV_RET_ASID_OWNED, + SEV_RET_INVALID_ASID, + SEV_RET_WBINVD_REQUIRED, + SEV_RET_DFFLUSH_REQUIRED, + SEV_RET_INVALID_GUEST, + SEV_RET_INVALID_COMMAND, + SEV_RET_ACTIVE, + SEV_RET_HWSEV_RET_PLATFORM, + SEV_RET_HWSEV_RET_UNSAFE, + SEV_RET_UNSUPPORTED, + SEV_RET_MAX, +} sev_ret_code; + +/** + * struct sev_user_data_status - PLATFORM_STATUS command parameters + * + * @major: major API version + * @minor: minor API version + * @state: platform state + * @flags: platform config flags + * @build: firmware build id for API version + * @guest_count: number of active guests + */ +struct sev_user_data_status { + __u8 api_major; /* Out */ + __u8 api_minor; /* Out */ + __u8 state; /* Out */ + __u32 flags; /* Out */ + __u8 build; /* Out */ + __u32 guest_count; /* Out */ +} __attribute__((packed)); + +/** + * struct sev_user_data_pek_csr - PEK_CSR command parameters + * + * @address: PEK certificate chain + * @length: length of certificate + */ +struct sev_user_data_pek_csr { + __u64 address; /* In */ + __u32 length; /* In/Out */ +} __attribute__((packed)); + +/** + * struct sev_user_data_cert_import - PEK_CERT_IMPORT command parameters + * + * @pek_address: PEK certificate chain + * @pek_len: length of PEK certificate + * @oca_address: OCA certificate chain + * @oca_len: length of OCA certificate + */ +struct sev_user_data_pek_cert_import { + __u64 pek_cert_address; /* In */ + __u32 pek_cert_len; /* In */ + __u64 oca_cert_address; /* In */ + __u32 oca_cert_len; /* In */ +} __attribute__((packed)); + +/** + * struct sev_user_data_pdh_cert_export - PDH_CERT_EXPORT command parameters + * + * @pdh_address: PDH certificate address + * @pdh_len: length of PDH certificate + * @cert_chain_address: PDH certificate chain + * @cert_chain_len: length of PDH certificate chain + */ +struct sev_user_data_pdh_cert_export { + __u64 pdh_cert_address; /* In */ + __u32 pdh_cert_len; /* In/Out */ + __u64 cert_chain_address; /* In */ + __u32 cert_chain_len; /* In/Out */ +} __attribute__((packed)); + +/** + * struct sev_issue_cmd - SEV ioctl parameters + * + * @cmd: SEV commands to execute + * @opaque: pointer to the command structure + * @error: SEV FW return code on failure + */ +struct sev_issue_cmd { + __u32 cmd; /* In */ + __u64 data; /* In */ + __u32 error; /* Out */ +} __attribute__((packed)); + +#define SEV_IOC_TYPE 'S' +#define SEV_ISSUE_CMD _IOWR(SEV_IOC_TYPE, 0x0, struct sev_issue_cmd) + +#endif /* __PSP_USER_SEV_H */ diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index 4312e961ff..3a0a305c8c 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -301,6 +301,16 @@ struct vfio_region_info_cap_type { #define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2) #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3) +/* + * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped + * which allows direct access to non-MSIX registers which happened to be within + * the same system page. + * + * Even though the userspace gets direct access to the MSIX data, the existing + * VFIO_DEVICE_SET_IRQS interface must still be used for MSIX configuration. + */ +#define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3 + /** * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9, * struct vfio_irq_info) @@ -503,6 +513,68 @@ struct vfio_pci_hot_reset { #define VFIO_DEVICE_PCI_HOT_RESET _IO(VFIO_TYPE, VFIO_BASE + 13) +/** + * VFIO_DEVICE_QUERY_GFX_PLANE - _IOW(VFIO_TYPE, VFIO_BASE + 14, + * struct vfio_device_query_gfx_plane) + * + * Set the drm_plane_type and flags, then retrieve the gfx plane info. + * + * flags supported: + * - VFIO_GFX_PLANE_TYPE_PROBE and VFIO_GFX_PLANE_TYPE_DMABUF are set + * to ask if the mdev supports dma-buf. 0 on support, -EINVAL on no + * support for dma-buf. + * - VFIO_GFX_PLANE_TYPE_PROBE and VFIO_GFX_PLANE_TYPE_REGION are set + * to ask if the mdev supports region. 0 on support, -EINVAL on no + * support for region. + * - VFIO_GFX_PLANE_TYPE_DMABUF or VFIO_GFX_PLANE_TYPE_REGION is set + * with each call to query the plane info. + * - Others are invalid and return -EINVAL. + * + * Note: + * 1. Plane could be disabled by guest. In that case, success will be + * returned with zero-initialized drm_format, size, width and height + * fields. + * 2. x_hot/y_hot is set to 0xFFFFFFFF if no hotspot information available + * + * Return: 0 on success, -errno on other failure. + */ +struct vfio_device_gfx_plane_info { + __u32 argsz; + __u32 flags; +#define VFIO_GFX_PLANE_TYPE_PROBE (1 << 0) +#define VFIO_GFX_PLANE_TYPE_DMABUF (1 << 1) +#define VFIO_GFX_PLANE_TYPE_REGION (1 << 2) + /* in */ + __u32 drm_plane_type; /* type of plane: DRM_PLANE_TYPE_* */ + /* out */ + __u32 drm_format; /* drm format of plane */ + __u64 drm_format_mod; /* tiled mode */ + __u32 width; /* width of plane */ + __u32 height; /* height of plane */ + __u32 stride; /* stride of plane */ + __u32 size; /* size of plane in bytes, align on page*/ + __u32 x_pos; /* horizontal position of cursor plane */ + __u32 y_pos; /* vertical position of cursor plane*/ + __u32 x_hot; /* horizontal position of cursor hotspot */ + __u32 y_hot; /* vertical position of cursor hotspot */ + union { + __u32 region_index; /* region index */ + __u32 dmabuf_id; /* dma-buf id */ + }; +}; + +#define VFIO_DEVICE_QUERY_GFX_PLANE _IO(VFIO_TYPE, VFIO_BASE + 14) + +/** + * VFIO_DEVICE_GET_GFX_DMABUF - _IOW(VFIO_TYPE, VFIO_BASE + 15, __u32) + * + * Return a new dma-buf file descriptor for an exposed guest framebuffer + * described by the provided dmabuf_id. The dmabuf_id is returned from VFIO_ + * DEVICE_QUERY_GFX_PLANE as a token of the exposed guest framebuffer. + */ + +#define VFIO_DEVICE_GET_GFX_DMABUF _IO(VFIO_TYPE, VFIO_BASE + 15) + /* -------- API for Type1 VFIO IOMMU -------- */ /** @@ -983,6 +983,9 @@ static void qmp_unregister_commands_hack(void) #endif #ifndef TARGET_I386 qmp_unregister_command(&qmp_commands, "rtc-reset-reinjection"); + qmp_unregister_command(&qmp_commands, "query-sev"); + qmp_unregister_command(&qmp_commands, "query-sev-launch-measure"); + qmp_unregister_command(&qmp_commands, "query-sev-capabilities"); #endif #ifndef TARGET_S390X qmp_unregister_command(&qmp_commands, "dump-skeys"); @@ -4103,6 +4106,24 @@ void qmp_rtc_reset_reinjection(Error **errp) { error_setg(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection"); } + +SevInfo *qmp_query_sev(Error **errp) +{ + error_setg(errp, QERR_FEATURE_DISABLED, "query-sev"); + return NULL; +} + +SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp) +{ + error_setg(errp, QERR_FEATURE_DISABLED, "query-sev-launch-measure"); + return NULL; +} + +SevCapability *qmp_query_sev_capabilities(Error **errp) +{ + error_setg(errp, QERR_FEATURE_DISABLED, "query-sev-capabilities"); + return NULL; +} #endif #ifndef TARGET_S390X diff --git a/qapi/misc.json b/qapi/misc.json index bcd5d10778..6150b9a003 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -3216,3 +3216,151 @@ # Since: 2.9 ## { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' } + + +## +# @SevState: +# +# An enumeration of SEV state information used during @query-sev. +# +# @uninit: The guest is uninitialized. +# +# @launch-update: The guest is currently being launched; plaintext data and +# register state is being imported. +# +# @launch-secret: The guest is currently being launched; ciphertext data +# is being imported. +# +# @running: The guest is fully launched or migrated in. +# +# @send-update: The guest is currently being migrated out to another machine. +# +# @receive-update: The guest is currently being migrated from another machine. +# +# Since: 2.12 +## +{ 'enum': 'SevState', + 'data': ['uninit', 'launch-update', 'launch-secret', 'running', + 'send-update', 'receive-update' ] } + +## +# @SevInfo: +# +# Information about Secure Encrypted Virtualization (SEV) support +# +# @enabled: true if SEV is active +# +# @api-major: SEV API major version +# +# @api-minor: SEV API minor version +# +# @build-id: SEV FW build id +# +# @policy: SEV policy value +# +# @state: SEV guest state +# +# @handle: SEV firmware handle +# +# Since: 2.12 +## +{ 'struct': 'SevInfo', + 'data': { 'enabled': 'bool', + 'api-major': 'uint8', + 'api-minor' : 'uint8', + 'build-id' : 'uint8', + 'policy' : 'uint32', + 'state' : 'SevState', + 'handle' : 'uint32' + } +} + +## +# @query-sev: +# +# Returns information about SEV +# +# Returns: @SevInfo +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev" } +# <- { "return": { "enabled": true, "api-major" : 0, "api-minor" : 0, +# "build-id" : 0, "policy" : 0, "state" : "running", +# "handle" : 1 } } +# +## +{ 'command': 'query-sev', 'returns': 'SevInfo' } + +## +# @SevLaunchMeasureInfo: +# +# SEV Guest Launch measurement information +# +# @data: the measurement value encoded in base64 +# +# Since: 2.12 +# +## +{ 'struct': 'SevLaunchMeasureInfo', 'data': {'data': 'str'} } + +## +# @query-sev-launch-measure: +# +# Query the SEV guest launch information. +# +# Returns: The @SevLaunchMeasureInfo for the guest +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev-launch-measure" } +# <- { "return": { "data": "4l8LXeNlSPUDlXPJG5966/8%YZ" } } +# +## +{ 'command': 'query-sev-launch-measure', 'returns': 'SevLaunchMeasureInfo' } + +## +# @SevCapability: +# +# The struct describes capability for a Secure Encrypted Virtualization +# feature. +# +# @pdh: Platform Diffie-Hellman key (base64 encoded) +# +# @cert-chain: PDH certificate chain (base64 encoded) +# +# @cbitpos: C-bit location in page table entry +# +# @reduced-phys-bits: Number of physical Address bit reduction when SEV is +# enabled +# +# Since: 2.12 +## +{ 'struct': 'SevCapability', + 'data': { 'pdh': 'str', + 'cert-chain': 'str', + 'cbitpos': 'int', + 'reduced-phys-bits': 'int'} } + +## +# @query-sev-capabilities: +# +# This command is used to get the SEV capabilities, and is supported on AMD +# X86 platforms only. +# +# Returns: SevCapability objects. +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "query-sev-capabilities" } +# <- { "return": { "pdh": "8CCDD8DDD", "cert-chain": "888CCCDDDEE", +# "cbitpos": 47, "reduced-phys-bits": 5}} +# +## +{ 'command': 'query-sev-capabilities', 'returns': 'SevCapability' } diff --git a/qemu-options.hx b/qemu-options.hx index 6585058c6c..6113bce08a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -43,7 +43,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " suppress-vmdesc=on|off disables self-describing migration (default=off)\n" " nvdimm=on|off controls NVDIMM support (default=off)\n" " enforce-config-section=on|off enforce configuration section migration (default=off)\n" - " s390-squash-mcss=on|off (deprecated) controls support for squashing into default css (default=off)\n", + " s390-squash-mcss=on|off (deprecated) controls support for squashing into default css (default=off)\n" + " memory-encryption=@var{} memory encryption object to use (default=none)\n", QEMU_ARCH_ALL) STEXI @item -machine [type=]@var{name}[,prop=@var{value}[,...]] @@ -110,6 +111,8 @@ code to send configuration section even if the machine-type sets the @option{migration.send-configuration} property to @var{off}. NOTE: this parameter is deprecated. Please use @option{-global} @option{migration.send-configuration}=@var{on|off} instead. +@item memory-encryption=@var{} +Memory encryption object to use. The default is none. @end table ETEXI @@ -4350,6 +4353,50 @@ contents of @code{iv.b64} to the second secret data=$SECRET,iv=$(<iv.b64) @end example +@item -object sev-guest,id=@var{id},cbitpos=@var{cbitpos},reduced-phys-bits=@var{val},[sev-device=@var{string},policy=@var{policy},handle=@var{handle},dh-cert-file=@var{file},session-file=@var{file}] + +Create a Secure Encrypted Virtualization (SEV) guest object, which can be used +to provide the guest memory encryption support on AMD processors. + +When memory encryption is enabled, one of the physical address bit (aka the +C-bit) is utilized to mark if a memory page is protected. The @option{cbitpos} +is used to provide the C-bit position. The C-bit position is Host family dependent +hence user must provide this value. On EPYC, the value should be 47. + +When memory encryption is enabled, we loose certain bits in physical address space. +The @option{reduced-phys-bits} is used to provide the number of bits we loose in +physical address space. Similar to C-bit, the value is Host family dependent. +On EPYC, the value should be 5. + +The @option{sev-device} provides the device file to use for communicating with +the SEV firmware running inside AMD Secure Processor. The default device is +'/dev/sev'. If hardware supports memory encryption then /dev/sev devices are +created by CCP driver. + +The @option{policy} provides the guest policy to be enforced by the SEV firmware +and restrict what configuration and operational commands can be performed on this +guest by the hypervisor. The policy should be provided by the guest owner and is +bound to the guest and cannot be changed throughout the lifetime of the guest. +The default is 0. + +If guest @option{policy} allows sharing the key with another SEV guest then +@option{handle} can be use to provide handle of the guest from which to share +the key. + +The @option{dh-cert-file} and @option{session-file} provides the guest owner's +Public Diffie-Hillman key defined in SEV spec. The PDH and session parameters +are used for establishing a cryptographic session with the guest owner to +negotiate keys used for attestation. The file must be encoded in base64. + +e.g to launch a SEV guest +@example + # $QEMU \ + ...... + -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 \ + -machine ...,memory-encryption=sev0 + ..... + +@end example @end table ETEXI diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index be065704df..e152417936 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -56,6 +56,7 @@ cp_portable() { -e 's/__bitwise//' \ -e 's/__attribute__((packed))/QEMU_PACKED/' \ -e 's/__inline__/inline/' \ + -e 's/__BITS_PER_LONG/HOST_LONG_BITS/' \ -e '/sys\/ioctl.h/d' \ -e 's/SW_MAX/SW_MAX_/' \ -e 's/atomic_t/int/' \ @@ -99,6 +100,8 @@ for arch in $ARCHLIST; do mkdir -p "$output/include/standard-headers/asm-$arch" if [ $arch = s390 ]; then cp_portable "$tmpdir/include/asm/virtio-ccw.h" "$output/include/standard-headers/asm-s390/" + cp "$tmpdir/include/asm/unistd_32.h" "$output/linux-headers/asm-s390/" + cp "$tmpdir/include/asm/unistd_64.h" "$output/linux-headers/asm-s390/" fi if [ $arch = arm ]; then cp "$tmpdir/include/asm/unistd-eabi.h" "$output/linux-headers/asm-arm/" @@ -118,7 +121,7 @@ done rm -rf "$output/linux-headers/linux" mkdir -p "$output/linux-headers/linux" for header in kvm.h kvm_para.h vfio.h vfio_ccw.h vhost.h \ - psci.h userfaultfd.h; do + psci.h psp-sev.h userfaultfd.h; do cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux" done rm -rf "$output/linux-headers/asm-generic" diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs index f5c6ef20a7..04678f5503 100644 --- a/target/i386/Makefile.objs +++ b/target/i386/Makefile.objs @@ -5,7 +5,9 @@ obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o mpx_helper.o obj-$(CONFIG_TCG) += seg_helper.o smm_helper.o svm_helper.o obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o monitor.o obj-$(CONFIG_KVM) += kvm.o hyperv.o +obj-$(CONFIG_SEV) += sev.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o +obj-$(call lnot,$(CONFIG_SEV)) += sev-stub.o # HAX support ifdef CONFIG_WIN32 obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-windows.o diff --git a/target/i386/cpu.c b/target/i386/cpu.c index ec1efd3a3c..6bb4ce8719 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -26,6 +26,7 @@ #include "sysemu/hvf.h" #include "sysemu/cpus.h" #include "kvm_i386.h" +#include "sev_i386.h" #include "qemu/error-report.h" #include "qemu/option.h" @@ -3672,6 +3673,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx = 0; *edx = 0; break; + case 0x8000001F: + *eax = sev_enabled() ? 0x2 : 0; + *ebx = sev_get_cbit_position(); + *ebx |= sev_get_reduced_phys_bits() << 6; + *ecx = 0; + *edx = 0; + break; default: /* reserved values: zero */ *eax = 0; @@ -3705,6 +3713,7 @@ static void x86_cpu_reset(CPUState *s) cpu_x86_update_cr0(env, 0x60000010); env->a20_mask = ~0x0; env->smbase = 0x30000; + env->msr_smi_count = 0; env->idt.limit = 0xffff; env->gdt.limit = 0xffff; @@ -4101,6 +4110,11 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000000A); } + + /* SEV requires CPUID[0x8000001F] */ + if (sev_enabled()) { + x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel, 0x8000001F); + } } /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */ diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 0c3f51445e..2e2bab5ff3 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1,3 +1,4 @@ + /* * i386 virtual CPU header * @@ -359,6 +360,7 @@ typedef enum X86Seg { #define MSR_P6_PERFCTR0 0xc1 #define MSR_IA32_SMBASE 0x9e +#define MSR_SMI_COUNT 0x34 #define MSR_MTRRcap 0xfe #define MSR_MTRRcap_VCNT 8 #define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8) @@ -1142,6 +1144,7 @@ typedef struct CPUX86State { uint64_t pat; uint32_t smbase; + uint64_t msr_smi_count; uint32_t pkru; diff --git a/target/i386/kvm.c b/target/i386/kvm.c index d996cca68b..d23fff12f5 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -92,6 +92,7 @@ static bool has_msr_hv_stimer; static bool has_msr_hv_frequencies; static bool has_msr_xss; static bool has_msr_spec_ctrl; +static bool has_msr_smi_count; static uint32_t has_architectural_pmu_version; static uint32_t num_architectural_pmu_gp_counters; @@ -1151,6 +1152,9 @@ static int kvm_get_supported_msrs(KVMState *s) case MSR_IA32_SMBASE: has_msr_smbase = true; break; + case MSR_SMI_COUNT: + has_msr_smi_count = true; + break; case MSR_IA32_MISC_ENABLE: has_msr_misc_enable = true; break; @@ -1660,6 +1664,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) if (has_msr_smbase) { kvm_msr_entry_add(cpu, MSR_IA32_SMBASE, env->smbase); } + if (has_msr_smi_count) { + kvm_msr_entry_add(cpu, MSR_SMI_COUNT, env->msr_smi_count); + } if (has_msr_bndcfgs) { kvm_msr_entry_add(cpu, MSR_IA32_BNDCFGS, env->msr_bndcfgs); } @@ -2025,6 +2032,9 @@ static int kvm_get_msrs(X86CPU *cpu) if (has_msr_smbase) { kvm_msr_entry_add(cpu, MSR_IA32_SMBASE, 0); } + if (has_msr_smi_count) { + kvm_msr_entry_add(cpu, MSR_SMI_COUNT, 0); + } if (has_msr_feature_control) { kvm_msr_entry_add(cpu, MSR_IA32_FEATURE_CONTROL, 0); } @@ -2265,6 +2275,9 @@ static int kvm_get_msrs(X86CPU *cpu) case MSR_IA32_SMBASE: env->smbase = msrs[i].data; break; + case MSR_SMI_COUNT: + env->msr_smi_count = msrs[i].data; + break; case MSR_IA32_FEATURE_CONTROL: env->msr_ia32_feature_control = msrs[i].data; break; diff --git a/target/i386/machine.c b/target/i386/machine.c index c05fe6fb1a..bd2d82e91b 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -395,6 +395,25 @@ static const VMStateDescription vmstate_msr_tsc_adjust = { } }; +static bool msr_smi_count_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return env->msr_smi_count != 0; +} + +static const VMStateDescription vmstate_msr_smi_count = { + .name = "cpu/msr_smi_count", + .version_id = 1, + .minimum_version_id = 1, + .needed = msr_smi_count_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT64(env.msr_smi_count, X86CPU), + VMSTATE_END_OF_LIST() + } +}; + static bool tscdeadline_needed(void *opaque) { X86CPU *cpu = opaque; @@ -989,6 +1008,7 @@ VMStateDescription vmstate_x86_cpu = { &vmstate_avx512, &vmstate_xss, &vmstate_tsc_khz, + &vmstate_msr_smi_count, #ifdef TARGET_X86_64 &vmstate_pkru, #endif diff --git a/target/i386/monitor.c b/target/i386/monitor.c index 75429129fd..011419eba2 100644 --- a/target/i386/monitor.c +++ b/target/i386/monitor.c @@ -29,7 +29,11 @@ #include "qapi/qmp/qdict.h" #include "hw/i386/pc.h" #include "sysemu/kvm.h" +#include "sysemu/sev.h" #include "hmp.h" +#include "qapi/error.h" +#include "sev_i386.h" +#include "qapi/qapi-commands-misc.h" static void print_pte(Monitor *mon, CPUArchState *env, hwaddr addr, @@ -661,3 +665,65 @@ void hmp_info_io_apic(Monitor *mon, const QDict *qdict) ioapic_dump_state(mon, qdict); } } + +SevInfo *qmp_query_sev(Error **errp) +{ + SevInfo *info; + + info = sev_get_info(); + if (!info) { + error_setg(errp, "SEV feature is not available"); + return NULL; + } + + return info; +} + +void hmp_info_sev(Monitor *mon, const QDict *qdict) +{ + SevInfo *info = sev_get_info(); + + if (info && info->enabled) { + monitor_printf(mon, "handle: %d\n", info->handle); + monitor_printf(mon, "state: %s\n", SevState_str(info->state)); + monitor_printf(mon, "build: %d\n", info->build_id); + monitor_printf(mon, "api version: %d.%d\n", + info->api_major, info->api_minor); + monitor_printf(mon, "debug: %s\n", + info->policy & SEV_POLICY_NODBG ? "off" : "on"); + monitor_printf(mon, "key-sharing: %s\n", + info->policy & SEV_POLICY_NOKS ? "off" : "on"); + } else { + monitor_printf(mon, "SEV is not enabled\n"); + } +} + +SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp) +{ + char *data; + SevLaunchMeasureInfo *info; + + data = sev_get_launch_measurement(); + if (!data) { + error_setg(errp, "Measurement is not available"); + return NULL; + } + + info = g_malloc0(sizeof(*info)); + info->data = data; + + return info; +} + +SevCapability *qmp_query_sev_capabilities(Error **errp) +{ + SevCapability *data; + + data = sev_get_capabilities(); + if (!data) { + error_setg(errp, "SEV feature is not available"); + return NULL; + } + + return data; +} diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c new file mode 100644 index 0000000000..59a003a4eb --- /dev/null +++ b/target/i386/sev-stub.c @@ -0,0 +1,51 @@ +/* + * QEMU SEV stub + * + * Copyright Advanced Micro Devices 2018 + * + * Authors: + * Brijesh Singh <brijesh.singh@amd.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "sev_i386.h" + +SevInfo *sev_get_info(void) +{ + return NULL; +} + +bool sev_enabled(void) +{ + return false; +} + +uint64_t sev_get_me_mask(void) +{ + return ~0; +} + +uint32_t sev_get_cbit_position(void) +{ + return 0; +} + +uint32_t sev_get_reduced_phys_bits(void) +{ + return 0; +} + +char *sev_get_launch_measurement(void) +{ + return NULL; +} + +SevCapability *sev_get_capabilities(void) +{ + return NULL; +} diff --git a/target/i386/sev.c b/target/i386/sev.c new file mode 100644 index 0000000000..019d84cef2 --- /dev/null +++ b/target/i386/sev.c @@ -0,0 +1,811 @@ +/* + * QEMU SEV support + * + * Copyright Advanced Micro Devices 2016-2018 + * + * Author: + * Brijesh Singh <brijesh.singh@amd.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include <linux/kvm.h> +#include <linux/psp-sev.h> + +#include <sys/ioctl.h> + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qom/object_interfaces.h" +#include "qemu/base64.h" +#include "sysemu/kvm.h" +#include "sev_i386.h" +#include "sysemu/sysemu.h" +#include "trace.h" +#include "migration/blocker.h" + +#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */ +#define DEFAULT_SEV_DEVICE "/dev/sev" + +static SEVState *sev_state; +static Error *sev_mig_blocker; + +static const char *const sev_fw_errlist[] = { + "", + "Platform state is invalid", + "Guest state is invalid", + "Platform configuration is invalid", + "Buffer too small", + "Platform is already owned", + "Certificate is invalid", + "Policy is not allowed", + "Guest is not active", + "Invalid address", + "Bad signature", + "Bad measurement", + "Asid is already owned", + "Invalid ASID", + "WBINVD is required", + "DF_FLUSH is required", + "Guest handle is invalid", + "Invalid command", + "Guest is active", + "Hardware error", + "Hardware unsafe", + "Feature not supported", + "Invalid parameter" +}; + +#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist) + +static int +sev_ioctl(int fd, int cmd, void *data, int *error) +{ + int r; + struct kvm_sev_cmd input; + + memset(&input, 0x0, sizeof(input)); + + input.id = cmd; + input.sev_fd = fd; + input.data = (__u64)(unsigned long)data; + + r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input); + + if (error) { + *error = input.error; + } + + return r; +} + +static int +sev_platform_ioctl(int fd, int cmd, void *data, int *error) +{ + int r; + struct sev_issue_cmd arg; + + arg.cmd = cmd; + arg.data = (unsigned long)data; + r = ioctl(fd, SEV_ISSUE_CMD, &arg); + if (error) { + *error = arg.error; + } + + return r; +} + +static const char * +fw_error_to_str(int code) +{ + if (code < 0 || code >= SEV_FW_MAX_ERROR) { + return "unknown error"; + } + + return sev_fw_errlist[code]; +} + +static bool +sev_check_state(SevState state) +{ + assert(sev_state); + return sev_state->state == state ? true : false; +} + +static void +sev_set_guest_state(SevState new_state) +{ + assert(new_state < SEV_STATE__MAX); + assert(sev_state); + + trace_kvm_sev_change_state(SevState_str(sev_state->state), + SevState_str(new_state)); + sev_state->state = new_state; +} + +static void +sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) +{ + int r; + struct kvm_enc_region range; + + range.addr = (__u64)(unsigned long)host; + range.size = size; + + trace_kvm_memcrypt_register_region(host, size); + r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range); + if (r) { + error_report("%s: failed to register region (%p+%#zx) error '%s'", + __func__, host, size, strerror(errno)); + exit(1); + } +} + +static void +sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size) +{ + int r; + struct kvm_enc_region range; + + range.addr = (__u64)(unsigned long)host; + range.size = size; + + trace_kvm_memcrypt_unregister_region(host, size); + r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range); + if (r) { + error_report("%s: failed to unregister region (%p+%#zx)", + __func__, host, size); + } +} + +static struct RAMBlockNotifier sev_ram_notifier = { + .ram_block_added = sev_ram_block_added, + .ram_block_removed = sev_ram_block_removed, +}; + +static void +qsev_guest_finalize(Object *obj) +{ +} + +static char * +qsev_guest_get_session_file(Object *obj, Error **errp) +{ + QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + + return s->session_file ? g_strdup(s->session_file) : NULL; +} + +static void +qsev_guest_set_session_file(Object *obj, const char *value, Error **errp) +{ + QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + + s->session_file = g_strdup(value); +} + +static char * +qsev_guest_get_dh_cert_file(Object *obj, Error **errp) +{ + QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + + return g_strdup(s->dh_cert_file); +} + +static void +qsev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp) +{ + QSevGuestInfo *s = QSEV_GUEST_INFO(obj); + + s->dh_cert_file = g_strdup(value); +} + +static char * +qsev_guest_get_sev_device(Object *obj, Error **errp) +{ + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + + return g_strdup(sev->sev_device); +} + +static void +qsev_guest_set_sev_device(Object *obj, const char *value, Error **errp) +{ + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + + sev->sev_device = g_strdup(value); +} + +static void +qsev_guest_class_init(ObjectClass *oc, void *data) +{ + object_class_property_add_str(oc, "sev-device", + qsev_guest_get_sev_device, + qsev_guest_set_sev_device, + NULL); + object_class_property_set_description(oc, "sev-device", + "SEV device to use", NULL); + object_class_property_add_str(oc, "dh-cert-file", + qsev_guest_get_dh_cert_file, + qsev_guest_set_dh_cert_file, + NULL); + object_class_property_set_description(oc, "dh-cert-file", + "guest owners DH certificate (encoded with base64)", NULL); + object_class_property_add_str(oc, "session-file", + qsev_guest_get_session_file, + qsev_guest_set_session_file, + NULL); + object_class_property_set_description(oc, "session-file", + "guest owners session parameters (encoded with base64)", NULL); +} + +static void +qsev_guest_set_handle(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + uint32_t value; + + visit_type_uint32(v, name, &value, errp); + sev->handle = value; +} + +static void +qsev_guest_set_policy(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + uint32_t value; + + visit_type_uint32(v, name, &value, errp); + sev->policy = value; +} + +static void +qsev_guest_set_cbitpos(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + uint32_t value; + + visit_type_uint32(v, name, &value, errp); + sev->cbitpos = value; +} + +static void +qsev_guest_set_reduced_phys_bits(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + uint32_t value; + + visit_type_uint32(v, name, &value, errp); + sev->reduced_phys_bits = value; +} + +static void +qsev_guest_get_policy(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint32_t value; + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + + value = sev->policy; + visit_type_uint32(v, name, &value, errp); +} + +static void +qsev_guest_get_handle(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint32_t value; + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + + value = sev->handle; + visit_type_uint32(v, name, &value, errp); +} + +static void +qsev_guest_get_cbitpos(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint32_t value; + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + + value = sev->cbitpos; + visit_type_uint32(v, name, &value, errp); +} + +static void +qsev_guest_get_reduced_phys_bits(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint32_t value; + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + + value = sev->reduced_phys_bits; + visit_type_uint32(v, name, &value, errp); +} + +static void +qsev_guest_init(Object *obj) +{ + QSevGuestInfo *sev = QSEV_GUEST_INFO(obj); + + sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE); + sev->policy = DEFAULT_GUEST_POLICY; + object_property_add(obj, "policy", "uint32", qsev_guest_get_policy, + qsev_guest_set_policy, NULL, NULL, NULL); + object_property_add(obj, "handle", "uint32", qsev_guest_get_handle, + qsev_guest_set_handle, NULL, NULL, NULL); + object_property_add(obj, "cbitpos", "uint32", qsev_guest_get_cbitpos, + qsev_guest_set_cbitpos, NULL, NULL, NULL); + object_property_add(obj, "reduced-phys-bits", "uint32", + qsev_guest_get_reduced_phys_bits, + qsev_guest_set_reduced_phys_bits, NULL, NULL, NULL); +} + +/* sev guest info */ +static const TypeInfo qsev_guest_info = { + .parent = TYPE_OBJECT, + .name = TYPE_QSEV_GUEST_INFO, + .instance_size = sizeof(QSevGuestInfo), + .instance_finalize = qsev_guest_finalize, + .class_size = sizeof(QSevGuestInfoClass), + .class_init = qsev_guest_class_init, + .instance_init = qsev_guest_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } +}; + +static QSevGuestInfo * +lookup_sev_guest_info(const char *id) +{ + Object *obj; + QSevGuestInfo *info; + + obj = object_resolve_path_component(object_get_objects_root(), id); + if (!obj) { + return NULL; + } + + info = (QSevGuestInfo *) + object_dynamic_cast(obj, TYPE_QSEV_GUEST_INFO); + if (!info) { + return NULL; + } + + return info; +} + +bool +sev_enabled(void) +{ + return sev_state ? true : false; +} + +uint64_t +sev_get_me_mask(void) +{ + return sev_state ? sev_state->me_mask : ~0; +} + +uint32_t +sev_get_cbit_position(void) +{ + return sev_state ? sev_state->cbitpos : 0; +} + +uint32_t +sev_get_reduced_phys_bits(void) +{ + return sev_state ? sev_state->reduced_phys_bits : 0; +} + +SevInfo * +sev_get_info(void) +{ + SevInfo *info; + + info = g_new0(SevInfo, 1); + info->enabled = sev_state ? true : false; + + if (info->enabled) { + info->api_major = sev_state->api_major; + info->api_minor = sev_state->api_minor; + info->build_id = sev_state->build_id; + info->policy = sev_state->policy; + info->state = sev_state->state; + info->handle = sev_state->handle; + } + + return info; +} + +static int +sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain, + size_t *cert_chain_len) +{ + guchar *pdh_data, *cert_chain_data; + struct sev_user_data_pdh_cert_export export = {}; + int err, r; + + /* query the certificate length */ + r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err); + if (r < 0) { + if (err != SEV_RET_INVALID_LEN) { + error_report("failed to export PDH cert ret=%d fw_err=%d (%s)", + r, err, fw_error_to_str(err)); + return 1; + } + } + + pdh_data = g_new(guchar, export.pdh_cert_len); + cert_chain_data = g_new(guchar, export.cert_chain_len); + export.pdh_cert_address = (unsigned long)pdh_data; + export.cert_chain_address = (unsigned long)cert_chain_data; + + r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err); + if (r < 0) { + error_report("failed to export PDH cert ret=%d fw_err=%d (%s)", + r, err, fw_error_to_str(err)); + goto e_free; + } + + *pdh = pdh_data; + *pdh_len = export.pdh_cert_len; + *cert_chain = cert_chain_data; + *cert_chain_len = export.cert_chain_len; + return 0; + +e_free: + g_free(pdh_data); + g_free(cert_chain_data); + return 1; +} + +SevCapability * +sev_get_capabilities(void) +{ + SevCapability *cap; + guchar *pdh_data, *cert_chain_data; + size_t pdh_len = 0, cert_chain_len = 0; + uint32_t ebx; + int fd; + + fd = open(DEFAULT_SEV_DEVICE, O_RDWR); + if (fd < 0) { + error_report("%s: Failed to open %s '%s'", __func__, + DEFAULT_SEV_DEVICE, strerror(errno)); + return NULL; + } + + if (sev_get_pdh_info(fd, &pdh_data, &pdh_len, + &cert_chain_data, &cert_chain_len)) { + return NULL; + } + + cap = g_new0(SevCapability, 1); + cap->pdh = g_base64_encode(pdh_data, pdh_len); + cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len); + + host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL); + cap->cbitpos = ebx & 0x3f; + + /* + * When SEV feature is enabled, we loose one bit in guest physical + * addressing. + */ + cap->reduced_phys_bits = 1; + + g_free(pdh_data); + g_free(cert_chain_data); + + close(fd); + return cap; +} + +static int +sev_read_file_base64(const char *filename, guchar **data, gsize *len) +{ + gsize sz; + gchar *base64; + GError *error = NULL; + + if (!g_file_get_contents(filename, &base64, &sz, &error)) { + error_report("failed to read '%s' (%s)", filename, error->message); + return -1; + } + + *data = g_base64_decode(base64, len); + return 0; +} + +static int +sev_launch_start(SEVState *s) +{ + gsize sz; + int ret = 1; + int fw_error; + QSevGuestInfo *sev = s->sev_info; + struct kvm_sev_launch_start *start; + guchar *session = NULL, *dh_cert = NULL; + + start = g_new0(struct kvm_sev_launch_start, 1); + + start->handle = object_property_get_int(OBJECT(sev), "handle", + &error_abort); + start->policy = object_property_get_int(OBJECT(sev), "policy", + &error_abort); + if (sev->session_file) { + if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) { + return 1; + } + start->session_uaddr = (unsigned long)session; + start->session_len = sz; + } + + if (sev->dh_cert_file) { + if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) { + return 1; + } + start->dh_uaddr = (unsigned long)dh_cert; + start->dh_len = sz; + } + + trace_kvm_sev_launch_start(start->policy, session, dh_cert); + ret = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error); + if (ret < 0) { + error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'", + __func__, ret, fw_error, fw_error_to_str(fw_error)); + return 1; + } + + object_property_set_int(OBJECT(sev), start->handle, "handle", + &error_abort); + sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE); + s->handle = start->handle; + s->policy = start->policy; + + g_free(start); + g_free(session); + g_free(dh_cert); + + return 0; +} + +static int +sev_launch_update_data(uint8_t *addr, uint64_t len) +{ + int ret, fw_error; + struct kvm_sev_launch_update_data update; + + if (!addr || !len) { + return 1; + } + + update.uaddr = (__u64)(unsigned long)addr; + update.len = len; + trace_kvm_sev_launch_update_data(addr, len); + ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA, + &update, &fw_error); + if (ret) { + error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'", + __func__, ret, fw_error, fw_error_to_str(fw_error)); + } + + return ret; +} + +static void +sev_launch_get_measure(Notifier *notifier, void *unused) +{ + int ret, error; + guchar *data; + SEVState *s = sev_state; + struct kvm_sev_launch_measure *measurement; + + if (!sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { + return; + } + + measurement = g_new0(struct kvm_sev_launch_measure, 1); + + /* query the measurement blob length */ + ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, + measurement, &error); + if (!measurement->len) { + error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", + __func__, ret, error, fw_error_to_str(errno)); + goto free_measurement; + } + + data = g_new0(guchar, measurement->len); + measurement->uaddr = (unsigned long)data; + + /* get the measurement blob */ + ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_MEASURE, + measurement, &error); + if (ret) { + error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'", + __func__, ret, error, fw_error_to_str(errno)); + goto free_data; + } + + sev_set_guest_state(SEV_STATE_LAUNCH_SECRET); + + /* encode the measurement value and emit the event */ + s->measurement = g_base64_encode(data, measurement->len); + trace_kvm_sev_launch_measurement(s->measurement); + +free_data: + g_free(data); +free_measurement: + g_free(measurement); +} + +char * +sev_get_launch_measurement(void) +{ + if (sev_state && + sev_state->state >= SEV_STATE_LAUNCH_SECRET) { + return g_strdup(sev_state->measurement); + } + + return NULL; +} + +static Notifier sev_machine_done_notify = { + .notify = sev_launch_get_measure, +}; + +static void +sev_launch_finish(SEVState *s) +{ + int ret, error; + Error *local_err = NULL; + + trace_kvm_sev_launch_finish(); + ret = sev_ioctl(sev_state->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error); + if (ret) { + error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'", + __func__, ret, error, fw_error_to_str(error)); + exit(1); + } + + sev_set_guest_state(SEV_STATE_RUNNING); + + /* add migration blocker */ + error_setg(&sev_mig_blocker, + "SEV: Migration is not implemented"); + ret = migrate_add_blocker(sev_mig_blocker, &local_err); + if (local_err) { + error_report_err(local_err); + error_free(sev_mig_blocker); + exit(1); + } +} + +static void +sev_vm_state_change(void *opaque, int running, RunState state) +{ + SEVState *s = opaque; + + if (running) { + if (!sev_check_state(SEV_STATE_RUNNING)) { + sev_launch_finish(s); + } + } +} + +void * +sev_guest_init(const char *id) +{ + SEVState *s; + char *devname; + int ret, fw_error; + uint32_t ebx; + uint32_t host_cbitpos; + struct sev_user_data_status status = {}; + + s = g_new0(SEVState, 1); + s->sev_info = lookup_sev_guest_info(id); + if (!s->sev_info) { + error_report("%s: '%s' is not a valid '%s' object", + __func__, id, TYPE_QSEV_GUEST_INFO); + goto err; + } + + sev_state = s; + s->state = SEV_STATE_UNINIT; + + host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL); + host_cbitpos = ebx & 0x3f; + + s->cbitpos = object_property_get_int(OBJECT(s->sev_info), "cbitpos", NULL); + if (host_cbitpos != s->cbitpos) { + error_report("%s: cbitpos check failed, host '%d' requested '%d'", + __func__, host_cbitpos, s->cbitpos); + goto err; + } + + s->reduced_phys_bits = object_property_get_int(OBJECT(s->sev_info), + "reduced-phys-bits", NULL); + if (s->reduced_phys_bits < 1) { + error_report("%s: reduced_phys_bits check failed, it should be >=1," + "' requested '%d'", __func__, s->reduced_phys_bits); + goto err; + } + + s->me_mask = ~(1UL << s->cbitpos); + + devname = object_property_get_str(OBJECT(s->sev_info), "sev-device", NULL); + s->sev_fd = open(devname, O_RDWR); + if (s->sev_fd < 0) { + error_report("%s: Failed to open %s '%s'", __func__, + devname, strerror(errno)); + goto err; + } + g_free(devname); + + ret = sev_platform_ioctl(s->sev_fd, SEV_PLATFORM_STATUS, &status, + &fw_error); + if (ret) { + error_report("%s: failed to get platform status ret=%d" + "fw_error='%d: %s'", __func__, ret, fw_error, + fw_error_to_str(fw_error)); + goto err; + } + s->build_id = status.build; + s->api_major = status.api_major; + s->api_minor = status.api_minor; + + trace_kvm_sev_init(); + ret = sev_ioctl(s->sev_fd, KVM_SEV_INIT, NULL, &fw_error); + if (ret) { + error_report("%s: failed to initialize ret=%d fw_error=%d '%s'", + __func__, ret, fw_error, fw_error_to_str(fw_error)); + goto err; + } + + ret = sev_launch_start(s); + if (ret) { + error_report("%s: failed to create encryption context", __func__); + goto err; + } + + ram_block_notifier_add(&sev_ram_notifier); + qemu_add_machine_init_done_notifier(&sev_machine_done_notify); + qemu_add_vm_change_state_handler(sev_vm_state_change, s); + + return s; +err: + g_free(sev_state); + sev_state = NULL; + return NULL; +} + +int +sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len) +{ + assert(handle); + + /* if SEV is in update state then encrypt the data else do nothing */ + if (sev_check_state(SEV_STATE_LAUNCH_UPDATE)) { + return sev_launch_update_data(ptr, len); + } + + return 0; +} + +static void +sev_register_types(void) +{ + type_register_static(&qsev_guest_info); +} + +type_init(sev_register_types); diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h new file mode 100644 index 0000000000..b8622dfb1e --- /dev/null +++ b/target/i386/sev_i386.h @@ -0,0 +1,88 @@ +/* + * QEMU Secure Encrypted Virutualization (SEV) support + * + * Copyright: Advanced Micro Devices, 2016-2018 + * + * Authors: + * Brijesh Singh <brijesh.singh@amd.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_SEV_I386_H +#define QEMU_SEV_I386_H + +#include "qom/object.h" +#include "qapi/error.h" +#include "sysemu/kvm.h" +#include "sysemu/sev.h" +#include "qemu/error-report.h" +#include "qapi/qapi-commands-misc.h" + +#define SEV_POLICY_NODBG 0x1 +#define SEV_POLICY_NOKS 0x2 +#define SEV_POLICY_ES 0x4 +#define SEV_POLICY_NOSEND 0x8 +#define SEV_POLICY_DOMAIN 0x10 +#define SEV_POLICY_SEV 0x20 + +#define TYPE_QSEV_GUEST_INFO "sev-guest" +#define QSEV_GUEST_INFO(obj) \ + OBJECT_CHECK(QSevGuestInfo, (obj), TYPE_QSEV_GUEST_INFO) + +extern bool sev_enabled(void); +extern uint64_t sev_get_me_mask(void); +extern SevInfo *sev_get_info(void); +extern uint32_t sev_get_cbit_position(void); +extern uint32_t sev_get_reduced_phys_bits(void); +extern char *sev_get_launch_measurement(void); +extern SevCapability *sev_get_capabilities(void); + +typedef struct QSevGuestInfo QSevGuestInfo; +typedef struct QSevGuestInfoClass QSevGuestInfoClass; + +/** + * QSevGuestInfo: + * + * The QSevGuestInfo object is used for creating a SEV guest. + * + * # $QEMU \ + * -object sev-guest,id=sev0 \ + * -machine ...,memory-encryption=sev0 + */ +struct QSevGuestInfo { + Object parent_obj; + + char *sev_device; + uint32_t policy; + uint32_t handle; + char *dh_cert_file; + char *session_file; + uint32_t cbitpos; + uint32_t reduced_phys_bits; +}; + +struct QSevGuestInfoClass { + ObjectClass parent_class; +}; + +struct SEVState { + QSevGuestInfo *sev_info; + uint8_t api_major; + uint8_t api_minor; + uint8_t build_id; + uint32_t policy; + uint64_t me_mask; + uint32_t cbitpos; + uint32_t reduced_phys_bits; + uint32_t handle; + int sev_fd; + SevState state; + gchar *measurement; +}; + +typedef struct SEVState SEVState; + +#endif diff --git a/target/i386/trace-events b/target/i386/trace-events index 3153fd4454..6a19a69af5 100644 --- a/target/i386/trace-events +++ b/target/i386/trace-events @@ -5,3 +5,13 @@ kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %" kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d" kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d" kvm_x86_update_msi_routes(int num) "Updated %d MSI routes" + +# target/i386/sev.c +kvm_sev_init(void) "" +kvm_memcrypt_register_region(void *addr, size_t len) "addr %p len 0x%zu" +kvm_memcrypt_unregister_region(void *addr, size_t len) "addr %p len 0x%zu" +kvm_sev_change_state(const char *old, const char *new) "%s -> %s" +kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p" +kvm_sev_launch_update_data(void *addr, uint64_t len) "addr %p len 0x%" PRIu64 +kvm_sev_launch_measurement(const char *value) "data %s" +kvm_sev_launch_finish(void) "" diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 22445d9ec2..7470c6b754 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -204,6 +204,11 @@ static bool query_is_blacklisted(const char *cmd) "query-gic-capabilities", /* arm */ /* Success depends on target-specific build configuration: */ "query-pci", /* CONFIG_PCI */ + /* Success depends on launching SEV guest */ + "query-sev-launch-measure", + /* Success depends on Host or Hypervisor SEV support */ + "query-sev", + "query-sev-capabilities", NULL }; int i; |