]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
KVM: ia64: Implement some pal calls needed for windows 2008
authorXiantao Zhang <xiantao.zhang@intel.com>
Wed, 21 Jan 2009 03:21:27 +0000 (11:21 +0800)
committerAvi Kivity <avi@redhat.com>
Tue, 24 Mar 2009 09:03:06 +0000 (11:03 +0200)
For windows 2008, it needs more pal calls to implement for booting.
In addition, also changes the name of set_{sal, pal}_call_result to
get_{sal,pal}_call_result for readability.

Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/ia64/kvm/kvm_fw.c
arch/ia64/kvm/process.c

index cb7600bdff9d3a81bcf76648e0859a4061820a0f..a8ae52ed56358e3e3d1b81edf095ebfceaa36a3b 100644 (file)
@@ -227,6 +227,18 @@ static struct ia64_pal_retval pal_proc_get_features(struct kvm_vcpu *vcpu)
        return result;
 }
 
+static struct ia64_pal_retval pal_register_info(struct kvm_vcpu *vcpu)
+{
+
+       struct ia64_pal_retval result = {0, 0, 0, 0};
+       long in0, in1, in2, in3;
+
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+       result.status = ia64_pal_register_info(in1, &result.v1, &result.v2);
+
+       return result;
+}
+
 static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu)
 {
 
@@ -268,8 +280,12 @@ static struct ia64_pal_retval pal_vm_summary(struct kvm_vcpu *vcpu)
 static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu)
 {
        struct ia64_pal_retval result;
+       unsigned long in0, in1, in2, in3;
 
-       INIT_PAL_STATUS_UNIMPLEMENTED(result);
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+
+       result.status = ia64_pal_vm_info(in1, in2,
+                       (pal_tc_info_u_t *)&result.v1, &result.v2);
 
        return result;
 }
@@ -292,6 +308,108 @@ static void prepare_for_halt(struct kvm_vcpu *vcpu)
        vcpu->arch.timer_fired = 0;
 }
 
+static struct ia64_pal_retval pal_perf_mon_info(struct kvm_vcpu *vcpu)
+{
+       long status;
+       unsigned long in0, in1, in2, in3, r9;
+       unsigned long pm_buffer[16];
+
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+       status = ia64_pal_perf_mon_info(pm_buffer,
+                               (pal_perf_mon_info_u_t *) &r9);
+       if (status != 0) {
+               printk(KERN_DEBUG"PAL_PERF_MON_INFO fails ret=%ld\n", status);
+       } else {
+               if (in1)
+                       memcpy((void *)in1, pm_buffer, sizeof(pm_buffer));
+               else {
+                       status = PAL_STATUS_EINVAL;
+                       printk(KERN_WARNING"Invalid parameters "
+                                               "for PAL call:0x%lx!\n", in0);
+               }
+       }
+       return (struct ia64_pal_retval){status, r9, 0, 0};
+}
+
+static struct ia64_pal_retval pal_halt_info(struct kvm_vcpu *vcpu)
+{
+       unsigned long in0, in1, in2, in3;
+       long status;
+       unsigned long res = 1000UL | (1000UL << 16) | (10UL << 32)
+                                       | (1UL << 61) | (1UL << 60);
+
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+       if (in1) {
+               memcpy((void *)in1, &res, sizeof(res));
+               status = 0;
+       } else{
+               status = PAL_STATUS_EINVAL;
+               printk(KERN_WARNING"Invalid parameters "
+                                       "for PAL call:0x%lx!\n", in0);
+       }
+
+       return (struct ia64_pal_retval){status, 0, 0, 0};
+}
+
+static struct ia64_pal_retval pal_mem_attrib(struct kvm_vcpu *vcpu)
+{
+       unsigned long r9;
+       long status;
+
+       status = ia64_pal_mem_attrib(&r9);
+
+       return (struct ia64_pal_retval){status, r9, 0, 0};
+}
+
+static void remote_pal_prefetch_visibility(void *v)
+{
+       s64 trans_type = (s64)v;
+       ia64_pal_prefetch_visibility(trans_type);
+}
+
+static struct ia64_pal_retval pal_prefetch_visibility(struct kvm_vcpu *vcpu)
+{
+       struct ia64_pal_retval result = {0, 0, 0, 0};
+       unsigned long in0, in1, in2, in3;
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+       result.status = ia64_pal_prefetch_visibility(in1);
+       if (result.status == 0) {
+               /* Must be performed on all remote processors
+               in the coherence domain. */
+               smp_call_function(remote_pal_prefetch_visibility,
+                                       (void *)in1, 1);
+               /* Unnecessary on remote processor for other vcpus!*/
+               result.status = 1;
+       }
+       return result;
+}
+
+static void remote_pal_mc_drain(void *v)
+{
+       ia64_pal_mc_drain();
+}
+
+static struct ia64_pal_retval pal_get_brand_info(struct kvm_vcpu *vcpu)
+{
+       struct ia64_pal_retval result = {0, 0, 0, 0};
+       unsigned long in0, in1, in2, in3;
+
+       kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+
+       if (in1 == 0 && in2) {
+               char brand_info[128];
+               result.status = ia64_pal_get_brand_info(brand_info);
+               if (result.status == PAL_STATUS_SUCCESS)
+                       memcpy((void *)in2, brand_info, 128);
+       } else {
+               result.status = PAL_STATUS_REQUIRES_MEMORY;
+               printk(KERN_WARNING"Invalid parameters for "
+                                       "PAL call:0x%lx!\n", in0);
+       }
+
+       return result;
+}
+
 int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 
@@ -300,14 +418,22 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
        int ret = 1;
 
        gr28 = kvm_get_pal_call_index(vcpu);
-       /*printk("pal_call index:%lx\n",gr28);*/
        switch (gr28) {
        case PAL_CACHE_FLUSH:
                result = pal_cache_flush(vcpu);
                break;
+       case PAL_MEM_ATTRIB:
+               result = pal_mem_attrib(vcpu);
+               break;
        case PAL_CACHE_SUMMARY:
                result = pal_cache_summary(vcpu);
                break;
+       case PAL_PERF_MON_INFO:
+               result = pal_perf_mon_info(vcpu);
+               break;
+       case PAL_HALT_INFO:
+               result = pal_halt_info(vcpu);
+               break;
        case PAL_HALT_LIGHT:
        {
                INIT_PAL_STATUS_SUCCESS(result);
@@ -317,6 +443,16 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
        }
                break;
 
+       case PAL_PREFETCH_VISIBILITY:
+               result = pal_prefetch_visibility(vcpu);
+               break;
+       case PAL_MC_DRAIN:
+               result.status = ia64_pal_mc_drain();
+               /* FIXME: All vcpus likely call PAL_MC_DRAIN.
+                  That causes the congestion. */
+               smp_call_function(remote_pal_mc_drain, NULL, 1);
+               break;
+
        case PAL_FREQ_RATIOS:
                result = pal_freq_ratios(vcpu);
                break;
@@ -346,6 +482,9 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
                INIT_PAL_STATUS_SUCCESS(result);
                result.v1 = (1L << 32) | 1L;
                break;
+       case PAL_REGISTER_INFO:
+               result = pal_register_info(vcpu);
+               break;
        case PAL_VM_PAGE_SIZE:
                result.status = ia64_pal_vm_page_size(&result.v0,
                                                        &result.v1);
@@ -365,12 +504,18 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
                result.status = ia64_pal_version(
                                (pal_version_u_t *)&result.v0,
                                (pal_version_u_t *)&result.v1);
-
                break;
        case PAL_FIXED_ADDR:
                result.status = PAL_STATUS_SUCCESS;
                result.v0 = vcpu->vcpu_id;
                break;
+       case PAL_BRAND_INFO:
+               result = pal_get_brand_info(vcpu);
+               break;
+       case PAL_GET_PSTATE:
+       case PAL_CACHE_SHARED_INFO:
+               INIT_PAL_STATUS_UNIMPLEMENTED(result);
+               break;
        default:
                INIT_PAL_STATUS_UNIMPLEMENTED(result);
                printk(KERN_WARNING"kvm: Unsupported pal call,"
index 0e727ce0d55c5ff7caaaa47bb7fb30636e3e96fd..b1dc80952d91fc49918de183bbeb454276e723e7 100644 (file)
@@ -607,7 +607,7 @@ static void set_pal_call_data(struct kvm_vcpu *vcpu)
        p->exit_reason = EXIT_REASON_PAL_CALL;
 }
 
-static void set_pal_call_result(struct kvm_vcpu *vcpu)
+static void get_pal_call_result(struct kvm_vcpu *vcpu)
 {
        struct exit_ctl_data *p = &vcpu->arch.exit_data;
 
@@ -635,7 +635,7 @@ static void set_sal_call_data(struct kvm_vcpu *vcpu)
        p->exit_reason = EXIT_REASON_SAL_CALL;
 }
 
-static void set_sal_call_result(struct kvm_vcpu *vcpu)
+static void get_sal_call_result(struct kvm_vcpu *vcpu)
 {
        struct exit_ctl_data *p = &vcpu->arch.exit_data;
 
@@ -658,13 +658,13 @@ void  kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs,
                if (iim == DOMN_PAL_REQUEST) {
                        set_pal_call_data(v);
                        vmm_transition(v);
-                       set_pal_call_result(v);
+                       get_pal_call_result(v);
                        vcpu_increment_iip(v);
                        return;
                } else if (iim == DOMN_SAL_REQUEST) {
                        set_sal_call_data(v);
                        vmm_transition(v);
-                       set_sal_call_result(v);
+                       get_sal_call_result(v);
                        vcpu_increment_iip(v);
                        return;
                }