mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
[HVM] Replace shared-memory PIC state with a set-irq-level hypercall.
This simplifies the IRQ logic significantly and avoids the bogus
hvm_pic_assist() on domain resume path.
There is more work to be done here. At least:
1. set-irq-level should really be set-interrupt-wire-level. Wire
state needs to be distinguished from PIC (in particular, PIC IRR)
state.
2. Hypercalls can be batched in qemu and pushed down in one
multicall.
Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
bcc2aed22a
commit
25f5b0ff15
21 files changed
+135
-281
No files matched your search
@@ -22,58 +22,18 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
|
||||
/* debug PIC */
|
||||
//#define DEBUG_PIC
|
||||
|
||||
//#define DEBUG_IRQ_LATENCY
|
||||
//#define DEBUG_IRQ_COUNT
|
||||
|
||||
#include "xenctrl.h"
|
||||
#include <xen/hvm/ioreq.h>
|
||||
#include <stdio.h>
|
||||
#include "cpu.h"
|
||||
#include "cpu-all.h"
|
||||
|
||||
extern shared_iopage_t *shared_page;
|
||||
|
||||
struct PicState2 {
|
||||
};
|
||||
|
||||
void pic_set_irq_new(void *opaque, int irq, int level)
|
||||
{
|
||||
/* PicState2 *s = opaque; */
|
||||
global_iodata_t *gio;
|
||||
int mask;
|
||||
|
||||
gio = &shared_page->sp_global;
|
||||
mask = 1 << irq;
|
||||
if ( gio->pic_elcr & mask ) {
|
||||
/* level */
|
||||
if ( level ) {
|
||||
atomic_clear_bit(irq, &gio->pic_clear_irr);
|
||||
atomic_set_bit(irq, &gio->pic_irr);
|
||||
cpu_single_env->send_event = 1;
|
||||
}
|
||||
else {
|
||||
atomic_clear_bit(irq, &gio->pic_irr);
|
||||
atomic_set_bit(irq, &gio->pic_clear_irr);
|
||||
cpu_single_env->send_event = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* edge */
|
||||
if ( level ) {
|
||||
if ( (mask & gio->pic_last_irr) == 0 ) {
|
||||
atomic_set_bit(irq, &gio->pic_irr);
|
||||
atomic_set_bit(irq, &gio->pic_last_irr);
|
||||
cpu_single_env->send_event = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
atomic_clear_bit(irq, &gio->pic_last_irr);
|
||||
}
|
||||
}
|
||||
xc_hvm_set_irq_level(xc_handle, domid, irq, level);
|
||||
}
|
||||
|
||||
/* obsolete function */
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "xc_private.h"
|
||||
#include <xen/hvm/hvm_op.h>
|
||||
|
||||
int xc_readconsolering(int xc_handle,
|
||||
char **pbuffer,
|
||||
@@ -89,6 +90,33 @@ int xc_perfc_control(int xc_handle,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int xc_hvm_set_irq_level(int xc_handle, domid_t dom, int irq, int level)
|
||||
{
|
||||
DECLARE_HYPERCALL;
|
||||
struct xen_hvm_set_irq_level arg;
|
||||
int rc;
|
||||
|
||||
hypercall.op = __HYPERVISOR_hvm_op;
|
||||
hypercall.arg[0] = HVMOP_set_irq_level;
|
||||
hypercall.arg[1] = (unsigned long)&arg;
|
||||
|
||||
arg.domid = dom;
|
||||
arg.irq = irq;
|
||||
arg.level = level;
|
||||
|
||||
if ( mlock(&arg, sizeof(arg)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = do_xen_hypercall(xc_handle, &hypercall);
|
||||
|
||||
safe_munlock(&arg, sizeof(arg));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -666,4 +666,6 @@ evtchn_port_t xc_evtchn_pending(int xce_handle);
|
||||
*/
|
||||
int xc_evtchn_unmask(int xce_handle, evtchn_port_t port);
|
||||
|
||||
int xc_hvm_set_irq_level(int xce_handle, domid_t dom, int irq, int level);
|
||||
|
||||
#endif
|
||||
@@ -324,39 +324,6 @@ void vtm_domain_in(VCPU *vcpu)
|
||||
*/
|
||||
|
||||
#ifdef V_IOSAPIC_READY
|
||||
/* Assist to check virtual interrupt lines */
|
||||
void vmx_virq_line_assist(struct vcpu *v)
|
||||
{
|
||||
global_iodata_t *spg = &get_sp(v->domain)->sp_global;
|
||||
uint16_t *virq_line, irqs;
|
||||
|
||||
virq_line = &spg->pic_irr;
|
||||
if (*virq_line) {
|
||||
do {
|
||||
irqs = *(volatile uint16_t*)virq_line;
|
||||
} while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs);
|
||||
hvm_vioapic_do_irqs(v->domain, irqs);
|
||||
}
|
||||
|
||||
virq_line = &spg->pic_clear_irr;
|
||||
if (*virq_line) {
|
||||
do {
|
||||
irqs = *(volatile uint16_t*)virq_line;
|
||||
} while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs);
|
||||
hvm_vioapic_do_irqs_clear(v->domain, irqs);
|
||||
}
|
||||
}
|
||||
|
||||
void vmx_virq_line_init(struct domain *d)
|
||||
{
|
||||
global_iodata_t *spg = &get_sp(d)->sp_global;
|
||||
|
||||
spg->pic_elcr = 0xdef8; /* Level/Edge trigger mode */
|
||||
spg->pic_irr = 0;
|
||||
spg->pic_last_irr = 0;
|
||||
spg->pic_clear_irr = 0;
|
||||
}
|
||||
|
||||
int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint16_t dest)
|
||||
{
|
||||
return (VLAPIC_ID(s->lapic_info[number]) == dest);
|
||||
|
||||
@@ -322,8 +322,6 @@ vmx_final_setup_guest(struct vcpu *v)
|
||||
vlsapic_reset(v);
|
||||
vtm_init(v);
|
||||
|
||||
/* One more step to enable interrupt assist */
|
||||
set_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags);
|
||||
/* Set up guest 's indicator for VTi domain*/
|
||||
set_bit(ARCH_VMX_DOMAIN, &v->arch.arch_vmx.flags);
|
||||
}
|
||||
@@ -457,9 +455,6 @@ void vmx_setup_platform(struct domain *d)
|
||||
/* initiate spinlock for pass virq */
|
||||
spin_lock_init(&d->arch.arch_vmx.virq_assist_lock);
|
||||
|
||||
/* Initialize the virtual interrupt lines */
|
||||
vmx_virq_line_init(d);
|
||||
|
||||
/* Initialize iosapic model within hypervisor */
|
||||
hvm_vioapic_init(d);
|
||||
}
|
||||
|
||||
@@ -209,10 +209,6 @@ void leave_hypervisor_tail(struct pt_regs *regs)
|
||||
// if (user_regs != regs)
|
||||
// printk("WARNING: checking pending interrupt in nested interrupt!!!\n");
|
||||
|
||||
/* VMX Domain N has other interrupt source, saying DM */
|
||||
if (test_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags))
|
||||
vmx_intr_assist(v);
|
||||
|
||||
/* FIXME: Check event pending indicator, and set
|
||||
* pending bit if necessary to inject back to guest.
|
||||
* Should be careful about window between this check
|
||||
|
||||
@@ -60,27 +60,6 @@ void vmx_io_assist(struct vcpu *v)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* VMX domainN has two types of interrupt source: lsapic model within
|
||||
* HV, and device model within domain 0 (service OS). There're another
|
||||
* pending array in share page, manipulated by device model directly.
|
||||
* To conform to VT-i spec, we have to sync pending bits in shared page
|
||||
* into VPD. This has to be done before checking pending interrupt at
|
||||
* resume to guest. For domain 0, all the interrupt sources come from
|
||||
* HV, which then doesn't require this assist.
|
||||
*/
|
||||
void vmx_intr_assist(struct vcpu *v)
|
||||
{
|
||||
#ifdef V_IOSAPIC_READY
|
||||
/* Confirm virtual interrupt line signals, and set pending bits in vpd */
|
||||
if (spin_trylock(&v->domain->arch.arch_vmx.virq_assist_lock)) {
|
||||
vmx_virq_line_assist(v);
|
||||
spin_unlock(&v->domain->arch.arch_vmx.virq_assist_lock);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void vmx_send_assist_req(struct vcpu *v)
|
||||
{
|
||||
ioreq_t *p;
|
||||
|
||||
+26
-23
@@ -208,29 +208,6 @@ void pic_irq_request(void *data, int level)
|
||||
*interrupt_request = level;
|
||||
}
|
||||
|
||||
void hvm_pic_assist(struct vcpu *v)
|
||||
{
|
||||
global_iodata_t *spg;
|
||||
u16 *virq_line, irqs;
|
||||
struct hvm_virpic *pic = &v->domain->arch.hvm_domain.vpic;
|
||||
|
||||
spg = &get_sp(v->domain)->sp_global;
|
||||
virq_line = &spg->pic_clear_irr;
|
||||
if ( *virq_line ) {
|
||||
do {
|
||||
irqs = *(volatile u16*)virq_line;
|
||||
} while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
|
||||
do_pic_irqs_clear(pic, irqs);
|
||||
}
|
||||
virq_line = &spg->pic_irr;
|
||||
if ( *virq_line ) {
|
||||
do {
|
||||
irqs = *(volatile u16*)virq_line;
|
||||
} while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
|
||||
do_pic_irqs(pic, irqs);
|
||||
}
|
||||
}
|
||||
|
||||
u64 hvm_get_guest_time(struct vcpu *v)
|
||||
{
|
||||
u64 host_tsc;
|
||||
@@ -679,6 +656,32 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
break;
|
||||
}
|
||||
|
||||
case HVMOP_set_irq_level:
|
||||
{
|
||||
struct xen_hvm_set_irq_level op;
|
||||
struct domain *d;
|
||||
|
||||
if ( copy_from_guest(&op, arg, 1) )
|
||||
return -EFAULT;
|
||||
|
||||
if ( !IS_PRIV(current->domain) )
|
||||
return -EPERM;
|
||||
|
||||
d = find_domain_by_id(op.domid);
|
||||
if ( d == NULL )
|
||||
return -ESRCH;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( is_hvm_domain(d) )
|
||||
{
|
||||
pic_set_irq(&d->arch.hvm_domain.vpic, op.irq, op.level);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
put_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
gdprintk(XENLOG_WARNING, "Bad HVM op %ld.\n", op);
|
||||
|
||||
+10
-57
@@ -152,48 +152,24 @@ void pic_set_xen_irq(void *opaque, int irq, int level)
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
}
|
||||
|
||||
void pic_set_irq_new(void *opaque, int irq, int level)
|
||||
{
|
||||
struct hvm_virpic *s = opaque;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
hvm_vioapic_set_irq(current->domain, irq, level);
|
||||
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
|
||||
pic_update_irq(s);
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
}
|
||||
|
||||
void do_pic_irqs (struct hvm_virpic *s, uint16_t irqs)
|
||||
void pic_set_irq(struct hvm_virpic *s, int irq, int level)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
s->pics[1].irr |= (uint8_t)(irqs >> 8);
|
||||
s->pics[0].irr |= (uint8_t) irqs;
|
||||
hvm_vioapic_do_irqs(current->domain, irqs);
|
||||
pic_update_irq(s);
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
}
|
||||
|
||||
void do_pic_irqs_clear (struct hvm_virpic *s, uint16_t irqs)
|
||||
{
|
||||
unsigned long flags;
|
||||
if ( irq < 0 )
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
s->pics[1].irr &= ~(uint8_t)(irqs >> 8);
|
||||
s->pics[0].irr &= ~(uint8_t) irqs;
|
||||
hvm_vioapic_do_irqs_clear(current->domain, irqs);
|
||||
pic_update_irq(s);
|
||||
hvm_vioapic_set_irq(container_of(s, struct domain, arch.hvm_domain.vpic),
|
||||
irq, level);
|
||||
if ( irq < 16 )
|
||||
{
|
||||
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
|
||||
pic_update_irq(s);
|
||||
}
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
}
|
||||
|
||||
/* obsolete function */
|
||||
void pic_set_irq(struct hvm_virpic *isa_pic, int irq, int level)
|
||||
{
|
||||
pic_set_irq_new(isa_pic, irq, level);
|
||||
}
|
||||
|
||||
/* acknowledge interrupt 'irq' */
|
||||
static inline void pic_intack(PicState *s, int irq)
|
||||
{
|
||||
@@ -245,26 +221,6 @@ static int pic_read_irq(struct hvm_virpic *s)
|
||||
return intno;
|
||||
}
|
||||
|
||||
static void update_shared_irr(struct hvm_virpic *s, PicState *c)
|
||||
{
|
||||
uint8_t *pl, *pe;
|
||||
|
||||
ASSERT(spin_is_locked(&s->lock));
|
||||
|
||||
get_sp(current->domain)->sp_global.pic_elcr =
|
||||
s->pics[0].elcr | ((u16)s->pics[1].elcr << 8);
|
||||
pl =(uint8_t*)&get_sp(current->domain)->sp_global.pic_last_irr;
|
||||
pe =(uint8_t*)&get_sp(current->domain)->sp_global.pic_elcr;
|
||||
if ( c == &s->pics[0] ) {
|
||||
*pl = c->last_irr;
|
||||
*pe = c->elcr;
|
||||
}
|
||||
else {
|
||||
*(pl+1) = c->last_irr;
|
||||
*(pe+1) = c->elcr;
|
||||
}
|
||||
}
|
||||
|
||||
static void pic_reset(void *opaque)
|
||||
{
|
||||
PicState *s = opaque;
|
||||
@@ -300,7 +256,6 @@ static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
if (val & 0x10) {
|
||||
/* init */
|
||||
pic_reset(s);
|
||||
update_shared_irr(s->pics_state, s);
|
||||
/* deassert a pending interrupt */
|
||||
s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
|
||||
s->init_state = 1;
|
||||
@@ -533,8 +488,6 @@ static int intercept_elcr_io(ioreq_t *p)
|
||||
spin_lock_irqsave(&s->lock, flags);
|
||||
elcr_ioport_write((void*)&s->pics[p->addr&1],
|
||||
(uint32_t) p->addr, (uint32_t)( data & 0xff));
|
||||
get_sp(current->domain)->sp_global.pic_elcr =
|
||||
s->pics[0].elcr | ((u16)s->pics[1].elcr << 8);
|
||||
spin_unlock_irqrestore(&s->lock, flags);
|
||||
}
|
||||
else {
|
||||
|
||||
+37
-41
@@ -46,12 +46,8 @@
|
||||
static inline int svm_inject_extint(struct vcpu *v, int trap)
|
||||
{
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
vintr_t intr;
|
||||
vintr_t intr = vmcb->vintr;
|
||||
|
||||
ASSERT(vmcb);
|
||||
|
||||
/* Save all fields */
|
||||
intr = vmcb->vintr;
|
||||
/* Update only relevant fields */
|
||||
intr.fields.irq = 1;
|
||||
intr.fields.intr_masking = 1;
|
||||
@@ -75,11 +71,10 @@ asmlinkage void svm_intr_assist(void)
|
||||
int intr_vector = -1;
|
||||
int re_injecting = 0;
|
||||
|
||||
ASSERT(vmcb);
|
||||
|
||||
/* Check if an Injection is active */
|
||||
/* Previous Interrupt delivery caused this Intercept? */
|
||||
if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
|
||||
if ( vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0) )
|
||||
{
|
||||
v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
|
||||
vmcb->exitintinfo.bytes = 0;
|
||||
re_injecting = 1;
|
||||
@@ -88,70 +83,71 @@ asmlinkage void svm_intr_assist(void)
|
||||
/*
|
||||
* If event requires injecting then do not inject int.
|
||||
*/
|
||||
if (unlikely(v->arch.hvm_svm.inject_event)) {
|
||||
if ( unlikely(v->arch.hvm_svm.inject_event) )
|
||||
{
|
||||
v->arch.hvm_svm.inject_event = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a 'fake' virtual interrupt on to intercept as soon
|
||||
* as the guest _can_ take interrupts
|
||||
* Create a 'fake' virtual interrupt on to intercept as soon
|
||||
* as the guest _can_ take interrupts.
|
||||
*/
|
||||
if (irq_masked(vmcb->rflags) || vmcb->interrupt_shadow) {
|
||||
if ( irq_masked(vmcb->rflags) || vmcb->interrupt_shadow )
|
||||
{
|
||||
vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
|
||||
svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Previous interrupt still pending? */
|
||||
if (vmcb->vintr.fields.irq) {
|
||||
// printk("Re-injecting IRQ from Vintr\n");
|
||||
if ( vmcb->vintr.fields.irq )
|
||||
{
|
||||
intr_vector = vmcb->vintr.fields.vector;
|
||||
vmcb->vintr.bytes = 0;
|
||||
re_injecting = 1;
|
||||
}
|
||||
/* Pending IRQ saved at last VMExit? */
|
||||
else if ( v->arch.hvm_svm.saved_irq_vector >= 0) {
|
||||
// printk("Re-Injecting saved IRQ\n");
|
||||
else if ( v->arch.hvm_svm.saved_irq_vector >= 0 )
|
||||
{
|
||||
intr_vector = v->arch.hvm_svm.saved_irq_vector;
|
||||
v->arch.hvm_svm.saved_irq_vector = -1;
|
||||
re_injecting = 1;
|
||||
}
|
||||
/* Now let's check for newer interrrupts */
|
||||
else {
|
||||
else
|
||||
{
|
||||
if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr )
|
||||
{
|
||||
pic_set_irq(pic, pt->irq, 0);
|
||||
pic_set_irq(pic, pt->irq, 1);
|
||||
}
|
||||
|
||||
if ( v->vcpu_id == 0 )
|
||||
hvm_pic_assist(v);
|
||||
|
||||
|
||||
if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr ) {
|
||||
pic_set_irq(pic, pt->irq, 0);
|
||||
pic_set_irq(pic, pt->irq, 1);
|
||||
}
|
||||
|
||||
if (v->vcpu_id == 0) {
|
||||
callback_irq =
|
||||
v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
|
||||
if ( callback_irq != 0)
|
||||
pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
|
||||
}
|
||||
|
||||
if ( cpu_has_pending_irq(v) )
|
||||
intr_vector = cpu_get_interrupt(v, &intr_type);
|
||||
if ( v->vcpu_id == 0 )
|
||||
{
|
||||
callback_irq =
|
||||
v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
|
||||
if ( callback_irq != 0 )
|
||||
pic_set_xen_irq(pic, callback_irq,
|
||||
local_events_need_delivery());
|
||||
}
|
||||
|
||||
if ( cpu_has_pending_irq(v) )
|
||||
intr_vector = cpu_get_interrupt(v, &intr_type);
|
||||
}
|
||||
|
||||
/* have we got an interrupt to inject? */
|
||||
if (intr_vector >= 0) {
|
||||
switch (intr_type) {
|
||||
if ( intr_vector >= 0 )
|
||||
{
|
||||
switch ( intr_type )
|
||||
{
|
||||
case APIC_DM_EXTINT:
|
||||
case APIC_DM_FIXED:
|
||||
case APIC_DM_LOWEST:
|
||||
/* Re-injecting a PIT interruptt? */
|
||||
if (re_injecting && pt->enabled &&
|
||||
is_periodic_irq(v, intr_vector, intr_type)) {
|
||||
++pt->pending_intr_nr;
|
||||
}
|
||||
if ( re_injecting && pt->enabled &&
|
||||
is_periodic_irq(v, intr_vector, intr_type) )
|
||||
++pt->pending_intr_nr;
|
||||
/* let's inject this interrupt */
|
||||
TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0);
|
||||
svm_inject_extint(v, intr_vector);
|
||||
|
||||
@@ -526,22 +526,6 @@ static void service_ioapic(hvm_vioapic_t *s)
|
||||
}
|
||||
}
|
||||
|
||||
void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs)
|
||||
{
|
||||
hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
|
||||
|
||||
s->irr |= irqs & ~s->imr;
|
||||
service_ioapic(s);
|
||||
}
|
||||
|
||||
void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs)
|
||||
{
|
||||
hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
|
||||
|
||||
s->irr &= ~irqs;
|
||||
service_ioapic(s);
|
||||
}
|
||||
|
||||
void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level)
|
||||
{
|
||||
hvm_vioapic_t *s = &d->arch.hvm_domain.vioapic;
|
||||
@@ -565,12 +549,10 @@ void hvm_vioapic_set_irq(struct domain *d, int irq, int level)
|
||||
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq "
|
||||
"irq %x level %x\n", irq, level);
|
||||
|
||||
if (irq < 0 || irq >= IOAPIC_NUM_PINS) {
|
||||
printk("ioapic_set_irq irq %x is illegal\n", irq);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
if ( (irq < 0) || (irq >= IOAPIC_NUM_PINS) )
|
||||
return;
|
||||
|
||||
if (!IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask)
|
||||
if ( !IOAPICEnabled(s) || s->redirtbl[irq].RedirForm.mask )
|
||||
return;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_set_irq entry %x "
|
||||
|
||||
@@ -104,9 +104,6 @@ asmlinkage void vmx_intr_assist(void)
|
||||
unsigned long inst_len;
|
||||
int has_ext_irq;
|
||||
|
||||
if ( v->vcpu_id == 0 )
|
||||
hvm_pic_assist(v);
|
||||
|
||||
if ( (v->vcpu_id == 0) && pt->enabled && pt->pending_intr_nr ) {
|
||||
pic_set_irq(pic, pt->irq, 0);
|
||||
pic_set_irq(pic, pt->irq, 1);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#define _LSAPIC_H
|
||||
#include <xen/sched.h>
|
||||
|
||||
extern void vmx_virq_line_init(struct domain *d);
|
||||
extern void vtm_init(struct vcpu *vcpu);
|
||||
extern void vtm_set_itc(struct vcpu *vcpu, uint64_t new_itc);
|
||||
extern void vtm_set_itm(struct vcpu *vcpu, uint64_t val);
|
||||
|
||||
@@ -44,13 +44,11 @@ extern void show_registers(struct pt_regs *regs);
|
||||
#define show_execution_state show_registers
|
||||
extern unsigned long __gpfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
|
||||
extern void sync_split_caches(void);
|
||||
extern void vmx_virq_line_assist(struct vcpu *v);
|
||||
extern void set_privileged_operation_isr (struct vcpu *vcpu,int inst);
|
||||
extern void privilege_op (struct vcpu *vcpu);
|
||||
extern void set_ifa_itir_iha (struct vcpu *vcpu, u64 vadr,
|
||||
int set_ifa, int set_itir, int set_iha);
|
||||
extern void inject_guest_interruption(struct vcpu *vcpu, u64 vec);
|
||||
extern void vmx_intr_assist(struct vcpu *v);
|
||||
extern void set_illegal_op_isr (struct vcpu *vcpu);
|
||||
extern void illegal_op (struct vcpu *vcpu);
|
||||
extern void vmx_relinquish_guest_resources(struct domain *d);
|
||||
|
||||
@@ -116,7 +116,6 @@ struct arch_vmx_struct {
|
||||
#define VMX_DOMAIN(v) v->arch.arch_vmx.flags
|
||||
|
||||
#define ARCH_VMX_IO_WAIT 3 /* Waiting for I/O completion */
|
||||
#define ARCH_VMX_INTR_ASSIST 4 /* Need DM's assist to issue intr */
|
||||
#define ARCH_VMX_DOMAIN 5 /* Need it to indicate VTi domain */
|
||||
|
||||
|
||||
|
||||
@@ -148,7 +148,6 @@ extern void handle_mmio(unsigned long gpa);
|
||||
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
|
||||
extern void hvm_io_assist(struct vcpu *v);
|
||||
extern void pic_irq_request(void *data, int level);
|
||||
extern void hvm_pic_assist(struct vcpu *v);
|
||||
extern int cpu_get_interrupt(struct vcpu *v, int *type);
|
||||
extern int cpu_has_pending_irq(struct vcpu *v);
|
||||
|
||||
|
||||
@@ -104,8 +104,6 @@ typedef struct hvm_vioapic {
|
||||
|
||||
hvm_vioapic_t *hvm_vioapic_init(struct domain *d);
|
||||
|
||||
void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs);
|
||||
void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs);
|
||||
void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level);
|
||||
void hvm_vioapic_set_irq(struct domain *d, int irq, int level);
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ struct hvm_virpic {
|
||||
|
||||
void pic_set_xen_irq(void *opaque, int irq, int level);
|
||||
void pic_set_irq(struct hvm_virpic *s, int irq, int level);
|
||||
void pic_set_irq_new(void *opaque, int irq, int level);
|
||||
void pic_init(struct hvm_virpic *s,
|
||||
void (*irq_request)(void *, int),
|
||||
void *irq_request_opaque);
|
||||
@@ -75,7 +74,5 @@ void register_pic_io_hook(struct domain *d);
|
||||
int cpu_get_pic_interrupt(struct vcpu *v, int *type);
|
||||
int is_periodic_irq(struct vcpu *v, int irq, int type);
|
||||
int is_irq_enabled(struct vcpu *v, int irq);
|
||||
void do_pic_irqs (struct hvm_virpic *s, uint16_t irqs);
|
||||
void do_pic_irqs_clear (struct hvm_virpic *s, uint16_t irqs);
|
||||
|
||||
#endif /* __ASM_X86_HVM_VPIC_H__ */
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
|
||||
#define __XEN_PUBLIC_HVM_HVM_OP_H__
|
||||
|
||||
/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
|
||||
#define HVMOP_set_param 0
|
||||
#define HVMOP_get_param 1
|
||||
struct xen_hvm_param {
|
||||
domid_t domid; /* IN */
|
||||
uint32_t index; /* IN */
|
||||
uint64_t value; /* IN/OUT */
|
||||
};
|
||||
typedef struct xen_hvm_param xen_hvm_param_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
|
||||
|
||||
/* Set the logical level of one of a domain's IRQ lines. */
|
||||
#define HVMOP_set_irq_level 2
|
||||
struct xen_hvm_set_irq_level {
|
||||
domid_t domid; /* Domain to be updated. */
|
||||
uint16_t level; /* New level of the IRQ (0 or 1). */
|
||||
uint32_t irq; /* IRQ to be updated. */
|
||||
};
|
||||
typedef struct xen_hvm_set_irq_level xen_hvm_set_irq_level_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_irq_level_t);
|
||||
|
||||
#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
|
||||
@@ -56,14 +56,6 @@ struct ioreq {
|
||||
};
|
||||
typedef struct ioreq ioreq_t;
|
||||
|
||||
struct global_iodata {
|
||||
uint16_t pic_elcr;
|
||||
uint16_t pic_irr;
|
||||
uint16_t pic_last_irr;
|
||||
uint16_t pic_clear_irr;
|
||||
};
|
||||
typedef struct global_iodata global_iodata_t;
|
||||
|
||||
struct vcpu_iodata {
|
||||
struct ioreq vp_ioreq;
|
||||
/* Event channel port */
|
||||
@@ -72,7 +64,6 @@ struct vcpu_iodata {
|
||||
typedef struct vcpu_iodata vcpu_iodata_t;
|
||||
|
||||
struct shared_iopage {
|
||||
struct global_iodata sp_global;
|
||||
struct vcpu_iodata vcpu_iodata[1];
|
||||
};
|
||||
typedef struct shared_iopage shared_iopage_t;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
|
||||
#define __XEN_PUBLIC_HVM_PARAMS_H__
|
||||
|
||||
/* Parameter space. */
|
||||
#include "hvm_op.h"
|
||||
|
||||
/* Parameter space for HVMOP_{set,get}_param. */
|
||||
#define HVM_PARAM_CALLBACK_IRQ 0
|
||||
#define HVM_PARAM_STORE_PFN 1
|
||||
#define HVM_PARAM_STORE_EVTCHN 2
|
||||
@@ -10,16 +12,4 @@
|
||||
#define HVM_PARAM_BUFIOREQ_PFN 6
|
||||
#define HVM_NR_PARAMS 7
|
||||
|
||||
/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
|
||||
#define HVMOP_set_param 0
|
||||
#define HVMOP_get_param 1
|
||||
|
||||
struct xen_hvm_param {
|
||||
domid_t domid; /* IN */
|
||||
uint32_t index; /* IN */
|
||||
uint64_t value; /* IN/OUT */
|
||||
};
|
||||
typedef struct xen_hvm_param xen_hvm_param_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
|
||||
|
||||
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
|
||||