diff --git a/hypervisor/arch/x86/guest/pm.c b/hypervisor/arch/x86/guest/pm.c index 8a32f425c..0dabbbaca 100644 --- a/hypervisor/arch/x86/guest/pm.c +++ b/hypervisor/arch/x86/guest/pm.c @@ -110,8 +110,24 @@ static void vm_setup_cpu_cx(struct vm *vm) } +static inline void init_cx_port(struct vm *vm) +{ + uint8_t cx_idx; + + for (cx_idx = 2; cx_idx <= vm->pm.cx_cnt; cx_idx++) { + struct cpu_cx_data *cx_data = vm->pm.cx_data + cx_idx; + + if (cx_data->cx_reg.space_id == SPACE_SYSTEM_IO) { + uint16_t port = (uint16_t)cx_data->cx_reg.address; + + allow_guest_io_access(vm, port, 1); + } + } +} + void vm_setup_cpu_state(struct vm *vm) { vm_setup_cpu_px(vm); vm_setup_cpu_cx(vm); + init_cx_port(vm); } diff --git a/hypervisor/arch/x86/io.c b/hypervisor/arch/x86/io.c index fba3b58f0..932fd8f5e 100644 --- a/hypervisor/arch/x86/io.c +++ b/hypervisor/arch/x86/io.c @@ -190,6 +190,22 @@ void free_io_emulation_resource(struct vm *vm) free(vm->arch_vm.iobitmap[1]); } +void allow_guest_io_access(struct vm *vm, uint32_t address, uint32_t nbytes) +{ + uint32_t *b; + uint32_t i; + uint32_t a; + + b = vm->arch_vm.iobitmap[0]; + for (i = 0; i < nbytes; i++) { + if (address & 0x8000) + b = vm->arch_vm.iobitmap[1]; + a = address & 0x7fff; + b[a >> 5] &= ~(1 << (a & 0x1f)); + address++; + } +} + static void deny_guest_io_access(struct vm *vm, uint32_t address, uint32_t nbytes) { uint32_t *b; diff --git a/hypervisor/include/arch/x86/io.h b/hypervisor/include/arch/x86/io.h index 0dbf9c0c5..2914f70d5 100644 --- a/hypervisor/include/arch/x86/io.h +++ b/hypervisor/include/arch/x86/io.h @@ -170,6 +170,7 @@ struct vm_io_handler { int io_instr_vmexit_handler(struct vcpu *vcpu); void setup_io_bitmap(struct vm *vm); void free_io_emulation_resource(struct vm *vm); +void allow_guest_io_access(struct vm *vm, uint32_t address, uint32_t nbytes); void register_io_emulation_handler(struct vm *vm, struct vm_io_range *range, io_read_fn_t io_read_fn_ptr, io_write_fn_t io_write_fn_ptr);