From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47017) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YOe59-0003Xa-Ci for qemu-devel@nongnu.org; Thu, 19 Feb 2015 22:16:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YOe54-0008P9-L7 for qemu-devel@nongnu.org; Thu, 19 Feb 2015 22:16:47 -0500 Received: from mail-qg0-x22c.google.com ([2607:f8b0:400d:c04::22c]:54772) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YOe54-0008P4-F9 for qemu-devel@nongnu.org; Thu, 19 Feb 2015 22:16:42 -0500 Received: by mail-qg0-f44.google.com with SMTP id j5so11628395qga.3 for ; Thu, 19 Feb 2015 19:16:41 -0800 (PST) Received: from t430.minyard.home (pool-173-57-158-30.dllstx.fios.verizon.net. [173.57.158.30]) by mx.google.com with ESMTPSA id l4sm21151799qao.24.2015.02.19.19.16.39 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Feb 2015 19:16:40 -0800 (PST) Sender: Corey Minyard Message-ID: <54E6A717.7070403@acm.org> Date: Thu, 19 Feb 2015 21:16:39 -0600 From: Corey Minyard MIME-Version: 1.0 References: <1418411751-3614-1-git-send-email-minyard@acm.org> <1418411751-3614-16-git-send-email-minyard@acm.org> <1424314469.26254.26.camel@kernel.crashing.org> In-Reply-To: <1424314469.26254.26.camel@kernel.crashing.org> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 15/16] ipmi: Add ACPI table entries for BMCs Reply-To: minyard@acm.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org On 02/18/2015 08:54 PM, Benjamin Herrenschmidt wrote: > On Fri, 2014-12-12 at 13:15 -0600, minyard@acm.org wrote: >> From: Corey Minyard >> >> Use the new ACPI table construction tools to create an ACPI >> entry for IPMI. > Same question as for the smbios business... Can this be made optional > possibly via instanciation attributes for the BMC device ? I was thinking about how to do this. I wasn't too terribly concerned right now because none of this ACPI stuff is going in as is, there are other patches for handling this and there's a lot to work out for SMBIOS and ACPI. However, there is another pressing concern, assuming your device is on the ISA bus, and that's the default address, interrupt, etc. It may vary from platform to platform, and it would be nice to have a way for it to be set more automatically. If it's not on an ISA bus, another interface will need to be written. -corey > Ben. > >> Signed-off-by: Corey Minyard >> --- >> hw/ipmi/isa_ipmi.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 145 insertions(+) >> >> diff --git a/hw/ipmi/isa_ipmi.c b/hw/ipmi/isa_ipmi.c >> index 83ea706..1652166 100644 >> --- a/hw/ipmi/isa_ipmi.c >> +++ b/hw/ipmi/isa_ipmi.c >> @@ -23,6 +23,8 @@ >> */ >> #include "hw/hw.h" >> #include "hw/isa/isa.h" >> +#include "hw/acpi/acpi-elements.h" >> +#include "hw/acpi/acpi.h" >> #include "hw/i386/pc.h" >> #include "qemu/timer.h" >> #include "sysemu/char.h" >> @@ -39,6 +41,8 @@ typedef struct ISAIPMIDevice { >> char *interface; >> int intftype; >> uint32_t iobase; >> + uint32_t iolength; >> + uint8_t regspacing; >> int32 isairq; >> uint8_t slave_addr; >> uint8_t version; >> @@ -58,6 +62,143 @@ struct smbios_type_38 { >> uint8_t interrupt_number; >> } QEMU_PACKED; >> >> +static int >> +acpi_ipmi_crs_ops(char **data, int dlen, void *opaque) >> +{ >> + ISAIPMIDevice *info = opaque; >> + int len, rv; >> + uint8_t regspacing = info->regspacing; >> + >> + if (regspacing == 1) { >> + regspacing = 0; >> + } >> + >> + /* IO(Decode16, x, y, z, c) */ >> + len = acpi_add_IO16(data, dlen, info->iobase, >> + info->iobase + info->iolength - 1, >> + regspacing, info->iolength); >> + if (len < 0) { >> + return len; >> + } >> + >> + if (info->isairq) { >> + /* Interrupt(ResourceConsumer,Level,ActiveHigh,Exclusive) {n} */ >> + rv = acpi_add_Interrupt(data, dlen, info->isairq, >> + ACPI_RESOURCE_CONSUMER, >> + ACPI_INTERRUPT_MODE_LEVEL, >> + ACPI_INTERRUPT_POLARITY_ACTIVE_HIGH, >> + ACPI_INTERRUPT_EXCLUSIVE); >> + if (rv < 0) { >> + return rv; >> + } >> + len += rv; >> + } >> + rv = acpi_add_EndResource(data, dlen); >> + if (rv < 0) { >> + return rv; >> + } >> + len += rv; >> + return len; >> +} >> + >> +static int >> +acpi_ipmi_crs(char **data, int dlen, void *opaque) >> +{ >> + ISAIPMIDevice *info = opaque; >> + int len; >> + >> + len = acpi_add_BufferOp(NULL, 0, acpi_ipmi_crs_ops, info); >> + if (len < 0) { >> + return len; >> + } >> + if (len <= dlen) { >> + acpi_add_BufferOp(data, dlen, acpi_ipmi_crs_ops, info); >> + } >> + return len; >> +} >> + >> +static int >> +acpi_ipmi_dev(char **data, int dlen, void *opaque) >> +{ >> + ISAIPMIDevice *info = opaque; >> + int len, rv; >> + char *name; >> + uint64_t val; >> + >> + name = g_strdup_printf("ipmi_%s", info->interface); >> + >> + /* Name(_HID, EISAID("IPI0001")) */ >> + len = acpi_add_Name(data, dlen, "_HID", acpi_add_EISAID, >> + (void *) "IPI0001"); >> + if (len < 0) { >> + return len; >> + } >> + /* Name(_STR, Unicode("ipmi_xxx")) */ >> + rv = acpi_add_Name(data, dlen, "_STR", acpi_add_Unicode, name); >> + if (rv < 0) { >> + return rv; >> + } >> + len += rv; >> + val = 0; >> + /* Name(_UID, 0) */ >> + rv = acpi_add_Name(data, dlen, "_UID", acpi_add_Integer, &val); >> + if (rv < 0) { >> + return rv; >> + } >> + len += rv; >> + /* Name(_CRS, ResourceTemplate() { */ >> + rv = acpi_add_Name(data, dlen, "_CRS", acpi_ipmi_crs, info); >> + if (rv < 0) { >> + return rv; >> + } >> + len += rv; >> + val = info->intftype; >> + /* Method(_IFT) { Return(i) } */ >> + rv = acpi_add_Method(data, dlen, "_IFT", 0, acpi_add_Return, &val); >> + if (rv < 0) { >> + return rv; >> + } >> + len += rv; >> + val = ((info->version & 0xf0) << 4) | (info->version & 0x0f); >> + /* Method(_SRV) { Return(version) } */ >> + rv = acpi_add_Method(data, dlen, "_SRV", 0, acpi_add_Return, &val); >> + if (rv < 0) { >> + return rv; >> + } >> + len += rv; >> + return len; >> +} >> + >> +static int >> +acpi_ipmi_scope(char **data, int dlen, void *opaque) >> +{ >> + ISAIPMIDevice *info = opaque; >> + >> + /* Device(MI0) { */ >> + return acpi_add_Device(data, dlen, "MI0", acpi_ipmi_dev, info); >> + /* } */ >> +} >> + >> +static void >> +ipmi_encode_acpi(ISAIPMIDevice *info) >> +{ >> + char ipmitable[200]; >> + char *tblptr = ipmitable; >> + int rc; >> + Error *err = NULL; >> + >> + /* Scope(\_SB.PCI0.ISA) { */ >> + rc = acpi_add_Scope(&tblptr, sizeof(ipmitable), "\\_SB.PCI0.ISA", >> + acpi_ipmi_scope, info); >> + /* } */ >> + if (rc < 0) { >> + fprintf(stderr, "Unable to format IPMI ACPI table entry\n"); >> + return; >> + } >> + >> + acpi_append_to_table("SSDT", ipmitable, rc, &err); >> +} >> + >> static void ipmi_encode_smbios(void *opaque) >> { >> ISAIPMIDevice *info = opaque; >> @@ -79,6 +220,8 @@ static void ipmi_encode_smbios(void *opaque) >> smb38.interrupt_number = info->isairq; >> smbios_table_entry_add((struct smbios_structure_header *) &smb38, >> sizeof(smb38), true); >> + >> + ipmi_encode_acpi(info); >> } >> >> static void ipmi_isa_realizefn(DeviceState *dev, Error **errp) >> @@ -110,6 +253,7 @@ static void ipmi_isa_realizefn(DeviceState *dev, Error **errp) >> intfk = IPMI_INTERFACE_GET_CLASS(intf); >> bmc->intf = intf; >> intf->bmc = bmc; >> + ipmi->regspacing = 1; >> intf->io_base = ipmi->iobase; >> intf->slave_addr = ipmi->slave_addr; >> ipmi->intftype = intfk->smbios_type; >> @@ -118,6 +262,7 @@ static void ipmi_isa_realizefn(DeviceState *dev, Error **errp) >> if (*errp) { >> return; >> } >> + ipmi->iolength = intf->io_length; >> ipmi_bmc_init(bmc, errp); >> if (*errp) { >> return; > >