From patchwork Thu Nov 7 20:28:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gabriel L. Somlo" X-Patchwork-Id: 289478 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9032E2C007A for ; Fri, 8 Nov 2013 07:29:16 +1100 (EST) Received: from localhost ([::1]:42087 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VeWCY-00012Z-Bl for incoming@patchwork.ozlabs.org; Thu, 07 Nov 2013 15:29:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42018) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VeWCB-000126-Qk for qemu-devel@nongnu.org; Thu, 07 Nov 2013 15:28:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VeWC6-0007UN-6c for qemu-devel@nongnu.org; Thu, 07 Nov 2013 15:28:51 -0500 Received: from mail-qe0-x22e.google.com ([2607:f8b0:400d:c02::22e]:59584) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VeWC6-0007UC-1H for qemu-devel@nongnu.org; Thu, 07 Nov 2013 15:28:46 -0500 Received: by mail-qe0-f46.google.com with SMTP id s14so1029713qeb.5 for ; Thu, 07 Nov 2013 12:28:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=dzwLi/5S4Fj9S8JR/+6Q5lNg7Ugq15a3JIEnszshx8s=; b=xuTf1XYK7pjspdWaK2ORuBdijasJuQXnjW/6ZCsKVerhkEaxfcgTPO05h7uLbVbUhR IpDfFfRAOUobEIJD0LrVMPRYCK4bUV979vaooFXm0FqShzqryf4RPIEobMCDKaOy/hue OsHyHDt+rzPu9tb0fUcNnPY2Qw9tWn7ZatrsndEKkY19b0JjKAR6ptV3DU+Gx9XagI20 sr236eG1jVCUSz/4TehtTqii3/TzTEIwDFhh/mv0zR0fDeH1GOy73zlez+fnWh9FqPl8 z8tt/xaHXJkFrVkU0zfOVcOEwppi8iw+keIDsvraI3tj/cds7Qc/C1boQcPMRu+XXIWu x5Lg== X-Received: by 10.49.72.3 with SMTP id z3mr16357749qeu.23.1383856125406; Thu, 07 Nov 2013 12:28:45 -0800 (PST) Received: from HEDWIG.INI.CMU.EDU (HEDWIG.INI.CMU.EDU. [128.2.16.5]) by mx.google.com with ESMTPSA id n7sm13726829qai.1.2013.11.07.12.28.44 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 07 Nov 2013 12:28:45 -0800 (PST) Date: Thu, 7 Nov 2013 15:28:42 -0500 From: "Gabriel L. Somlo" To: qemu-devel@nongnu.org Message-ID: <20131107202842.GD13775@HEDWIG.INI.CMU.EDU> References: <20131031150651.GI9423@HEDWIG.INI.CMU.EDU> <20131107180440.GC13775@HEDWIG.INI.CMU.EDU> <527BE9EF.50906@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <527BE9EF.50906@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400d:c02::22e Cc: pbonzini@redhat.com, jaceksburghardt@gmail.com, stefanha@gmail.com Subject: [Qemu-devel] [PATCH v2] e1000: initial link negotiation on mac osx X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Some guest operating systems' drivers (particularly Mac OS X) expect the link state to be pre-initialized by an earlier component such as a proprietary BIOS. This patch injects additional LSC events upon PHY reset, allowing the OS X driver to successfully complete initial link negotiation. This is a follow-up to commit 372254c6e5c078fb13b236bb648d2b9b2b0c70f1, which works around the OS X driver's failure to properly set up the MAC address. Signed-off-by: Gabriel Somlo --- On Thu, Nov 07, 2013 at 08:28:47PM +0100, Paolo Bonzini wrote: > Is there any way to work around this in the guest? Such as using a > UEFI driver for e1000 or something like that. Currently OS X boots on top of SeaBIOS and Chameleon, neither of which know anything about the e1000 hardware. On real hardware, the XNU e1000 driver expects the proprietary BIOS to set things up "just right", and doesn't have to bother jumping through all the hoops to properly initialize the hardware from scratch (after all, the XNU driver developers only have to care about a limited range of carefully controlled hardware). In the VM/guest scenario, QEMU is the only piece that has any knowledge of the e1000 hardware, so having it prep things for the guest would be the path of least resistance. Using a completely different alternative to SeaBIOS (one that would/could assume e1000 is present and would know enough about it to configure it just right) sounds a lot less feasible. Oh, and it gets worse :) My v1 patch does enough cheating to get OS X to link up successfully on a e1000-equipped *Q35* VM. If Q35 is not specified, then another bit of trickery is needed (i.e. inject another LSC when the driver initially unmasks LSC in the IMS register... Anyhow, this second version seems to work both with Q35 and without, on my vanilla SnowLeopard image. Any more thoughts and ideas much appreciated! Thanks, Gabriel hw/net/e1000.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/hw/net/e1000.c b/hw/net/e1000.c index ae63591..fe0f34e 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -186,6 +186,9 @@ e1000_link_up(E1000State *s) s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS; } +/* Forward decl. for use in set_phy_ctrl() (OS X link nego. workaround) */ +static void set_ics(E1000State *s, int index, uint32_t val); + static void set_phy_ctrl(E1000State *s, int index, uint16_t val) { @@ -197,6 +200,15 @@ set_phy_ctrl(E1000State *s, int index, uint16_t val) if (!(s->compat_flags & E1000_FLAG_AUTONEG)) { return; } + /* + * The Mac OS X driver expects a pre-initialized network card; injecting + * an extra LSC event here allows initial link negotiation to succeed in + * the absence of the Apple EFI BIOS. + */ + if ((val & MII_CR_RESET)) { + set_ics(s, 0, E1000_ICR_LSC); + return; + } if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) { e1000_link_down(s); s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE; @@ -1159,8 +1171,14 @@ set_imc(E1000State *s, int index, uint32_t val) static void set_ims(E1000State *s, int index, uint32_t val) { + uint32_t ics_val = 0; + + /* When Mac OS X initially unmasks LSC, it expects to see it set in ICS */ + if (s->mac_reg[IMS] == 0 && (val & E1000_IMS_LSC)) + ics_val |= E1000_ICR_LSC; + s->mac_reg[IMS] |= val; - set_ics(s, 0, 0); + set_ics(s, 0, ics_val); } #define getreg(x) [x] = mac_readreg