direct-io.hg
changeset 7514:cc23d4236b20
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@intel.com>
Signed-off-by: Li Xin <xin.b.li@intel.com>
Signed-off-by: Eddie Dong <eddie.dong@intel.com>
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
A configure option is also added to disable it, which is off by default.
Signed-off-by: Jiang Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Li Xin <xin.b.li@intel.com>
Signed-off-by: Eddie Dong <eddie.dong@intel.com>
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
line diff
1.1 --- a/tools/libxc/xc_vmx_build.c Thu Oct 27 18:22:45 2005 +0100 1.2 +++ b/tools/libxc/xc_vmx_build.c Fri Oct 28 09:48:46 2005 +0100 1.3 @@ -279,6 +279,7 @@ static int setup_guest(int xc_handle, 1.4 vcpu_guest_context_t *ctxt, 1.5 unsigned long shared_info_frame, 1.6 unsigned int control_evtchn, 1.7 + unsigned int lapic, 1.8 unsigned int vcpus, 1.9 unsigned int store_evtchn, 1.10 unsigned long *store_mfn) 1.11 @@ -554,7 +555,7 @@ static int setup_guest(int xc_handle, 1.12 ctxt->user_regs.eax = 0; 1.13 ctxt->user_regs.esp = 0; 1.14 ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot cpu */ 1.15 - ctxt->user_regs.ecx = 0; 1.16 + ctxt->user_regs.ecx = lapic; 1.17 ctxt->user_regs.esi = 0; 1.18 ctxt->user_regs.edi = 0; 1.19 ctxt->user_regs.ebp = 0; 1.20 @@ -597,6 +598,7 @@ int xc_vmx_build(int xc_handle, 1.21 int memsize, 1.22 const char *image_name, 1.23 unsigned int control_evtchn, 1.24 + unsigned int lapic, 1.25 unsigned int vcpus, 1.26 unsigned int store_evtchn, 1.27 unsigned long *store_mfn) 1.28 @@ -651,9 +653,9 @@ int xc_vmx_build(int xc_handle, 1.29 goto error_out; 1.30 } 1.31 1.32 - if ( setup_guest(xc_handle, domid, memsize, image, image_size, 1.33 - nr_pages, ctxt, op.u.getdomaininfo.shared_info_frame, 1.34 - control_evtchn, vcpus, store_evtchn, store_mfn) < 0) 1.35 + if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages, 1.36 + ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn, 1.37 + lapic, vcpus, store_evtchn, store_mfn) < 0) 1.38 { 1.39 ERROR("Error constructing guest OS"); 1.40 goto error_out;
2.1 --- a/tools/libxc/xenguest.h Thu Oct 27 18:22:45 2005 +0100 2.2 +++ b/tools/libxc/xenguest.h Fri Oct 28 09:48:46 2005 +0100 2.3 @@ -56,6 +56,7 @@ int xc_vmx_build(int xc_handle, 2.4 int memsize, 2.5 const char *image_name, 2.6 unsigned int control_evtchn, 2.7 + unsigned int lapic, 2.8 unsigned int vcpus, 2.9 unsigned int store_evtchn, 2.10 unsigned long *store_mfn);
3.1 --- a/tools/python/xen/lowlevel/xc/xc.c Thu Oct 27 18:22:45 2005 +0100 3.2 +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 28 09:48:46 2005 +0100 3.3 @@ -438,19 +438,20 @@ static PyObject *pyxc_vmx_build(PyObject 3.4 char *image; 3.5 int control_evtchn, store_evtchn; 3.6 int vcpus = 1; 3.7 + int lapic = 0; 3.8 int memsize; 3.9 unsigned long store_mfn = 0; 3.10 3.11 static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn", 3.12 - "memsize", "image", "vcpus", NULL }; 3.13 + "memsize", "image", "lapic", "vcpus", NULL }; 3.14 3.15 - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisi", kwd_list, 3.16 + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list, 3.17 &dom, &control_evtchn, &store_evtchn, 3.18 - &memsize, &image, &vcpus) ) 3.19 + &memsize, &image, &lapic, &vcpus) ) 3.20 return NULL; 3.21 3.22 if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn, 3.23 - vcpus, store_evtchn, &store_mfn) != 0 ) 3.24 + lapic, vcpus, store_evtchn, &store_mfn) != 0 ) 3.25 return PyErr_SetFromErrno(xc_error); 3.26 3.27 return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
4.1 --- a/tools/python/xen/xend/image.py Thu Oct 27 18:22:45 2005 +0100 4.2 +++ b/tools/python/xen/xend/image.py Fri Oct 28 09:48:46 2005 +0100 4.3 @@ -203,6 +203,10 @@ class VmxImageHandler(ImageHandler): 4.4 4.5 self.dmargs += self.configVNC(imageConfig) 4.6 4.7 + self.lapic = 0 4.8 + lapic = sxp.child_value(imageConfig, 'lapic') 4.9 + if not lapic is None: 4.10 + self.lapic = int(lapic) 4.11 4.12 def buildDomain(self): 4.13 # Create an event channel 4.14 @@ -217,6 +221,7 @@ class VmxImageHandler(ImageHandler): 4.15 log.debug("control_evtchn = %d", self.device_channel) 4.16 log.debug("store_evtchn = %d", store_evtchn) 4.17 log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024) 4.18 + log.debug("lapic = %d", self.lapic) 4.19 log.debug("vcpus = %d", self.vm.getVCpuCount()) 4.20 4.21 return xc.vmx_build(dom = self.vm.getDomid(), 4.22 @@ -224,6 +229,7 @@ class VmxImageHandler(ImageHandler): 4.23 control_evtchn = self.device_channel, 4.24 store_evtchn = store_evtchn, 4.25 memsize = self.vm.getMemoryTarget() / 1024, 4.26 + lapic = self.lapic, 4.27 vcpus = self.vm.getVCpuCount()) 4.28 4.29
5.1 --- a/tools/python/xen/xm/create.py Thu Oct 27 18:22:45 2005 +0100 5.2 +++ b/tools/python/xen/xm/create.py Fri Oct 28 09:48:46 2005 +0100 5.3 @@ -158,6 +158,10 @@ gopts.var('cpu', val='CPU', 5.4 fn=set_int, default=None, 5.5 use="CPU to run the domain on.") 5.6 5.7 +gopts.var('lapic', val='LAPIC', 5.8 + fn=set_int, default=0, 5.9 + use="Disable or enable local APIC of VMX domain.") 5.10 + 5.11 gopts.var('vcpus', val='VCPUS', 5.12 fn=set_int, default=1, 5.13 use="# of Virtual CPUS in domain.") 5.14 @@ -316,10 +320,6 @@ gopts.var('nfs_root', val="PATH", 5.15 fn=set_value, default=None, 5.16 use="Set the path of the root NFS directory.") 5.17 5.18 -gopts.var('memmap', val='FILE', 5.19 - fn=set_value, default='', 5.20 - use="Path to memap SXP file.") 5.21 - 5.22 gopts.var('device_model', val='FILE', 5.23 fn=set_value, default='', 5.24 use="Path to device model program.") 5.25 @@ -542,9 +542,9 @@ def configure_vfr(opts, config, vals): 5.26 def configure_vmx(opts, config_image, vals): 5.27 """Create the config for VMX devices. 5.28 """ 5.29 - args = [ 'memmap', 'device_model', 'vcpus', 'cdrom', 5.30 - 'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga', 5.31 - 'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000'] 5.32 + args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb', 5.33 + 'localtime', 'serial', 'macaddr', 'stdvga', 'isa', 'nographic', 5.34 + 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic'] 5.35 for a in args: 5.36 if (vals.__dict__[a]): 5.37 config_image.append([a, vals.__dict__[a]])
6.1 --- a/xen/arch/x86/apic.c Thu Oct 27 18:22:45 2005 +0100 6.2 +++ b/xen/arch/x86/apic.c Fri Oct 28 09:48:46 2005 +0100 6.3 @@ -815,6 +815,10 @@ int __init calibrate_APIC_clock(void) 6.4 return result; 6.5 } 6.6 6.7 +unsigned int get_apic_bus_scale(void) 6.8 +{ 6.9 + return bus_scale; 6.10 +} 6.11 6.12 static unsigned int calibration_result; 6.13
7.1 --- a/xen/arch/x86/dm/i8259.c Thu Oct 27 18:22:45 2005 +0100 7.2 +++ b/xen/arch/x86/dm/i8259.c Fri Oct 28 09:48:46 2005 +0100 7.3 @@ -32,8 +32,8 @@ 7.4 #include <public/io/ioreq.h> 7.5 #include <asm/vmx.h> 7.6 #include <public/io/vmx_vpic.h> 7.7 -#include <public/io/vmx_vlapic.h> 7.8 #include <asm/current.h> 7.9 +#include <asm/vmx_vlapic.h> 7.10 7.11 /* set irq level. If an edge is detected, then the IRR is set to 1 */ 7.12 static inline void pic_set_irq1(PicState *s, int irq, int level) 7.13 @@ -135,7 +135,6 @@ void do_pic_irqs (struct vmx_virpic *s, 7.14 { 7.15 s->pics[1].irr |= (uint8_t)(irqs >> 8); 7.16 s->pics[0].irr |= (uint8_t) irqs; 7.17 - /* TODO for alt_irq_func */ 7.18 pic_update_irq(s); 7.19 } 7.20 7.21 @@ -505,14 +504,22 @@ int cpu_get_pic_interrupt(struct vcpu *v 7.22 { 7.23 int intno; 7.24 struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic; 7.25 - 7.26 + struct vmx_platform *plat = &v->domain->arch.vmx_platform; 7.27 + 7.28 + if ( !vlapic_accept_pic_intr(v) ) 7.29 + return -1; 7.30 + 7.31 + if ( !plat->interrupt_request ) 7.32 + return -1; 7.33 + 7.34 /* read the irq from the PIC */ 7.35 intno = pic_read_irq(s); 7.36 *type = VLAPIC_DELIV_MODE_EXT; 7.37 + plat->interrupt_request = 0; 7.38 return intno; 7.39 } 7.40 7.41 -int is_pit_irq(struct vcpu *v, int irq) 7.42 +int is_pit_irq(struct vcpu *v, int irq, int type) 7.43 { 7.44 int pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base; 7.45
8.1 --- a/xen/arch/x86/vmx.c Thu Oct 27 18:22:45 2005 +0100 8.2 +++ b/xen/arch/x86/vmx.c Fri Oct 28 09:48:46 2005 +0100 8.3 @@ -65,6 +65,11 @@ void vmx_final_setup_guest(struct vcpu * 8.4 8.5 if ( v == v->domain->vcpu[0] ) 8.6 { 8.7 + v->domain->arch.vmx_platform.lapic_enable = 8.8 + v->arch.guest_context.user_regs.ecx; 8.9 + v->arch.guest_context.user_regs.ecx = 0; 8.10 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "lapic enable is %d.\n", 8.11 + v->domain->arch.vmx_platform.lapic_enable); 8.12 /* 8.13 * Required to do this once per domain 8.14 * XXX todo: add a seperate function to do these. 8.15 @@ -96,6 +101,10 @@ void vmx_relinquish_resources(struct vcp 8.16 destroy_vmcs(&v->arch.arch_vmx); 8.17 free_monitor_pagetable(v); 8.18 rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer); 8.19 + if ( vmx_apic_support(v->domain) ) { 8.20 + rem_ac_timer( &(VLAPIC(v)->vlapic_timer) ); 8.21 + xfree( VLAPIC(v) ); 8.22 + } 8.23 } 8.24 8.25 #ifdef __x86_64__ 8.26 @@ -442,7 +451,9 @@ static int vmx_do_page_fault(unsigned lo 8.27 8.28 /* Use 1:1 page table to identify MMIO address space */ 8.29 if ( mmio_space(gpa) ){ 8.30 - if (gpa >= 0xFEE00000) { /* workaround for local APIC */ 8.31 + struct vcpu *v = current; 8.32 + /* No support for APIC */ 8.33 + if (!vmx_apic_support(v->domain) && gpa >= 0xFEC00000) { 8.34 u32 inst_len; 8.35 __vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len)); 8.36 __update_guest_eip(inst_len); 8.37 @@ -487,6 +498,7 @@ static void vmx_vmexit_do_cpuid(unsigned 8.38 { 8.39 unsigned int eax, ebx, ecx, edx; 8.40 unsigned long eip; 8.41 + struct vcpu *v = current; 8.42 8.43 __vmread(GUEST_RIP, &eip); 8.44 8.45 @@ -500,6 +512,9 @@ static void vmx_vmexit_do_cpuid(unsigned 8.46 cpuid(input, &eax, &ebx, &ecx, &edx); 8.47 8.48 if (input == 1) { 8.49 + if ( vmx_apic_support(v->domain) && 8.50 + !vlapic_global_enabled((VLAPIC(v))) ) 8.51 + clear_bit(X86_FEATURE_APIC, &edx); 8.52 #ifdef __i386__ 8.53 clear_bit(X86_FEATURE_PSE, &edx); 8.54 clear_bit(X86_FEATURE_PAE, &edx); 8.55 @@ -1441,6 +1456,7 @@ static int vmx_cr_access(unsigned long e 8.56 static inline void vmx_do_msr_read(struct cpu_user_regs *regs) 8.57 { 8.58 u64 msr_content = 0; 8.59 + struct vcpu *v = current; 8.60 8.61 VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx", 8.62 (unsigned long)regs->ecx, (unsigned long)regs->eax, 8.63 @@ -1455,6 +1471,9 @@ static inline void vmx_do_msr_read(struc 8.64 case MSR_IA32_SYSENTER_EIP: 8.65 __vmread(GUEST_SYSENTER_EIP, &msr_content); 8.66 break; 8.67 + case MSR_IA32_APICBASE: 8.68 + msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0; 8.69 + break; 8.70 default: 8.71 if(long_mode_do_msr_read(regs)) 8.72 return; 8.73 @@ -1474,6 +1493,7 @@ static inline void vmx_do_msr_read(struc 8.74 static inline void vmx_do_msr_write(struct cpu_user_regs *regs) 8.75 { 8.76 u64 msr_content; 8.77 + struct vcpu *v = current; 8.78 8.79 VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx", 8.80 (unsigned long)regs->ecx, (unsigned long)regs->eax, 8.81 @@ -1491,6 +1511,9 @@ static inline void vmx_do_msr_write(stru 8.82 case MSR_IA32_SYSENTER_EIP: 8.83 __vmwrite(GUEST_SYSENTER_EIP, msr_content); 8.84 break; 8.85 + case MSR_IA32_APICBASE: 8.86 + vlapic_msr_set(VLAPIC(v), msr_content); 8.87 + break; 8.88 default: 8.89 long_mode_do_msr_write(regs); 8.90 break;
9.1 --- a/xen/arch/x86/vmx_intercept.c Thu Oct 27 18:22:45 2005 +0100 9.2 +++ b/xen/arch/x86/vmx_intercept.c Fri Oct 28 09:48:46 2005 +0100 9.3 @@ -23,6 +23,7 @@ 9.4 #include <asm/vmx_platform.h> 9.5 #include <asm/vmx_virpit.h> 9.6 #include <asm/vmx_intercept.h> 9.7 +#include <asm/vmx_vlapic.h> 9.8 #include <public/io/ioreq.h> 9.9 #include <xen/lib.h> 9.10 #include <xen/sched.h> 9.11 @@ -32,6 +33,123 @@ 9.12 9.13 #ifdef CONFIG_VMX 9.14 9.15 +struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR] = 9.16 +{ 9.17 + { 9.18 + .check_handler = vlapic_range, 9.19 + .read_handler = vlapic_read, 9.20 + .write_handler = vlapic_write 9.21 + } 9.22 +}; 9.23 + 9.24 +static inline void vmx_mmio_access(struct vcpu *v, 9.25 + ioreq_t *p, 9.26 + vmx_mmio_read_t read_handler, 9.27 + vmx_mmio_write_t write_handler) 9.28 +{ 9.29 + ioreq_t *req; 9.30 + vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id); 9.31 + unsigned int tmp1, tmp2; 9.32 + unsigned long data; 9.33 + 9.34 + if (vio == NULL) { 9.35 + printk("vlapic_access: bad shared page\n"); 9.36 + domain_crash_synchronous(); 9.37 + } 9.38 + 9.39 + req = &vio->vp_ioreq; 9.40 + 9.41 + switch (req->type) { 9.42 + case IOREQ_TYPE_COPY: 9.43 + { 9.44 + int sign = (req->df) ? -1 : 1, i; 9.45 + 9.46 + if (!req->pdata_valid) { 9.47 + if (req->dir == IOREQ_READ){ 9.48 + req->u.data = read_handler(v, req->addr, req->size); 9.49 + } else { /* req->dir != IOREQ_READ */ 9.50 + write_handler(v, req->addr, req->size, req->u.data); 9.51 + } 9.52 + } else { /* !req->pdata_valid */ 9.53 + if (req->dir == IOREQ_READ) { 9.54 + for (i = 0; i < req->count; i++) { 9.55 + data = read_handler(v, 9.56 + req->addr + (sign * i * req->size), 9.57 + req->size); 9.58 + vmx_copy(&data, 9.59 + (unsigned long)p->u.pdata + (sign * i * req->size), 9.60 + p->size, 9.61 + VMX_COPY_OUT); 9.62 + } 9.63 + } else { /* !req->dir == IOREQ_READ */ 9.64 + for (i = 0; i < req->count; i++) { 9.65 + vmx_copy(&data, 9.66 + (unsigned long)p->u.pdata + (sign * i * req->size), 9.67 + p->size, 9.68 + VMX_COPY_IN); 9.69 + write_handler(v, 9.70 + req->addr + (sign * i * req->size), 9.71 + req->size, data); 9.72 + } 9.73 + } 9.74 + } 9.75 + break; 9.76 + } 9.77 + 9.78 + case IOREQ_TYPE_AND: 9.79 + tmp1 = read_handler(v, req->addr, req->size); 9.80 + if (req->dir == IOREQ_WRITE) { 9.81 + tmp2 = tmp1 & (unsigned long) req->u.data; 9.82 + write_handler(v, req->addr, req->size, tmp2); 9.83 + } 9.84 + req->u.data = tmp1; 9.85 + break; 9.86 + 9.87 + case IOREQ_TYPE_OR: 9.88 + tmp1 = read_handler(v, req->addr, req->size); 9.89 + if (req->dir == IOREQ_WRITE) { 9.90 + tmp2 = tmp1 | (unsigned long) req->u.data; 9.91 + write_handler(v, req->addr, req->size, tmp2); 9.92 + } 9.93 + req->u.data = tmp1; 9.94 + break; 9.95 + 9.96 + case IOREQ_TYPE_XOR: 9.97 + tmp1 = read_handler(v, req->addr, req->size); 9.98 + if (req->dir == IOREQ_WRITE) { 9.99 + tmp2 = tmp1 ^ (unsigned long) req->u.data; 9.100 + write_handler(v, req->addr, req->size, tmp2); 9.101 + } 9.102 + req->u.data = tmp1; 9.103 + break; 9.104 + 9.105 + default: 9.106 + printk("error ioreq type for local APIC %x\n", req->type); 9.107 + domain_crash_synchronous(); 9.108 + break; 9.109 + } 9.110 +} 9.111 + 9.112 +int vmx_mmio_intercept(ioreq_t *p) 9.113 +{ 9.114 + struct vcpu *v = current; 9.115 + int i; 9.116 + struct vmx_mmio_handler *handler = vmx_mmio_handers; 9.117 + 9.118 + /* XXX currently only APIC use intercept */ 9.119 + if ( !vmx_apic_support(v->domain) ) 9.120 + return 0; 9.121 + 9.122 + for ( i = 0; i < VMX_MMIO_HANDLER_NR; i++ ) { 9.123 + if ( handler[i].check_handler(v, p->addr) ) { 9.124 + vmx_mmio_access(v, p, 9.125 + handler[i].read_handler, handler[i].write_handler); 9.126 + return 1; 9.127 + } 9.128 + } 9.129 + return 0; 9.130 +} 9.131 + 9.132 /* 9.133 * Check if the request is handled inside xen 9.134 * return value: 0 --not handled; 1 --handled
10.1 --- a/xen/arch/x86/vmx_io.c Thu Oct 27 18:22:45 2005 +0100 10.2 +++ b/xen/arch/x86/vmx_io.c Fri Oct 28 09:48:46 2005 +0100 10.3 @@ -36,9 +36,9 @@ 10.4 #include <asm/apic.h> 10.5 #include <asm/shadow.h> 10.6 10.7 +#include <asm/vmx_vlapic.h> 10.8 #include <public/io/ioreq.h> 10.9 #include <public/io/vmx_vpic.h> 10.10 -#include <public/io/vmx_vlapic.h> 10.11 10.12 #ifdef CONFIG_VMX 10.13 #if defined (__i386__) 10.14 @@ -732,48 +732,6 @@ void vmx_wait_io() 10.15 } while(1); 10.16 } 10.17 10.18 -#if defined(__i386__) || defined(__x86_64__) 10.19 -static inline int __fls(u32 word) 10.20 -{ 10.21 - int bit; 10.22 - 10.23 - __asm__("bsrl %1,%0" 10.24 - :"=r" (bit) 10.25 - :"rm" (word)); 10.26 - return word ? bit : -1; 10.27 -} 10.28 -#else 10.29 -#define __fls(x) generic_fls(x) 10.30 -static __inline__ int generic_fls(u32 x) 10.31 -{ 10.32 - int r = 31; 10.33 - 10.34 - if (!x) 10.35 - return -1; 10.36 - if (!(x & 0xffff0000u)) { 10.37 - x <<= 16; 10.38 - r -= 16; 10.39 - } 10.40 - if (!(x & 0xff000000u)) { 10.41 - x <<= 8; 10.42 - r -= 8; 10.43 - } 10.44 - if (!(x & 0xf0000000u)) { 10.45 - x <<= 4; 10.46 - r -= 4; 10.47 - } 10.48 - if (!(x & 0xc0000000u)) { 10.49 - x <<= 2; 10.50 - r -= 2; 10.51 - } 10.52 - if (!(x & 0x80000000u)) { 10.53 - x <<= 1; 10.54 - r -= 1; 10.55 - } 10.56 - return r; 10.57 -} 10.58 -#endif 10.59 - 10.60 /* Simple minded Local APIC priority implementation. Fix later */ 10.61 static __inline__ int find_highest_irq(u32 *pintr) 10.62 { 10.63 @@ -801,31 +759,31 @@ interrupt_post_injection(struct vcpu * v 10.64 struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit); 10.65 u64 drift; 10.66 10.67 + if ( is_pit_irq(v, vector, type) ) { 10.68 + if ( !vpit->first_injected ) { 10.69 + vpit->first_injected = 1; 10.70 + vpit->pending_intr_nr = 0; 10.71 + } else { 10.72 + vpit->pending_intr_nr--; 10.73 + } 10.74 + vpit->inject_point = NOW(); 10.75 + drift = vpit->period_cycles * vpit->pending_intr_nr; 10.76 + drift = v->arch.arch_vmx.tsc_offset - drift; 10.77 + __vmwrite(TSC_OFFSET, drift); 10.78 + 10.79 +#if defined (__i386__) 10.80 + __vmwrite(TSC_OFFSET_HIGH, (drift >> 32)); 10.81 +#endif 10.82 + 10.83 + } 10.84 + 10.85 switch(type) 10.86 { 10.87 case VLAPIC_DELIV_MODE_EXT: 10.88 - if ( is_pit_irq(v, vector) ) { 10.89 - if ( !vpit->first_injected ) { 10.90 - vpit->first_injected = 1; 10.91 - vpit->pending_intr_nr = 0; 10.92 - } 10.93 - else { 10.94 - vpit->pending_intr_nr--; 10.95 - } 10.96 - vpit->inject_point = NOW(); 10.97 - drift = vpit->period_cycles * vpit->pending_intr_nr; 10.98 - drift = v->arch.arch_vmx.tsc_offset - drift; 10.99 - __vmwrite(TSC_OFFSET, drift); 10.100 - 10.101 -#if defined (__i386__) 10.102 - __vmwrite(TSC_OFFSET_HIGH, (drift >> 32)); 10.103 -#endif 10.104 - 10.105 - } 10.106 break; 10.107 10.108 default: 10.109 - printk("Not support interrupt type\n"); 10.110 + vlapic_post_injection(v, vector, type); 10.111 break; 10.112 } 10.113 } 10.114 @@ -885,6 +843,24 @@ void vmx_pic_assist(struct vcpu *v) 10.115 10.116 } 10.117 10.118 +int cpu_get_interrupt(struct vcpu *v, int *type) 10.119 +{ 10.120 + int intno; 10.121 + struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic; 10.122 + 10.123 + if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) { 10.124 + /* set irq request if a PIC irq is still pending */ 10.125 + /* XXX: improve that */ 10.126 + pic_update_irq(s); 10.127 + return intno; 10.128 + } 10.129 + /* read the irq from the PIC */ 10.130 + if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 ) 10.131 + return intno; 10.132 + 10.133 + return -1; 10.134 +} 10.135 + 10.136 asmlinkage void vmx_intr_assist(void) 10.137 { 10.138 int intr_type = 0; 10.139 @@ -902,11 +878,6 @@ asmlinkage void vmx_intr_assist(void) 10.140 pic_set_irq(pic, 0, 1); 10.141 } 10.142 10.143 - if ( !plat->interrupt_request ) { 10.144 - disable_irq_window(cpu_exec_control); 10.145 - return; 10.146 - } 10.147 - 10.148 __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields); 10.149 10.150 if (intr_fields & INTR_INFO_VALID_MASK) { 10.151 @@ -928,16 +899,21 @@ asmlinkage void vmx_intr_assist(void) 10.152 enable_irq_window(cpu_exec_control); 10.153 return; 10.154 } 10.155 - plat->interrupt_request = 0; 10.156 - highest_vector = cpu_get_pic_interrupt(v, &intr_type); 10.157 + 10.158 + highest_vector = cpu_get_interrupt(v, &intr_type); 10.159 + 10.160 + if (highest_vector == -1) { 10.161 + disable_irq_window(cpu_exec_control); 10.162 + return; 10.163 + } 10.164 10.165 switch (intr_type) { 10.166 case VLAPIC_DELIV_MODE_EXT: 10.167 + case VLAPIC_DELIV_MODE_FIXED: 10.168 + case VLAPIC_DELIV_MODE_LPRI: 10.169 vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE); 10.170 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0); 10.171 break; 10.172 - case VLAPIC_DELIV_MODE_FIXED: 10.173 - case VLAPIC_DELIV_MODE_LPRI: 10.174 case VLAPIC_DELIV_MODE_SMI: 10.175 case VLAPIC_DELIV_MODE_NMI: 10.176 case VLAPIC_DELIV_MODE_INIT:
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/xen/arch/x86/vmx_vlapic.c Fri Oct 28 09:48:46 2005 +0100 11.3 @@ -0,0 +1,997 @@ 11.4 +/* 11.5 + * vmx_vlapic.c: virtualize LAPIC for VMX vcpus. 11.6 + * Copyright (c) 2004, Intel Corporation. 11.7 + * 11.8 + * This program is free software; you can redistribute it and/or modify it 11.9 + * under the terms and conditions of the GNU General Public License, 11.10 + * version 2, as published by the Free Software Foundation. 11.11 + * 11.12 + * This program is distributed in the hope it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11.15 + * more details. 11.16 + * 11.17 + * You should have received a copy of the GNU General Public License along with 11.18 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 11.19 + * Place - Suite 330, Boston, MA 02111-1307 USA. 11.20 + * 11.21 + */ 11.22 + 11.23 +#include <xen/config.h> 11.24 +#include <xen/types.h> 11.25 +#include <xen/mm.h> 11.26 +#include <xen/xmalloc.h> 11.27 +#include <asm/shadow.h> 11.28 +#include <asm/page.h> 11.29 +#include <xen/event.h> 11.30 +#include <xen/trace.h> 11.31 +#include <asm/vmx.h> 11.32 +#include <asm/vmx_platform.h> 11.33 +#include <asm/vmx_vlapic.h> 11.34 + 11.35 +#include <xen/lib.h> 11.36 +#include <xen/sched.h> 11.37 +#include <asm/current.h> 11.38 +#include <public/io/ioreq.h> 11.39 + 11.40 +#ifdef CONFIG_VMX 11.41 + 11.42 +/* XXX remove this definition after GFW enabled */ 11.43 +#define VLAPIC_NO_BIOS 11.44 + 11.45 +extern unsigned int get_apic_bus_scale(void); 11.46 + 11.47 +static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] = 11.48 +{ 11.49 + 0x310ff, 0x117ff, 0x117ff, 0x1f7ff, 0x1f7ff, 0x117ff 11.50 +}; 11.51 + 11.52 +int vlapic_find_highest_irr(struct vlapic *vlapic) 11.53 +{ 11.54 + int result; 11.55 + 11.56 + result = find_highest_bit((uint32_t *)&vlapic->irr[0], INTR_LEN_32); 11.57 + 11.58 + if (result != -1 && result < 16) { 11.59 + printk("VLAPIC: irr on reserved bits %d\n ", result); 11.60 + domain_crash_synchronous(); 11.61 + } 11.62 + 11.63 + return result; 11.64 +} 11.65 + 11.66 +inline int vmx_apic_support(struct domain *d) 11.67 +{ 11.68 + return d->arch.vmx_platform.lapic_enable; 11.69 +} 11.70 + 11.71 +int vlapic_find_highest_isr(struct vlapic *vlapic) 11.72 +{ 11.73 + int result; 11.74 + 11.75 + result = find_highest_bit((uint32_t *)&vlapic->isr[0], INTR_LEN_32); 11.76 + 11.77 + if (result != -1 && result < 16) { 11.78 + int i = 0; 11.79 + printk("VLAPIC: isr on reserved bits %d, isr is\n ", result); 11.80 + for (i = 0; i < INTR_LEN_32; i += 2) 11.81 + printk("%d: 0x%08x%08x\n", i, vlapic->isr[i], vlapic->isr[i+1]); 11.82 + return -1; 11.83 + } 11.84 + 11.85 + return result; 11.86 +} 11.87 + 11.88 +uint32_t vlapic_update_ppr(struct vlapic *vlapic) 11.89 +{ 11.90 + uint32_t tpr, isrv, ppr; 11.91 + int isr; 11.92 + 11.93 + tpr = (vlapic->task_priority >> 4) & 0xf; /* we want 7:4 */ 11.94 + 11.95 + isr = vlapic_find_highest_isr(vlapic); 11.96 + if (isr != -1) 11.97 + isrv = (isr >> 4) & 0xf; /* ditto */ 11.98 + else 11.99 + isrv = 0; 11.100 + 11.101 + if (tpr >= isrv) 11.102 + ppr = vlapic->task_priority & 0xff; 11.103 + else 11.104 + ppr = isrv << 4; /* low 4 bits of PPR have to be cleared */ 11.105 + 11.106 + vlapic->processor_priority = ppr; 11.107 + 11.108 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT, 11.109 + "vlapic_update_ppr: vlapic %p ppr %x isr %x isrv %x", 11.110 + vlapic, ppr, isr, isrv); 11.111 + 11.112 + return ppr; 11.113 +} 11.114 + 11.115 +/* This only for fixed delivery mode */ 11.116 +int vlapic_match_dest(struct vlapic *target, struct vlapic *source, 11.117 + int short_hand, int dest, int dest_mode, 11.118 + int delivery_mode) 11.119 +{ 11.120 + int result = 0; 11.121 + 11.122 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: " 11.123 + "target %p source %p dest %x dest_mode %x short_hand %x " 11.124 + "delivery_mode %x", 11.125 + target, source, dest, dest_mode, short_hand, delivery_mode); 11.126 + 11.127 + switch (short_hand) { 11.128 + case VLAPIC_NO_SHORTHAND: 11.129 + if (!dest_mode) { /* Physical */ 11.130 + result = (target->id == dest); 11.131 + } else { /* Logical */ 11.132 + if (((target->dest_format >> 28) & 0xf) == 0xf) { /* Flat mode */ 11.133 + result = (target->logical_dest >> 24) & dest; 11.134 + } else { 11.135 + if ((delivery_mode == VLAPIC_DELIV_MODE_LPRI) && 11.136 + (dest == 0xff)) { 11.137 + /* What shall we do now? */ 11.138 + printk("Broadcast IPI with lowest priority " 11.139 + "delivery mode\n"); 11.140 + domain_crash_synchronous(); 11.141 + } 11.142 + result = (target->logical_dest == (dest & 0xf)) ? 11.143 + ((target->logical_dest >> 4) & (dest >> 4)) : 0; 11.144 + } 11.145 + } 11.146 + break; 11.147 + 11.148 + case VLAPIC_SHORTHAND_SELF: 11.149 + if (target == source) 11.150 + result = 1; 11.151 + break; 11.152 + 11.153 + case VLAPIC_SHORTHAND_INCLUDE_SELF: 11.154 + result = 1; 11.155 + break; 11.156 + 11.157 + case VLAPIC_SHORTHAND_EXCLUDE_SELF: 11.158 + if (target != source) 11.159 + result = 1; 11.160 + break; 11.161 + 11.162 + default: 11.163 + break; 11.164 + } 11.165 + 11.166 + return result; 11.167 +} 11.168 + 11.169 +/* 11.170 + * Add a pending IRQ into lapic. 11.171 + * Return 1 if successfully added and 0 if discarded. 11.172 + */ 11.173 +int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode, 11.174 + int vector, int level, int trig_mode) 11.175 +{ 11.176 + int result = 1; 11.177 + 11.178 + switch (delivery_mode) { 11.179 + case VLAPIC_DELIV_MODE_FIXED: 11.180 + case VLAPIC_DELIV_MODE_LPRI: 11.181 + /* FIXME add logic for vcpu on reset */ 11.182 + if (!vlapic->vcpu || !vlapic_enabled(vlapic)) 11.183 + return 0; 11.184 + 11.185 + if (test_and_set_bit(vector, &vlapic->irr[0])) { 11.186 + printk("<vlapic_accept_irq>" 11.187 + "level trig mode repeatedly for vector %d\n", vector); 11.188 + result = 0; 11.189 + } else { 11.190 + if (level) { 11.191 + printk("<vlapic_accept_irq> level trig mode for vector %d\n", vector); 11.192 + set_bit(vector, &vlapic->tmr[0]); 11.193 + } 11.194 + } 11.195 + evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain)); 11.196 + break; 11.197 + 11.198 + case VLAPIC_DELIV_MODE_RESERVED: 11.199 + printk("Ignore deliver mode 3 in vlapic_accept_irq\n"); 11.200 + break; 11.201 + 11.202 + case VLAPIC_DELIV_MODE_SMI: 11.203 + case VLAPIC_DELIV_MODE_NMI: 11.204 + /* Fixme */ 11.205 + printk("TODO: for guest SMI/NMI\n"); 11.206 + break; 11.207 + 11.208 + case VLAPIC_DELIV_MODE_INIT: 11.209 + if (!level && trig_mode == 1) { //Deassert 11.210 + printk("This vmx_vlapic is for P4, no work for De-assert init\n"); 11.211 + } else { 11.212 + /* FIXME How to check the situation after vcpu reset? */ 11.213 + vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI; 11.214 + if (vlapic->vcpu) { 11.215 + vcpu_pause(vlapic->vcpu); 11.216 + } 11.217 + } 11.218 + break; 11.219 + 11.220 + case VLAPIC_DELIV_MODE_STARTUP: 11.221 + if (vlapic->init_sipi_sipi_state != VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI) 11.222 + break; 11.223 + vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_NORM; 11.224 + if (!vlapic->vcpu) { 11.225 + /* XXX Call vmx_bringup_ap here */ 11.226 + result = 0; 11.227 + }else{ 11.228 + //vmx_vcpu_reset(vlapic->vcpu); 11.229 + } 11.230 + break; 11.231 + 11.232 + default: 11.233 + printk("TODO: not support interrup type %x\n", delivery_mode); 11.234 + domain_crash_synchronous(); 11.235 + break; 11.236 + } 11.237 + 11.238 + return result; 11.239 +} 11.240 +/* 11.241 + This function is used by both ioapic and local APIC 11.242 + The bitmap is for vcpu_id 11.243 + */ 11.244 +struct vlapic* apic_round_robin(struct domain *d, 11.245 + uint8_t dest_mode, 11.246 + uint8_t vector, 11.247 + uint32_t bitmap) 11.248 +{ 11.249 + int next, old; 11.250 + struct vlapic* target = NULL; 11.251 + 11.252 + if (dest_mode == 0) { //Physical mode 11.253 + printk("<apic_round_robin> lowest priority for physical mode\n"); 11.254 + return NULL; 11.255 + } 11.256 + 11.257 + if (!bitmap) { 11.258 + printk("<apic_round_robin> no bit on bitmap\n"); 11.259 + return NULL; 11.260 + } 11.261 + 11.262 + spin_lock(&d->arch.vmx_platform.round_robin_lock); 11.263 + 11.264 + old = next = d->arch.vmx_platform.round_info[vector]; 11.265 + 11.266 + next++; 11.267 + if (next == MAX_VIRT_CPUS || !d->vcpu[next]) 11.268 + next = 0; 11.269 + 11.270 + do { 11.271 + /* the vcpu array is arranged according to vcpu_id */ 11.272 + if (test_bit(next, &bitmap)) { 11.273 + target = d->vcpu[next]->arch.arch_vmx.vlapic; 11.274 + if (!vlapic_enabled(target)) { 11.275 + printk("warning: targe round robin local apic disabled\n"); 11.276 + /* XXX should we domain crash?? Or should we return NULL */ 11.277 + } 11.278 + break; 11.279 + } 11.280 + 11.281 + next ++; 11.282 + if (next == MAX_VIRT_CPUS || !d->vcpu[next]) 11.283 + next = 0; 11.284 + }while(next != old); 11.285 + 11.286 + d->arch.vmx_platform.round_info[vector] = next; 11.287 + spin_unlock(&d->arch.vmx_platform.round_robin_lock); 11.288 + return target; 11.289 +} 11.290 + 11.291 +void 11.292 +vlapic_EOI_set(struct vlapic *vlapic) 11.293 +{ 11.294 + int vector = vlapic_find_highest_isr(vlapic); 11.295 + 11.296 + /* Not every write EOI will has correpsoning ISR, 11.297 + one example is when Kernel check timer on setup_IO_APIC */ 11.298 + if (vector == -1) { 11.299 + return ; 11.300 + } 11.301 + 11.302 + vlapic_clear_isr(vlapic, vector); 11.303 + vlapic_update_ppr(vlapic); 11.304 +} 11.305 + 11.306 +int vlapic_check_vector(struct vlapic *vlapic, 11.307 + unsigned char dm, int vector) 11.308 +{ 11.309 + if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) { 11.310 + vlapic->err_status |= 0x40; 11.311 + vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED, 11.312 + vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0); 11.313 + printk("<vlapic_check_vector>: check fail\n"); 11.314 + return 0; 11.315 + } 11.316 + return 1; 11.317 +} 11.318 + 11.319 + 11.320 +void vlapic_ipi(struct vlapic *vlapic) 11.321 +{ 11.322 + unsigned int dest = (vlapic->icr_high >> 24) & 0xff; 11.323 + unsigned int short_hand = (vlapic->icr_low >> 18) & 3; 11.324 + unsigned int trig_mode = (vlapic->icr_low >> 15) & 1; 11.325 + unsigned int level = (vlapic->icr_low >> 14) & 1; 11.326 + unsigned int dest_mode = (vlapic->icr_low >> 11) & 1; 11.327 + unsigned int delivery_mode = (vlapic->icr_low >> 8) & 7; 11.328 + unsigned int vector = (vlapic->icr_low & 0xff); 11.329 + 11.330 + struct vlapic *target; 11.331 + struct vcpu *v = NULL; 11.332 + int result = 0; 11.333 + uint32_t lpr_map; 11.334 + 11.335 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: " 11.336 + "icr_high %x icr_low %x " 11.337 + "short_hand %x dest %x trig_mode %x level %x " 11.338 + "dest_mode %x delivery_mode %x vector %x", 11.339 + vlapic->icr_high, vlapic->icr_low, 11.340 + short_hand, dest, trig_mode, level, dest_mode, 11.341 + delivery_mode, vector); 11.342 + 11.343 + for_each_vcpu ( vlapic->domain, v ) { 11.344 + target = VLAPIC(v); 11.345 + if (vlapic_match_dest(target, vlapic, short_hand, 11.346 + dest, dest_mode, delivery_mode)) { 11.347 + if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) { 11.348 + set_bit(v->vcpu_id, &lpr_map); 11.349 + }else 11.350 + result = vlapic_accept_irq(target, delivery_mode, 11.351 + vector, level, trig_mode); 11.352 + } 11.353 + } 11.354 + 11.355 + if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) { 11.356 + extern struct vlapic* 11.357 + apic_round_robin(struct domain *d, 11.358 + uint8_t dest_mode, uint8_t vector, uint32_t bitmap); 11.359 + 11.360 + v = vlapic->vcpu; 11.361 + target = apic_round_robin(v->domain, dest_mode, vector, lpr_map); 11.362 + 11.363 + if (target) 11.364 + vlapic_accept_irq(target, delivery_mode, 11.365 + vector, level, trig_mode); 11.366 + } 11.367 +} 11.368 + 11.369 +void vlapic_begin_timer(struct vlapic *vlapic) 11.370 +{ 11.371 + s_time_t cur = NOW(), offset; 11.372 + 11.373 + offset = vlapic->timer_current * 11.374 + (262144 / get_apic_bus_scale()) * vlapic->timer_divide_counter; 11.375 + vlapic->vlapic_timer.expires = cur + offset; 11.376 + 11.377 + set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires ); 11.378 + 11.379 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_begin_timer: " 11.380 + "bus_scale %x now %08x%08x expire %08x%08x " 11.381 + "offset %08x%08x current %x", 11.382 + get_apic_bus_scale(), (uint32_t)(cur >> 32), (uint32_t)cur, 11.383 + (uint32_t)(vlapic->vlapic_timer.expires >> 32), 11.384 + (uint32_t) vlapic->vlapic_timer.expires, 11.385 + (uint32_t)(offset >> 32), (uint32_t)offset, 11.386 + vlapic->timer_current); 11.387 +} 11.388 + 11.389 +void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset, 11.390 + unsigned int len, unsigned int *result) 11.391 +{ 11.392 + if (len != 4) { 11.393 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, 11.394 + "local apic read with len=%d (should be 4)", len); 11.395 + } 11.396 + 11.397 + *result = 0; 11.398 + 11.399 + switch (offset) { 11.400 + case APIC_ID: 11.401 + *result = (vlapic->id) << 24; 11.402 + break; 11.403 + 11.404 + case APIC_LVR: 11.405 + *result = vlapic->version; 11.406 + break; 11.407 + 11.408 + case APIC_TASKPRI: 11.409 + *result = vlapic->task_priority; 11.410 + break; 11.411 + 11.412 + case APIC_ARBPRI: 11.413 + printk("Access local APIC ARBPRI register which is for P6\n"); 11.414 + break; 11.415 + 11.416 + case APIC_PROCPRI: 11.417 + *result = vlapic->processor_priority; 11.418 + break; 11.419 + 11.420 + case APIC_EOI: /* EOI is write only */ 11.421 + break; 11.422 + 11.423 + case APIC_LDR: 11.424 + *result = vlapic->logical_dest; 11.425 + break; 11.426 + 11.427 + case APIC_DFR: 11.428 + *result = vlapic->dest_format; 11.429 + break; 11.430 + 11.431 + case APIC_SPIV: 11.432 + *result = vlapic->spurious_vec; 11.433 + break; 11.434 + 11.435 + case APIC_ISR: 11.436 + case 0x110: 11.437 + case 0x120: 11.438 + case 0x130: 11.439 + case 0x140: 11.440 + case 0x150: 11.441 + case 0x160: 11.442 + case 0x170: 11.443 + *result = vlapic->isr[(offset - APIC_ISR) >> 4]; 11.444 + break; 11.445 + 11.446 + case APIC_TMR: 11.447 + case 0x190: 11.448 + case 0x1a0: 11.449 + case 0x1b0: 11.450 + case 0x1c0: 11.451 + case 0x1d0: 11.452 + case 0x1e0: 11.453 + case 0x1f0: 11.454 + *result = vlapic->tmr[(offset - APIC_TMR) >> 4]; 11.455 + break; 11.456 + 11.457 + case APIC_IRR: 11.458 + case 0x210: 11.459 + case 0x220: 11.460 + case 0x230: 11.461 + case 0x240: 11.462 + case 0x250: 11.463 + case 0x260: 11.464 + case 0x270: 11.465 + *result = vlapic->irr[(offset - APIC_IRR) >> 4]; 11.466 + break; 11.467 + 11.468 + case APIC_ESR: 11.469 + if (vlapic->err_write_count) 11.470 + *result = vlapic->err_status; 11.471 + break; 11.472 + 11.473 + case APIC_ICR: 11.474 + *result = vlapic->icr_low; 11.475 + break; 11.476 + 11.477 + case APIC_ICR2: 11.478 + *result = vlapic->icr_high; 11.479 + break; 11.480 + 11.481 + case APIC_LVTT: /* LVT Timer Reg */ 11.482 + case APIC_LVTTHMR: /* LVT Thermal Monitor */ 11.483 + case APIC_LVTPC: /* LVT Performance Counter */ 11.484 + case APIC_LVT0: /* LVT LINT0 Reg */ 11.485 + case APIC_LVT1: /* LVT Lint1 Reg */ 11.486 + case APIC_LVTERR: /* LVT Error Reg */ 11.487 + *result = vlapic->lvt[(offset - APIC_LVTT) >> 4]; 11.488 + break; 11.489 + 11.490 + case APIC_TMICT: 11.491 + *result = vlapic->timer_initial; 11.492 + break; 11.493 + 11.494 + case APIC_TMCCT: //Timer CCR 11.495 + { 11.496 + uint32_t counter; 11.497 + s_time_t passed, cur = NOW(); 11.498 + 11.499 + if (cur <= vlapic->timer_current_update) { 11.500 + passed = ~0x0LL - vlapic->timer_current_update + cur; 11.501 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC,"time elapsed"); 11.502 + }else 11.503 + passed = cur - vlapic->timer_current_update; 11.504 + 11.505 + counter = (passed * get_apic_bus_scale()) / (262144* vlapic->timer_divide_counter); 11.506 + if (vlapic->timer_current > counter) 11.507 + *result = vlapic->timer_current - counter; 11.508 + else { 11.509 + if (!vlapic_lvt_timer_period(vlapic)) 11.510 + *result = 0; 11.511 + //FIXME should we add interrupt here? 11.512 + else 11.513 + //*result = counter % vlapic->timer_initial; 11.514 + *result = vlapic->timer_initial - (counter - vlapic->timer_current); 11.515 + } 11.516 + vlapic->timer_current = *result; 11.517 + vlapic->timer_current_update = NOW(); 11.518 + 11.519 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, 11.520 + "initial %x timer current %x " 11.521 + "update %08x%08x cur %08x%08x offset %d", 11.522 + vlapic->timer_initial, vlapic->timer_current, 11.523 + (uint32_t)(vlapic->timer_current_update >> 32), 11.524 + (uint32_t)vlapic->timer_current_update , 11.525 + (uint32_t)(cur >> 32), (uint32_t)cur, counter); 11.526 + } 11.527 + break; 11.528 + 11.529 + case APIC_TDCR: 11.530 + *result = vlapic->timer_divconf; 11.531 + break; 11.532 + 11.533 + default: 11.534 + printk("Read local APIC address %x not implemented\n",offset); 11.535 + *result = 0; 11.536 + break; 11.537 + } 11.538 +} 11.539 + 11.540 +unsigned long vlapic_read(struct vcpu *v, unsigned long address, 11.541 + unsigned long len) 11.542 +{ 11.543 + unsigned int alignment; 11.544 + unsigned int tmp; 11.545 + unsigned long result; 11.546 + struct vlapic *vlapic = VLAPIC(v); 11.547 + unsigned int offset = address - vlapic->base_address; 11.548 + 11.549 + if ( len != 4) { 11.550 + /* some bugs on kernel cause read this with byte*/ 11.551 + printk("Local APIC read with len = %lx, should be 4 instead\n", len); 11.552 + } 11.553 + 11.554 + alignment = offset & 0x3; 11.555 + 11.556 + vlapic_read_aligned(vlapic, offset & ~0x3, 4, &tmp); 11.557 + switch (len) { 11.558 + case 1: 11.559 + result = *((unsigned char *)&tmp + alignment); 11.560 + break; 11.561 + 11.562 + case 2: 11.563 + result = *(unsigned short *)((unsigned char *)&tmp + alignment); 11.564 + break; 11.565 + 11.566 + case 4: 11.567 + result = *(unsigned int *)((unsigned char *)&tmp + alignment); 11.568 + break; 11.569 + 11.570 + default: 11.571 + printk("Local APIC read with len = %lx, should be 4 instead\n", len); 11.572 + domain_crash_synchronous(); 11.573 + break; 11.574 + } 11.575 + 11.576 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, 11.577 + "vlapic_read offset %x with length %lx and the result is %lx", 11.578 + offset, len, result); 11.579 + return result; 11.580 +} 11.581 + 11.582 +unsigned long vlapic_write(struct vcpu *v, unsigned long address, 11.583 + unsigned long len, unsigned long val) 11.584 +{ 11.585 + struct vlapic *vlapic = VLAPIC(v); 11.586 + unsigned int offset = address - vlapic->base_address; 11.587 + 11.588 + if (offset != 0xb0) 11.589 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, 11.590 + "vlapic_write offset %x with length %lx source %lx", 11.591 + offset, len, val); 11.592 + 11.593 + /* 11.594 + * According to IA 32 Manual, all resgiters should be accessed with 11.595 + * 32 bits alignment. 11.596 + */ 11.597 + if (len != 4) { 11.598 + unsigned int tmp; 11.599 + unsigned char alignment; 11.600 + 11.601 + /* Some kernel do will access with byte/word alignment*/ 11.602 + printk("Notice: Local APIC write with len = %lx\n",len); 11.603 + alignment = offset & 0x3; 11.604 + tmp = vlapic_read(v, offset & (~0x3), 4); 11.605 + switch (len) { 11.606 + case 1: 11.607 + /* XXX the saddr is a tmp variable from caller, so should be ok 11.608 + But we should still change the following ref to val to 11.609 + local variable later */ 11.610 + val = (tmp & ~(0xff << alignment)) | 11.611 + ((val & 0xff) << alignment); 11.612 + break; 11.613 + 11.614 + case 2: 11.615 + if (alignment != 0x0 && alignment != 0x2) { 11.616 + printk("alignment error for vlapic with len == 2\n"); 11.617 + domain_crash_synchronous(); 11.618 + } 11.619 + 11.620 + val = (tmp & ~(0xffff << alignment)) | 11.621 + ((val & 0xffff) << alignment); 11.622 + break; 11.623 + 11.624 + case 3: 11.625 + /* will it happen? */ 11.626 + printk("vlapic_write with len = 3 !!!\n"); 11.627 + domain_crash_synchronous(); 11.628 + break; 11.629 + 11.630 + default: 11.631 + printk("Local APIC write with len = %lx, should be 4 instead\n", len); 11.632 + domain_crash_synchronous(); 11.633 + break; 11.634 + } 11.635 + } 11.636 + 11.637 + offset &= 0xff0; 11.638 + 11.639 + switch (offset) { 11.640 + case APIC_ID: /* Local APIC ID */ 11.641 + vlapic->id = ((val) >> 24) & VAPIC_ID_MASK; 11.642 + break; 11.643 + 11.644 + case APIC_TASKPRI: 11.645 + vlapic->task_priority = val & 0xff; 11.646 + vlapic_update_ppr(vlapic); 11.647 + break; 11.648 + 11.649 + case APIC_EOI: 11.650 + vlapic_EOI_set(vlapic); 11.651 + break; 11.652 + 11.653 + case APIC_LDR: 11.654 + vlapic->logical_dest = val & VAPIC_LDR_MASK; 11.655 + break; 11.656 + 11.657 + case APIC_DFR: 11.658 + vlapic->dest_format = val ; 11.659 + break; 11.660 + 11.661 + case APIC_SPIV: 11.662 + vlapic->spurious_vec = val & 0x1ff; 11.663 + if (!(vlapic->spurious_vec & 0x100)) { 11.664 + int i = 0; 11.665 + for (i=0; i < VLAPIC_LVT_NUM; i++) 11.666 + vlapic->lvt[i] |= 0x10000; 11.667 + vlapic->status |= VLAPIC_SOFTWARE_DISABLE_MASK; 11.668 + } 11.669 + else 11.670 + vlapic->status &= ~VLAPIC_SOFTWARE_DISABLE_MASK; 11.671 + break; 11.672 + 11.673 + case APIC_ESR: 11.674 + vlapic->err_write_count = !vlapic->err_write_count; 11.675 + if (!vlapic->err_write_count) 11.676 + vlapic->err_status = 0; 11.677 + break; 11.678 + 11.679 + case APIC_ICR: 11.680 + /* No delay here, so we always clear the pending bit*/ 11.681 + vlapic->icr_low = val & ~(1 << 12); 11.682 + vlapic_ipi(vlapic); 11.683 + break; 11.684 + 11.685 + case APIC_ICR2: 11.686 + vlapic->icr_high = val & 0xff000000; 11.687 + break; 11.688 + 11.689 + case APIC_LVTT: // LVT Timer Reg 11.690 + case APIC_LVTTHMR: // LVT Thermal Monitor 11.691 + case APIC_LVTPC: // LVT Performance Counter 11.692 + case APIC_LVT0: // LVT LINT0 Reg 11.693 + case APIC_LVT1: // LVT Lint1 Reg 11.694 + case APIC_LVTERR: // LVT Error Reg 11.695 + { 11.696 + int vt = (offset - APIC_LVTT) >> 4; 11.697 + 11.698 + vlapic->lvt[vt] = val & vlapic_lvt_mask[vt]; 11.699 + if (vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK) 11.700 + vlapic->lvt[vt] |= VLAPIC_LVT_BIT_MASK; 11.701 + 11.702 + /* On hardware, when write vector less than 0x20 will error */ 11.703 + vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic->lvt[vt]), 11.704 + vlapic_lvt_vector(vlapic, vt)); 11.705 + 11.706 + if (!vlapic->vcpu_id && (offset == APIC_LVT0)) { 11.707 + if ((vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_DELIMOD) 11.708 + == 0x700) { 11.709 + if (!(vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_MASK)) { 11.710 + set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status); 11.711 + }else 11.712 + clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status); 11.713 + } 11.714 + else 11.715 + clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status); 11.716 + } 11.717 + 11.718 + } 11.719 + break; 11.720 + 11.721 + case APIC_TMICT: 11.722 + if (vlapic_timer_active(vlapic)) 11.723 + rem_ac_timer(&(vlapic->vlapic_timer)); 11.724 + 11.725 + vlapic->timer_initial = val; 11.726 + vlapic->timer_current = val; 11.727 + vlapic->timer_current_update = NOW(); 11.728 + 11.729 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, 11.730 + "timer_init %x timer_current %x timer_current_update %08x%08x", 11.731 + vlapic->timer_initial, vlapic->timer_current, (uint32_t)(vlapic->timer_current_update>>32), (uint32_t)vlapic->timer_current_update); 11.732 + vlapic_begin_timer(vlapic); 11.733 + break; 11.734 + 11.735 + case APIC_TDCR: 11.736 + { 11.737 + //FIXME clean this code 11.738 + unsigned char tmp1,tmp2; 11.739 + tmp1 = (val & 0xf); 11.740 + tmp2 = ((tmp1 & 0x3 )|((tmp1 & 0x8) >>1)) + 1; 11.741 + vlapic->timer_divide_counter = 0x1<<tmp2; 11.742 + 11.743 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, 11.744 + "timer divider is 0x%x", 11.745 + vlapic->timer_divide_counter); 11.746 + } 11.747 + break; 11.748 + 11.749 + default: 11.750 + printk("Local APIC Write to read-only register\n"); 11.751 + break; 11.752 + } 11.753 + return 1; 11.754 +} 11.755 + 11.756 +int vlapic_range(struct vcpu *v, unsigned long addr) 11.757 +{ 11.758 + struct vlapic *vlapic = VLAPIC(v); 11.759 + 11.760 + if (vlapic_global_enabled(vlapic) && 11.761 + (addr >= vlapic->base_address) && 11.762 + (addr <= (vlapic->base_address + VLOCAL_APIC_MEM_LENGTH))) 11.763 + return 1; 11.764 + 11.765 + return 0; 11.766 +} 11.767 + 11.768 +void vlapic_msr_set(struct vlapic *vlapic, uint64_t value) 11.769 +{ 11.770 + /* When apic disabled */ 11.771 + if (!vlapic) 11.772 + return; 11.773 + 11.774 + if (vlapic->vcpu_id) 11.775 + value &= ~MSR_IA32_APICBASE_BSP; 11.776 + 11.777 + vlapic->apic_base_msr = value; 11.778 + vlapic->base_address = vlapic_get_base_address(vlapic); 11.779 + 11.780 + if (!(value & 0x800)) 11.781 + set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status ); 11.782 + 11.783 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, 11.784 + "apic base msr = 0x%08x%08x,\nbase address = 0x%lx", 11.785 + (uint32_t)(vlapic->apic_base_msr >> 32), 11.786 + (uint32_t)vlapic->apic_base_msr, 11.787 + vlapic->base_address); 11.788 +} 11.789 + 11.790 +static inline int vlapic_get_init_id(struct vcpu *v) 11.791 +{ 11.792 + return v->vcpu_id; 11.793 +} 11.794 + 11.795 +void vlapic_timer_fn(void *data) 11.796 +{ 11.797 + struct vlapic *vlapic; 11.798 + 11.799 + vlapic = data; 11.800 + if (!vlapic_enabled(vlapic)) return; 11.801 + 11.802 + vlapic->timer_current_update = NOW(); 11.803 + 11.804 + if (vlapic_lvt_timer_enabled(vlapic)) { 11.805 + if (!vlapic_irr_status(vlapic, 11.806 + vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER))) { 11.807 + test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER), 11.808 + &vlapic->irr[0]); 11.809 + } 11.810 + else 11.811 + vlapic->intr_pending_count[vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)]++; 11.812 + } 11.813 + 11.814 + vlapic->timer_current_update = NOW(); 11.815 + if (vlapic_lvt_timer_period(vlapic)) { 11.816 + s_time_t offset; 11.817 + 11.818 + vlapic->timer_current = vlapic->timer_initial; 11.819 + offset = vlapic->timer_current * (262144/get_apic_bus_scale()) * vlapic->timer_divide_counter; 11.820 + vlapic->vlapic_timer.expires = NOW() + offset; 11.821 + set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires); 11.822 + }else { 11.823 + vlapic->timer_current = 0; 11.824 + } 11.825 + 11.826 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER, 11.827 + "vlapic_timer_fn: now: %08x%08x expire %08x%08x init %x current %x", 11.828 + (uint32_t)(NOW() >> 32),(uint32_t)NOW(), 11.829 + (uint32_t)(vlapic->vlapic_timer.expires >> 32), 11.830 + (uint32_t)vlapic->vlapic_timer.expires, 11.831 + vlapic->timer_initial,vlapic->timer_current); 11.832 +} 11.833 + 11.834 +#if 0 11.835 +static int 11.836 +vlapic_check_direct_intr(struct vcpu *v, int * mode) 11.837 +{ 11.838 + struct vlapic *vlapic = VLAPIC(v); 11.839 + int type; 11.840 + 11.841 + type = __fls(vlapic->direct_intr.deliver_mode); 11.842 + if (type == -1) 11.843 + return -1; 11.844 + 11.845 + *mode = type; 11.846 + return 0; 11.847 +} 11.848 +#endif 11.849 + 11.850 +int 11.851 +vlapic_accept_pic_intr(struct vcpu *v) 11.852 +{ 11.853 + struct vlapic *vlapic = VLAPIC(v); 11.854 + 11.855 + return vlapic ? test_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status) : 1; 11.856 +} 11.857 + 11.858 +int cpu_get_apic_interrupt(struct vcpu* v, int *mode) 11.859 +{ 11.860 + struct vlapic *vlapic = VLAPIC(v); 11.861 + 11.862 + if (vlapic && vlapic_enabled(vlapic)) { 11.863 + int highest_irr = vlapic_find_highest_irr(vlapic); 11.864 + 11.865 + if (highest_irr != -1 && highest_irr >= vlapic->processor_priority) { 11.866 + if (highest_irr < 0x10) { 11.867 + vlapic->err_status |= 0x20; 11.868 + /* XXX What will happen if this vector illegal stil */ 11.869 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, 11.870 + "vmx_intr_assist: illegal vector number %x err_status %x", 11.871 + highest_irr, vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR)); 11.872 + 11.873 + set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), &vlapic->irr[0]); 11.874 + highest_irr = vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR); 11.875 + } 11.876 + 11.877 + *mode = VLAPIC_DELIV_MODE_FIXED; 11.878 + return highest_irr; 11.879 + } 11.880 + } 11.881 + return -1; 11.882 +} 11.883 + 11.884 +void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode) { 11.885 + struct vlapic *vlapic = VLAPIC(v); 11.886 + 11.887 + if (!vlapic) 11.888 + return; 11.889 + 11.890 + switch (deliver_mode) { 11.891 + case VLAPIC_DELIV_MODE_FIXED: 11.892 + case VLAPIC_DELIV_MODE_LPRI: 11.893 + vlapic_set_isr(vlapic, vector); 11.894 + vlapic_clear_irr(vlapic, vector); 11.895 + vlapic_update_ppr(vlapic); 11.896 + 11.897 + if (vector == vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)) { 11.898 + vlapic->intr_pending_count[vector]--; 11.899 + if (vlapic->intr_pending_count[vector] > 0) 11.900 + test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER), 11.901 + &vlapic->irr[0]); 11.902 + } 11.903 + 11.904 + break; 11.905 + /*XXX deal with these later */ 11.906 + 11.907 + case VLAPIC_DELIV_MODE_RESERVED: 11.908 + printk("Ignore deliver mode 3 in vlapic_post_injection\n"); 11.909 + break; 11.910 + 11.911 + case VLAPIC_DELIV_MODE_SMI: 11.912 + case VLAPIC_DELIV_MODE_NMI: 11.913 + case VLAPIC_DELIV_MODE_INIT: 11.914 + case VLAPIC_DELIV_MODE_STARTUP: 11.915 + vlapic->direct_intr.deliver_mode &= ~(1 << deliver_mode); 11.916 + break; 11.917 + 11.918 + default: 11.919 + printk("<vlapic_post_injection> error deliver mode\n"); 11.920 + break; 11.921 + } 11.922 +} 11.923 + 11.924 +static int vlapic_reset(struct vlapic *vlapic) 11.925 +{ 11.926 + struct vcpu *v = vlapic->vcpu; 11.927 + int apic_id = v->vcpu_id, i; 11.928 + 11.929 + if (!v || !vlapic) 11.930 + return 0; 11.931 + 11.932 + memset(vlapic, 0,sizeof(struct vlapic)); 11.933 + 11.934 + v->arch.arch_vmx.vlapic = vlapic; 11.935 + 11.936 + vlapic->domain = v->domain; 11.937 + 11.938 + vlapic->id = apic_id; 11.939 + 11.940 + vlapic->version = VLAPIC_VERSION; 11.941 + 11.942 + vlapic->apic_base_msr = VLAPIC_BASE_MSR_INIT_VALUE; 11.943 + 11.944 + if (apic_id == 0) 11.945 + vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP; 11.946 + vlapic->base_address = vlapic_get_base_address(vlapic); 11.947 + 11.948 + for (i = 0; i < VLAPIC_LVT_NUM; i++) 11.949 + vlapic->lvt[i] = VLAPIC_LVT_BIT_MASK; 11.950 + 11.951 + vlapic->dest_format = 0xffffffffU; 11.952 + 11.953 + vlapic->spurious_vec = 0xff; 11.954 + 11.955 + 11.956 + init_ac_timer(&vlapic->vlapic_timer, 11.957 + vlapic_timer_fn, vlapic, v->processor); 11.958 + 11.959 +#ifdef VLAPIC_NO_BIOS 11.960 + /* 11.961 + * XXX According to mp sepcific, BIOS will enable LVT0/1, 11.962 + * remove it after BIOS enabled 11.963 + */ 11.964 + if (!v->vcpu_id) { 11.965 + vlapic->lvt[VLAPIC_LVT_LINT0] = 0x700; 11.966 + vlapic->lvt[VLAPIC_LVT_LINT1] = 0x500; 11.967 + set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status); 11.968 + } 11.969 +#endif 11.970 + 11.971 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_reset: " 11.972 + "vcpu=%p id=%d vlapic_apic_base_msr=%08x%08x " 11.973 + "vlapic_base_address=%0lx", 11.974 + v, vlapic->id, (uint32_t)(vlapic->apic_base_msr >> 32), 11.975 + (uint32_t)vlapic->apic_base_msr, vlapic->base_address); 11.976 + 11.977 + return 1; 11.978 +} 11.979 + 11.980 +int vlapic_init(struct vcpu *v) 11.981 +{ 11.982 + struct vlapic *vlapic = NULL; 11.983 + 11.984 + VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id); 11.985 + 11.986 + vlapic = xmalloc_bytes(sizeof(struct vlapic)); 11.987 + 11.988 + if (!vlapic) { 11.989 + printk("malloc vlapic error for vcpu %x\n", v->vcpu_id); 11.990 + return -ENOMEM; 11.991 + } 11.992 + 11.993 + vlapic->vcpu = v; 11.994 + 11.995 + vlapic_reset(vlapic); 11.996 + 11.997 + return 0; 11.998 +} 11.999 + 11.1000 +#endif /* CONFIG_VMX */
12.1 --- a/xen/arch/x86/vmx_vmcs.c Thu Oct 27 18:22:45 2005 +0100 12.2 +++ b/xen/arch/x86/vmx_vmcs.c Fri Oct 28 09:48:46 2005 +0100 12.3 @@ -252,6 +252,10 @@ static void vmx_setup_platform(struct do 12.4 pic_init(&platform->vmx_pic, pic_irq_request, 12.5 &platform->interrupt_request); 12.6 register_pic_io_hook(); 12.7 + 12.8 + if ( vmx_apic_support(d) ) { 12.9 + spin_lock_init(&d->arch.vmx_platform.round_robin_lock); 12.10 + } 12.11 } 12.12 12.13 static void vmx_set_host_env(struct vcpu *v) 12.14 @@ -313,6 +317,9 @@ static void vmx_do_launch(struct vcpu *v 12.15 12.16 vmx_stts(); 12.17 12.18 + if(vmx_apic_support(v->domain)) 12.19 + vlapic_init(v); 12.20 + 12.21 vmx_set_host_env(v); 12.22 12.23 error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
13.1 --- a/xen/include/asm-x86/vmx_intercept.h Thu Oct 27 18:22:45 2005 +0100 13.2 +++ b/xen/include/asm-x86/vmx_intercept.h Fri Oct 28 09:48:46 2005 +0100 13.3 @@ -14,6 +14,16 @@ 13.4 #define VMX_MMIO 1 13.5 13.6 typedef int (*intercept_action_t)(ioreq_t *); 13.7 +typedef unsigned long (*vmx_mmio_read_t)(struct vcpu *v, 13.8 + unsigned long addr, 13.9 + unsigned long length); 13.10 + 13.11 +typedef unsigned long (*vmx_mmio_write_t)(struct vcpu *v, 13.12 + unsigned long addr, 13.13 + unsigned long length, 13.14 + unsigned long val); 13.15 + 13.16 +typedef int (*vmx_mmio_check_t)(struct vcpu *v, unsigned long addr); 13.17 13.18 struct io_handler { 13.19 int type; 13.20 @@ -27,6 +37,16 @@ struct vmx_io_handler { 13.21 struct io_handler hdl_list[MAX_IO_HANDLER]; 13.22 }; 13.23 13.24 +struct vmx_mmio_handler { 13.25 + vmx_mmio_check_t check_handler; 13.26 + vmx_mmio_read_t read_handler; 13.27 + vmx_mmio_write_t write_handler; 13.28 +}; 13.29 + 13.30 +#define VMX_MMIO_HANDLER_NR 1 13.31 + 13.32 +extern struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR]; 13.33 + 13.34 /* global io interception point in HV */ 13.35 extern int vmx_io_intercept(ioreq_t *p, int type); 13.36 extern int register_io_handler(unsigned long addr, unsigned long size, 13.37 @@ -37,10 +57,7 @@ static inline int vmx_portio_intercept(i 13.38 return vmx_io_intercept(p, VMX_PORTIO); 13.39 } 13.40 13.41 -static inline int vmx_mmio_intercept(ioreq_t *p) 13.42 -{ 13.43 - return vmx_io_intercept(p, VMX_MMIO); 13.44 -} 13.45 +int vmx_mmio_intercept(ioreq_t *p); 13.46 13.47 static inline int register_portio_handler(unsigned long addr, 13.48 unsigned long size, 13.49 @@ -49,11 +66,4 @@ static inline int register_portio_handle 13.50 return register_io_handler(addr, size, action, VMX_PORTIO); 13.51 } 13.52 13.53 -static inline int register_mmio_handler(unsigned long addr, 13.54 - unsigned long size, 13.55 - intercept_action_t action) 13.56 -{ 13.57 - return register_io_handler(addr, size, action, VMX_MMIO); 13.58 -} 13.59 - 13.60 #endif /* _VMX_INTERCEPT_H */
14.1 --- a/xen/include/asm-x86/vmx_platform.h Thu Oct 27 18:22:45 2005 +0100 14.2 +++ b/xen/include/asm-x86/vmx_platform.h Fri Oct 28 09:48:46 2005 +0100 14.3 @@ -80,10 +80,13 @@ struct instruction { 14.4 struct vmx_platform { 14.5 unsigned long shared_page_va; 14.6 unsigned int nr_vcpu; 14.7 + unsigned int lapic_enable; 14.8 14.9 struct vmx_virpit vmx_pit; 14.10 struct vmx_io_handler vmx_io_handler; 14.11 struct vmx_virpic vmx_pic; 14.12 + unsigned char round_info[256]; 14.13 + spinlock_t round_robin_lock; 14.14 int interrupt_request; 14.15 }; 14.16
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/xen/include/asm-x86/vmx_vlapic.h Fri Oct 28 09:48:46 2005 +0100 15.3 @@ -0,0 +1,245 @@ 15.4 +/* 15.5 + * vmx_vlapic.h: virtualize LAPIC definitions. 15.6 + * Copyright (c) 2004, Intel Corporation. 15.7 + * 15.8 + * This program is free software; you can redistribute it and/or modify it 15.9 + * under the terms and conditions of the GNU General Public License, 15.10 + * version 2, as published by the Free Software Foundation. 15.11 + * 15.12 + * This program is distributed in the hope it will be useful, but WITHOUT 15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15.15 + * more details. 15.16 + * 15.17 + * You should have received a copy of the GNU General Public License along with 15.18 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15.19 + * Place - Suite 330, Boston, MA 02111-1307 USA. 15.20 + * 15.21 + */ 15.22 + 15.23 +#ifndef VMX_VLAPIC_H 15.24 +#define VMX_VLAPIC_H 15.25 + 15.26 +#include <asm/msr.h> 15.27 +#include <public/io/ioreq.h> 15.28 + 15.29 +#if defined(__i386__) || defined(__x86_64__) 15.30 +static inline int __fls(uint32_t word) 15.31 +{ 15.32 + int bit; 15.33 + 15.34 + __asm__("bsrl %1,%0" 15.35 + :"=r" (bit) 15.36 + :"rm" (word)); 15.37 + return word ? bit : -1; 15.38 +} 15.39 +#else 15.40 +#define __fls(x) generic_fls(x) 15.41 +static __inline__ int generic_fls(uint32_t x) 15.42 +{ 15.43 + int r = 31; 15.44 + 15.45 + if (!x) 15.46 + return -1; 15.47 + if (!(x & 0xffff0000u)) { 15.48 + x <<= 16; 15.49 + r -= 16; 15.50 + } 15.51 + if (!(x & 0xff000000u)) { 15.52 + x <<= 8; 15.53 + r -= 8; 15.54 + } 15.55 + if (!(x & 0xf0000000u)) { 15.56 + x <<= 4; 15.57 + r -= 4; 15.58 + } 15.59 + if (!(x & 0xc0000000u)) { 15.60 + x <<= 2; 15.61 + r -= 2; 15.62 + } 15.63 + if (!(x & 0x80000000u)) { 15.64 + x <<= 1; 15.65 + r -= 1; 15.66 + } 15.67 + return r; 15.68 +} 15.69 +#endif 15.70 + 15.71 +static __inline__ int find_highest_bit(uint32_t *data, int length) 15.72 +{ 15.73 + while(length && !data[--length]); 15.74 + return __fls(data[length]) + 32 * length; 15.75 +} 15.76 + 15.77 +#define VLAPIC(v) (v->arch.arch_vmx.vlapic) 15.78 + 15.79 +#define VAPIC_ID_MASK 0xff 15.80 +#define VAPIC_LDR_MASK (VAPIC_ID_MASK << 24) 15.81 +#define VLAPIC_VERSION 0x00050014 15.82 + 15.83 +#define VLAPIC_BASE_MSR_MASK 0x00000000fffff900ULL 15.84 +#define VLAPIC_BASE_MSR_INIT_BASE_ADDR 0xfee00000U 15.85 +#define VLAPIC_BASE_MSR_BASE_ADDR_MASK 0xfffff000U 15.86 +#define VLAPIC_BASE_MSR_INIT_VALUE (VLAPIC_BASE_MSR_INIT_BASE_ADDR | \ 15.87 + MSR_IA32_APICBASE_ENABLE) 15.88 +#define VLOCAL_APIC_MEM_LENGTH (1 << 12) 15.89 + 15.90 +#define VLAPIC_LVT_TIMER 0 15.91 +#define VLAPIC_LVT_THERMAL 1 15.92 +#define VLAPIC_LVT_PERFORM 2 15.93 +#define VLAPIC_LVT_LINT0 3 15.94 +#define VLAPIC_LVT_LINT1 4 15.95 +#define VLAPIC_LVT_ERROR 5 15.96 +#define VLAPIC_LVT_NUM 6 15.97 + 15.98 +#define VLAPIC_LVT_BIT_MASK (1 << 16) 15.99 +#define VLAPIC_LVT_BIT_VECTOR 0xff 15.100 +#define VLAPIC_LVT_BIT_DELIMOD (0x7 << 8) 15.101 +#define VLAPIC_LVT_BIT_DELISTATUS (1 << 12) 15.102 +#define VLAPIC_LVT_BIT_POLARITY (1 << 13) 15.103 +#define VLAPIC_LVT_BIT_IRR (1 << 14) 15.104 +#define VLAPIC_LVT_BIT_TRIG (1 << 15) 15.105 +#define VLAPIC_LVT_TIMERMODE (1 << 17) 15.106 + 15.107 +#define VLAPIC_DELIV_MODE_FIXED 0x0 15.108 +#define VLAPIC_DELIV_MODE_LPRI 0x1 15.109 +#define VLAPIC_DELIV_MODE_SMI 0x2 15.110 +#define VLAPIC_DELIV_MODE_RESERVED 0x3 15.111 +#define VLAPIC_DELIV_MODE_NMI 0x4 15.112 +#define VLAPIC_DELIV_MODE_INIT 0x5 15.113 +#define VLAPIC_DELIV_MODE_STARTUP 0x6 15.114 +#define VLAPIC_DELIV_MODE_EXT 0x7 15.115 + 15.116 + 15.117 + 15.118 +#define VLAPIC_NO_SHORTHAND 0x0 15.119 +#define VLAPIC_SHORTHAND_SELF 0x1 15.120 +#define VLAPIC_SHORTHAND_INCLUDE_SELF 0x2 15.121 +#define VLAPIC_SHORTHAND_EXCLUDE_SELF 0x3 15.122 + 15.123 +#define vlapic_lvt_timer_enabled(vlapic) \ 15.124 + (!(vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_BIT_MASK)) 15.125 + 15.126 +#define vlapic_lvt_vector(vlapic, type) \ 15.127 + (vlapic->lvt[type] & VLAPIC_LVT_BIT_VECTOR) 15.128 + 15.129 +#define vlapic_lvt_dm(value) ((value >> 8) && 7) 15.130 +#define vlapic_lvt_timer_period(vlapic) \ 15.131 + (vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_TIMERMODE) 15.132 + 15.133 +#define vlapic_isr_status(vlapic,vector) \ 15.134 + test_bit(vector, &vlapic->isr[0]) 15.135 + 15.136 +#define vlapic_irr_status(vlapic,vector) \ 15.137 + test_bit(vector, &vlapic->irr[0]) 15.138 + 15.139 +#define vlapic_set_isr(vlapic,vector) \ 15.140 + test_and_set_bit(vector, &vlapic->isr[0]) 15.141 + 15.142 +#define vlapic_set_irr(vlapic,vector) \ 15.143 + test_and_set_bit(vector, &vlapic->irr[0]) 15.144 + 15.145 +#define vlapic_clear_irr(vlapic,vector) \ 15.146 + clear_bit(vector, &vlapic->irr[0]) 15.147 +#define vlapic_clear_isr(vlapic,vector) \ 15.148 + clear_bit(vector, &vlapic->isr[0]) 15.149 + 15.150 +#define vlapic_enabled(vlapic) \ 15.151 + (!(vlapic->status & \ 15.152 + (VLAPIC_GLOB_DISABLE_MASK | VLAPIC_SOFTWARE_DISABLE_MASK))) 15.153 + 15.154 +#define vlapic_global_enabled(vlapic) \ 15.155 + !(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status)) 15.156 + 15.157 +typedef struct direct_intr_info { 15.158 + int deliver_mode; 15.159 + int source[6]; 15.160 +} direct_intr_info_t; 15.161 + 15.162 +#define VLAPIC_INIT_SIPI_SIPI_STATE_NORM 0 15.163 +#define VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI 1 15.164 + 15.165 +struct vlapic 15.166 +{ 15.167 + //FIXME check what would be 64 bit on EM64T 15.168 + uint32_t version; 15.169 +#define _VLAPIC_GLOB_DISABLE 0x0 15.170 +#define VLAPIC_GLOB_DISABLE_MASK 0x1 15.171 +#define VLAPIC_SOFTWARE_DISABLE_MASK 0x2 15.172 +#define _VLAPIC_BSP_ACCEPT_PIC 0x3 15.173 + uint32_t status; 15.174 + uint32_t id; 15.175 + uint32_t vcpu_id; 15.176 + unsigned long base_address; 15.177 + uint32_t isr[8]; 15.178 + uint32_t irr[INTR_LEN_32]; 15.179 + uint32_t tmr[INTR_LEN_32]; 15.180 + uint32_t task_priority; 15.181 + uint32_t processor_priority; 15.182 + uint32_t logical_dest; 15.183 + uint32_t dest_format; 15.184 + uint32_t spurious_vec; 15.185 + uint32_t lvt[6]; 15.186 + uint32_t timer_initial; 15.187 + uint32_t timer_current; 15.188 + uint32_t timer_divconf; 15.189 + uint32_t timer_divide_counter; 15.190 + struct ac_timer vlapic_timer; 15.191 + int intr_pending_count[MAX_VECTOR]; 15.192 + s_time_t timer_current_update; 15.193 + uint32_t icr_high; 15.194 + uint32_t icr_low; 15.195 + direct_intr_info_t direct_intr; 15.196 + uint32_t err_status; 15.197 + unsigned long init_ticks; 15.198 + uint32_t err_write_count; 15.199 + uint64_t apic_base_msr; 15.200 + uint32_t init_sipi_sipi_state; 15.201 + struct vcpu *vcpu; 15.202 + struct domain *domain; 15.203 +}; 15.204 + 15.205 +static inline int vlapic_timer_active(struct vlapic *vlapic) 15.206 +{ 15.207 + return active_ac_timer(&(vlapic->vlapic_timer)); 15.208 +} 15.209 + 15.210 +int vlapic_find_highest_irr(struct vlapic *vlapic); 15.211 + 15.212 +int vlapic_find_highest_isr(struct vlapic *vlapic); 15.213 + 15.214 +static uint32_t inline vlapic_get_base_address(struct vlapic *vlapic) 15.215 +{ 15.216 + return (vlapic->apic_base_msr & VLAPIC_BASE_MSR_BASE_ADDR_MASK); 15.217 +} 15.218 + 15.219 +void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode); 15.220 + 15.221 +int cpu_get_apic_interrupt(struct vcpu* v, int *mode); 15.222 + 15.223 +extern uint32_t vlapic_update_ppr(struct vlapic *vlapic); 15.224 + 15.225 +int vlapic_update(struct vcpu *v); 15.226 + 15.227 +extern int vlapic_init(struct vcpu *vc); 15.228 + 15.229 +extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value); 15.230 + 15.231 +int vlapic_range(struct vcpu *v, unsigned long addr); 15.232 + 15.233 +unsigned long vlapic_write(struct vcpu *v, unsigned long address, 15.234 + unsigned long len, unsigned long val); 15.235 + 15.236 +unsigned long vlapic_read(struct vcpu *v, unsigned long address, 15.237 + unsigned long len); 15.238 + 15.239 +int vlapic_accept_pic_intr(struct vcpu *v); 15.240 + 15.241 +struct vlapic* apic_round_robin(struct domain *d, 15.242 + uint8_t dest_mode, 15.243 + uint8_t vector, 15.244 + uint32_t bitmap); 15.245 + 15.246 +int vmx_apic_support(struct domain *d); 15.247 + 15.248 +#endif /* VMX_VLAPIC_H */
16.1 --- a/xen/include/asm-x86/vmx_vmcs.h Thu Oct 27 18:22:45 2005 +0100 16.2 +++ b/xen/include/asm-x86/vmx_vmcs.h Fri Oct 28 09:48:46 2005 +0100 16.3 @@ -22,6 +22,7 @@ 16.4 #include <asm/config.h> 16.5 #include <asm/vmx_cpu.h> 16.6 #include <asm/vmx_platform.h> 16.7 +#include <asm/vmx_vlapic.h> 16.8 #include <public/vmx_assist.h> 16.9 16.10 extern int start_vmx(void); 16.11 @@ -96,6 +97,7 @@ struct arch_vmx_struct { 16.12 struct msr_state msr_content; 16.13 struct mmio_op mmio_op; /* MMIO */ 16.14 void *io_bitmap_a, *io_bitmap_b; 16.15 + struct vlapic *vlapic; 16.16 u64 tsc_offset; 16.17 }; 16.18 16.19 @@ -272,18 +274,21 @@ enum vmcs_field { 16.20 16.21 #define VMX_DEBUG 1 16.22 #if VMX_DEBUG 16.23 -#define DBG_LEVEL_0 (1 << 0) 16.24 -#define DBG_LEVEL_1 (1 << 1) 16.25 -#define DBG_LEVEL_2 (1 << 2) 16.26 -#define DBG_LEVEL_3 (1 << 3) 16.27 -#define DBG_LEVEL_IO (1 << 4) 16.28 -#define DBG_LEVEL_VMMU (1 << 5) 16.29 +#define DBG_LEVEL_0 (1 << 0) 16.30 +#define DBG_LEVEL_1 (1 << 1) 16.31 +#define DBG_LEVEL_2 (1 << 2) 16.32 +#define DBG_LEVEL_3 (1 << 3) 16.33 +#define DBG_LEVEL_IO (1 << 4) 16.34 +#define DBG_LEVEL_VMMU (1 << 5) 16.35 +#define DBG_LEVEL_VLAPIC (1 << 6) 16.36 +#define DBG_LEVEL_VLAPIC_TIMER (1 << 7) 16.37 +#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 7) 16.38 16.39 extern unsigned int opt_vmx_debug_level; 16.40 #define VMX_DBG_LOG(level, _f, _a...) \ 16.41 if ((level) & opt_vmx_debug_level) \ 16.42 printk("[VMX:%d.%d] " _f "\n", \ 16.43 - current->domain->domain_id, current->vcpu_id, ## _a) 16.44 + current->domain->domain_id, current->vcpu_id, ## _a) 16.45 #else 16.46 #define VMX_DBG_LOG(level, _f, _a...) 16.47 #endif
17.1 --- a/xen/include/public/io/ioreq.h Thu Oct 27 18:22:45 2005 +0100 17.2 +++ b/xen/include/public/io/ioreq.h Fri Oct 28 09:48:46 2005 +0100 17.3 @@ -29,11 +29,11 @@ 17.4 #define STATE_IORESP_READY 3 17.5 #define STATE_IORESP_HOOK 4 17.6 17.7 -#define IOREQ_TYPE_PIO 0 /* pio */ 17.8 -#define IOREQ_TYPE_COPY 1 /* mmio ops */ 17.9 -#define IOREQ_TYPE_AND 2 17.10 -#define IOREQ_TYPE_OR 3 17.11 -#define IOREQ_TYPE_XOR 4 17.12 +#define IOREQ_TYPE_PIO 0 /* pio */ 17.13 +#define IOREQ_TYPE_COPY 1 /* mmio ops */ 17.14 +#define IOREQ_TYPE_AND 2 17.15 +#define IOREQ_TYPE_OR 3 17.16 +#define IOREQ_TYPE_XOR 4 17.17 17.18 /* 17.19 * VMExit dispatcher should cooperate with instruction decoder to 17.20 @@ -55,9 +55,10 @@ typedef struct { 17.21 uint8_t type; /* I/O type */ 17.22 } ioreq_t; 17.23 17.24 -#define MAX_VECTOR 256 17.25 +#define MAX_VECTOR 256 17.26 #define BITS_PER_BYTE 8 17.27 #define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint64_t))) 17.28 +#define INTR_LEN_32 (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint32_t))) 17.29 17.30 typedef struct { 17.31 uint16_t pic_elcr;
18.1 --- a/xen/include/public/io/vmx_vpic.h Thu Oct 27 18:22:45 2005 +0100 18.2 +++ b/xen/include/public/io/vmx_vpic.h Fri Oct 28 09:48:46 2005 +0100 18.3 @@ -76,7 +76,7 @@ void pic_update_irq(struct vmx_virpic *s 18.4 uint32_t pic_intack_read(struct vmx_virpic *s); 18.5 void register_pic_io_hook (void); 18.6 int cpu_get_pic_interrupt(struct vcpu *v, int *type); 18.7 -int is_pit_irq(struct vcpu *v, int irq); 18.8 +int is_pit_irq(struct vcpu *v, int irq, int type); 18.9 void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs); 18.10 void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs); 18.11