From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Gregory Haskins" Subject: Re: [PATCH] Support for in-kernel mmio handlers Date: Wed, 04 Apr 2007 20:21:03 -0400 Message-ID: <4613FA95.BA47.005A.0@novell.com> References: <4613C73F.BA47.005A.0@novell.com> <20070404224806.GA15078@sequoia.sous-sol.org> <4613E891.BA47.005A.0@novell.com> <20070405001021.GV10574@sequoia.sous-sol.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part85A2DAFF.0__=" To: , "Chris Wright" Return-path: In-Reply-To: <20070405001021.GV10574-JyIX8gxvWYPr2PDY2+4mTGD2FQJk+8+b@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org Errors-To: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org List-Id: kvm.vger.kernel.org --=__Part85A2DAFF.0__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline The attachment contains fixes based on the feedback from Chris. Thanks Chris! Regards, -Greg --=__Part85A2DAFF.0__= Content-Type: text/plain; name="mmio.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="mmio.patch" diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index fceeb84..0e6eb04 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -236,6 +236,54 @@ struct kvm_pio_request { int rep; }; =20 +struct kvm_io_device { + unsigned long (*read)(struct kvm_io_device *this, + gpa_t addr, + unsigned long length); + void (*write)(struct kvm_io_device *this, + gpa_t addr, + unsigned long length, + unsigned long val); + int (*in_range)(struct kvm_io_device *this, gpa_t addr); + + void *private; + struct list_head link; +}; + +/* It would be nice to use something smarter than a linear search, TBD... + * Thankfully we dont expect many devices to register (famous last words = :), + * so until then it will suffice. At least its abstracted so we can = change + * in one place. + */ +struct kvm_io_bus { + struct list_head list; +}; + +static inline void=20 +kvm_io_bus_init(struct kvm_io_bus *bus) +{ + INIT_LIST_HEAD(&bus->list); +} + +static inline struct kvm_io_device*=20 +kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr) +{ + struct kvm_io_device *pos =3D NULL; + + list_for_each_entry(pos, &bus->list, link) { + if (pos->in_range(pos, addr)) + return pos; + } + + return NULL; +} + +static inline void=20 +kvm_io_bus_register_dev(struct kvm_io_bus *bus, struct kvm_io_device = *dev) +{ + list_add_tail(&dev->link, &bus->list); +} + struct kvm_vcpu { struct kvm *kvm; union { @@ -294,6 +342,7 @@ struct kvm_vcpu { gpa_t mmio_phys_addr; struct kvm_pio_request pio; void *pio_data; + struct kvm_io_bus mmio_bus; =20 int sigset_active; sigset_t sigset; @@ -345,6 +394,7 @@ struct kvm { unsigned long rmap_overflow; struct list_head vm_list; struct file *filp; + struct kvm_io_bus mmio_bus; }; =20 struct kvm_stat { diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 4473174..c8109b7 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -294,6 +294,7 @@ static struct kvm *kvm_create_vm(void) =20 spin_lock_init(&kvm->lock); INIT_LIST_HEAD(&kvm->active_mmu_pages); + kvm_io_bus_init(&kvm->mmio_bus); for (i =3D 0; i < KVM_MAX_VCPUS; ++i) { struct kvm_vcpu *vcpu =3D &kvm->vcpus[i]; =20 @@ -302,6 +303,7 @@ static struct kvm *kvm_create_vm(void) vcpu->kvm =3D kvm; vcpu->mmu.root_hpa =3D INVALID_PAGE; INIT_LIST_HEAD(&vcpu->free_pages); + kvm_io_bus_init(&vcpu->mmio_bus); spin_lock(&kvm_lock); list_add(&kvm->vm_list, &vm_list); spin_unlock(&kvm_lock); @@ -1015,12 +1017,30 @@ static int emulator_write_std(unsigned long addr, return X86EMUL_UNHANDLEABLE; } =20 +static struct kvm_io_device* vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,=20 + gpa_t addr) +{ + struct kvm_io_device *mmio_dev; + + /* First check the local CPU addresses */ + mmio_dev =3D kvm_io_bus_find_dev(&vcpu->mmio_bus, addr); + if (!mmio_dev) { + /* Then check the entire VM */ + mmio_dev =3D kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, = addr); + } +=09 + return mmio_dev; +} + static int emulator_read_emulated(unsigned long addr, unsigned long *val, unsigned int bytes, struct x86_emulate_ctxt *ctxt) { struct kvm_vcpu *vcpu =3D ctxt->vcpu; + gpa_t gpa; + int i; + struct kvm_io_device *mmio_dev; =20 if (vcpu->mmio_read_completed) { memcpy(val, vcpu->mmio_data, bytes); @@ -1029,18 +1049,24 @@ static int emulator_read_emulated(unsigned long = addr, } else if (emulator_read_std(addr, val, bytes, ctxt) =3D=3D X86EMUL_CONTINUE) return X86EMUL_CONTINUE; - else { - gpa_t gpa =3D vcpu->mmu.gva_to_gpa(vcpu, addr); =20 - if (gpa =3D=3D UNMAPPED_GVA) - return X86EMUL_PROPAGATE_FAULT; - vcpu->mmio_needed =3D 1; - vcpu->mmio_phys_addr =3D gpa; - vcpu->mmio_size =3D bytes; - vcpu->mmio_is_write =3D 0; + gpa =3D vcpu->mmu.gva_to_gpa(vcpu, addr); + if (gpa =3D=3D UNMAPPED_GVA) + return vcpu_printf(vcpu, "not present\n"), X86EMUL_PROPAGAT= E_FAULT; =20 - return X86EMUL_UNHANDLEABLE; + /* Is this MMIO handled locally? */ + mmio_dev =3D vcpu_find_mmio_dev(vcpu, gpa); + if (mmio_dev) { + *val =3D mmio_dev->read(mmio_dev, gpa, bytes); + return X86EMUL_CONTINUE; } + + vcpu->mmio_needed =3D 1; + vcpu->mmio_phys_addr =3D gpa; + vcpu->mmio_size =3D bytes; + vcpu->mmio_is_write =3D 0; +=09 + return X86EMUL_UNHANDLEABLE; } =20 static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, @@ -1070,6 +1096,8 @@ static int emulator_write_emulated(unsigned long = addr, { struct kvm_vcpu *vcpu =3D ctxt->vcpu; gpa_t gpa =3D vcpu->mmu.gva_to_gpa(vcpu, addr); + int i; + struct kvm_io_device *mmio_dev; =20 if (gpa =3D=3D UNMAPPED_GVA) return X86EMUL_PROPAGATE_FAULT; @@ -1077,6 +1105,13 @@ static int emulator_write_emulated(unsigned long = addr, if (emulator_write_phys(vcpu, gpa, val, bytes)) return X86EMUL_CONTINUE; =20 + /* Is this MMIO handled locally? */ + mmio_dev =3D vcpu_find_mmio_dev(vcpu, gpa); + if (mmio_dev) { + mmio_dev->write(mmio_dev, gpa, bytes, val); + return X86EMUL_CONTINUE; + } + vcpu->mmio_needed =3D 1; vcpu->mmio_phys_addr =3D gpa; vcpu->mmio_size =3D bytes; --=__Part85A2DAFF.0__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV --=__Part85A2DAFF.0__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kvm-devel mailing list kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/kvm-devel --=__Part85A2DAFF.0__=--