mirror of
				https://github.com/projectacrn/acrn-hypervisor.git
				synced 2025-10-31 01:09:28 +00:00 
			
		
		
		
	for each pass-thru device and its entry owned by one VM, so change the pass-thru device's softirq lock & entry list into per VM, so one VM's PT device interrupt process will not interfere with other VMs; especially in case one user OS "interrupt storm" happens, it will have little effect on service OS. Tracked-On: #866 Signed-off-by: Minggui Cao <minggui.cao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
		
			
				
	
	
		
			303 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			303 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2018 Intel Corporation. All rights reserved.
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-3-Clause
 | |
|  */
 | |
| 
 | |
| #ifndef VM_H_
 | |
| #define VM_H_
 | |
| #include <bsp_extern.h>
 | |
| 
 | |
| #ifdef CONFIG_PARTITION_MODE
 | |
| #include <mptable.h>
 | |
| #include <vpci.h>
 | |
| #endif
 | |
| enum vm_privilege_level {
 | |
| 	VM_PRIVILEGE_LEVEL_HIGH = 0,
 | |
| 	VM_PRIVILEGE_LEVEL_MEDIUM,
 | |
| 	VM_PRIVILEGE_LEVEL_LOW
 | |
| };
 | |
| 
 | |
| #define	MAX_VM_NAME_LEN		16
 | |
| #define INVALID_VM_ID 0xffffU
 | |
| 
 | |
| struct vm_hw_info {
 | |
| 	uint16_t num_vcpus;	/* Number of total virtual cores */
 | |
| 	uint16_t exp_num_vcpus;	/* Number of real expected virtual cores */
 | |
| 	uint16_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;		/* HVA */
 | |
| 	void *ramdisk_load_addr;	/* GPA */
 | |
| 	uint32_t ramdisk_size;
 | |
| 	void *bootargs_src_addr;	/* HVA */
 | |
| 	void *bootargs_load_addr;	/* GPA */
 | |
| 	uint32_t bootargs_size;
 | |
| 	void *dtb_src_addr;		/* HVA */
 | |
| 	void *dtb_load_addr;		/* GPA */
 | |
| 	uint32_t dtb_size;
 | |
| };
 | |
| 
 | |
| struct sw_kernel_info {
 | |
| 	void *kernel_src_addr;		/* HVA */
 | |
| 	void *kernel_load_addr;		/* GPA */
 | |
| 	void *kernel_entry_addr;	/* GPA */
 | |
| 	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;
 | |
| 	/* HVA to IO shared page */
 | |
| 	void *io_shared_page;
 | |
| };
 | |
| 
 | |
| struct vm_pm_info {
 | |
| 	uint8_t			px_cnt;		/* count of all Px states */
 | |
| 	struct cpu_px_data	px_data[MAX_PSTATE];
 | |
| 	uint8_t			cx_cnt;		/* count of all Cx entries */
 | |
| 	struct cpu_cx_data	cx_data[MAX_CSTATE];
 | |
| 	struct pm_s_state_data	*sx_state_data;	/* data for S3/S5 implementation */
 | |
| };
 | |
| 
 | |
| /* 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
 | |
| };
 | |
| 
 | |
| struct vm_arch {
 | |
| 	uint64_t guest_init_pml4;/* Guest init pml4 */
 | |
| 	/* EPT hierarchy for Normal World */
 | |
| 	void *nworld_eptp;
 | |
| 	/* EPT hierarchy for Secure World
 | |
| 	 * Secure world can access Normal World's memory,
 | |
| 	 * but Normal World can not access Secure World's memory.
 | |
| 	 */
 | |
| 	void *sworld_eptp;
 | |
| 	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 */
 | |
| 	struct acrn_vioapic vioapic;	/* Virtual IOAPIC base address */
 | |
| 	struct acrn_vpic vpic;      /* Virtual PIC */
 | |
| 	/**
 | |
| 	 * 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) */
 | |
| };
 | |
| 
 | |
| #define CPUID_CHECK_SUBLEAF	(1U << 0)
 | |
| #define MAX_VM_VCPUID_ENTRIES	64U
 | |
| struct vcpuid_entry {
 | |
| 	uint32_t eax;
 | |
| 	uint32_t ebx;
 | |
| 	uint32_t ecx;
 | |
| 	uint32_t edx;
 | |
| 	uint32_t leaf;
 | |
| 	uint32_t subleaf;
 | |
| 	uint32_t flags;
 | |
| 	uint32_t padding;
 | |
| };
 | |
| 
 | |
| struct vm {
 | |
| 	uint16_t vm_id;		    /* Virtual machine identifier */
 | |
| 	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_pm_info pm;	/* Reference to this VM's arch information */
 | |
| 	struct vm_arch arch_vm;	/* Reference to this VM's arch information */
 | |
| 	enum vm_state state;	/* VM state */
 | |
| 	struct acrn_vuart vuart;		/* Virtual UART */
 | |
| 	enum vpic_wire_mode wire_mode;
 | |
| 	struct iommu_domain *iommu;	/* 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;
 | |
| 
 | |
| 	unsigned char GUID[16];
 | |
| 	struct secure_world_control sworld_control;
 | |
| 
 | |
| 	/* Secure World's snapshot
 | |
| 	 * Currently, Secure World is only running on vcpu[0],
 | |
| 	 * so the snapshot only stores the vcpu0's run_context
 | |
| 	 * of secure world.
 | |
| 	 */
 | |
| 	struct cpu_context sworld_snapshot;
 | |
| 
 | |
| 	uint32_t vcpuid_entry_nr, vcpuid_level, vcpuid_xlevel;
 | |
| 	struct vcpuid_entry vcpuid_entries[MAX_VM_VCPUID_ENTRIES];
 | |
| #ifdef CONFIG_PARTITION_MODE
 | |
| 	struct vm_description	*vm_desc;
 | |
| 	struct vpci vpci;
 | |
| 	uint8_t vrtc_offset;
 | |
| #endif
 | |
| 
 | |
| 	spinlock_t softirq_dev_lock;
 | |
| 	struct list_head softirq_dev_entry_list;
 | |
| };
 | |
| 
 | |
| #ifdef CONFIG_PARTITION_MODE
 | |
| struct vpci_vdev_array {
 | |
| 	int num_pci_vdev;
 | |
| 	struct pci_vdev vpci_vdev_list[];
 | |
| };
 | |
| #endif
 | |
| 
 | |
| struct vm_description {
 | |
| 	/* The physical CPU IDs associated with this VM - The first CPU listed
 | |
| 	 * will be the VM's BSP
 | |
| 	 */
 | |
| 	uint16_t               *vm_pcpu_ids;
 | |
| 	unsigned char          GUID[16]; /* GUID of the vm will be created */
 | |
| 	uint16_t               vm_hw_num_cores;   /* Number of virtual cores */
 | |
| 	/* Whether secure world is supported for current VM. */
 | |
| 	bool                   sworld_supported;
 | |
| #ifdef CONFIG_PARTITION_MODE
 | |
| 	uint8_t			vm_id;
 | |
| 	struct mptable_info	*mptable;
 | |
| 	uint64_t		start_hpa;
 | |
| 	uint64_t		mem_size; /* UOS memory size in hex */
 | |
| 	bool			vm_vuart;
 | |
| 	const char		*bootargs;
 | |
| 	struct vpci_vdev_array  *vpci_vdev_array;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| static inline bool is_vm0(struct vm *vm)
 | |
| {
 | |
| 	return (vm->vm_id) == 0U;
 | |
| }
 | |
| 
 | |
| static inline struct vcpu *vcpu_from_vid(struct vm *vm, uint16_t vcpu_id)
 | |
| {
 | |
| 	uint16_t i;
 | |
| 	struct vcpu *vcpu;
 | |
| 
 | |
| 	foreach_vcpu(i, vm, vcpu) {
 | |
| 		if (vcpu->vcpu_id == vcpu_id) {
 | |
| 			return vcpu;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| static inline struct vcpu *vcpu_from_pid(const struct vm *vm, uint16_t pcpu_id)
 | |
| {
 | |
| 	uint16_t i;
 | |
| 	struct vcpu *vcpu;
 | |
| 
 | |
| 	foreach_vcpu(i, vm, vcpu) {
 | |
| 		if (vcpu->pcpu_id == pcpu_id) {
 | |
| 			return vcpu;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| static inline struct vcpu *get_primary_vcpu(struct vm *vm)
 | |
| {
 | |
| 	uint16_t i;
 | |
| 	struct vcpu *vcpu;
 | |
| 
 | |
| 	foreach_vcpu(i, vm, vcpu) {
 | |
| 		if (is_vcpu_bsp(vcpu)) {
 | |
| 			return vcpu;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| static inline struct acrn_vuart*
 | |
| vm_vuart(struct vm *vm)
 | |
| {
 | |
| 	return (struct acrn_vuart *)&(vm->vuart);
 | |
| }
 | |
| 
 | |
| static inline struct acrn_vpic *
 | |
| vm_pic(struct vm *vm)
 | |
| {
 | |
| 	return (struct acrn_vpic *)&(vm->arch_vm.vpic);
 | |
| }
 | |
| 
 | |
| static inline struct acrn_vioapic *
 | |
| vm_ioapic(struct vm *vm)
 | |
| {
 | |
| 	return (struct acrn_vioapic *)&(vm->arch_vm.vioapic);
 | |
| }
 | |
| 
 | |
| int shutdown_vm(struct vm *vm);
 | |
| void pause_vm(struct vm *vm);
 | |
| void resume_vm(struct vm *vm);
 | |
| void resume_vm_from_s3(struct vm *vm, uint32_t wakeup_vec);
 | |
| int start_vm(struct vm *vm);
 | |
| int reset_vm(struct vm *vm);
 | |
| int create_vm(struct vm_description *vm_desc, struct vm **rtn_vm);
 | |
| int prepare_vm(uint16_t pcpu_id);
 | |
| #ifdef CONFIG_VM0_DESC
 | |
| void vm_fixup(struct vm *vm);
 | |
| #endif
 | |
| 
 | |
| #ifdef CONFIG_PARTITION_MODE
 | |
| const struct vm_description_array *get_vm_desc_base(void);
 | |
| #endif
 | |
| 
 | |
| struct vm *get_vm_from_vmid(uint16_t vm_id);
 | |
| 
 | |
| extern struct list_head vm_list;
 | |
| extern spinlock_t vm_list_lock;
 | |
| 
 | |
| #ifdef CONFIG_PARTITION_MODE
 | |
| struct vm_description_array {
 | |
| 	int                     num_vm_desc;
 | |
| 	const struct vm_description   vm_desc_array[];
 | |
| };
 | |
| 
 | |
| struct pcpu_vm_desc_mapping {
 | |
| 	const struct vm_descriptin *vm_desc_ptr;
 | |
| 	bool is_bsp;
 | |
| };
 | |
| extern const struct pcpu_vm_desc_mapping pcpu_vm_desc_map[];
 | |
| 
 | |
| void vrtc_init(struct vm *vm);
 | |
| #endif
 | |
| #endif /* VM_H_ */
 |