From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NUQBG-0001tN-9n for qemu-devel@nongnu.org; Mon, 11 Jan 2010 14:44:02 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NUQBA-0001qF-UT for qemu-devel@nongnu.org; Mon, 11 Jan 2010 14:44:01 -0500 Received: from [199.232.76.173] (port=38531 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NUQBA-0001q8-Ii for qemu-devel@nongnu.org; Mon, 11 Jan 2010 14:43:56 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48726) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NUQB9-0001OA-8I for qemu-devel@nongnu.org; Mon, 11 Jan 2010 14:43:55 -0500 Date: Mon, 11 Jan 2010 21:40:54 +0200 From: "Michael S. Tsirkin" Message-ID: <20100111194053.GA15857@redhat.com> References: <4B45C209.1030802@mail.berlios.de> <1262862925-5205-1-git-send-email-weil@mail.berlios.de> <20100107123400.GE599@redhat.com> <4B45F8AE.1050400@mail.berlios.de> <20100111183437.GA13712@redhat.com> <4B4B7E4D.5010101@mail.berlios.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4B4B7E4D.5010101@mail.berlios.de> Subject: [Qemu-devel] Re: [RFC] API change for pci_set_word and related functions List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Stefan Weil Cc: qemu-devel@nongnu.org On Mon, Jan 11, 2010 at 08:38:53PM +0100, Stefan Weil wrote: > Michael S. Tsirkin schrieb: > > On Thu, Jan 07, 2010 at 04:07:26PM +0100, Stefan Weil wrote: > >> Michael S. Tsirkin schrieb: > >>> On Thu, Jan 07, 2010 at 12:15:25PM +0100, Stefan Weil wrote: > >>> ... > >>>> --- > >>>> hw/eepro100.c | 4 +--- > >>>> 1 files changed, 1 insertions(+), 3 deletions(-) > >>>> > >>>> diff --git a/hw/eepro100.c b/hw/eepro100.c > >>>> index 336ca49..a21c984 100644 > >>>> --- a/hw/eepro100.c > >>>> +++ b/hw/eepro100.c > >>>> @@ -420,10 +420,8 @@ static void pci_reset(EEPRO100State * s) > >>>> /* TODO: this is the default, do not override. */ > >>>> PCI_CONFIG_16(PCI_COMMAND, 0x0000); > >>>> /* PCI Status */ > >>>> - /* TODO: this seems to make no sense. */ > >>>> /* TODO: Value at RST# should be 0. */ > >>> So this second todo can go too. I've removed it in my tree. > >>> > >>>> - PCI_CONFIG_16(PCI_STATUS, > >>>> - PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_SIG_TARGET_ABORT); > >>>> + PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM | > >>>> PCI_STATUS_FAST_BACK); > >>>> /* PCI Revision ID */ > >>>> PCI_CONFIG_8(PCI_REVISION_ID, 0x08); > >>> BTW if you are not afraid of churn, there's no reason > >>> for PCI_CONFIG_8 and friends anymore, because pci.h > >>> has much nicer pci_set_byte etc. > >> Hello Michael, > >> > >> I already noticed pci_set_byte, pci_set_word, pci_set_long and > >> the corresponding pci_get_xxx functions and thought about using them. > >> > >> I did not start it because I want to suggest a different API > >> for use in PCI device emulations: > >> > >> instead of > >> > >> pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_CAP_LIST); > >> > >> or > >> > >> pci_set_word(&pci_conf[PCI_STATUS], PCI_STATUS_CAP_LIST); > >> > >> it would be better to call > >> > >> pci_set_word(pci_conf, PCI_STATUS, PCI_STATUS_CAP_LIST); > >> > >> > >> The prototypes would look like this: > >> > >> /* Set PCI config value. */ > >> void pci_set_word(PCIDevice *s, uint8_t offset, uint16_t val); > >> > >> /* Set PCI cmask value. */ > >> void pci_set_cmask_word(PCIDevice *s, uint8_t offset, uint16_t val); > >> > >> /* Set PCI wmask value. */ > >> void pci_set_wmask_word(PCIDevice *s, uint8_t offset, uint16_t val); > >> > >> What are the advantages? > >> * strict type checking (the old API takes any uint8_t *) > > > > So IMO it's easier to make mistakes with your proposed API because if > > you confuse offset and value compiler does not complain. More > > importantly, if you want to pass some other uint8_t pointer to e.g. > > pci_set_word, you can *and nothing unexpected will happen* > > it will set the word to the given value. So the current > > API is more type safe than what you propose. > > > > No. The current API takes any uint8_t pointer to read or write > a value. This is not safe. Why isn't it? > The proposed API only takes a PCIDevice pointer > and reads or writes only configuration (or cmask or > wmask) values. Yes, you can take offset for value. > If you are lucky and value is an uint16_t or uint32_t, > your compiler will complain. Such a compiler will also complain over most of qemu code. > And even if your compiler > does not complain, it is wrong but still safe, because > the code will only access the PCI configuration data. > Correct and safe beats wrong and safe every time. > >> * many other pci_* functions also have a first parameter of type PCIDevice > > > > So what would make sense IMO is higer level abstraction, > > for example similar to what we have with capabilities > > and msix, I think we could have something like this > > for e.g. power management. > > > > For low-level bit tweaking, the advantages of current API is that same > > thing can be used to set wmask, cmask, config itself, and whatever else > > we will come up with. > > The low level API can be used where low level is > adequate: in pci.c for example. > > To implement emulated PCI devices, a more robust API > would be better. Think of the number of devices which > are still missing, think of people who want to write > a new PCI device emulation for QEMU without being > a QEMU expert. > > > > >> * calls look nicer (at least in my opinion) > > > > What I value is the fact that it's obvious which > > data is changed. > > Here there is no difference between current and > proposed API: > > old: pci_set_word(&pci_conf[PCI_STATUS], PCI_STATUS_CAP_LIST); > new: pci_set_word(pci_conf, PCI_STATUS, PCI_STATUS_CAP_LIST); > > Every function call hides what happens. If you really wanted > to see which data is changed, you would have to write > > *(uint16_t *)&pci_conf[PCI_STATUS] = cpu_to_le16(PCI_STATUS_CAP_LIST); That's what we used to have, and it's not all bad, but very verbose and ugly. > > > >> * strict range checking (offset is limited to 0...255, additional > >> assertions possible - the old API is unsafe because it just takes > >> a pointer) > > > > I don't think we want to add return status, so there wouldn't > > be a benefit to range checking as we can't act on it. > > Anyway, it's very unusual to use anything but a constant > > as an offset, so range errors are very uncommon. > > There is an implicit range checking in the proposed > API because the offset is uint8_t, so it cannot > exceed the range which is valid for configuration > offsets. Oh, btw, this is wrong on pci express. > A more elaborated check could require that > configuration byte values are only addressed > using pci_set_byte (not pci_set_long) > and raise a fatal runtime error otherwise. > > Runtime checks without return values > are well established in QEMU's code, > and they are very useful for code writers. > > > > >> The functions are inline, so the resulting code won't differ. > >> > >> Instead of _byte, _word and _long I personally prefer something > >> like _8, _16, _32 because _word and _long need interpretation. > >> But this is only a matter of taste - the API change is more important. > >> > >> > >> Regards, > >> > >> Stefan Weil > >