KVM: In-kernel string pio write support
Add string pio write support to support some version of Windows. Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
This commit is contained in:
@@ -1760,18 +1760,35 @@ static int complete_pio(struct kvm_vcpu *vcpu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kernel_pio(struct kvm_io_device *pio_dev, struct kvm_vcpu *vcpu)
|
static void kernel_pio(struct kvm_io_device *pio_dev,
|
||||||
|
struct kvm_vcpu *vcpu,
|
||||||
|
void *pd)
|
||||||
{
|
{
|
||||||
/* TODO: String I/O for in kernel device */
|
/* TODO: String I/O for in kernel device */
|
||||||
|
|
||||||
if (vcpu->pio.in)
|
if (vcpu->pio.in)
|
||||||
kvm_iodevice_read(pio_dev, vcpu->pio.port,
|
kvm_iodevice_read(pio_dev, vcpu->pio.port,
|
||||||
vcpu->pio.size,
|
vcpu->pio.size,
|
||||||
vcpu->pio_data);
|
pd);
|
||||||
else
|
else
|
||||||
kvm_iodevice_write(pio_dev, vcpu->pio.port,
|
kvm_iodevice_write(pio_dev, vcpu->pio.port,
|
||||||
vcpu->pio.size,
|
vcpu->pio.size,
|
||||||
vcpu->pio_data);
|
pd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pio_string_write(struct kvm_io_device *pio_dev,
|
||||||
|
struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
struct kvm_pio_request *io = &vcpu->pio;
|
||||||
|
void *pd = vcpu->pio_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < io->cur_count; i++) {
|
||||||
|
kvm_iodevice_write(pio_dev, io->port,
|
||||||
|
io->size,
|
||||||
|
pd);
|
||||||
|
pd += io->size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
|
int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
|
||||||
@@ -1779,7 +1796,7 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
|
|||||||
gva_t address, int rep, unsigned port)
|
gva_t address, int rep, unsigned port)
|
||||||
{
|
{
|
||||||
unsigned now, in_page;
|
unsigned now, in_page;
|
||||||
int i;
|
int i, ret = 0;
|
||||||
int nr_pages = 1;
|
int nr_pages = 1;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
struct kvm_io_device *pio_dev;
|
struct kvm_io_device *pio_dev;
|
||||||
@@ -1806,15 +1823,12 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
|
|||||||
memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4);
|
memcpy(vcpu->pio_data, &vcpu->regs[VCPU_REGS_RAX], 4);
|
||||||
kvm_arch_ops->decache_regs(vcpu);
|
kvm_arch_ops->decache_regs(vcpu);
|
||||||
if (pio_dev) {
|
if (pio_dev) {
|
||||||
kernel_pio(pio_dev, vcpu);
|
kernel_pio(pio_dev, vcpu, vcpu->pio_data);
|
||||||
complete_pio(vcpu);
|
complete_pio(vcpu);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* TODO: String I/O for in kernel device */
|
|
||||||
if (pio_dev)
|
|
||||||
printk(KERN_ERR "kvm_setup_pio: no string io support\n");
|
|
||||||
|
|
||||||
if (!count) {
|
if (!count) {
|
||||||
kvm_arch_ops->skip_emulated_instruction(vcpu);
|
kvm_arch_ops->skip_emulated_instruction(vcpu);
|
||||||
@@ -1862,9 +1876,21 @@ int kvm_setup_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vcpu->pio.in)
|
if (!vcpu->pio.in) {
|
||||||
return pio_copy_data(vcpu);
|
/* string PIO write */
|
||||||
return 0;
|
ret = pio_copy_data(vcpu);
|
||||||
|
if (ret >= 0 && pio_dev) {
|
||||||
|
pio_string_write(pio_dev, vcpu);
|
||||||
|
complete_pio(vcpu);
|
||||||
|
if (vcpu->pio.count == 0)
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
} else if (pio_dev)
|
||||||
|
printk(KERN_ERR "no string pio read support yet, "
|
||||||
|
"port %x size %d count %ld\n",
|
||||||
|
port, size, count);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvm_setup_pio);
|
EXPORT_SYMBOL_GPL(kvm_setup_pio);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user