initial import

internal commit: 14ac2bc2299032fa6714d1fefa7cf0987b3e3085

Signed-off-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Eddie Dong
2018-03-07 20:57:14 +08:00
committed by lijinxia
parent bd31b1c53e
commit 7a3a539b17
156 changed files with 41265 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GUEST_H
#define GUEST_H
/* Defines for VM Launch and Resume */
#define VM_RESUME 0
#define VM_LAUNCH 1
#define ACRN_DBG_PTIRQ 6
#define ACRN_DBG_IRQ 6
#ifndef ASSEMBLER
#define foreach_vcpu(idx, vm, vcpu) \
for (idx = 0, vcpu = vm->hw.vcpu_array[idx]; \
(idx < vm->hw.num_vcpus) & (vcpu != NULL); \
idx++, vcpu = vm->hw.vcpu_array[idx])
struct vhm_request;
/*
* VCPU related APIs
*/
#define ACRN_REQUEST_EVENT 0
#define ACRN_REQUEST_EXTINT 1
#define ACRN_REQUEST_NMI 2
#define ACRN_REQUEST_GP 3
#define ACRN_REQUEST_TMR_UPDATE 4
#define ACRN_REQUEST_TLB_FLUSH 5
#define E820_MAX_ENTRIES 32
struct e820_mem_params {
uint64_t mem_bottom;
uint64_t mem_top;
uint64_t max_ram_blk_base; /* used for the start address of UOS */
uint64_t max_ram_blk_size;
};
int prepare_vm0_memmap_and_e820(struct vm *vm);
/* Definition for a mem map lookup */
struct vm_lu_mem_map {
struct list_head list; /* EPT mem map lookup list*/
void *hpa; /* Host physical start address of the map*/
void *gpa; /* Guest physical start address of the map */
uint64_t size; /* Size of map */
};
/*
* VM related APIs
*/
bool is_vm0(struct vm *vm);
bool vm_lapic_disabled(struct vm *vm);
uint64_t vcpumask2pcpumask(struct vm *vm, uint64_t vdmask);
int init_vm0_boot_info(struct vm *vm);
uint64_t gva2gpa(struct vm *vm, uint64_t cr3, uint64_t gva);
struct vcpu *get_primary_vcpu(struct vm *vm);
struct vcpu *vcpu_from_vid(struct vm *vm, int vcpu_id);
struct vcpu *vcpu_from_pid(struct vm *vm, int pcpu_id);
void init_e820(void);
void obtain_e820_mem_info(void);
extern uint32_t e820_entries;
extern struct e820_entry e820[E820_MAX_ENTRIES];
extern uint32_t boot_regs[];
extern struct e820_mem_params e820_mem;
int rdmsr_handler(struct vcpu *vcpu);
int wrmsr_handler(struct vcpu *vcpu);
void init_msr_emulation(struct vcpu *vcpu);
extern const char vm_exit[];
int vmx_vmrun(struct run_context *context, int ops, int ibrs);
int load_guest(struct vm *vm, struct vcpu *vcpu);
int general_sw_loader(struct vm *vm, struct vcpu *vcpu);
typedef int (*vm_sw_loader_t)(struct vm *, struct vcpu *);
extern vm_sw_loader_t vm_sw_loader;
#endif /* !ASSEMBLER */
#endif /* GUEST_H*/

View File

@@ -0,0 +1,288 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _VCPU_H_
#define _VCPU_H_
#define ACRN_VCPU_MMIO_COMPLETE (0)
/* Size of various elements within the VCPU structure */
#define REG_SIZE 8
/* Number of GPRs saved / restored for guest in VCPU structure */
#define NUM_GPRS 15
#define GUEST_STATE_AREA_SIZE 512
/* Indexes of GPRs saved / restored for guest */
#define VMX_MACHINE_T_GUEST_RAX_INDEX 0
#define VMX_MACHINE_T_GUEST_RBX_INDEX 1
#define VMX_MACHINE_T_GUEST_RCX_INDEX 2
#define VMX_MACHINE_T_GUEST_RDX_INDEX 3
#define VMX_MACHINE_T_GUEST_RBP_INDEX 4
#define VMX_MACHINE_T_GUEST_RSI_INDEX 5
#define VMX_MACHINE_T_GUEST_R8_INDEX 6
#define VMX_MACHINE_T_GUEST_R9_INDEX 7
#define VMX_MACHINE_T_GUEST_R10_INDEX 8
#define VMX_MACHINE_T_GUEST_R11_INDEX 9
#define VMX_MACHINE_T_GUEST_R12_INDEX 10
#define VMX_MACHINE_T_GUEST_R13_INDEX 11
#define VMX_MACHINE_T_GUEST_R14_INDEX 12
#define VMX_MACHINE_T_GUEST_R15_INDEX 13
#define VMX_MACHINE_T_GUEST_RDI_INDEX 14
/* Offsets of GPRs for guest within the VCPU data structure */
#define VMX_MACHINE_T_GUEST_RAX_OFFSET (VMX_MACHINE_T_GUEST_RAX_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_RBX_OFFSET (VMX_MACHINE_T_GUEST_RBX_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_RCX_OFFSET (VMX_MACHINE_T_GUEST_RCX_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_RDX_OFFSET (VMX_MACHINE_T_GUEST_RDX_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_RBP_OFFSET (VMX_MACHINE_T_GUEST_RBP_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_RSI_OFFSET (VMX_MACHINE_T_GUEST_RSI_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_RDI_OFFSET (VMX_MACHINE_T_GUEST_RDI_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R8_OFFSET (VMX_MACHINE_T_GUEST_R8_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R9_OFFSET (VMX_MACHINE_T_GUEST_R9_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R10_OFFSET (VMX_MACHINE_T_GUEST_R10_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R11_OFFSET (VMX_MACHINE_T_GUEST_R11_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R12_OFFSET (VMX_MACHINE_T_GUEST_R12_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R13_OFFSET (VMX_MACHINE_T_GUEST_R13_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R14_OFFSET (VMX_MACHINE_T_GUEST_R14_INDEX*REG_SIZE)
#define VMX_MACHINE_T_GUEST_R15_OFFSET (VMX_MACHINE_T_GUEST_R15_INDEX*REG_SIZE)
/* Hard-coded offset of cr2 in struct run_context!! */
#define VMX_MACHINE_T_GUEST_CR2_OFFSET (128)
/* Hard-coded offset of cr2 in struct run_context!! */
#define VMX_MACHINE_T_GUEST_SPEC_CTRL_OFFSET (192)
/*sizes of various registers within the VCPU data structure */
#define VMX_CPU_S_FXSAVE_GUEST_AREA_SIZE GUEST_STATE_AREA_SIZE
#ifndef ASSEMBLER
enum vcpu_state {
VCPU_INIT,
VCPU_RUNNING,
VCPU_PAUSED,
VCPU_ZOMBIE,
VCPU_UNKNOWN_STATE,
};
struct cpu_regs {
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
uint64_t rdx;
uint64_t rbp;
uint64_t rsi;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rdi;
};
struct segment {
uint64_t selector;
uint64_t base;
uint64_t limit;
uint64_t attr;
};
struct run_context {
/* Contains the guest register set.
* NOTE: This must be the first element in the structure, so that the offsets
* in vmx_asm.S match
*/
union {
struct cpu_regs regs;
uint64_t longs[NUM_GPRS];
} guest_cpu_regs;
/** The guests CR registers 0, 2, 3 and 4. */
uint64_t cr0;
/* VMX_MACHINE_T_GUEST_CR2_OFFSET =
* offsetof(struct run_context, cr2) = 128
*/
uint64_t cr2;
uint64_t cr3;
uint64_t cr4;
uint64_t rip;
uint64_t rsp;
uint64_t rflags;
uint64_t dr7;
uint64_t tsc_offset;
/* MSRs */
/* VMX_MACHINE_T_GUEST_SPEC_CTRL_OFFSET =
* offsetof(struct run_context, ia32_spec_ctrl) = 192
*/
uint64_t ia32_spec_ctrl;
uint64_t ia32_star;
uint64_t ia32_lstar;
uint64_t ia32_fmask;
uint64_t ia32_kernel_gs_base;
uint64_t ia32_pat;
uint64_t ia32_efer;
uint64_t ia32_sysenter_cs;
uint64_t ia32_sysenter_esp;
uint64_t ia32_sysenter_eip;
uint64_t ia32_debugctl;
/* segment registers */
struct segment cs;
struct segment ss;
struct segment ds;
struct segment es;
struct segment fs;
struct segment gs;
struct segment tr;
struct segment idtr;
struct segment ldtr;
struct segment gdtr;
/* The 512 bytes area to save the FPU/MMX/SSE states for the guest */
uint64_t
fxstore_guest_area[VMX_CPU_S_FXSAVE_GUEST_AREA_SIZE / sizeof(uint64_t)]
__aligned(16);
};
/* 2 worlds: 0 for Normal World, 1 for Secure World */
#define NR_WORLD 2
#define NORMAL_WORLD 0
#define SECURE_WORLD 1
struct vcpu_arch {
int cur_context;
struct run_context contexts[NR_WORLD];
/* A pointer to the VMCS for this CPU. */
void *vmcs;
/* Holds the information needed for IRQ/exception handling. */
struct {
/* The number of the exception to raise. */
int exception;
/* The error number for the exception. */
int error;
} exception_info;
uint8_t lapic_mask;
uint32_t irq_window_enabled;
uint32_t nrexits;
/* Auxiliary TSC value */
uint64_t msr_tsc_aux;
/* VCPU context state information */
uint64_t exit_reason;
uint64_t exit_interrupt_info;
uint64_t exit_qualification;
uint8_t inst_len;
/* Information related to secondary / AP VCPU start-up */
uint8_t cpu_mode;
uint8_t nr_sipi;
uint32_t sipi_vector;
/* interrupt injection information */
uint64_t pending_intr;
/* per vcpu lapic */
void *vlapic;
};
struct vm;
struct vcpu {
int pcpu_id; /* Physical CPU ID of this VCPU */
int vcpu_id; /* virtual identifier for VCPU */
struct vcpu_arch arch_vcpu;
/* Architecture specific definitions for this VCPU */
struct vm *vm; /* Reference to the VM this VCPU belongs to */
void *entry_addr; /* Entry address for this VCPU when first started */
/* State of this VCPU before suspend */
volatile enum vcpu_state prev_state;
volatile enum vcpu_state state; /* State of this VCPU */
/* State of debug request for this VCPU */
volatile enum vcpu_state dbg_req_state;
unsigned long sync; /*hold the bit events*/
struct vlapic *vlapic; /* per vCPU virtualized LAPIC */
struct list_head run_list; /* inserted to schedule runqueue */
unsigned long pending_pre_work; /* any pre work pending? */
bool launched; /* Whether the vcpu is launched on target pcpu */
unsigned int paused_cnt; /* how many times vcpu is paused */
unsigned int running; /* vcpu is picked up and run? */
unsigned int ioreq_pending; /* ioreq is ongoing or not? */
struct vhm_request req; /* used by io/ept emulation */
struct mem_io mmio; /* used by io/ept emulation */
/* save guest msr tsc aux register.
* Before VMENTRY, save guest MSR_TSC_AUX to this fields.
* After VMEXIT, restore this fields to guest MSR_TSC_AUX.
* This is only temperary workaround. Once MSR emulation
* is enabled, we should remove this fields and related
* code.
*/
uint64_t msr_tsc_aux_guest;
uint64_t *guest_msrs;
};
#define is_vcpu_bsp(vcpu) ((vcpu)->vcpu_id == 0)
/* do not update Guest RIP for next VM Enter */
#define VCPU_RETAIN_RIP(vcpu) ((vcpu)->arch_vcpu.inst_len = 0)
/* External Interfaces */
int create_vcpu(int cpu_id, struct vm *vm, struct vcpu **rtn_vcpu_handle);
int start_vcpu(struct vcpu *vcpu);
int shutdown_vcpu(struct vcpu *vcpu);
int destroy_vcpu(struct vcpu *vcpu);
void reset_vcpu(struct vcpu *vcpu);
void init_vcpu(struct vcpu *vcpu);
void pause_vcpu(struct vcpu *vcpu, enum vcpu_state new_state);
void resume_vcpu(struct vcpu *vcpu);
void schedule_vcpu(struct vcpu *vcpu);
int prepare_vcpu(struct vm *vm, int pcpu_id);
void request_vcpu_pre_work(struct vcpu *vcpu, int pre_work_id);
#endif
#endif

View File

@@ -0,0 +1,57 @@
/*-
* Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
* Copyright (c) 2013 Neel Natu <neel@freebsd.org>
* Copyright (c) 2017 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _VIOAPIC_H_
#define _VIOAPIC_H_
#define VIOAPIC_BASE 0xFEC00000UL
#define VIOAPIC_SIZE 4096UL
struct vioapic *vioapic_init(struct vm *vm);
void vioapic_cleanup(struct vioapic *vioapic);
int vioapic_assert_irq(struct vm *vm, int irq);
int vioapic_deassert_irq(struct vm *vm, int irq);
int vioapic_pulse_irq(struct vm *vm, int irq);
void vioapic_update_tmr(struct vcpu *vcpu);
int vioapic_mmio_write(void *vm, uint64_t gpa,
uint64_t wval, int size);
int vioapic_mmio_read(void *vm, uint64_t gpa,
uint64_t *rval, int size);
int vioapic_pincount(struct vm *vm);
void vioapic_process_eoi(struct vm *vm, int vector);
bool vioapic_get_rte(struct vm *vm, int pin, void *rte);
int vioapic_mmio_access_handler(struct vcpu *vcpu, struct mem_io *mmio,
void *handler_private_data);
int get_vioapic_info(char *str, int str_max, int vmid);
#endif

View File

@@ -0,0 +1,132 @@
/*-
* Copyright (c) 2011 NetApp, Inc.
* Copyright (c) 2017 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _VLAPIC_H_
#define _VLAPIC_H_
struct vlapic;
/* APIC write handlers */
void vlapic_set_cr8(struct vlapic *vlapic, uint64_t val);
uint64_t vlapic_get_cr8(struct vlapic *vlapic);
/*
* Returns 0 if there is no eligible vector that can be delivered to the
* guest at this time and non-zero otherwise.
*
* If an eligible vector number is found and 'vecptr' is not NULL then it will
* be stored in the location pointed to by 'vecptr'.
*
* Note that the vector does not automatically transition to the ISR as a
* result of calling this function.
*/
int vlapic_pending_intr(struct vlapic *vlapic, int *vecptr);
/*
* Transition 'vector' from IRR to ISR. This function is called with the
* vector returned by 'vlapic_pending_intr()' when the guest is able to
* accept this interrupt (i.e. RFLAGS.IF = 1 and no conditions exist that
* block interrupt delivery).
*/
void vlapic_intr_accepted(struct vlapic *vlapic, int vector);
struct vlapic *vm_lapic_from_vcpuid(struct vm *vm, int vcpu_id);
struct vlapic *vm_lapic_from_pcpuid(struct vm *vm, int pcpu_id);
bool vlapic_msr(uint32_t num);
int vlapic_rdmsr(struct vcpu *vcpu, uint32_t msr, uint64_t *rval, bool *retu);
int vlapic_wrmsr(struct vcpu *vcpu, uint32_t msr, uint64_t wval, bool *retu);
int vlapic_mmio_read(struct vcpu *vcpu, uint64_t gpa, uint64_t *rval, int size);
int vlapic_mmio_write(struct vcpu *vcpu, uint64_t gpa, uint64_t wval, int size);
/*
* Signals to the LAPIC that an interrupt at 'vector' needs to be generated
* to the 'cpu', the state is recorded in IRR.
*/
int vlapic_set_intr(struct vcpu *vcpu, int vector, bool trig);
#define LAPIC_TRIG_LEVEL true
#define LAPIC_TRIG_EDGE false
static inline int
vlapic_intr_level(struct vcpu *vcpu, int vector)
{
return vlapic_set_intr(vcpu, vector, LAPIC_TRIG_LEVEL);
}
static inline int
vlapic_intr_edge(struct vcpu *vcpu, int vector)
{
return vlapic_set_intr(vcpu, vector, LAPIC_TRIG_EDGE);
}
/*
* Triggers the LAPIC local interrupt (LVT) 'vector' on 'cpu'. 'cpu' can
* be set to -1 to trigger the interrupt on all CPUs.
*/
int vlapic_set_local_intr(struct vm *vm, int cpu, int vector);
int vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg);
void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest,
bool phys, int delmode, int vec);
/* Reset the trigger-mode bits for all vectors to be edge-triggered */
void vlapic_reset_tmr(struct vlapic *vlapic);
/*
* Set the trigger-mode bit associated with 'vector' to level-triggered if
* the (dest,phys,delmode) tuple resolves to an interrupt being delivered to
* this 'vlapic'.
*/
void vlapic_set_tmr_one_vec(struct vlapic *vlapic, int delmode,
int vector, bool level);
void
vlapic_apicv_batch_set_tmr(struct vlapic *vlapic);
int vlapic_mmio_access_handler(struct vcpu *vcpu, struct mem_io *mmio,
void *handler_private_data);
uint32_t vlapic_get_id(struct vlapic *vlapic);
uint8_t vlapic_get_apicid(struct vlapic *vlapic);
int vlapic_create(struct vcpu *vcpu);
void vlapic_free(struct vcpu *vcpu);
void vlapic_init(struct vlapic *vlapic);
bool vlapic_enabled(struct vlapic *vlapic);
uint64_t apicv_get_apic_access_addr(struct vm *vm);
uint64_t apicv_get_apic_page_addr(struct vlapic *vlapic);
bool vlapic_apicv_enabled(struct vcpu *vcpu);
void apicv_inject_pir(struct vlapic *vlapic);
int apicv_access_exit_handler(struct vcpu *vcpu);
int apicv_write_exit_handler(struct vcpu *vcpu);
int apicv_virtualized_eoi_exit_handler(struct vcpu *vcpu);
void calcvdest(struct vm *vm, uint64_t *dmask, uint32_t dest, bool phys);
#endif /* _VLAPIC_H_ */

View File

@@ -0,0 +1,202 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VM_H_
#define VM_H_
enum vm_privilege_level {
VM_PRIVILEGE_LEVEL_HIGH = 0,
VM_PRIVILEGE_LEVEL_MEDIUM,
VM_PRIVILEGE_LEVEL_LOW
};
#define MAX_VM_NAME_LEN 16
struct vm_attr {
char name[16]; /* Virtual machine name string */
int id; /* Virtual machine identifier */
int boot_idx; /* Index indicating the boot sequence for this VM */
};
struct vm_hw_info {
int num_vcpus; /* Number of total virtual cores */
uint32_t created_vcpus; /* Number of created vcpus */
struct vcpu **vcpu_array; /* vcpu array of this VM */
uint64_t gpa_lowtop; /* top lowmem gpa of this VM */
};
struct sw_linux {
void *ramdisk_src_addr;
void *ramdisk_load_addr;
uint32_t ramdisk_size;
void *bootargs_src_addr;
void *bootargs_load_addr;
uint32_t bootargs_size;
void *dtb_src_addr;
void *dtb_load_addr;
uint32_t dtb_size;
};
struct sw_kernel_info {
void *kernel_src_addr;
void *kernel_load_addr;
void *kernel_entry_addr;
uint32_t kernel_size;
};
struct vm_sw_info {
int kernel_type; /* Guest kernel type */
/* Kernel information (common for all guest types) */
struct sw_kernel_info kernel_info;
/* Additional information specific to Linux guests */
struct sw_linux linux_info;
/* GPA Address of guest OS's request buffer */
uint64_t req_buf;
};
/* VM guest types */
#define VM_LINUX_GUEST 0x02
#define VM_MONO_GUEST 0x01
enum vpic_wire_mode {
VPIC_WIRE_INTR = 0,
VPIC_WIRE_LAPIC,
VPIC_WIRE_IOAPIC,
VPIC_WIRE_NULL
};
/* Enumerated type for VM states */
enum vm_state {
VM_CREATED = 0, /* VM created / awaiting start (boot) */
VM_STARTED, /* VM started (booted) */
VM_PAUSED, /* VM paused */
VM_STATE_UNKNOWN
};
/* Structure for VM state information */
struct vm_state_info {
enum vm_state state; /* State of the VM */
unsigned int privilege; /* Privilege level of the VM */
unsigned int boot_count;/* Number of times the VM has booted */
};
struct vm_arch {
void *guest_pml4; /* Guest pml4 */
void *ept; /* EPT hierarchy */
void *m2p; /* machine address to guest physical address */
void *tmp_pg_array; /* Page array for tmp guest paging struct */
void *iobitmap[2];/* IO bitmap page array base address for this VM */
void *msr_bitmap; /* MSR bitmap page base address for this VM */
void *virt_ioapic; /* Virtual IOAPIC base address */
/**
* A link to the IO handler of this VM.
* We only register io handle to this link
* when create VM on sequences and ungister it when
* destory VM. So there no need lock to prevent preempt.
* Besides, there only a few io handlers now, we don't
* need binary search temporary.
*/
struct vm_io_handler *io_handler;
/* reference to virtual platform to come here (as needed) */
};
struct vpic;
struct vm {
struct vm_attr attr; /* Reference to this VM's attributes */
struct vm_hw_info hw; /* Reference to this VM's HW information */
struct vm_sw_info sw; /* Reference to SW associated with this VM */
struct vm_arch arch_vm; /* Reference to this VM's arch information */
struct vm_state_info state_info;/* State info of this VM */
enum vm_state state; /* VM state */
struct vcpu *current_vcpu; /* VCPU that caused vm exit */
void *vuart; /* Virtual UART */
struct vpic *vpic; /* Virtual PIC */
uint32_t vpic_wire_mode;
struct iommu_domain *iommu_domain; /* iommu domain of this VM */
struct list_head list; /* list of VM */
spinlock_t spinlock; /* Spin-lock used to protect VM modifications */
struct list_head mmio_list; /* list for mmio. This list is not updated
* when vm is active. So no lock needed
*/
struct _vm_shared_memory *shared_memory_area;
struct {
struct _vm_virtual_device_node *head;
struct _vm_virtual_device_node *tail;
} virtual_device_list;
/* passthrough device link */
struct list_head ptdev_list;
spinlock_t ptdev_lock;
unsigned char GUID[16];
unsigned int secure_world_enabled;
};
struct vm_description {
/* Virtual machine identifier, assigned by the system */
char *vm_attr_name;
/* The logical CPU IDs associated with this VM - The first CPU listed
* will be the VM's BSP
*/
int *vm_hw_logical_core_ids;
unsigned char GUID[16]; /* GUID of the vm will be created */
int vm_hw_num_cores; /* Number of virtual cores */
/* Indicates to APs that the BSP has created a VM for this
* description
*/
bool vm_created;
/* Index indicating VM's privilege level */
unsigned int vm_state_info_privilege;
unsigned int secure_world_enabled; /* secure_world enabled? */
};
struct vm_description_array {
int num_vm_desc;
struct vm_description vm_desc_array[];
};
int shutdown_vm(struct vm *vm);
int pause_vm(struct vm *vm);
int start_vm(struct vm *vm);
int create_vm(struct vm_description *vm_desc, struct vm **vm);
int prepare_vm0(void);
struct vm *get_vm_from_vmid(int vm_id);
struct vm_description *get_vm_desc(int idx);
extern struct list_head vm_list;
extern spinlock_t vm_list_lock;
extern bool x2apic_enabled;
#endif /* VM_H_ */

View File

@@ -0,0 +1,110 @@
/*-
* Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
* Copyright (c) 2017 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _VPIC_H_
#define _VPIC_H_
#define ICU_IMR_OFFSET 1
/* Initialization control word 1. Written to even address. */
#define ICW1_IC4 0x01 /* ICW4 present */
#define ICW1_SNGL 0x02 /* 1 = single, 0 = cascaded */
#define ICW1_ADI 0x04 /* 1 = 4, 0 = 8 byte vectors */
#define ICW1_LTIM 0x08 /* 1 = level trigger, 0 = edge */
#define ICW1_RESET 0x10 /* must be 1 */
/* 0x20 - 0x80 - in 8080/8085 mode only */
/* Initialization control word 2. Written to the odd address. */
/* No definitions, it is the base vector of the IDT for 8086 mode */
/* Initialization control word 3. Written to the odd address. */
/* For a master PIC, bitfield indicating a slave 8259 on given input */
/* For slave, lower 3 bits are the slave's ID binary id on master */
/* Initialization control word 4. Written to the odd address. */
#define ICW4_8086 0x01 /* 1 = 8086, 0 = 8080 */
#define ICW4_AEOI 0x02 /* 1 = Auto EOI */
#define ICW4_MS 0x04 /* 1 = buffered master, 0 = slave */
#define ICW4_BUF 0x08 /* 1 = enable buffer mode */
#define ICW4_SFNM 0x10 /* 1 = special fully nested mode */
/* Operation control words. Written after initialization. */
/* Operation control word type 1 */
/*
* No definitions. Written to the odd address. Bitmask for interrupts.
* 1 = disabled.
*/
/* Operation control word type 2. Bit 3 (0x08) must be zero. Even address. */
#define OCW2_L0 0x01 /* Level */
#define OCW2_L1 0x02
#define OCW2_L2 0x04
/* 0x08 must be 0 to select OCW2 vs OCW3 */
/* 0x10 must be 0 to select OCW2 vs ICW1 */
#define OCW2_EOI 0x20 /* 1 = EOI */
#define OCW2_SL 0x40 /* EOI mode */
#define OCW2_R 0x80 /* EOI mode */
/* Operation control word type 3. Bit 3 (0x08) must be set. Even address. */
#define OCW3_RIS 0x01 /* 1 = read IS, 0 = read IR */
#define OCW3_RR 0x02 /* register read */
#define OCW3_P 0x04 /* poll mode command */
/* 0x08 must be 1 to select OCW3 vs OCW2 */
#define OCW3_SEL 0x08 /* must be 1 */
/* 0x10 must be 0 to select OCW3 vs ICW1 */
#define OCW3_SMM 0x20 /* special mode mask */
#define OCW3_ESMM 0x40 /* enable SMM */
#define IO_ELCR1 0x4d0
#define IO_ELCR2 0x4d1
enum vpic_trigger {
EDGE_TRIGGER,
LEVEL_TRIGGER
};
void *vpic_init(struct vm *vm);
void vpic_cleanup(struct vm *vm);
int vpic_assert_irq(struct vm *vm, int irq);
int vpic_deassert_irq(struct vm *vm, int irq);
int vpic_pulse_irq(struct vm *vm, int irq);
void vpic_pending_intr(struct vm *vm, int *vecptr);
void vpic_intr_accepted(struct vm *vm, int vector);
int vpic_set_irq_trigger(struct vm *vm, int irq, enum vpic_trigger trigger);
int vpic_get_irq_trigger(struct vm *vm, int irq, enum vpic_trigger *trigger);
struct vm_io_handler *vpic_create_io_handler(int flags, uint32_t port,
uint32_t len);
bool vpic_is_pin_mask(struct vpic *vpic, uint8_t virt_pin);
#endif /* _VPIC_H_ */