mirror of
				https://github.com/projectacrn/acrn-hypervisor.git
				synced 2025-11-04 11:48:50 +00:00 
			
		
		
		
	The ve820 table' hpa1_low area is divided into two parts, which is making the code too complicated and causing problems. Moving the entries that divides the hpa1_low could make things easier. This patch moves the GPU OpRegion to the tail area of 2G, consecutive to the acpi data/nvs area. before: |<---low_1M--->| |<---hpa1_low_part1--->| |<---SSRAM--->| |<---GPU_OpRegion--->| |<---hpa1_low_part2--->| |<---ACPI DATA--->| |<---ACPI NVS--->| ---2G--- after: |<---low_1M--->| |<---hpa1_low_part1--->| |<---SSRAM--->| |<---hpa1_low_part2--->| |<---GPU_OpRegion--->| |<---ACPI DATA--->| |<---ACPI NVS--->| ---2G--- Tracked-On: #6674 Signed-off-by: Zhou, Wu <wu.zhou@intel.com> Reviewed-by: Victor Sun <victor.sun@intel.com> Reviewed-by: Wang, Yu1 <yu1.wang@intel.com>
		
			
				
	
	
		
			296 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2018 Intel Corporation. All rights reserved.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: BSD-3-Clause
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef PTDEV_H
 | 
						|
#define PTDEV_H
 | 
						|
#include <list.h>
 | 
						|
#include <asm/lib/spinlock.h>
 | 
						|
#include <timer.h>
 | 
						|
#include <vacpi.h>
 | 
						|
 | 
						|
 | 
						|
enum intx_ctlr {
 | 
						|
	INTX_CTLR_IOAPIC	= 0U,
 | 
						|
	INTX_CTLR_PIC
 | 
						|
};
 | 
						|
 | 
						|
#define PTDEV_INTR_MSI		(1U << 0U)
 | 
						|
#define PTDEV_INTR_INTX		(1U << 1U)
 | 
						|
 | 
						|
#define GPU_OPREGION_SIZE	0x5000U
 | 
						|
#define GPU_OPREGION_GPA	(VIRT_ACPI_DATA_ADDR  - GPU_OPREGION_SIZE)
 | 
						|
#define PCIR_ASLS_CTL		0xfcU /* register offset in PCIe configuration space for Opregion base address */
 | 
						|
#define PCIM_ASLS_OPREGION_MASK	0xfffff000U /* opregion need 4KB aligned */
 | 
						|
 | 
						|
#define INVALID_PTDEV_ENTRY_ID 0xffffU
 | 
						|
 | 
						|
#define DEFINE_MSI_SID(name, a, b)	\
 | 
						|
union source_id (name) = {.msi_id = {.bdf = (a), .entry_nr = (b)} }
 | 
						|
 | 
						|
#define DEFINE_INTX_SID(name, a, b)	\
 | 
						|
union source_id (name) = {.intx_id = {.gsi = (a), .ctlr = (b)} }
 | 
						|
 | 
						|
union irte_index {
 | 
						|
	uint16_t index;
 | 
						|
	struct {
 | 
						|
		uint16_t index_low:15;
 | 
						|
		uint16_t index_high:1;
 | 
						|
	} bits __packed;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
union source_id {
 | 
						|
	uint64_t value;
 | 
						|
	struct {
 | 
						|
		uint16_t bdf;
 | 
						|
		uint16_t entry_nr;
 | 
						|
		uint32_t reserved;
 | 
						|
	} msi_id;
 | 
						|
	/*
 | 
						|
	 * ctlr indicates if the source of interrupt is IO-APIC or PIC
 | 
						|
	 * pin indicates the pin number of interrupt controller determined by ctlr
 | 
						|
	 */
 | 
						|
	struct {
 | 
						|
		enum intx_ctlr ctlr;
 | 
						|
		uint32_t gsi;
 | 
						|
	} intx_id;
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * Macros for bits in union msi_addr_reg
 | 
						|
 */
 | 
						|
 | 
						|
#define	MSI_ADDR_BASE			0xfeeUL	/* Base address for MSI messages */
 | 
						|
#define	MSI_ADDR_RH			0x1U	/* Redirection Hint */
 | 
						|
#define	MSI_ADDR_DESTMODE_LOGICAL	0x1U	/* Destination Mode: Logical*/
 | 
						|
#define	MSI_ADDR_DESTMODE_PHYS		0x0U	/* Destination Mode: Physical*/
 | 
						|
 | 
						|
union msi_addr_reg {
 | 
						|
	uint64_t full;
 | 
						|
	struct {
 | 
						|
		uint32_t rsvd_1:2;
 | 
						|
		uint32_t dest_mode:1;
 | 
						|
		uint32_t rh:1;
 | 
						|
		uint32_t rsvd_2:8;
 | 
						|
		uint32_t dest_field:8;
 | 
						|
		uint32_t addr_base:12;
 | 
						|
		uint32_t hi_32;
 | 
						|
	} bits __packed;
 | 
						|
	struct {
 | 
						|
		uint32_t rsvd_1:2;
 | 
						|
		uint32_t intr_index_high:1;
 | 
						|
		uint32_t shv:1;
 | 
						|
		uint32_t intr_format:1;
 | 
						|
		uint32_t intr_index_low:15;
 | 
						|
		uint32_t constant:12;
 | 
						|
		uint32_t hi_32;
 | 
						|
	} ir_bits __packed;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
/*
 | 
						|
 * Macros for bits in union msi_data_reg
 | 
						|
 */
 | 
						|
 | 
						|
#define MSI_DATA_DELMODE_FIXED		0x0U	/* Delivery Mode: Fixed */
 | 
						|
#define MSI_DATA_DELMODE_LOPRI		0x1U	/* Delivery Mode: Low Priority */
 | 
						|
#define MSI_DATA_TRGRMODE_EDGE		0x0U	/* Trigger Mode: Edge */
 | 
						|
#define MSI_DATA_TRGRMODE_LEVEL		0x1U	/* Trigger Mode: Level */
 | 
						|
 | 
						|
union msi_data_reg {
 | 
						|
	uint32_t full;
 | 
						|
	struct {
 | 
						|
		uint32_t vector:8;
 | 
						|
		uint32_t delivery_mode:3;
 | 
						|
		uint32_t rsvd_1:3;
 | 
						|
		uint32_t level:1;
 | 
						|
		uint32_t trigger_mode:1;
 | 
						|
		uint32_t rsvd_2:16;
 | 
						|
	} bits __packed;
 | 
						|
};
 | 
						|
 | 
						|
struct msi_info {
 | 
						|
	union msi_addr_reg addr;
 | 
						|
	union msi_data_reg data;
 | 
						|
};
 | 
						|
 | 
						|
struct ptirq_remapping_info;
 | 
						|
typedef void (*ptirq_arch_release_fn_t)(const struct ptirq_remapping_info *entry);
 | 
						|
 | 
						|
/* entry per each allocated irq/vector
 | 
						|
 * it represents a pass-thru device's remapping data entry which collecting
 | 
						|
 * information related with its vm and msi/intx mapping & interaction nodes
 | 
						|
 * with interrupt handler and softirq.
 | 
						|
 */
 | 
						|
struct ptirq_remapping_info {
 | 
						|
	struct hlist_node phys_link;
 | 
						|
	struct hlist_node virt_link;
 | 
						|
	uint16_t ptdev_entry_id;
 | 
						|
	uint32_t intr_type;
 | 
						|
	union source_id phys_sid;
 | 
						|
	union source_id virt_sid;
 | 
						|
	struct acrn_vm *vm;
 | 
						|
	bool active;	/* true=active, false=inactive*/
 | 
						|
	uint32_t allocated_pirq;
 | 
						|
	uint32_t polarity; /* 0=active high, 1=active low*/
 | 
						|
	struct list_head softirq_node;
 | 
						|
	struct msi_info vmsi;
 | 
						|
	struct msi_info pmsi;
 | 
						|
	uint16_t irte_idx;
 | 
						|
 | 
						|
	uint64_t intr_count;
 | 
						|
	struct hv_timer intr_delay_timer; /* used for delay intr injection */
 | 
						|
	ptirq_arch_release_fn_t release_cb;
 | 
						|
};
 | 
						|
 | 
						|
static inline bool is_entry_active(const struct ptirq_remapping_info *entry)
 | 
						|
{
 | 
						|
	return entry->active;
 | 
						|
}
 | 
						|
 | 
						|
extern struct ptirq_remapping_info ptirq_entries[CONFIG_MAX_PT_IRQ_ENTRIES];
 | 
						|
extern spinlock_t ptdev_lock;
 | 
						|
 | 
						|
/**
 | 
						|
 * @file ptdev.h
 | 
						|
 *
 | 
						|
 * @brief public APIs for ptdev
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief ptdev
 | 
						|
 *
 | 
						|
 * @addtogroup acrn_passthrough
 | 
						|
 * @{
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * @brief Find a ptdev entry by sid
 | 
						|
 *
 | 
						|
 * param[in] intr_type interrupt type of the ptirq entry
 | 
						|
 * param[in] sid source id of the ptirq entry
 | 
						|
 * param[in] vm vm pointer of the ptirq entry if find the ptdev entry by virtual sid
 | 
						|
 *
 | 
						|
 * @retval NULL when no ptirq entry match the sid
 | 
						|
 * @retval ptirq entry when there is available ptirq entry match the sid
 | 
						|
 *
 | 
						|
 * @pre: vm must be NULL when lookup by physical sid, otherwise,
 | 
						|
 * vm must not be NULL when lookup by virtual sid.
 | 
						|
 */
 | 
						|
struct ptirq_remapping_info *find_ptirq_entry(uint32_t intr_type,
 | 
						|
		const union source_id *sid, const struct acrn_vm *vm);
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Handler of softirq for passthrough device.
 | 
						|
 *
 | 
						|
 * When hypervisor receive a physical interrupt from passthrough device, it
 | 
						|
 * will enqueue a ptirq entry and raise softirq SOFTIRQ_PTDEV. This function
 | 
						|
 * is the handler of the softirq, it handles the interrupt and injects the
 | 
						|
 * virtual into VM.
 | 
						|
 * The handler is registered by calling @ref ptdev_init during hypervisor
 | 
						|
 * initialization.
 | 
						|
 *
 | 
						|
 * @param[in]    pcpu_id physical cpu id of the soft irq
 | 
						|
 *
 | 
						|
 */
 | 
						|
void ptirq_softirq(uint16_t pcpu_id);
 | 
						|
/**
 | 
						|
 * @brief Passthrough device global data structure initialization.
 | 
						|
 *
 | 
						|
 * During the hypervisor cpu initialization stage, this function:
 | 
						|
 * - init global spinlock for ptdev (on BSP)
 | 
						|
 * - register SOFTIRQ_PTDEV handler (on BSP)
 | 
						|
 * - init the softirq entry list for each CPU
 | 
						|
 *
 | 
						|
 */
 | 
						|
void ptdev_init(void);
 | 
						|
/**
 | 
						|
 * @brief Deactivate and release all ptirq entries for a VM.
 | 
						|
 *
 | 
						|
 * This function deactivates and releases all ptirq entries for a VM. The function
 | 
						|
 * should only be called after the VM is already down.
 | 
						|
 *
 | 
						|
 * @param[in]    vm acrn_vm on which the ptirq entries will be released
 | 
						|
 *
 | 
						|
 * @pre VM is already down
 | 
						|
 *
 | 
						|
 */
 | 
						|
void ptdev_release_all_entries(const struct acrn_vm *vm);
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Dequeue an entry from per cpu ptdev softirq queue.
 | 
						|
 *
 | 
						|
 * Dequeue an entry from the ptdev softirq queue on the specific physical cpu.
 | 
						|
 *
 | 
						|
 * @param[in]    pcpu_id physical cpu id
 | 
						|
 *
 | 
						|
 * @retval NULL when the queue is empty
 | 
						|
 * @retval !NULL when there is available ptirq_remapping_info entry in the queue
 | 
						|
 *
 | 
						|
 */
 | 
						|
struct ptirq_remapping_info *ptirq_dequeue_softirq(uint16_t pcpu_id);
 | 
						|
/**
 | 
						|
 * @brief Allocate a ptirq_remapping_info entry.
 | 
						|
 *
 | 
						|
 * Allocate a ptirq_remapping_info entry for hypervisor to store the remapping information.
 | 
						|
 * The total number of the entries is statically defined as CONFIG_MAX_PT_IRQ_ENTRIES.
 | 
						|
 * Appropriate number should be configured on different platforms.
 | 
						|
 *
 | 
						|
 * @param[in]    vm acrn_vm that the entry allocated for.
 | 
						|
 * @param[in]    intr_type interrupt type: PTDEV_INTR_MSI or PTDEV_INTR_INTX
 | 
						|
 *
 | 
						|
 * @retval NULL when the number of entries allocated is CONFIG_MAX_PT_IRQ_ENTRIES
 | 
						|
 * @retval !NULL when the number of entries allocated is less than CONFIG_MAX_PT_IRQ_ENTRIES
 | 
						|
 *
 | 
						|
 */
 | 
						|
struct ptirq_remapping_info *ptirq_alloc_entry(struct acrn_vm *vm, uint32_t intr_type);
 | 
						|
/**
 | 
						|
 * @brief Release a ptirq_remapping_info entry.
 | 
						|
 *
 | 
						|
 * @param[in]    entry the ptirq_remapping_info entry to release.
 | 
						|
 *
 | 
						|
 */
 | 
						|
void ptirq_release_entry(struct ptirq_remapping_info *entry);
 | 
						|
/**
 | 
						|
 * @brief Activate a irq for the associated passthrough device.
 | 
						|
 *
 | 
						|
 * After activating the ptirq entry, the physical interrupt irq of passthrough device will be handled
 | 
						|
 * by the handler  ptirq_interrupt_handler.
 | 
						|
 *
 | 
						|
 * @param[in]    entry the ptirq_remapping_info entry that will be associated with the physical irq.
 | 
						|
 * @param[in]    phys_irq physical interrupt irq for the entry
 | 
						|
 *
 | 
						|
 * @retval success when return value >=0
 | 
						|
 * @retval failure when return value < 0
 | 
						|
 *
 | 
						|
 */
 | 
						|
int32_t ptirq_activate_entry(struct ptirq_remapping_info *entry, uint32_t phys_irq);
 | 
						|
/**
 | 
						|
 * @brief De-activate a irq for the associated passthrough device.
 | 
						|
 *
 | 
						|
 * @param[in]    entry the ptirq_remapping_info entry that will be de-activated.
 | 
						|
 *
 | 
						|
 */
 | 
						|
void ptirq_deactivate_entry(struct ptirq_remapping_info *entry);
 | 
						|
/**
 | 
						|
 * @brief Get the interrupt information and store to the buffer provided.
 | 
						|
 *
 | 
						|
 * @param[in]    target_vm the VM to get the interrupt information.
 | 
						|
 * @param[out]   buffer where interrupt information is stored.
 | 
						|
 * @param[in]    buffer_cnt the size of the buffer.
 | 
						|
 *
 | 
						|
 * @retval the actual size the buffer filled with the interrupt information
 | 
						|
 *
 | 
						|
 */
 | 
						|
uint32_t ptirq_get_intr_data(const struct acrn_vm *target_vm, uint64_t *buffer, uint32_t buffer_cnt);
 | 
						|
 | 
						|
/**
 | 
						|
  * @}
 | 
						|
  */
 | 
						|
 | 
						|
#endif /* PTDEV_H */
 |