Skip to content

Commit

Permalink
HV: Add hypercall to set/clear IRQ line
Browse files Browse the repository at this point in the history
    - wraps ASSERT/DEASSERT IRQ line hypercalls.
    - remove 'intr_type' from set/clear IRQ line interface.
    - deprecate "IRQ_ASSERT", "IRQ_DEASSERT" & "IRQ_PULSE".
    - new adding hypercall will support "GSI_SET_HIGH"/
      "GSI_SET_LOW"/ "GSI_RAISING_PULSE"/ "GSI_FALLING_PULSE"
      operations

Tracked-On: #861
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
  • Loading branch information
yonghuah authored and lijinxia committed Sep 27, 2018
1 parent 05ad6d6 commit dd6a5fb
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 27 deletions.
6 changes: 6 additions & 0 deletions hypervisor/arch/x86/guest/vmcall.c
Expand Up @@ -99,6 +99,12 @@ int vmcall_vmexit_handler(struct vcpu *vcpu)
ret = hcall_pulse_irqline(vm, (uint16_t)param1, param2);
break;

case HC_SET_IRQLINE:
/* param1: vmid */
ret = hcall_set_irqline(vm, (uint16_t)param1,
(struct acrn_irqline_ops *)&param2);
break;

case HC_INJECT_MSI:
/* param1: vmid */
ret = hcall_inject_msi(vm, (uint16_t)param1, param2);
Expand Down
66 changes: 44 additions & 22 deletions hypervisor/common/hypercall.c
Expand Up @@ -71,22 +71,19 @@ int32_t hcall_get_api_version(struct vm *vm, uint64_t param)
*@pre Pointer vm shall point to VM0
*/
static void
handle_vpic_irqline(struct vm *vm, uint32_t irq, enum irq_mode mode)
handle_vpic_irqline(struct vm *vm, uint32_t irq, uint32_t operation)
{

switch (mode) {
case IRQ_ASSERT:
switch (operation) {
case GSI_SET_HIGH:
vpic_assert_irq(vm, irq);
break;
case IRQ_DEASSERT:
case GSI_SET_LOW:
vpic_deassert_irq(vm, irq);
break;
case IRQ_PULSE:
case GSI_RAISING_PULSE:
vpic_pulse_irq(vm, irq);
default:
/*
* In this switch statement, mode shall either be IRQ_ASSERT or
* IRQ_DEASSERT or IRQ_PULSE.
* Gracefully return if prior case clauses have not been met.
*/
break;
Expand All @@ -97,22 +94,20 @@ handle_vpic_irqline(struct vm *vm, uint32_t irq, enum irq_mode mode)
*@pre Pointer vm shall point to VM0
*/
static void
handle_vioapic_irqline(struct vm *vm, uint32_t irq, enum irq_mode mode)
handle_vioapic_irqline(struct vm *vm, uint32_t irq, uint32_t operation)
{
switch (mode) {
case IRQ_ASSERT:
switch (operation) {
case GSI_SET_HIGH:
vioapic_assert_irq(vm, irq);
break;
case IRQ_DEASSERT:
case GSI_SET_LOW:
vioapic_deassert_irq(vm, irq);
break;
case IRQ_PULSE:
case GSI_RAISING_PULSE:
vioapic_pulse_irq(vm, irq);
break;
default:
/*
* In this switch statement, mode shall either be IRQ_ASSERT or
* IRQ_DEASSERT or IRQ_PULSE.
* Gracefully return if prior case clauses have not been met.
*/
break;
Expand All @@ -124,7 +119,7 @@ handle_vioapic_irqline(struct vm *vm, uint32_t irq, enum irq_mode mode)
*/
static int32_t
handle_virt_irqline(struct vm *vm, uint16_t target_vmid,
struct acrn_irqline *param, enum irq_mode mode)
struct acrn_irqline *param, uint32_t operation)
{
int32_t ret = 0;
uint32_t intr_type;
Expand Down Expand Up @@ -152,19 +147,19 @@ handle_virt_irqline(struct vm *vm, uint16_t target_vmid,
switch (intr_type) {
case ACRN_INTR_TYPE_ISA:
/* Call vpic for pic injection */
handle_vpic_irqline(target_vm, param->pic_irq, mode);
handle_vpic_irqline(target_vm, param->pic_irq, operation);

/* call vioapic for ioapic injection if ioapic_irq != ~0U*/
if (param->ioapic_irq != (~0U)) {
/* handle IOAPIC irqline */
handle_vioapic_irqline(target_vm,
param->ioapic_irq, mode);
param->ioapic_irq, operation);
}
break;
case ACRN_INTR_TYPE_IOAPIC:
/* handle IOAPIC irqline */
handle_vioapic_irqline(target_vm,
param->ioapic_irq, mode);
param->ioapic_irq, operation);
break;
default:
dev_dbg(ACRN_DBG_HYCALL, "vINTR inject failed. type=%d",
Expand Down Expand Up @@ -309,7 +304,7 @@ int32_t hcall_assert_irqline(struct vm *vm, uint16_t vmid, uint64_t param)
pr_err("%s: Unable copy param to vm\n", __func__);
return -1;
}
ret = handle_virt_irqline(vm, vmid, &irqline, IRQ_ASSERT);
ret = handle_virt_irqline(vm, vmid, &irqline, GSI_SET_HIGH);

return ret;
}
Expand All @@ -326,7 +321,7 @@ int32_t hcall_deassert_irqline(struct vm *vm, uint16_t vmid, uint64_t param)
pr_err("%s: Unable copy param to vm\n", __func__);
return -1;
}
ret = handle_virt_irqline(vm, vmid, &irqline, IRQ_DEASSERT);
ret = handle_virt_irqline(vm, vmid, &irqline, GSI_SET_LOW);

return ret;
}
Expand All @@ -343,11 +338,38 @@ int32_t hcall_pulse_irqline(struct vm *vm, uint16_t vmid, uint64_t param)
pr_err("%s: Unable copy param to vm\n", __func__);
return -1;
}
ret = handle_virt_irqline(vm, vmid, &irqline, IRQ_PULSE);
ret = handle_virt_irqline(vm, vmid, &irqline, GSI_RAISING_PULSE);

return ret;
}

/**
*@pre Pointer vm shall point to VM0
*/
int32_t hcall_set_irqline(struct vm *vm, uint16_t vmid,
struct acrn_irqline_ops *ops)
{
struct vm *target_vm = get_vm_from_vmid(vmid);

if (target_vm == NULL) {
return -EINVAL;
}

if (ops->nr_gsi >= vioapic_pincount(vm)) {
return -EINVAL;
}

if (ops->nr_gsi < vpic_pincount()) {
/* Call vpic for pic injection */
handle_vpic_irqline(target_vm, ops->nr_gsi, ops->op);
}

/* handle IOAPIC irqline */
handle_vioapic_irqline(target_vm, ops->nr_gsi, ops->op);

return 0;
}

/**
*@pre Pointer vm shall point to VM0
*/
Expand Down
17 changes: 17 additions & 0 deletions hypervisor/include/common/hypercall.h
Expand Up @@ -184,6 +184,23 @@ int32_t hcall_deassert_irqline(struct vm *vm, uint16_t vmid, uint64_t param);
*/
int32_t hcall_pulse_irqline(struct vm *vm, uint16_t vmid, uint64_t param);


/**
* @brief set or clear IRQ line
*
* Set or clear a virtual IRQ line for a VM, which could be from ISA
* or IOAPIC, normally it triggers an edge IRQ.
* The function will return -1 if the target VM does not exist.
*
* @param vm Pointer to VM data structure
* @param vmid ID of the VM
* @irq_req: request command for IRQ set or clear
*
* @pre Pointer vm shall point to VM0
* @return 0 on success, non-zero on error.
*/
int32_t hcall_set_irqline(struct vm *vm, uint16_t vmid,
struct acrn_irqline_ops *ops);
/**
* @brief inject MSI interrupt
*
Expand Down
5 changes: 0 additions & 5 deletions hypervisor/include/common/irq.h
Expand Up @@ -11,11 +11,6 @@
#define IRQF_LEVEL (1U << 1U) /* 1: level trigger; 0: edge trigger */
#define IRQF_PT (1U << 2U) /* 1: for passthrough dev */

enum irq_mode {
IRQ_PULSE,
IRQ_ASSERT,
IRQ_DEASSERT,
};

typedef void (*irq_action_t)(uint32_t irq, void *priv_data);

Expand Down
16 changes: 16 additions & 0 deletions hypervisor/include/public/acrn_common.h
Expand Up @@ -264,6 +264,22 @@ struct acrn_set_ioreq_buffer {
/** Interrupt type for acrn_irqline: inject interrupt to both PIC and IOAPIC */
#define ACRN_INTR_TYPE_IOAPIC 1U

/** Operation types for setting IRQ line */
#define GSI_SET_HIGH 0U
#define GSI_SET_LOW 1U
#define GSI_RAISING_PULSE 2U
#define GSI_FALLING_PULSE 3U

/**
* @brief Info to Set/Clear/Pulse a virtual IRQ line for a VM
*
* the parameter for HC_SET_IRQLINE hypercall
*/
struct acrn_irqline_ops {
uint32_t nr_gsi;
uint32_t op;
} __aligned(8);

/**
* @brief Info to assert/deassert/pulse a virtual IRQ line for a VM
*
Expand Down
1 change: 1 addition & 0 deletions hypervisor/include/public/acrn_hv_defs.h
Expand Up @@ -45,6 +45,7 @@
#define HC_PULSE_IRQLINE BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x02UL)
#define HC_INJECT_MSI BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x03UL)
#define HC_VM_INTR_MONITOR BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x04UL)
#define HC_SET_IRQLINE BASE_HC_ID(HC_ID, HC_ID_IRQ_BASE + 0x05UL)

/* DM ioreq management */
#define HC_ID_IOREQ_BASE 0x30UL
Expand Down

0 comments on commit dd6a5fb

Please sign in to comment.