# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID cc23d4236b2054f9d0cea98cff2e2955d6b3bdd9
# Parent f23b897930d15ec692060ff25c7acc1f44894d69
This patch provide local APIC support for vmx guest.
A configure option is also added to disable it, which is off by default.
Signed-off-by: Jiang Yunhong <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Li Xin <xin.b.li@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>
Signed-off-by: Jun Nakajima <jun.nakajima@xxxxxxxxx>
diff -r f23b897930d1 -r cc23d4236b20 tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c Thu Oct 27 17:22:45 2005
+++ b/tools/libxc/xc_vmx_build.c Fri Oct 28 08:48:46 2005
@@ -279,6 +279,7 @@
vcpu_guest_context_t *ctxt,
unsigned long shared_info_frame,
unsigned int control_evtchn,
+ unsigned int lapic,
unsigned int vcpus,
unsigned int store_evtchn,
unsigned long *store_mfn)
@@ -554,7 +555,7 @@
ctxt->user_regs.eax = 0;
ctxt->user_regs.esp = 0;
ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot
cpu */
- ctxt->user_regs.ecx = 0;
+ ctxt->user_regs.ecx = lapic;
ctxt->user_regs.esi = 0;
ctxt->user_regs.edi = 0;
ctxt->user_regs.ebp = 0;
@@ -597,6 +598,7 @@
int memsize,
const char *image_name,
unsigned int control_evtchn,
+ unsigned int lapic,
unsigned int vcpus,
unsigned int store_evtchn,
unsigned long *store_mfn)
@@ -651,9 +653,9 @@
goto error_out;
}
- if ( setup_guest(xc_handle, domid, memsize, image, image_size,
- nr_pages, ctxt, op.u.getdomaininfo.shared_info_frame,
- control_evtchn, vcpus, store_evtchn, store_mfn) < 0)
+ if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
+ ctxt, op.u.getdomaininfo.shared_info_frame,
control_evtchn,
+ lapic, vcpus, store_evtchn, store_mfn) < 0)
{
ERROR("Error constructing guest OS");
goto error_out;
diff -r f23b897930d1 -r cc23d4236b20 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Thu Oct 27 17:22:45 2005
+++ b/tools/libxc/xenguest.h Fri Oct 28 08:48:46 2005
@@ -56,6 +56,7 @@
int memsize,
const char *image_name,
unsigned int control_evtchn,
+ unsigned int lapic,
unsigned int vcpus,
unsigned int store_evtchn,
unsigned long *store_mfn);
diff -r f23b897930d1 -r cc23d4236b20 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Oct 27 17:22:45 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 28 08:48:46 2005
@@ -438,19 +438,20 @@
char *image;
int control_evtchn, store_evtchn;
int vcpus = 1;
+ int lapic = 0;
int memsize;
unsigned long store_mfn = 0;
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
- "memsize", "image", "vcpus", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisi", kwd_list,
+ "memsize", "image", "lapic", "vcpus", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
&dom, &control_evtchn, &store_evtchn,
- &memsize, &image, &vcpus) )
+ &memsize, &image, &lapic, &vcpus) )
return NULL;
if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn,
- vcpus, store_evtchn, &store_mfn) != 0 )
+ lapic, vcpus, store_evtchn, &store_mfn) != 0 )
return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
diff -r f23b897930d1 -r cc23d4236b20 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu Oct 27 17:22:45 2005
+++ b/tools/python/xen/xend/image.py Fri Oct 28 08:48:46 2005
@@ -203,6 +203,10 @@
self.dmargs += self.configVNC(imageConfig)
+ self.lapic = 0
+ lapic = sxp.child_value(imageConfig, 'lapic')
+ if not lapic is None:
+ self.lapic = int(lapic)
def buildDomain(self):
# Create an event channel
@@ -217,6 +221,7 @@
log.debug("control_evtchn = %d", self.device_channel)
log.debug("store_evtchn = %d", store_evtchn)
log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024)
+ log.debug("lapic = %d", self.lapic)
log.debug("vcpus = %d", self.vm.getVCpuCount())
return xc.vmx_build(dom = self.vm.getDomid(),
@@ -224,6 +229,7 @@
control_evtchn = self.device_channel,
store_evtchn = store_evtchn,
memsize = self.vm.getMemoryTarget() / 1024,
+ lapic = self.lapic,
vcpus = self.vm.getVCpuCount())
diff -r f23b897930d1 -r cc23d4236b20 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Thu Oct 27 17:22:45 2005
+++ b/tools/python/xen/xm/create.py Fri Oct 28 08:48:46 2005
@@ -158,6 +158,10 @@
fn=set_int, default=None,
use="CPU to run the domain on.")
+gopts.var('lapic', val='LAPIC',
+ fn=set_int, default=0,
+ use="Disable or enable local APIC of VMX domain.")
+
gopts.var('vcpus', val='VCPUS',
fn=set_int, default=1,
use="# of Virtual CPUS in domain.")
@@ -315,10 +319,6 @@
gopts.var('nfs_root', val="PATH",
fn=set_value, default=None,
use="Set the path of the root NFS directory.")
-
-gopts.var('memmap', val='FILE',
- fn=set_value, default='',
- use="Path to memap SXP file.")
gopts.var('device_model', val='FILE',
fn=set_value, default='',
@@ -542,9 +542,9 @@
def configure_vmx(opts, config_image, vals):
"""Create the config for VMX devices.
"""
- args = [ 'memmap', 'device_model', 'vcpus', 'cdrom',
- 'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga',
- 'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display',
'ne2000']
+ args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
+ 'localtime', 'serial', 'macaddr', 'stdvga', 'isa', 'nographic',
+ 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
for a in args:
if (vals.__dict__[a]):
config_image.append([a, vals.__dict__[a]])
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/apic.c Fri Oct 28 08:48:46 2005
@@ -815,6 +815,10 @@
return result;
}
+unsigned int get_apic_bus_scale(void)
+{
+ return bus_scale;
+}
static unsigned int calibration_result;
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/dm/i8259.c
--- a/xen/arch/x86/dm/i8259.c Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/dm/i8259.c Fri Oct 28 08:48:46 2005
@@ -32,8 +32,8 @@
#include <public/io/ioreq.h>
#include <asm/vmx.h>
#include <public/io/vmx_vpic.h>
-#include <public/io/vmx_vlapic.h>
#include <asm/current.h>
+#include <asm/vmx_vlapic.h>
/* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level)
@@ -135,7 +135,6 @@
{
s->pics[1].irr |= (uint8_t)(irqs >> 8);
s->pics[0].irr |= (uint8_t) irqs;
- /* TODO for alt_irq_func */
pic_update_irq(s);
}
@@ -505,14 +504,22 @@
{
int intno;
struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
-
+ struct vmx_platform *plat = &v->domain->arch.vmx_platform;
+
+ if ( !vlapic_accept_pic_intr(v) )
+ return -1;
+
+ if ( !plat->interrupt_request )
+ return -1;
+
/* read the irq from the PIC */
intno = pic_read_irq(s);
*type = VLAPIC_DELIV_MODE_EXT;
+ plat->interrupt_request = 0;
return intno;
}
-int is_pit_irq(struct vcpu *v, int irq)
+int is_pit_irq(struct vcpu *v, int irq, int type)
{
int pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base;
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx.c Fri Oct 28 08:48:46 2005
@@ -65,6 +65,11 @@
if ( v == v->domain->vcpu[0] )
{
+ v->domain->arch.vmx_platform.lapic_enable =
+ v->arch.guest_context.user_regs.ecx;
+ v->arch.guest_context.user_regs.ecx = 0;
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "lapic enable is %d.\n",
+ v->domain->arch.vmx_platform.lapic_enable);
/*
* Required to do this once per domain
* XXX todo: add a seperate function to do these.
@@ -96,6 +101,10 @@
destroy_vmcs(&v->arch.arch_vmx);
free_monitor_pagetable(v);
rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer);
+ if ( vmx_apic_support(v->domain) ) {
+ rem_ac_timer( &(VLAPIC(v)->vlapic_timer) );
+ xfree( VLAPIC(v) );
+ }
}
#ifdef __x86_64__
@@ -442,7 +451,9 @@
/* Use 1:1 page table to identify MMIO address space */
if ( mmio_space(gpa) ){
- if (gpa >= 0xFEE00000) { /* workaround for local APIC */
+ struct vcpu *v = current;
+ /* No support for APIC */
+ if (!vmx_apic_support(v->domain) && gpa >= 0xFEC00000) {
u32 inst_len;
__vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len));
__update_guest_eip(inst_len);
@@ -487,6 +498,7 @@
{
unsigned int eax, ebx, ecx, edx;
unsigned long eip;
+ struct vcpu *v = current;
__vmread(GUEST_RIP, &eip);
@@ -500,6 +512,9 @@
cpuid(input, &eax, &ebx, &ecx, &edx);
if (input == 1) {
+ if ( vmx_apic_support(v->domain) &&
+ !vlapic_global_enabled((VLAPIC(v))) )
+ clear_bit(X86_FEATURE_APIC, &edx);
#ifdef __i386__
clear_bit(X86_FEATURE_PSE, &edx);
clear_bit(X86_FEATURE_PAE, &edx);
@@ -1441,6 +1456,7 @@
static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
{
u64 msr_content = 0;
+ struct vcpu *v = current;
VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
@@ -1455,6 +1471,9 @@
case MSR_IA32_SYSENTER_EIP:
__vmread(GUEST_SYSENTER_EIP, &msr_content);
break;
+ case MSR_IA32_APICBASE:
+ msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0;
+ break;
default:
if(long_mode_do_msr_read(regs))
return;
@@ -1474,6 +1493,7 @@
static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
{
u64 msr_content;
+ struct vcpu *v = current;
VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
@@ -1490,6 +1510,9 @@
break;
case MSR_IA32_SYSENTER_EIP:
__vmwrite(GUEST_SYSENTER_EIP, msr_content);
+ break;
+ case MSR_IA32_APICBASE:
+ vlapic_msr_set(VLAPIC(v), msr_content);
break;
default:
long_mode_do_msr_write(regs);
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_intercept.c Fri Oct 28 08:48:46 2005
@@ -23,6 +23,7 @@
#include <asm/vmx_platform.h>
#include <asm/vmx_virpit.h>
#include <asm/vmx_intercept.h>
+#include <asm/vmx_vlapic.h>
#include <public/io/ioreq.h>
#include <xen/lib.h>
#include <xen/sched.h>
@@ -31,6 +32,123 @@
#include <xen/event.h>
#ifdef CONFIG_VMX
+
+struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR] =
+{
+ {
+ .check_handler = vlapic_range,
+ .read_handler = vlapic_read,
+ .write_handler = vlapic_write
+ }
+};
+
+static inline void vmx_mmio_access(struct vcpu *v,
+ ioreq_t *p,
+ vmx_mmio_read_t read_handler,
+ vmx_mmio_write_t write_handler)
+{
+ ioreq_t *req;
+ vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
+ unsigned int tmp1, tmp2;
+ unsigned long data;
+
+ if (vio == NULL) {
+ printk("vlapic_access: bad shared page\n");
+ domain_crash_synchronous();
+ }
+
+ req = &vio->vp_ioreq;
+
+ switch (req->type) {
+ case IOREQ_TYPE_COPY:
+ {
+ int sign = (req->df) ? -1 : 1, i;
+
+ if (!req->pdata_valid) {
+ if (req->dir == IOREQ_READ){
+ req->u.data = read_handler(v, req->addr, req->size);
+ } else { /* req->dir != IOREQ_READ */
+ write_handler(v, req->addr, req->size, req->u.data);
+ }
+ } else { /* !req->pdata_valid */
+ if (req->dir == IOREQ_READ) {
+ for (i = 0; i < req->count; i++) {
+ data = read_handler(v,
+ req->addr + (sign * i * req->size),
+ req->size);
+ vmx_copy(&data,
+ (unsigned long)p->u.pdata + (sign * i * req->size),
+ p->size,
+ VMX_COPY_OUT);
+ }
+ } else { /* !req->dir == IOREQ_READ */
+ for (i = 0; i < req->count; i++) {
+ vmx_copy(&data,
+ (unsigned long)p->u.pdata + (sign * i * req->size),
+ p->size,
+ VMX_COPY_IN);
+ write_handler(v,
+ req->addr + (sign * i * req->size),
+ req->size, data);
+ }
+ }
+ }
+ break;
+ }
+
+ case IOREQ_TYPE_AND:
+ tmp1 = read_handler(v, req->addr, req->size);
+ if (req->dir == IOREQ_WRITE) {
+ tmp2 = tmp1 & (unsigned long) req->u.data;
+ write_handler(v, req->addr, req->size, tmp2);
+ }
+ req->u.data = tmp1;
+ break;
+
+ case IOREQ_TYPE_OR:
+ tmp1 = read_handler(v, req->addr, req->size);
+ if (req->dir == IOREQ_WRITE) {
+ tmp2 = tmp1 | (unsigned long) req->u.data;
+ write_handler(v, req->addr, req->size, tmp2);
+ }
+ req->u.data = tmp1;
+ break;
+
+ case IOREQ_TYPE_XOR:
+ tmp1 = read_handler(v, req->addr, req->size);
+ if (req->dir == IOREQ_WRITE) {
+ tmp2 = tmp1 ^ (unsigned long) req->u.data;
+ write_handler(v, req->addr, req->size, tmp2);
+ }
+ req->u.data = tmp1;
+ break;
+
+ default:
+ printk("error ioreq type for local APIC %x\n", req->type);
+ domain_crash_synchronous();
+ break;
+ }
+}
+
+int vmx_mmio_intercept(ioreq_t *p)
+{
+ struct vcpu *v = current;
+ int i;
+ struct vmx_mmio_handler *handler = vmx_mmio_handers;
+
+ /* XXX currently only APIC use intercept */
+ if ( !vmx_apic_support(v->domain) )
+ return 0;
+
+ for ( i = 0; i < VMX_MMIO_HANDLER_NR; i++ ) {
+ if ( handler[i].check_handler(v, p->addr) ) {
+ vmx_mmio_access(v, p,
+ handler[i].read_handler, handler[i].write_handler);
+ return 1;
+ }
+ }
+ return 0;
+}
/*
* Check if the request is handled inside xen
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_io.c Fri Oct 28 08:48:46 2005
@@ -36,9 +36,9 @@
#include <asm/apic.h>
#include <asm/shadow.h>
+#include <asm/vmx_vlapic.h>
#include <public/io/ioreq.h>
#include <public/io/vmx_vpic.h>
-#include <public/io/vmx_vlapic.h>
#ifdef CONFIG_VMX
#if defined (__i386__)
@@ -732,48 +732,6 @@
} while(1);
}
-#if defined(__i386__) || defined(__x86_64__)
-static inline int __fls(u32 word)
-{
- int bit;
-
- __asm__("bsrl %1,%0"
- :"=r" (bit)
- :"rm" (word));
- return word ? bit : -1;
-}
-#else
-#define __fls(x) generic_fls(x)
-static __inline__ int generic_fls(u32 x)
-{
- int r = 31;
-
- if (!x)
- return -1;
- if (!(x & 0xffff0000u)) {
- x <<= 16;
- r -= 16;
- }
- if (!(x & 0xff000000u)) {
- x <<= 8;
- r -= 8;
- }
- if (!(x & 0xf0000000u)) {
- x <<= 4;
- r -= 4;
- }
- if (!(x & 0xc0000000u)) {
- x <<= 2;
- r -= 2;
- }
- if (!(x & 0x80000000u)) {
- x <<= 1;
- r -= 1;
- }
- return r;
-}
-#endif
-
/* Simple minded Local APIC priority implementation. Fix later */
static __inline__ int find_highest_irq(u32 *pintr)
{
@@ -801,31 +759,31 @@
struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
u64 drift;
+ if ( is_pit_irq(v, vector, type) ) {
+ if ( !vpit->first_injected ) {
+ vpit->first_injected = 1;
+ vpit->pending_intr_nr = 0;
+ } else {
+ vpit->pending_intr_nr--;
+ }
+ vpit->inject_point = NOW();
+ drift = vpit->period_cycles * vpit->pending_intr_nr;
+ drift = v->arch.arch_vmx.tsc_offset - drift;
+ __vmwrite(TSC_OFFSET, drift);
+
+#if defined (__i386__)
+ __vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
+#endif
+
+ }
+
switch(type)
{
case VLAPIC_DELIV_MODE_EXT:
- if ( is_pit_irq(v, vector) ) {
- if ( !vpit->first_injected ) {
- vpit->first_injected = 1;
- vpit->pending_intr_nr = 0;
- }
- else {
- vpit->pending_intr_nr--;
- }
- vpit->inject_point = NOW();
- drift = vpit->period_cycles * vpit->pending_intr_nr;
- drift = v->arch.arch_vmx.tsc_offset - drift;
- __vmwrite(TSC_OFFSET, drift);
-
-#if defined (__i386__)
- __vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
-#endif
-
- }
break;
default:
- printk("Not support interrupt type\n");
+ vlapic_post_injection(v, vector, type);
break;
}
}
@@ -885,6 +843,24 @@
}
+int cpu_get_interrupt(struct vcpu *v, int *type)
+{
+ int intno;
+ struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
+
+ if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
+ /* set irq request if a PIC irq is still pending */
+ /* XXX: improve that */
+ pic_update_irq(s);
+ return intno;
+ }
+ /* read the irq from the PIC */
+ if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 )
+ return intno;
+
+ return -1;
+}
+
asmlinkage void vmx_intr_assist(void)
{
int intr_type = 0;
@@ -902,11 +878,6 @@
pic_set_irq(pic, 0, 1);
}
- if ( !plat->interrupt_request ) {
- disable_irq_window(cpu_exec_control);
- return;
- }
-
__vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
if (intr_fields & INTR_INFO_VALID_MASK) {
@@ -928,16 +899,21 @@
enable_irq_window(cpu_exec_control);
return;
}
- plat->interrupt_request = 0;
- highest_vector = cpu_get_pic_interrupt(v, &intr_type);
+
+ highest_vector = cpu_get_interrupt(v, &intr_type);
+
+ if (highest_vector == -1) {
+ disable_irq_window(cpu_exec_control);
+ return;
+ }
switch (intr_type) {
case VLAPIC_DELIV_MODE_EXT:
+ case VLAPIC_DELIV_MODE_FIXED:
+ case VLAPIC_DELIV_MODE_LPRI:
vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
break;
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_LPRI:
case VLAPIC_DELIV_MODE_SMI:
case VLAPIC_DELIV_MODE_NMI:
case VLAPIC_DELIV_MODE_INIT:
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_vmcs.c Fri Oct 28 08:48:46 2005
@@ -252,6 +252,10 @@
pic_init(&platform->vmx_pic, pic_irq_request,
&platform->interrupt_request);
register_pic_io_hook();
+
+ if ( vmx_apic_support(d) ) {
+ spin_lock_init(&d->arch.vmx_platform.round_robin_lock);
+ }
}
static void vmx_set_host_env(struct vcpu *v)
@@ -312,6 +316,9 @@
error |= __vmwrite(CR4_READ_SHADOW, cr4);
vmx_stts();
+
+ if(vmx_apic_support(v->domain))
+ vlapic_init(v);
vmx_set_host_env(v);
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_intercept.h
--- a/xen/include/asm-x86/vmx_intercept.h Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_intercept.h Fri Oct 28 08:48:46 2005
@@ -14,6 +14,16 @@
#define VMX_MMIO 1
typedef int (*intercept_action_t)(ioreq_t *);
+typedef unsigned long (*vmx_mmio_read_t)(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length);
+
+typedef unsigned long (*vmx_mmio_write_t)(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long val);
+
+typedef int (*vmx_mmio_check_t)(struct vcpu *v, unsigned long addr);
struct io_handler {
int type;
@@ -27,6 +37,16 @@
struct io_handler hdl_list[MAX_IO_HANDLER];
};
+struct vmx_mmio_handler {
+ vmx_mmio_check_t check_handler;
+ vmx_mmio_read_t read_handler;
+ vmx_mmio_write_t write_handler;
+};
+
+#define VMX_MMIO_HANDLER_NR 1
+
+extern struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR];
+
/* global io interception point in HV */
extern int vmx_io_intercept(ioreq_t *p, int type);
extern int register_io_handler(unsigned long addr, unsigned long size,
@@ -37,10 +57,7 @@
return vmx_io_intercept(p, VMX_PORTIO);
}
-static inline int vmx_mmio_intercept(ioreq_t *p)
-{
- return vmx_io_intercept(p, VMX_MMIO);
-}
+int vmx_mmio_intercept(ioreq_t *p);
static inline int register_portio_handler(unsigned long addr,
unsigned long size,
@@ -49,11 +66,4 @@
return register_io_handler(addr, size, action, VMX_PORTIO);
}
-static inline int register_mmio_handler(unsigned long addr,
- unsigned long size,
- intercept_action_t action)
-{
- return register_io_handler(addr, size, action, VMX_MMIO);
-}
-
#endif /* _VMX_INTERCEPT_H */
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_platform.h
--- a/xen/include/asm-x86/vmx_platform.h Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_platform.h Fri Oct 28 08:48:46 2005
@@ -80,10 +80,13 @@
struct vmx_platform {
unsigned long shared_page_va;
unsigned int nr_vcpu;
+ unsigned int lapic_enable;
struct vmx_virpit vmx_pit;
struct vmx_io_handler vmx_io_handler;
struct vmx_virpic vmx_pic;
+ unsigned char round_info[256];
+ spinlock_t round_robin_lock;
int interrupt_request;
};
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_vmcs.h
--- a/xen/include/asm-x86/vmx_vmcs.h Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_vmcs.h Fri Oct 28 08:48:46 2005
@@ -22,6 +22,7 @@
#include <asm/config.h>
#include <asm/vmx_cpu.h>
#include <asm/vmx_platform.h>
+#include <asm/vmx_vlapic.h>
#include <public/vmx_assist.h>
extern int start_vmx(void);
@@ -96,6 +97,7 @@
struct msr_state msr_content;
struct mmio_op mmio_op; /* MMIO */
void *io_bitmap_a, *io_bitmap_b;
+ struct vlapic *vlapic;
u64 tsc_offset;
};
@@ -272,18 +274,21 @@
#define VMX_DEBUG 1
#if VMX_DEBUG
-#define DBG_LEVEL_0 (1 << 0)
-#define DBG_LEVEL_1 (1 << 1)
-#define DBG_LEVEL_2 (1 << 2)
-#define DBG_LEVEL_3 (1 << 3)
-#define DBG_LEVEL_IO (1 << 4)
-#define DBG_LEVEL_VMMU (1 << 5)
+#define DBG_LEVEL_0 (1 << 0)
+#define DBG_LEVEL_1 (1 << 1)
+#define DBG_LEVEL_2 (1 << 2)
+#define DBG_LEVEL_3 (1 << 3)
+#define DBG_LEVEL_IO (1 << 4)
+#define DBG_LEVEL_VMMU (1 << 5)
+#define DBG_LEVEL_VLAPIC (1 << 6)
+#define DBG_LEVEL_VLAPIC_TIMER (1 << 7)
+#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 7)
extern unsigned int opt_vmx_debug_level;
#define VMX_DBG_LOG(level, _f, _a...) \
if ((level) & opt_vmx_debug_level) \
printk("[VMX:%d.%d] " _f "\n", \
- current->domain->domain_id, current->vcpu_id, ## _a)
+ current->domain->domain_id, current->vcpu_id, ## _a)
#else
#define VMX_DBG_LOG(level, _f, _a...)
#endif
diff -r f23b897930d1 -r cc23d4236b20 xen/include/public/io/ioreq.h
--- a/xen/include/public/io/ioreq.h Thu Oct 27 17:22:45 2005
+++ b/xen/include/public/io/ioreq.h Fri Oct 28 08:48:46 2005
@@ -29,11 +29,11 @@
#define STATE_IORESP_READY 3
#define STATE_IORESP_HOOK 4
-#define IOREQ_TYPE_PIO 0 /* pio */
-#define IOREQ_TYPE_COPY 1 /* mmio ops */
-#define IOREQ_TYPE_AND 2
-#define IOREQ_TYPE_OR 3
-#define IOREQ_TYPE_XOR 4
+#define IOREQ_TYPE_PIO 0 /* pio */
+#define IOREQ_TYPE_COPY 1 /* mmio ops */
+#define IOREQ_TYPE_AND 2
+#define IOREQ_TYPE_OR 3
+#define IOREQ_TYPE_XOR 4
/*
* VMExit dispatcher should cooperate with instruction decoder to
@@ -55,9 +55,10 @@
uint8_t type; /* I/O type */
} ioreq_t;
-#define MAX_VECTOR 256
+#define MAX_VECTOR 256
#define BITS_PER_BYTE 8
#define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint64_t)))
+#define INTR_LEN_32 (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint32_t)))
typedef struct {
uint16_t pic_elcr;
diff -r f23b897930d1 -r cc23d4236b20 xen/include/public/io/vmx_vpic.h
--- a/xen/include/public/io/vmx_vpic.h Thu Oct 27 17:22:45 2005
+++ b/xen/include/public/io/vmx_vpic.h Fri Oct 28 08:48:46 2005
@@ -76,7 +76,7 @@
uint32_t pic_intack_read(struct vmx_virpic *s);
void register_pic_io_hook (void);
int cpu_get_pic_interrupt(struct vcpu *v, int *type);
-int is_pit_irq(struct vcpu *v, int irq);
+int is_pit_irq(struct vcpu *v, int irq, int type);
void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
diff -r f23b897930d1 -r cc23d4236b20 xen/arch/x86/vmx_vlapic.c
--- /dev/null Thu Oct 27 17:22:45 2005
+++ b/xen/arch/x86/vmx_vlapic.c Fri Oct 28 08:48:46 2005
@@ -0,0 +1,997 @@
+/*
+ * vmx_vlapic.c: virtualize LAPIC for VMX vcpus.
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/xmalloc.h>
+#include <asm/shadow.h>
+#include <asm/page.h>
+#include <xen/event.h>
+#include <xen/trace.h>
+#include <asm/vmx.h>
+#include <asm/vmx_platform.h>
+#include <asm/vmx_vlapic.h>
+
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <asm/current.h>
+#include <public/io/ioreq.h>
+
+#ifdef CONFIG_VMX
+
+/* XXX remove this definition after GFW enabled */
+#define VLAPIC_NO_BIOS
+
+extern unsigned int get_apic_bus_scale(void);
+
+static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
+{
+ 0x310ff, 0x117ff, 0x117ff, 0x1f7ff, 0x1f7ff, 0x117ff
+};
+
+int vlapic_find_highest_irr(struct vlapic *vlapic)
+{
+ int result;
+
+ result = find_highest_bit((uint32_t *)&vlapic->irr[0], INTR_LEN_32);
+
+ if (result != -1 && result < 16) {
+ printk("VLAPIC: irr on reserved bits %d\n ", result);
+ domain_crash_synchronous();
+ }
+
+ return result;
+}
+
+inline int vmx_apic_support(struct domain *d)
+{
+ return d->arch.vmx_platform.lapic_enable;
+}
+
+int vlapic_find_highest_isr(struct vlapic *vlapic)
+{
+ int result;
+
+ result = find_highest_bit((uint32_t *)&vlapic->isr[0], INTR_LEN_32);
+
+ if (result != -1 && result < 16) {
+ int i = 0;
+ printk("VLAPIC: isr on reserved bits %d, isr is\n ", result);
+ for (i = 0; i < INTR_LEN_32; i += 2)
+ printk("%d: 0x%08x%08x\n", i, vlapic->isr[i], vlapic->isr[i+1]);
+ return -1;
+ }
+
+ return result;
+}
+
+uint32_t vlapic_update_ppr(struct vlapic *vlapic)
+{
+ uint32_t tpr, isrv, ppr;
+ int isr;
+
+ tpr = (vlapic->task_priority >> 4) & 0xf; /* we want 7:4 */
+
+ isr = vlapic_find_highest_isr(vlapic);
+ if (isr != -1)
+ isrv = (isr >> 4) & 0xf; /* ditto */
+ else
+ isrv = 0;
+
+ if (tpr >= isrv)
+ ppr = vlapic->task_priority & 0xff;
+ else
+ ppr = isrv << 4; /* low 4 bits of PPR have to be cleared */
+
+ vlapic->processor_priority = ppr;
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT,
+ "vlapic_update_ppr: vlapic %p ppr %x isr %x isrv %x",
+ vlapic, ppr, isr, isrv);
+
+ return ppr;
+}
+
+/* This only for fixed delivery mode */
+int vlapic_match_dest(struct vlapic *target, struct vlapic *source,
+ int short_hand, int dest, int dest_mode,
+ int delivery_mode)
+{
+ int result = 0;
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
+ "target %p source %p dest %x dest_mode %x short_hand %x "
+ "delivery_mode %x",
+ target, source, dest, dest_mode, short_hand, delivery_mode);
+
+ switch (short_hand) {
+ case VLAPIC_NO_SHORTHAND:
+ if (!dest_mode) { /* Physical */
+ result = (target->id == dest);
+ } else { /* Logical */
+ if (((target->dest_format >> 28) & 0xf) == 0xf) { /* Flat mode */
+ result = (target->logical_dest >> 24) & dest;
+ } else {
+ if ((delivery_mode == VLAPIC_DELIV_MODE_LPRI) &&
+ (dest == 0xff)) {
+ /* What shall we do now? */
+ printk("Broadcast IPI with lowest priority "
+ "delivery mode\n");
+ domain_crash_synchronous();
+ }
+ result = (target->logical_dest == (dest & 0xf)) ?
+ ((target->logical_dest >> 4) & (dest >> 4)) : 0;
+ }
+ }
+ break;
+
+ case VLAPIC_SHORTHAND_SELF:
+ if (target == source)
+ result = 1;
+ break;
+
+ case VLAPIC_SHORTHAND_INCLUDE_SELF:
+ result = 1;
+ break;
+
+ case VLAPIC_SHORTHAND_EXCLUDE_SELF:
+ if (target != source)
+ result = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * Add a pending IRQ into lapic.
+ * Return 1 if successfully added and 0 if discarded.
+ */
+int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode,
+ int vector, int level, int trig_mode)
+{
+ int result = 1;
+
+ switch (delivery_mode) {
+ case VLAPIC_DELIV_MODE_FIXED:
+ case VLAPIC_DELIV_MODE_LPRI:
+ /* FIXME add logic for vcpu on reset */
+ if (!vlapic->vcpu || !vlapic_enabled(vlapic))
+ return 0;
+
+ if (test_and_set_bit(vector, &vlapic->irr[0])) {
+ printk("<vlapic_accept_irq>"
+ "level trig mode repeatedly for vector %d\n", vector);
+ result = 0;
+ } else {
+ if (level) {
+ printk("<vlapic_accept_irq> level trig mode for vector %d\n",
vector);
+ set_bit(vector, &vlapic->tmr[0]);
+ }
+ }
+ evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
+ break;
+
+ case VLAPIC_DELIV_MODE_RESERVED:
+ printk("Ignore deliver mode 3 in vlapic_accept_irq\n");
+ break;
+
+ case VLAPIC_DELIV_MODE_SMI:
+ case VLAPIC_DELIV_MODE_NMI:
+ /* Fixme */
+ printk("TODO: for guest SMI/NMI\n");
+ break;
+
+ case VLAPIC_DELIV_MODE_INIT:
+ if (!level && trig_mode == 1) { //Deassert
+ printk("This vmx_vlapic is for P4, no work for De-assert init\n");
+ } else {
+ /* FIXME How to check the situation after vcpu reset? */
+ vlapic->init_sipi_sipi_state =
VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
+ if (vlapic->vcpu) {
+ vcpu_pause(vlapic->vcpu);
+ }
+ }
+ break;
+
+ case VLAPIC_DELIV_MODE_STARTUP:
+ if (vlapic->init_sipi_sipi_state !=
VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI)
+ break;
+ vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_NORM;
+ if (!vlapic->vcpu) {
+ /* XXX Call vmx_bringup_ap here */
+ result = 0;
+ }else{
+ //vmx_vcpu_reset(vlapic->vcpu);
+ }
+ break;
+
+ default:
+ printk("TODO: not support interrup type %x\n", delivery_mode);
+ domain_crash_synchronous();
+ break;
+ }
+
+ return result;
+}
+/*
+ This function is used by both ioapic and local APIC
+ The bitmap is for vcpu_id
+ */
+struct vlapic* apic_round_robin(struct domain *d,
+ uint8_t dest_mode,
+ uint8_t vector,
+ uint32_t bitmap)
+{
+ int next, old;
+ struct vlapic* target = NULL;
+
+ if (dest_mode == 0) { //Physical mode
+ printk("<apic_round_robin> lowest priority for physical mode\n");
+ return NULL;
+ }
+
+ if (!bitmap) {
+ printk("<apic_round_robin> no bit on bitmap\n");
+ return NULL;
+ }
+
+ spin_lock(&d->arch.vmx_platform.round_robin_lock);
+
+ old = next = d->arch.vmx_platform.round_info[vector];
+
+ next++;
+ if (next == MAX_VIRT_CPUS || !d->vcpu[next])
+ next = 0;
+
+ do {
+ /* the vcpu array is arranged according to vcpu_id */
+ if (test_bit(next, &bitmap)) {
+ target = d->vcpu[next]->arch.arch_vmx.vlapic;
+ if (!vlapic_enabled(target)) {
+ printk("warning: targe round robin local apic disabled\n");
+ /* XXX should we domain crash?? Or should we return NULL */
+ }
+ break;
+ }
+
+ next ++;
+ if (next == MAX_VIRT_CPUS || !d->vcpu[next])
+ next = 0;
+ }while(next != old);
+
+ d->arch.vmx_platform.round_info[vector] = next;
+ spin_unlock(&d->arch.vmx_platform.round_robin_lock);
+ return target;
+}
+
+void
+vlapic_EOI_set(struct vlapic *vlapic)
+{
+ int vector = vlapic_find_highest_isr(vlapic);
+
+ /* Not every write EOI will has correpsoning ISR,
+ one example is when Kernel check timer on setup_IO_APIC */
+ if (vector == -1) {
+ return ;
+ }
+
+ vlapic_clear_isr(vlapic, vector);
+ vlapic_update_ppr(vlapic);
+}
+
+int vlapic_check_vector(struct vlapic *vlapic,
+ unsigned char dm, int vector)
+{
+ if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) {
+ vlapic->err_status |= 0x40;
+ vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED,
+ vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0);
+ printk("<vlapic_check_vector>: check fail\n");
+ return 0;
+ }
+ return 1;
+}
+
+
+void vlapic_ipi(struct vlapic *vlapic)
+{
+ unsigned int dest = (vlapic->icr_high >> 24) & 0xff;
+ unsigned int short_hand = (vlapic->icr_low >> 18) & 3;
+ unsigned int trig_mode = (vlapic->icr_low >> 15) & 1;
+ unsigned int level = (vlapic->icr_low >> 14) & 1;
+ unsigned int dest_mode = (vlapic->icr_low >> 11) & 1;
+ unsigned int delivery_mode = (vlapic->icr_low >> 8) & 7;
+ unsigned int vector = (vlapic->icr_low & 0xff);
+
+ struct vlapic *target;
+ struct vcpu *v = NULL;
+ int result = 0;
+ uint32_t lpr_map;
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
+ "icr_high %x icr_low %x "
+ "short_hand %x dest %x trig_mode %x level %x "
+ "dest_mode %x delivery_mode %x vector %x",
+ vlapic->icr_high, vlapic->icr_low,
+ short_hand, dest, trig_mode, level, dest_mode,
+ delivery_mode, vector);
+
+ for_each_vcpu ( vlapic->domain, v ) {
+ target = VLAPIC(v);
+ if (vlapic_match_dest(target, vlapic, short_hand,
+ dest, dest_mode, delivery_mode)) {
+ if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
+ set_bit(v->vcpu_id, &lpr_map);
+ }else
+ result = vlapic_accept_irq(target, delivery_mode,
+ vector, level, trig_mode);
+ }
+ }
+
+ if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
+ extern struct vlapic*
+ apic_round_robin(struct domain *d,
+ uint8_t dest_mode, uint8_t vector, uint32_t bitmap);
+
+ v = vlapic->vcpu;
+ target = apic_round_robin(v->domain, dest_mode, vector, lpr_map);
+
+ if (target)
+ vlapic_accept_irq(target, delivery_mode,
+ vector, level, trig_mode);
+ }
+}
+
+void vlapic_begin_timer(struct vlapic *vlapic)
+{
+ s_time_t cur = NOW(), offset;
+
+ offset = vlapic->timer_current *
+ (262144 / get_apic_bus_scale()) * vlapic->timer_divide_counter;
+ vlapic->vlapic_timer.expires = cur + offset;
+
+ set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires );
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_begin_timer: "
+ "bus_scale %x now %08x%08x expire %08x%08x "
+ "offset %08x%08x current %x",
+ get_apic_bus_scale(), (uint32_t)(cur >> 32), (uint32_t)cur,
+ (uint32_t)(vlapic->vlapic_timer.expires >> 32),
+ (uint32_t) vlapic->vlapic_timer.expires,
+ (uint32_t)(offset >> 32), (uint32_t)offset,
+ vlapic->timer_current);
+}
+
+void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
+ unsigned int len, unsigned int *result)
+{
+ if (len != 4) {
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ "local apic read with len=%d (should be 4)", len);
+ }
+
+ *result = 0;
+
+ switch (offset) {
+ case APIC_ID:
+ *result = (vlapic->id) << 24;
+ break;
+
+ case APIC_LVR:
+ *result = vlapic->version;
+ break;
+
+ case APIC_TASKPRI:
+ *result = vlapic->task_priority;
+ break;
+
+ case APIC_ARBPRI:
+ printk("Access local APIC ARBPRI register which is for P6\n");
+ break;
+
+ case APIC_PROCPRI:
+ *result = vlapic->processor_priority;
+ break;
+
+ case APIC_EOI: /* EOI is write only */
+ break;
+
+ case APIC_LDR:
+ *result = vlapic->logical_dest;
+ break;
+
+ case APIC_DFR:
+ *result = vlapic->dest_format;
+ break;
+
+ case APIC_SPIV:
+ *result = vlapic->spurious_vec;
+ break;
+
+ case APIC_ISR:
+ case 0x110:
+ case 0x120:
+ case 0x130:
+ case 0x140:
+ case 0x150:
+ case 0x160:
+ case 0x170:
+ *result = vlapic->isr[(offset - APIC_ISR) >> 4];
+ break;
+
+ case APIC_TMR:
+ case 0x190:
+ case 0x1a0:
+ case 0x1b0:
+ case 0x1c0:
+ case 0x1d0:
+ case 0x1e0:
+ case 0x1f0:
+ *result = vlapic->tmr[(offset - APIC_TMR) >> 4];
+ break;
+
+ case APIC_IRR:
+ case 0x210:
+ case 0x220:
+ case 0x230:
+ case 0x240:
+ case 0x250:
+ case 0x260:
+ case 0x270:
+ *result = vlapic->irr[(offset - APIC_IRR) >> 4];
+ break;
+
+ case APIC_ESR:
+ if (vlapic->err_write_count)
+ *result = vlapic->err_status;
+ break;
+
+ case APIC_ICR:
+ *result = vlapic->icr_low;
+ break;
+
+ case APIC_ICR2:
+ *result = vlapic->icr_high;
+ break;
+
+ case APIC_LVTT: /* LVT Timer Reg */
+ case APIC_LVTTHMR: /* LVT Thermal Monitor */
+ case APIC_LVTPC: /* LVT Performance Counter */
+ case APIC_LVT0: /* LVT LINT0 Reg */
+ case APIC_LVT1: /* LVT Lint1 Reg */
+ case APIC_LVTERR: /* LVT Error Reg */
+ *result = vlapic->lvt[(offset - APIC_LVTT) >> 4];
+ break;
+
+ case APIC_TMICT:
+ *result = vlapic->timer_initial;
+ break;
+
+ case APIC_TMCCT: //Timer CCR
+ {
+ uint32_t counter;
+ s_time_t passed, cur = NOW();
+
+ if (cur <= vlapic->timer_current_update) {
+ passed = ~0x0LL - vlapic->timer_current_update + cur;
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC,"time elapsed");
+ }else
+ passed = cur - vlapic->timer_current_update;
+
+ counter = (passed * get_apic_bus_scale()) / (262144*
vlapic->timer_divide_counter);
+ if (vlapic->timer_current > counter)
+ *result = vlapic->timer_current - counter;
+ else {
+ if (!vlapic_lvt_timer_period(vlapic))
+ *result = 0;
+ //FIXME should we add interrupt here?
+ else
+ //*result = counter % vlapic->timer_initial;
+ *result = vlapic->timer_initial - (counter -
vlapic->timer_current);
+ }
+ vlapic->timer_current = *result;
+ vlapic->timer_current_update = NOW();
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ "initial %x timer current %x "
+ "update %08x%08x cur %08x%08x offset %d",
+ vlapic->timer_initial, vlapic->timer_current,
+ (uint32_t)(vlapic->timer_current_update >> 32),
+ (uint32_t)vlapic->timer_current_update ,
+ (uint32_t)(cur >> 32), (uint32_t)cur, counter);
+ }
+ break;
+
+ case APIC_TDCR:
+ *result = vlapic->timer_divconf;
+ break;
+
+ default:
+ printk("Read local APIC address %x not implemented\n",offset);
+ *result = 0;
+ break;
+ }
+}
+
+unsigned long vlapic_read(struct vcpu *v, unsigned long address,
+ unsigned long len)
+{
+ unsigned int alignment;
+ unsigned int tmp;
+ unsigned long result;
+ struct vlapic *vlapic = VLAPIC(v);
+ unsigned int offset = address - vlapic->base_address;
+
+ if ( len != 4) {
+ /* some bugs on kernel cause read this with byte*/
+ printk("Local APIC read with len = %lx, should be 4 instead\n", len);
+ }
+
+ alignment = offset & 0x3;
+
+ vlapic_read_aligned(vlapic, offset & ~0x3, 4, &tmp);
+ switch (len) {
+ case 1:
+ result = *((unsigned char *)&tmp + alignment);
+ break;
+
+ case 2:
+ result = *(unsigned short *)((unsigned char *)&tmp + alignment);
+ break;
+
+ case 4:
+ result = *(unsigned int *)((unsigned char *)&tmp + alignment);
+ break;
+
+ default:
+ printk("Local APIC read with len = %lx, should be 4 instead\n", len);
+ domain_crash_synchronous();
+ break;
+ }
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ "vlapic_read offset %x with length %lx and the result is %lx",
+ offset, len, result);
+ return result;
+}
+
+unsigned long vlapic_write(struct vcpu *v, unsigned long address,
+ unsigned long len, unsigned long val)
+{
+ struct vlapic *vlapic = VLAPIC(v);
+ unsigned int offset = address - vlapic->base_address;
+
+ if (offset != 0xb0)
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ "vlapic_write offset %x with length %lx source %lx",
+ offset, len, val);
+
+ /*
+ * According to IA 32 Manual, all resgiters should be accessed with
+ * 32 bits alignment.
+ */
+ if (len != 4) {
+ unsigned int tmp;
+ unsigned char alignment;
+
+ /* Some kernel do will access with byte/word alignment*/
+ printk("Notice: Local APIC write with len = %lx\n",len);
+ alignment = offset & 0x3;
+ tmp = vlapic_read(v, offset & (~0x3), 4);
+ switch (len) {
+ case 1:
+ /* XXX the saddr is a tmp variable from caller, so should be ok
+ But we should still change the following ref to val to
+ local variable later */
+ val = (tmp & ~(0xff << alignment)) |
+ ((val & 0xff) << alignment);
+ break;
+
+ case 2:
+ if (alignment != 0x0 && alignment != 0x2) {
+ printk("alignment error for vlapic with len == 2\n");
+ domain_crash_synchronous();
+ }
+
+ val = (tmp & ~(0xffff << alignment)) |
+ ((val & 0xffff) << alignment);
+ break;
+
+ case 3:
+ /* will it happen? */
+ printk("vlapic_write with len = 3 !!!\n");
+ domain_crash_synchronous();
+ break;
+
+ default:
+ printk("Local APIC write with len = %lx, should be 4 instead\n",
len);
+ domain_crash_synchronous();
+ break;
+ }
+ }
+
+ offset &= 0xff0;
+
+ switch (offset) {
+ case APIC_ID: /* Local APIC ID */
+ vlapic->id = ((val) >> 24) & VAPIC_ID_MASK;
+ break;
+
+ case APIC_TASKPRI:
+ vlapic->task_priority = val & 0xff;
+ vlapic_update_ppr(vlapic);
+ break;
+
+ case APIC_EOI:
+ vlapic_EOI_set(vlapic);
+ break;
+
+ case APIC_LDR:
+ vlapic->logical_dest = val & VAPIC_LDR_MASK;
+ break;
+
+ case APIC_DFR:
+ vlapic->dest_format = val ;
+ break;
+
+ case APIC_SPIV:
+ vlapic->spurious_vec = val & 0x1ff;
+ if (!(vlapic->spurious_vec & 0x100)) {
+ int i = 0;
+ for (i=0; i < VLAPIC_LVT_NUM; i++)
+ vlapic->lvt[i] |= 0x10000;
+ vlapic->status |= VLAPIC_SOFTWARE_DISABLE_MASK;
+ }
+ else
+ vlapic->status &= ~VLAPIC_SOFTWARE_DISABLE_MASK;
+ break;
+
+ case APIC_ESR:
+ vlapic->err_write_count = !vlapic->err_write_count;
+ if (!vlapic->err_write_count)
+ vlapic->err_status = 0;
+ break;
+
+ case APIC_ICR:
+ /* No delay here, so we always clear the pending bit*/
+ vlapic->icr_low = val & ~(1 << 12);
+ vlapic_ipi(vlapic);
+ break;
+
+ case APIC_ICR2:
+ vlapic->icr_high = val & 0xff000000;
+ break;
+
+ case APIC_LVTT: // LVT Timer Reg
+ case APIC_LVTTHMR: // LVT Thermal Monitor
+ case APIC_LVTPC: // LVT Performance Counter
+ case APIC_LVT0: // LVT LINT0 Reg
+ case APIC_LVT1: // LVT Lint1 Reg
+ case APIC_LVTERR: // LVT Error Reg
+ {
+ int vt = (offset - APIC_LVTT) >> 4;
+
+ vlapic->lvt[vt] = val & vlapic_lvt_mask[vt];
+ if (vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK)
+ vlapic->lvt[vt] |= VLAPIC_LVT_BIT_MASK;
+
+ /* On hardware, when write vector less than 0x20 will error */
+ vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic->lvt[vt]),
+ vlapic_lvt_vector(vlapic, vt));
+
+ if (!vlapic->vcpu_id && (offset == APIC_LVT0)) {
+ if ((vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_DELIMOD)
+ == 0x700) {
+ if (!(vlapic->lvt[VLAPIC_LVT_LINT0] &
VLAPIC_LVT_BIT_MASK)) {
+ set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+ }else
+ clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+ }
+ else
+ clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+ }
+
+ }
+ break;
+
+ case APIC_TMICT:
+ if (vlapic_timer_active(vlapic))
+ rem_ac_timer(&(vlapic->vlapic_timer));
+
+ vlapic->timer_initial = val;
+ vlapic->timer_current = val;
+ vlapic->timer_current_update = NOW();
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ "timer_init %x timer_current %x timer_current_update %08x%08x",
+ vlapic->timer_initial, vlapic->timer_current,
(uint32_t)(vlapic->timer_current_update>>32),
(uint32_t)vlapic->timer_current_update);
+ vlapic_begin_timer(vlapic);
+ break;
+
+ case APIC_TDCR:
+ {
+ //FIXME clean this code
+ unsigned char tmp1,tmp2;
+ tmp1 = (val & 0xf);
+ tmp2 = ((tmp1 & 0x3 )|((tmp1 & 0x8) >>1)) + 1;
+ vlapic->timer_divide_counter = 0x1<<tmp2;
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ "timer divider is 0x%x",
+ vlapic->timer_divide_counter);
+ }
+ break;
+
+ default:
+ printk("Local APIC Write to read-only register\n");
+ break;
+ }
+ return 1;
+}
+
+int vlapic_range(struct vcpu *v, unsigned long addr)
+{
+ struct vlapic *vlapic = VLAPIC(v);
+
+ if (vlapic_global_enabled(vlapic) &&
+ (addr >= vlapic->base_address) &&
+ (addr <= (vlapic->base_address + VLOCAL_APIC_MEM_LENGTH)))
+ return 1;
+
+ return 0;
+}
+
+void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
+{
+ /* When apic disabled */
+ if (!vlapic)
+ return;
+
+ if (vlapic->vcpu_id)
+ value &= ~MSR_IA32_APICBASE_BSP;
+
+ vlapic->apic_base_msr = value;
+ vlapic->base_address = vlapic_get_base_address(vlapic);
+
+ if (!(value & 0x800))
+ set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status );
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ "apic base msr = 0x%08x%08x,\nbase address = 0x%lx",
+ (uint32_t)(vlapic->apic_base_msr >> 32),
+ (uint32_t)vlapic->apic_base_msr,
+ vlapic->base_address);
+}
+
+static inline int vlapic_get_init_id(struct vcpu *v)
+{
+ return v->vcpu_id;
+}
+
+void vlapic_timer_fn(void *data)
+{
+ struct vlapic *vlapic;
+
+ vlapic = data;
+ if (!vlapic_enabled(vlapic)) return;
+
+ vlapic->timer_current_update = NOW();
+
+ if (vlapic_lvt_timer_enabled(vlapic)) {
+ if (!vlapic_irr_status(vlapic,
+ vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER))) {
+ test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER),
+ &vlapic->irr[0]);
+ }
+ else
+ vlapic->intr_pending_count[vlapic_lvt_vector(vlapic,
VLAPIC_LVT_TIMER)]++;
+ }
+
+ vlapic->timer_current_update = NOW();
+ if (vlapic_lvt_timer_period(vlapic)) {
+ s_time_t offset;
+
+ vlapic->timer_current = vlapic->timer_initial;
+ offset = vlapic->timer_current * (262144/get_apic_bus_scale()) *
vlapic->timer_divide_counter;
+ vlapic->vlapic_timer.expires = NOW() + offset;
+ set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires);
+ }else {
+ vlapic->timer_current = 0;
+ }
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ "vlapic_timer_fn: now: %08x%08x expire %08x%08x init %x current %x",
+ (uint32_t)(NOW() >> 32),(uint32_t)NOW(),
+ (uint32_t)(vlapic->vlapic_timer.expires >> 32),
+ (uint32_t)vlapic->vlapic_timer.expires,
+ vlapic->timer_initial,vlapic->timer_current);
+}
+
+#if 0
+static int
+vlapic_check_direct_intr(struct vcpu *v, int * mode)
+{
+ struct vlapic *vlapic = VLAPIC(v);
+ int type;
+
+ type = __fls(vlapic->direct_intr.deliver_mode);
+ if (type == -1)
+ return -1;
+
+ *mode = type;
+ return 0;
+}
+#endif
+
+int
+vlapic_accept_pic_intr(struct vcpu *v)
+{
+ struct vlapic *vlapic = VLAPIC(v);
+
+ return vlapic ? test_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status) : 1;
+}
+
+int cpu_get_apic_interrupt(struct vcpu* v, int *mode)
+{
+ struct vlapic *vlapic = VLAPIC(v);
+
+ if (vlapic && vlapic_enabled(vlapic)) {
+ int highest_irr = vlapic_find_highest_irr(vlapic);
+
+ if (highest_irr != -1 && highest_irr >= vlapic->processor_priority) {
+ if (highest_irr < 0x10) {
+ vlapic->err_status |= 0x20;
+ /* XXX What will happen if this vector illegal stil */
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ "vmx_intr_assist: illegal vector number %x err_status %x",
+ highest_irr, vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR));
+
+ set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR),
&vlapic->irr[0]);
+ highest_irr = vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR);
+ }
+
+ *mode = VLAPIC_DELIV_MODE_FIXED;
+ return highest_irr;
+ }
+ }
+ return -1;
+}
+
+void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode) {
+ struct vlapic *vlapic = VLAPIC(v);
+
+ if (!vlapic)
+ return;
+
+ switch (deliver_mode) {
+ case VLAPIC_DELIV_MODE_FIXED:
+ case VLAPIC_DELIV_MODE_LPRI:
+ vlapic_set_isr(vlapic, vector);
+ vlapic_clear_irr(vlapic, vector);
+ vlapic_update_ppr(vlapic);
+
+ if (vector == vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)) {
+ vlapic->intr_pending_count[vector]--;
+ if (vlapic->intr_pending_count[vector] > 0)
+ test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER),
+ &vlapic->irr[0]);
+ }
+
+ break;
+ /*XXX deal with these later */
+
+ case VLAPIC_DELIV_MODE_RESERVED:
+ printk("Ignore deliver mode 3 in vlapic_post_injection\n");
+ break;
+
+ case VLAPIC_DELIV_MODE_SMI:
+ case VLAPIC_DELIV_MODE_NMI:
+ case VLAPIC_DELIV_MODE_INIT:
+ case VLAPIC_DELIV_MODE_STARTUP:
+ vlapic->direct_intr.deliver_mode &= ~(1 << deliver_mode);
+ break;
+
+ default:
+ printk("<vlapic_post_injection> error deliver mode\n");
+ break;
+ }
+}
+
+static int vlapic_reset(struct vlapic *vlapic)
+{
+ struct vcpu *v = vlapic->vcpu;
+ int apic_id = v->vcpu_id, i;
+
+ if (!v || !vlapic)
+ return 0;
+
+ memset(vlapic, 0,sizeof(struct vlapic));
+
+ v->arch.arch_vmx.vlapic = vlapic;
+
+ vlapic->domain = v->domain;
+
+ vlapic->id = apic_id;
+
+ vlapic->version = VLAPIC_VERSION;
+
+ vlapic->apic_base_msr = VLAPIC_BASE_MSR_INIT_VALUE;
+
+ if (apic_id == 0)
+ vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
+ vlapic->base_address = vlapic_get_base_address(vlapic);
+
+ for (i = 0; i < VLAPIC_LVT_NUM; i++)
+ vlapic->lvt[i] = VLAPIC_LVT_BIT_MASK;
+
+ vlapic->dest_format = 0xffffffffU;
+
+ vlapic->spurious_vec = 0xff;
+
+
+ init_ac_timer(&vlapic->vlapic_timer,
+ vlapic_timer_fn, vlapic, v->processor);
+
+#ifdef VLAPIC_NO_BIOS
+ /*
+ * XXX According to mp sepcific, BIOS will enable LVT0/1,
+ * remove it after BIOS enabled
+ */
+ if (!v->vcpu_id) {
+ vlapic->lvt[VLAPIC_LVT_LINT0] = 0x700;
+ vlapic->lvt[VLAPIC_LVT_LINT1] = 0x500;
+ set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
+ }
+#endif
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_reset: "
+ "vcpu=%p id=%d vlapic_apic_base_msr=%08x%08x "
+ "vlapic_base_address=%0lx",
+ v, vlapic->id, (uint32_t)(vlapic->apic_base_msr >> 32),
+ (uint32_t)vlapic->apic_base_msr, vlapic->base_address);
+
+ return 1;
+}
+
+int vlapic_init(struct vcpu *v)
+{
+ struct vlapic *vlapic = NULL;
+
+ VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id);
+
+ vlapic = xmalloc_bytes(sizeof(struct vlapic));
+
+ if (!vlapic) {
+ printk("malloc vlapic error for vcpu %x\n", v->vcpu_id);
+ return -ENOMEM;
+ }
+
+ vlapic->vcpu = v;
+
+ vlapic_reset(vlapic);
+
+ return 0;
+}
+
+#endif /* CONFIG_VMX */
diff -r f23b897930d1 -r cc23d4236b20 xen/include/asm-x86/vmx_vlapic.h
--- /dev/null Thu Oct 27 17:22:45 2005
+++ b/xen/include/asm-x86/vmx_vlapic.h Fri Oct 28 08:48:46 2005
@@ -0,0 +1,245 @@
+/*
+ * vmx_vlapic.h: virtualize LAPIC definitions.
+ * Copyright (c) 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#ifndef VMX_VLAPIC_H
+#define VMX_VLAPIC_H
+
+#include <asm/msr.h>
+#include <public/io/ioreq.h>
+
+#if defined(__i386__) || defined(__x86_64__)
+static inline int __fls(uint32_t word)
+{
+ int bit;
+
+ __asm__("bsrl %1,%0"
+ :"=r" (bit)
+ :"rm" (word));
+ return word ? bit : -1;
+}
+#else
+#define __fls(x) generic_fls(x)
+static __inline__ int generic_fls(uint32_t x)
+{
+ int r = 31;
+
+ if (!x)
+ return -1;
+ if (!(x & 0xffff0000u)) {
+ x <<= 16;
+ r -= 16;
+ }
+ if (!(x & 0xff000000u)) {
+ x <<= 8;
+ r -= 8;
+ }
+ if (!(x & 0xf0000000u)) {
+ x <<= 4;
+ r -= 4;
+ }
+ if (!(x & 0xc0000000u)) {
+ x <<= 2;
+ r -= 2;
+ }
+ if (!(x & 0x80000000u)) {
+ x <<= 1;
+ r -= 1;
+ }
+ return r;
+}
+#endif
+
+static __inline__ int find_highest_bit(uint32_t *data, int length)
+{
+ while(length && !data[--length]);
+ return __fls(data[length]) + 32 * length;
+}
+
+#define VLAPIC(v) (v->arch.arch_vmx.vlapic)
+
+#define VAPIC_ID_MASK 0xff
+#define VAPIC_LDR_MASK (VAPIC_ID_MASK << 24)
+#define VLAPIC_VERSION 0x00050014
+
+#define VLAPIC_BASE_MSR_MASK 0x00000000fffff900ULL
+#define VLAPIC_BASE_MSR_INIT_BASE_ADDR 0xfee00000U
+#define VLAPIC_BASE_MSR_BASE_ADDR_MASK 0xfffff000U
+#define VLAPIC_BASE_MSR_INIT_VALUE (VLAPIC_BASE_MSR_INIT_BASE_ADDR | \
+ MSR_IA32_APICBASE_ENABLE)
+#define VLOCAL_APIC_MEM_LENGTH (1 << 12)
+
+#define VLAPIC_LVT_TIMER 0
+#define VLAPIC_LVT_THERMAL 1
+#define VLAPIC_LVT_PERFORM 2
+#define VLAPIC_LVT_LINT0 3
+#define VLAPIC_LVT_LINT1 4
+#define VLAPIC_LVT_ERROR 5
+#define VLAPIC_LVT_NUM 6
+
+#define VLAPIC_LVT_BIT_MASK (1 << 16)
+#define VLAPIC_LVT_BIT_VECTOR 0xff
+#define VLAPIC_LVT_BIT_DELIMOD (0x7 << 8)
+#define VLAPIC_LVT_BIT_DELISTATUS (1 << 12)
+#define VLAPIC_LVT_BIT_POLARITY (1 << 13)
+#define VLAPIC_LVT_BIT_IRR (1 << 14)
+#define VLAPIC_LVT_BIT_TRIG (1 << 15)
+#define VLAPIC_LVT_TIMERMODE (1 << 17)
+
+#define VLAPIC_DELIV_MODE_FIXED 0x0
+#define VLAPIC_DELIV_MODE_LPRI 0x1
+#define VLAPIC_DELIV_MODE_SMI 0x2
+#define VLAPIC_DELIV_MODE_RESERVED 0x3
+#define VLAPIC_DELIV_MODE_NMI 0x4
+#define VLAPIC_DELIV_MODE_INIT 0x5
+#define VLAPIC_DELIV_MODE_STARTUP 0x6
+#define VLAPIC_DELIV_MODE_EXT 0x7
+
+
+
+#define VLAPIC_NO_SHORTHAND 0x0
+#define VLAPIC_SHORTHAND_SELF 0x1
+#define VLAPIC_SHORTHAND_INCLUDE_SELF 0x2
+#define VLAPIC_SHORTHAND_EXCLUDE_SELF 0x3
+
+#define vlapic_lvt_timer_enabled(vlapic) \
+ (!(vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_BIT_MASK))
+
+#define vlapic_lvt_vector(vlapic, type) \
+ (vlapic->lvt[type] & VLAPIC_LVT_BIT_VECTOR)
+
+#define vlapic_lvt_dm(value) ((value >> 8) && 7)
+#define vlapic_lvt_timer_period(vlapic) \
+ (vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_TIMERMODE)
+
+#define vlapic_isr_status(vlapic,vector) \
+ test_bit(vector, &vlapic->isr[0])
+
+#define vlapic_irr_status(vlapic,vector) \
+ test_bit(vector, &vlapic->irr[0])
+
+#define vlapic_set_isr(vlapic,vector) \
+ test_and_set_bit(vector, &vlapic->isr[0])
+
+#define vlapic_set_irr(vlapic,vector) \
+ test_and_set_bit(vector, &vlapic->irr[0])
+
+#define vlapic_clear_irr(vlapic,vector) \
+ clear_bit(vector, &vlapic->irr[0])
+#define vlapic_clear_isr(vlapic,vector) \
+ clear_bit(vector, &vlapic->isr[0])
+
+#define vlapic_enabled(vlapic) \
+ (!(vlapic->status & \
+ (VLAPIC_GLOB_DISABLE_MASK | VLAPIC_SOFTWARE_DISABLE_MASK)))
+
+#define vlapic_global_enabled(vlapic) \
+ !(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status))
+
+typedef struct direct_intr_info {
+ int deliver_mode;
+ int source[6];
+} direct_intr_info_t;
+
+#define VLAPIC_INIT_SIPI_SIPI_STATE_NORM 0
+#define VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI 1
+
+struct vlapic
+{
+ //FIXME check what would be 64 bit on EM64T
+ uint32_t version;
+#define _VLAPIC_GLOB_DISABLE 0x0
+#define VLAPIC_GLOB_DISABLE_MASK 0x1
+#define VLAPIC_SOFTWARE_DISABLE_MASK 0x2
+#define _VLAPIC_BSP_ACCEPT_PIC 0x3
+ uint32_t status;
+ uint32_t id;
+ uint32_t vcpu_id;
+ unsigned long base_address;
+ uint32_t isr[8];
+ uint32_t irr[INTR_LEN_32];
+ uint32_t tmr[INTR_LEN_32];
+ uint32_t task_priority;
+ uint32_t processor_priority;
+ uint32_t logical_dest;
+ uint32_t dest_format;
+ uint32_t spurious_vec;
+ uint32_t lvt[6];
+ uint32_t timer_initial;
+ uint32_t timer_current;
+ uint32_t timer_divconf;
+ uint32_t timer_divide_counter;
+ struct ac_timer vlapic_timer;
+ int intr_pending_count[MAX_VECTOR];
+ s_time_t timer_current_update;
+ uint32_t icr_high;
+ uint32_t icr_low;
+ direct_intr_info_t direct_intr;
+ uint32_t err_status;
+ unsigned long init_ticks;
+ uint32_t err_write_count;
+ uint64_t apic_base_msr;
+ uint32_t init_sipi_sipi_state;
+ struct vcpu *vcpu;
+ struct domain *domain;
+};
+
+static inline int vlapic_timer_active(struct vlapic *vlapic)
+{
+ return active_ac_timer(&(vlapic->vlapic_timer));
+}
+
+int vlapic_find_highest_irr(struct vlapic *vlapic);
+
+int vlapic_find_highest_isr(struct vlapic *vlapic);
+
+static uint32_t inline vlapic_get_base_address(struct vlapic *vlapic)
+{
+ return (vlapic->apic_base_msr & VLAPIC_BASE_MSR_BASE_ADDR_MASK);
+}
+
+void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode);
+
+int cpu_get_apic_interrupt(struct vcpu* v, int *mode);
+
+extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
+
+int vlapic_update(struct vcpu *v);
+
+extern int vlapic_init(struct vcpu *vc);
+
+extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
+
+int vlapic_range(struct vcpu *v, unsigned long addr);
+
+unsigned long vlapic_write(struct vcpu *v, unsigned long address,
+ unsigned long len, unsigned long val);
+
+unsigned long vlapic_read(struct vcpu *v, unsigned long address,
+ unsigned long len);
+
+int vlapic_accept_pic_intr(struct vcpu *v);
+
+struct vlapic* apic_round_robin(struct domain *d,
+ uint8_t dest_mode,
+ uint8_t vector,
+ uint32_t bitmap);
+
+int vmx_apic_support(struct domain *d);
+
+#endif /* VMX_VLAPIC_H */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|