mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-21 13:24:15 +08:00
KVM: ia64: Implement some pal calls needed for windows 2008
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>
This commit is contained in:
parent
4b7bb626e3
commit
7d656bd996
@ -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,"
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user