From patchwork Sun Mar 26 05:20:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bui Quang Minh X-Patchwork-Id: 1761215 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=GId/uYMR; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PkkrC1CX7z1yYV for ; Sun, 26 Mar 2023 16:23:37 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pgIqI-0007Qy-Vd; Sun, 26 Mar 2023 01:22:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pgIqH-0007O3-7E for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:22:57 -0400 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pgIqE-0007ze-Pb for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:22:56 -0400 Received: by mail-pj1-x102d.google.com with SMTP id l9-20020a17090a3f0900b0023d32684e7fso8423882pjc.1 for ; Sat, 25 Mar 2023 22:22:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1679808173; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6Y9tje19OFc2dSIBz+eR5m+FLZJ4QhzIEXL1qcEkTng=; b=GId/uYMRKKMVLlGgYAh6/42VIwE+nlQzB+DxIPG0dh+dBG/Cnzq+diAFa58Xp0BLEY HeyTLB4Ag4fjpvAn/QWiF+IdYM9fYTDY9wwddX48lETGCSZb4zoSDZ/bo17nVZIIX2jb aOdVVBHrPYwlD/lTw730/+R5vxOSgN5186MkVUEkld0xcDXzbf7DLu1EAM/MInlbvgj8 rkX8ZF1KkELoWi/SxvVL+3XCLYT9ekUG4OWFjAza3e20tnJO7Zlk3yycUuK3+hNxNGEb yJ//cYRtjEzM0Tcvi0omLCxrN7Ur4sILFBrGqvOLD0zTqJ11XQ4/xv/DlAXfXIH0Q7p2 Ph2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679808173; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6Y9tje19OFc2dSIBz+eR5m+FLZJ4QhzIEXL1qcEkTng=; b=sDmhy+LIOlVOMBTPxzglcSTVBIEImIMLFsap5z5emQrxhq/K26fZzgPBPknNR9Covl f5Z1tgX/fUwockBJU2fjQ6bh6CZ89ySxDv3XcTHZHHbnGwronkMPZRk64Q/jlicOg+5B pket6lD3w04rWvlV/jcl6/RbV4cLGp42h9M1UFnSoHhBZkX1rF6LEwJDKI6ayDnesHVo SgZL+CeiFnLWwvbprYFlam41FK6hF9TYPNHa/6LH0g6MTYJksSXycI8Q6SW083YPH3jx uhFs5wXJlnHJbciyLXRqiqnGhpXEXv6xaD/EA+0+YzRa2jtw8oV0vzdaBtIQGUz+3PsE ww/g== X-Gm-Message-State: AAQBX9e13mzp9RZI3mz1l8T1zNqa9GwzeudpXkzTFkADRj47rQag/T6s BOwe4kuOMzOanCtOSaNiVKI/jTSqBdeZwQ== X-Google-Smtp-Source: AKy350YfPmhJhxwJcp1n+ubvcuec5X653tYLyV4ivfCSxhDCp2YKywdCGtKaJiMV0J7i0gbubc7GHw== X-Received: by 2002:a17:902:c44b:b0:196:d05:bac7 with SMTP id m11-20020a170902c44b00b001960d05bac7mr6187138plm.58.1679808173061; Sat, 25 Mar 2023 22:22:53 -0700 (PDT) Received: from localhost.localdomain ([113.173.97.170]) by smtp.googlemail.com with ESMTPSA id bc9-20020a170902930900b001a20b31a23fsm5020258plb.293.2023.03.25.22.22.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Mar 2023 22:22:52 -0700 (PDT) From: Bui Quang Minh To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Richard Henderson , Eduardo Habkost , "Michael S . Tsirkin" , Marcel Apfelbaum , David Woodhouse , Igor Mammedov , =?utf-8?q?Alex_Benn=C3=A9e?= , Bui Quang Minh Subject: [PATCH v2 1/5] i386/tcg: implement x2APIC registers MSR access Date: Sun, 26 Mar 2023 12:20:35 +0700 Message-Id: <20230326052039.33717-2-minhquangbui99@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230326052039.33717-1-minhquangbui99@gmail.com> References: <20230326052039.33717-1-minhquangbui99@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::102d; envelope-from=minhquangbui99@gmail.com; helo=mail-pj1-x102d.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 This commit refactors apic_mem_read/write to support both MMIO access in xAPIC and MSR access in x2APIC. Signed-off-by: Bui Quang Minh --- hw/intc/apic.c | 79 ++++++++++++++++++---------- hw/intc/trace-events | 4 +- include/hw/i386/apic.h | 3 ++ target/i386/cpu.h | 3 ++ target/i386/tcg/sysemu/misc_helper.c | 27 ++++++++++ 5 files changed, 86 insertions(+), 30 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 20b5a94073..61b494b20a 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -288,6 +288,13 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode); } +bool is_x2apic_mode(DeviceState *dev) +{ + APICCommonState *s = APIC(dev); + + return s->apicbase & MSR_IA32_APICBASE_EXTD; +} + static void apic_set_base(APICCommonState *s, uint64_t val) { s->apicbase = (val & 0xfffff000) | @@ -636,16 +643,11 @@ static void apic_timer(void *opaque) apic_timer_update(s, s->next_time); } -static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) +uint64_t apic_register_read(int index) { DeviceState *dev; APICCommonState *s; - uint32_t val; - int index; - - if (size < 4) { - return 0; - } + uint64_t val; dev = cpu_get_current_apic(); if (!dev) { @@ -653,7 +655,6 @@ static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) } s = APIC(dev); - index = (addr >> 4) & 0xff; switch(index) { case 0x02: /* id */ val = s->id << 24; @@ -720,7 +721,23 @@ static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) val = 0; break; } - trace_apic_mem_readl(addr, val); + + trace_apic_register_read(index, val); + return val; +} + +static uint64_t apic_mem_read(void *opaque, hwaddr addr, unsigned size) +{ + uint32_t val; + int index; + + if (size < 4) { + return 0; + } + + index = (addr >> 4) & 0xff; + val = (uint32_t)apic_register_read(index); + return val; } @@ -737,27 +754,10 @@ static void apic_send_msi(MSIMessage *msi) apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode); } -static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, - unsigned size) +void apic_register_write(int index, uint64_t val) { DeviceState *dev; APICCommonState *s; - int index = (addr >> 4) & 0xff; - - if (size < 4) { - return; - } - - if (addr > 0xfff || !index) { - /* MSI and MMIO APIC are at the same memory location, - * but actually not on the global bus: MSI is on PCI bus - * APIC is connected directly to the CPU. - * Mapping them on the global bus happens to work because - * MSI registers are reserved in APIC MMIO and vice versa. */ - MSIMessage msi = { .address = addr, .data = val }; - apic_send_msi(&msi); - return; - } dev = cpu_get_current_apic(); if (!dev) { @@ -765,7 +765,7 @@ static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, } s = APIC(dev); - trace_apic_mem_writel(addr, val); + trace_apic_register_write(index, val); switch(index) { case 0x02: @@ -843,6 +843,29 @@ static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, } } +static void apic_mem_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + int index = (addr >> 4) & 0xff; + + if (size < 4) { + return; + } + + if (addr > 0xfff || !index) { + /* MSI and MMIO APIC are at the same memory location, + * but actually not on the global bus: MSI is on PCI bus + * APIC is connected directly to the CPU. + * Mapping them on the global bus happens to work because + * MSI registers are reserved in APIC MMIO and vice versa. */ + MSIMessage msi = { .address = addr, .data = val }; + apic_send_msi(&msi); + return; + } + + apic_register_write(index, val); +} + static void apic_pre_save(APICCommonState *s) { apic_sync_vapic(s, SYNC_FROM_VAPIC); diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 50cadfb996..9d4e7a67be 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -14,8 +14,8 @@ cpu_get_apic_base(uint64_t val) "0x%016"PRIx64 # apic.c apic_local_deliver(int vector, uint32_t lvt) "vector %d delivery mode %d" apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) "dest %d dest_mode %d delivery_mode %d vector %d trigger_mode %d" -apic_mem_readl(uint64_t addr, uint32_t val) "0x%"PRIx64" = 0x%08x" -apic_mem_writel(uint64_t addr, uint32_t val) "0x%"PRIx64" = 0x%08x" +apic_register_read(uint8_t reg, uint64_t val) "register 0x%02x = 0x%"PRIx64 +apic_register_write(uint8_t reg, uint64_t val) "register 0x%02x = 0x%"PRIx64 # ioapic.c ioapic_set_remote_irr(int n) "set remote irr for pin %d" diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h index bdc15a7a73..2cebeb4faf 100644 --- a/include/hw/i386/apic.h +++ b/include/hw/i386/apic.h @@ -18,6 +18,9 @@ void apic_sipi(DeviceState *s); void apic_poll_irq(DeviceState *d); void apic_designate_bsp(DeviceState *d, bool bsp); int apic_get_highest_priority_irr(DeviceState *dev); +uint64_t apic_register_read(int index); +void apic_register_write(int index, uint64_t val); +bool is_x2apic_mode(DeviceState *d); /* pc.c */ DeviceState *cpu_get_current_apic(void); diff --git a/target/i386/cpu.h b/target/i386/cpu.h index d243e290d3..02165a5ad2 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -545,6 +545,9 @@ typedef enum X86Seg { #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 #define MSR_IA32_VMX_VMFUNC 0x00000491 +#define MSR_APIC_START 0x00000800 +#define MSR_APIC_END 0x000008ff + #define XSTATE_FP_BIT 0 #define XSTATE_SSE_BIT 1 #define XSTATE_YMM_BIT 2 diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c index e1528b7f80..1fce2076a3 100644 --- a/target/i386/tcg/sysemu/misc_helper.c +++ b/target/i386/tcg/sysemu/misc_helper.c @@ -25,6 +25,7 @@ #include "exec/address-spaces.h" #include "exec/exec-all.h" #include "tcg/helper-tcg.h" +#include "hw/i386/apic.h" void helper_outb(CPUX86State *env, uint32_t port, uint32_t data) { @@ -289,6 +290,19 @@ void helper_wrmsr(CPUX86State *env) env->msr_bndcfgs = val; cpu_sync_bndcs_hflags(env); break; + case MSR_APIC_START ... MSR_APIC_END: { + int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; + + if (!is_x2apic_mode(env_archcpu(env)->apic_state)) { + goto error; + } + + qemu_mutex_lock_iothread(); + apic_register_write(index, val); + qemu_mutex_unlock_iothread(); + + break; + } default: if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + @@ -455,6 +469,19 @@ void helper_rdmsr(CPUX86State *env) val = (cs->nr_threads * cs->nr_cores) | (cs->nr_cores << 16); break; } + case MSR_APIC_START ... MSR_APIC_END: { + int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START; + + if (!is_x2apic_mode(env_archcpu(env)->apic_state)) { + raise_exception_ra(env, EXCP0D_GPF, GETPC()); + } + + qemu_mutex_lock_iothread(); + val = apic_register_read(index); + qemu_mutex_unlock_iothread(); + + break; + } default: if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + From patchwork Sun Mar 26 05:20:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bui Quang Minh X-Patchwork-Id: 1761216 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=HuPATwE7; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PkkrF22Tnz1yYB for ; Sun, 26 Mar 2023 16:23:41 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pgIqP-0007T6-W3; Sun, 26 Mar 2023 01:23:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pgIqN-0007Rx-GJ for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:03 -0400 Received: from mail-pj1-x1029.google.com ([2607:f8b0:4864:20::1029]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pgIqK-00089Z-Je for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:02 -0400 Received: by mail-pj1-x1029.google.com with SMTP id l7so4965108pjg.5 for ; Sat, 25 Mar 2023 22:23:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1679808179; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jdz2Zl8wq66450DGlx3qz956o9VH/nqcIu0bqufWs+4=; b=HuPATwE7cfvB3cPZm5r+XTAytJXq6FsG0NCXLEXNVhPT+rBaTqxPh662pA2vaQL/M0 ZdgeRooEsustyJz3VVsdeXmsMLCiOVq0zQRM1GtCpBd0KhrsD0d/awWedNwlybqnnI8U VqbF06J6lyg4efDLUTY45Nn1b0v7M+u98X/wFnKe3GgY3c5V5gArHGuszvmopfwB2gCT Hz5KTjyfz1k89ioEeDoS7ptv+4HM4utzhkrunD+n1+zsCxHcV2sDquuCw9DzMb68ZwtP Xkhgks6UwzSOE4KNsXAx4Bs/L9bfXkSNspkIs7IHDGOt+0/bVrH01tg0s6CzZKVKAjQx Q1MA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679808179; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jdz2Zl8wq66450DGlx3qz956o9VH/nqcIu0bqufWs+4=; b=ojuT1/qoQ6N55PCn5kdKvYcdND98or6Tp4ekbl2I+pmXxjJqOvZOowcQ4fxsjit7Cm KumZDvDAhgXpKyaWAdU6E8qDB+2EGhpcas3qlyrX2V1xwA9EZqmle/6BIwvly5r/QOyl Wla2B5LaiElZH6kJJyPJYtTfmRffvJxD3oU/whbshsBaO3JOq5bGq7E1ihjbhzXJwTO1 ttGZnjmaIe7xvw/bSzzGqbY4H8njyk8oc2Qkl+vVg52HcOyiqxN5WrJTuHrk3P3qScMv aLtcp0xLs9m6jQLg4utQ4uXLH1XYSqStibBzi8CbEYbPb0iBjFYNKzW67E8aX8fJF28C hyVg== X-Gm-Message-State: AAQBX9fMJqjWSVmbqheOpSRZtvGCpZ3dYbPU2iW5O9jrq4En4LJHvF8V 4y7ajU8cxmFInvDh+yTO7JmF5CHFSdfUcA== X-Google-Smtp-Source: AKy350ZO5kD7qa7VGnrjC5FQOsJH4H1fdLpXW+JoD8ZAclTqggbMUrg07ppbTqVuaWVIN1XVkX0xSw== X-Received: by 2002:a17:902:e0c5:b0:1a0:6eb4:3871 with SMTP id e5-20020a170902e0c500b001a06eb43871mr6481896pla.20.1679808178793; Sat, 25 Mar 2023 22:22:58 -0700 (PDT) Received: from localhost.localdomain ([113.173.97.170]) by smtp.googlemail.com with ESMTPSA id bc9-20020a170902930900b001a20b31a23fsm5020258plb.293.2023.03.25.22.22.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Mar 2023 22:22:58 -0700 (PDT) From: Bui Quang Minh To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Richard Henderson , Eduardo Habkost , "Michael S . Tsirkin" , Marcel Apfelbaum , David Woodhouse , Igor Mammedov , =?utf-8?q?Alex_Benn=C3=A9e?= , Bui Quang Minh Subject: [PATCH v2 2/5] apic: add support for x2APIC mode Date: Sun, 26 Mar 2023 12:20:36 +0700 Message-Id: <20230326052039.33717-3-minhquangbui99@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230326052039.33717-1-minhquangbui99@gmail.com> References: <20230326052039.33717-1-minhquangbui99@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1029; envelope-from=minhquangbui99@gmail.com; helo=mail-pj1-x1029.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 This commit extends the APIC ID to 32-bit long and remove the 255 max APIC ID limit in userspace APIC. The array that manages local APICs is now dynamically allocated based on the max APIC ID of created x86 machine. Also, new x2APIC IPI destination determination scheme, self IPI and x2APIC mode register access are supported. Signed-off-by: Bui Quang Minh --- hw/i386/x86.c | 8 +- hw/intc/apic.c | 229 +++++++++++++++++++++++--------- hw/intc/apic_common.c | 8 +- include/hw/i386/apic.h | 3 +- include/hw/i386/apic_internal.h | 2 +- 5 files changed, 184 insertions(+), 66 deletions(-) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index a88a126123..fa9b15190d 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -132,11 +132,11 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) * Can we support APIC ID 255 or higher? * * Under Xen: yes. - * With userspace emulated lapic: no + * With userspace emulated lapic: yes. * With KVM's in-kernel lapic: only if X2APIC API is enabled. */ if (x86ms->apic_id_limit > 255 && !xen_enabled() && - (!kvm_irqchip_in_kernel() || !kvm_enable_x2apic())) { + kvm_irqchip_in_kernel() && !kvm_enable_x2apic()) { error_report("current -smp configuration requires kernel " "irqchip and X2APIC API support."); exit(EXIT_FAILURE); @@ -146,6 +146,10 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) kvm_set_max_apic_id(x86ms->apic_id_limit); } + if (!kvm_irqchip_in_kernel()) { + apic_set_max_apic_id(x86ms->apic_id_limit); + } + possible_cpus = mc->possible_cpu_arch_ids(ms); for (i = 0; i < ms->smp.cpus; i++) { x86_cpu_new(x86ms, possible_cpus->cpus[i].arch_id, &error_fatal); diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 61b494b20a..159527af30 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -31,15 +31,15 @@ #include "hw/i386/apic-msidef.h" #include "qapi/error.h" #include "qom/object.h" - -#define MAX_APICS 255 -#define MAX_APIC_WORDS 8 +#include "tcg/helper-tcg.h" #define SYNC_FROM_VAPIC 0x1 #define SYNC_TO_VAPIC 0x2 #define SYNC_ISR_IRR_TO_VAPIC 0x4 -static APICCommonState *local_apics[MAX_APICS + 1]; +static APICCommonState **local_apics; +static uint32_t max_apics; +static uint32_t max_apic_words; #define TYPE_APIC "apic" /*This is reusing the APICCommonState typedef from APIC_COMMON */ @@ -49,7 +49,19 @@ DECLARE_INSTANCE_CHECKER(APICCommonState, APIC, static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode); static void apic_update_irq(APICCommonState *s); static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, - uint8_t dest, uint8_t dest_mode); + uint32_t dest, uint8_t dest_mode); + +void apic_set_max_apic_id(uint32_t max_apic_id) +{ + int word_size = 32; + + /* round up the max apic id to next multiple of words */ + max_apics = (max_apic_id + word_size - 1) & ~(word_size - 1); + + local_apics = g_malloc0(sizeof(*local_apics) * max_apics); + max_apic_words = max_apics >> 5; +} + /* Find first bit starting from msb */ static int apic_fls_bit(uint32_t value) @@ -199,7 +211,7 @@ static void apic_external_nmi(APICCommonState *s) #define foreach_apic(apic, deliver_bitmask, code) \ {\ int __i, __j;\ - for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\ + for(__i = 0; __i < max_apic_words; __i++) {\ uint32_t __mask = deliver_bitmask[__i];\ if (__mask) {\ for(__j = 0; __j < 32; __j++) {\ @@ -226,7 +238,7 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, { int i, d; d = -1; - for(i = 0; i < MAX_APIC_WORDS; i++) { + for(i = 0; i < max_apic_words; i++) { if (deliver_bitmask[i]) { d = i * 32 + apic_ffs_bit(deliver_bitmask[i]); break; @@ -276,16 +288,17 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask, apic_set_irq(apic_iter, vector_num, trigger_mode) ); } -void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, +void apic_deliver_irq(uint32_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode) { - uint32_t deliver_bitmask[MAX_APIC_WORDS]; + uint32_t *deliver_bitmask = g_malloc(max_apic_words * sizeof(uint32_t)); trace_apic_deliver_irq(dest, dest_mode, delivery_mode, vector_num, trigger_mode); apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode); + g_free(deliver_bitmask); } bool is_x2apic_mode(DeviceState *dev) @@ -442,57 +455,91 @@ static void apic_eoi(APICCommonState *s) apic_update_irq(s); } -static int apic_find_dest(uint8_t dest) +static bool apic_match_dest(APICCommonState *apic, uint32_t dest) { - APICCommonState *apic = local_apics[dest]; + if (is_x2apic_mode(&apic->parent_obj)) { + return apic->initial_apic_id == dest; + } else { + return apic->id == (uint8_t)dest; + } +} + +static void apic_find_dest(uint32_t *deliver_bitmask, uint32_t dest) +{ + APICCommonState *apic = NULL; int i; - if (apic && apic->id == dest) - return dest; /* shortcut in case apic->id == local_apics[dest]->id */ - - for (i = 0; i < MAX_APICS; i++) { + for (i = 0; i < max_apics; i++) { apic = local_apics[i]; - if (apic && apic->id == dest) - return i; - if (!apic) - break; + if (apic && apic_match_dest(apic, dest)) { + apic_set_bit(deliver_bitmask, i); + } } +} - return -1; +static void apic_get_broadcast_bitmask(uint32_t *deliver_bitmask, + bool is_x2apic_broadcast) +{ + int i; + APICCommonState *apic_iter; + + for (i = 0; i < max_apics; i++) { + apic_iter = local_apics[i]; + if (apic_iter) { + bool apic_in_x2apic = is_x2apic_mode(&apic_iter->parent_obj); + + if (is_x2apic_broadcast && apic_in_x2apic) { + apic_set_bit(deliver_bitmask, i); + } else if (!is_x2apic_broadcast && !apic_in_x2apic) { + apic_set_bit(deliver_bitmask, i); + } + } + } } static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, - uint8_t dest, uint8_t dest_mode) + uint32_t dest, uint8_t dest_mode) { APICCommonState *apic_iter; int i; + memset(deliver_bitmask, 0x00, max_apic_words * sizeof(uint32_t)); + + /* x2APIC broadcast id for both physical and logical (cluster) mode */ + if (dest == 0xffffffff) { + apic_get_broadcast_bitmask(deliver_bitmask, true); + return; + } + if (dest_mode == 0) { + apic_find_dest(deliver_bitmask, dest); + /* Broadcast to xAPIC mode apics */ if (dest == 0xff) { - memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t)); - } else { - int idx = apic_find_dest(dest); - memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); - if (idx >= 0) - apic_set_bit(deliver_bitmask, idx); + apic_get_broadcast_bitmask(deliver_bitmask, false); } } else { /* XXX: cluster mode */ - memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); - for(i = 0; i < MAX_APICS; i++) { + for(i = 0; i < max_apics; i++) { apic_iter = local_apics[i]; if (apic_iter) { - if (apic_iter->dest_mode == 0xf) { - if (dest & apic_iter->log_dest) - apic_set_bit(deliver_bitmask, i); - } else if (apic_iter->dest_mode == 0x0) { - if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) && - (dest & apic_iter->log_dest & 0x0f)) { + /* x2APIC mode */ + if (apic_iter->apicbase & MSR_IA32_APICBASE_EXTD) { + if ((dest & 0xffff0000) == (apic_iter->log_dest & 0xffff0000) && + (dest & apic_iter->log_dest & 0xffff)) { apic_set_bit(deliver_bitmask, i); } + } else { + if (apic_iter->dest_mode == 0xf) { + if (dest & apic_iter->log_dest) { + apic_set_bit(deliver_bitmask, i); + } + } else if (apic_iter->dest_mode == 0x0) { + if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) && + (dest & apic_iter->log_dest & 0x0f)) { + apic_set_bit(deliver_bitmask, i); + } + } } - } else { - break; } } } @@ -516,29 +563,36 @@ void apic_sipi(DeviceState *dev) s->wait_for_sipi = 0; } -static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode, +static void apic_deliver(DeviceState *dev, uint32_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, - uint8_t trigger_mode) + uint8_t trigger_mode, uint8_t dest_shorthand) { APICCommonState *s = APIC(dev); - uint32_t deliver_bitmask[MAX_APIC_WORDS]; - int dest_shorthand = (s->icr[0] >> 18) & 3; APICCommonState *apic_iter; + uint32_t deliver_bitmask_size = max_apic_words * sizeof(uint32_t); + uint32_t *deliver_bitmask = g_malloc(deliver_bitmask_size); + uint32_t current_apic_id; + + if (is_x2apic_mode(dev)) { + current_apic_id = s->initial_apic_id; + } else { + current_apic_id = s->id; + } switch (dest_shorthand) { case 0: apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode); break; case 1: - memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); - apic_set_bit(deliver_bitmask, s->id); + memset(deliver_bitmask, 0x00, deliver_bitmask_size); + apic_set_bit(deliver_bitmask, current_apic_id); break; case 2: - memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); + memset(deliver_bitmask, 0xff, deliver_bitmask_size); break; case 3: - memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); - apic_reset_bit(deliver_bitmask, s->id); + memset(deliver_bitmask, 0xff, deliver_bitmask_size); + apic_reset_bit(deliver_bitmask, current_apic_id); break; } @@ -562,6 +616,7 @@ static void apic_deliver(DeviceState *dev, uint8_t dest, uint8_t dest_mode, } apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, trigger_mode); + g_free(deliver_bitmask); } static bool apic_check_pic(APICCommonState *s) @@ -657,7 +712,11 @@ uint64_t apic_register_read(int index) switch(index) { case 0x02: /* id */ - val = s->id << 24; + if (is_x2apic_mode(dev)) { + val = s->initial_apic_id; + } else { + val = s->id << 24; + } break; case 0x03: /* version */ val = s->version | ((APIC_LVT_NB - 1) << 16); @@ -680,9 +739,17 @@ uint64_t apic_register_read(int index) val = 0; break; case 0x0d: - val = s->log_dest << 24; + if (is_x2apic_mode(dev)) { + val = s->log_dest; + } else { + val = s->log_dest << 24; + } break; case 0x0e: + if (is_x2apic_mode(dev)) { + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + } + val = (s->dest_mode << 28) | 0xfffffff; break; case 0x0f: @@ -745,7 +812,12 @@ static void apic_send_msi(MSIMessage *msi) { uint64_t addr = msi->address; uint32_t data = msi->data; - uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; + uint32_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; + /* + * The higher 3 bytes of destination id is stored in higher word of + * msi address. See x86_iommu_irq_to_msi_message() + */ + dest = dest | (addr >> 32); uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1; uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1; @@ -769,6 +841,10 @@ void apic_register_write(int index, uint64_t val) switch(index) { case 0x02: + if (is_x2apic_mode(dev)) { + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + } + s->id = (val >> 24); break; case 0x03: @@ -788,9 +864,17 @@ void apic_register_write(int index, uint64_t val) apic_eoi(s); break; case 0x0d: + if (is_x2apic_mode(dev)) { + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + } + s->log_dest = val >> 24; break; case 0x0e: + if (is_x2apic_mode(dev)) { + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + } + s->dest_mode = val >> 28; break; case 0x0f: @@ -802,13 +886,27 @@ void apic_register_write(int index, uint64_t val) case 0x20 ... 0x27: case 0x28: break; - case 0x30: + case 0x30: { + uint32_t dest; + s->icr[0] = val; - apic_deliver(dev, (s->icr[1] >> 24) & 0xff, (s->icr[0] >> 11) & 1, + if (is_x2apic_mode(dev)) { + s->icr[1] = val >> 32; + dest = s->icr[1]; + } else { + dest = (s->icr[1] >> 24) & 0xff; + } + + apic_deliver(dev, dest, (s->icr[0] >> 11) & 1, (s->icr[0] >> 8) & 7, (s->icr[0] & 0xff), - (s->icr[0] >> 15) & 1); + (s->icr[0] >> 15) & 1, (s->icr[0] >> 18) & 3); break; + } case 0x31: + if (is_x2apic_mode(dev)) { + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + } + s->icr[1] = val; break; case 0x32 ... 0x37: @@ -837,6 +935,23 @@ void apic_register_write(int index, uint64_t val) s->count_shift = (v + 1) & 7; } break; + case 0x3f: { + int vector = val & 0xff; + + if (!is_x2apic_mode(dev)) { + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + } + + /* + * Self IPI is identical to IPI with + * - Destination shorthand: 1 (Self) + * - Trigger mode: 0 (Edge) + * - Delivery mode: 0 (Fixed) + */ + apic_deliver(dev, 0, 0, APIC_DM_FIXED, vector, 0, 1); + + break; + } default: s->esr |= APIC_ESR_ILLEGAL_ADDRESS; break; @@ -894,12 +1009,6 @@ static void apic_realize(DeviceState *dev, Error **errp) { APICCommonState *s = APIC(dev); - if (s->id >= MAX_APICS) { - error_setg(errp, "%s initialization failed. APIC ID %d is invalid", - object_get_typename(OBJECT(dev)), s->id); - return; - } - if (kvm_enabled()) { warn_report("Userspace local APIC is deprecated for KVM."); warn_report("Do not use kernel-irqchip except for the -M isapc machine type."); @@ -909,7 +1018,7 @@ static void apic_realize(DeviceState *dev, Error **errp) APIC_SPACE_SIZE); s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s); - local_apics[s->id] = s; + local_apics[s->initial_apic_id] = s; msi_nonbroken = true; } @@ -919,7 +1028,7 @@ static void apic_unrealize(DeviceState *dev) APICCommonState *s = APIC(dev); timer_free(s->timer); - local_apics[s->id] = NULL; + local_apics[s->initial_apic_id] = NULL; } static void apic_class_init(ObjectClass *klass, void *data) diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 4a34f03047..39c207bd21 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -194,7 +194,11 @@ void apic_init_reset(DeviceState *dev) s = APIC_COMMON(dev); s->tpr = 0; s->spurious_vec = 0xff; - s->log_dest = 0; + + if (!is_x2apic_mode(dev)) { + s->log_dest = 0; + } + s->dest_mode = 0xf; memset(s->isr, 0, sizeof(s->isr)); memset(s->tmr, 0, sizeof(s->tmr)); @@ -366,7 +370,7 @@ static const VMStateDescription vmstate_apic_common = { VMSTATE_UINT8(arb_id, APICCommonState), VMSTATE_UINT8(tpr, APICCommonState), VMSTATE_UINT32(spurious_vec, APICCommonState), - VMSTATE_UINT8(log_dest, APICCommonState), + VMSTATE_UINT32(log_dest, APICCommonState), VMSTATE_UINT8(dest_mode, APICCommonState), VMSTATE_UINT32_ARRAY(isr, APICCommonState, 8), VMSTATE_UINT32_ARRAY(tmr, APICCommonState, 8), diff --git a/include/hw/i386/apic.h b/include/hw/i386/apic.h index 2cebeb4faf..d938bfa8e0 100644 --- a/include/hw/i386/apic.h +++ b/include/hw/i386/apic.h @@ -3,7 +3,8 @@ /* apic.c */ -void apic_deliver_irq(uint8_t dest, uint8_t dest_mode, uint8_t delivery_mode, +void apic_set_max_apic_id(uint32_t max_apic_id); +void apic_deliver_irq(uint32_t dest, uint8_t dest_mode, uint8_t delivery_mode, uint8_t vector_num, uint8_t trigger_mode); int apic_accept_pic_intr(DeviceState *s); void apic_deliver_pic_intr(DeviceState *s, int level); diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h index 5f2ba24bfc..5f60cd5e78 100644 --- a/include/hw/i386/apic_internal.h +++ b/include/hw/i386/apic_internal.h @@ -164,7 +164,7 @@ struct APICCommonState { uint8_t arb_id; uint8_t tpr; uint32_t spurious_vec; - uint8_t log_dest; + uint32_t log_dest; uint8_t dest_mode; uint32_t isr[8]; /* in service register */ uint32_t tmr[8]; /* trigger mode register */ From patchwork Sun Mar 26 05:20:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bui Quang Minh X-Patchwork-Id: 1761217 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=d46tvM0v; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PkkrX0XsMz1yYB for ; Sun, 26 Mar 2023 16:23:56 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pgIqT-0007Vn-VO; Sun, 26 Mar 2023 01:23:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pgIqS-0007Tv-OE for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:08 -0400 Received: from mail-pl1-x630.google.com ([2607:f8b0:4864:20::630]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pgIqQ-0008D9-RI for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:08 -0400 Received: by mail-pl1-x630.google.com with SMTP id o11so5618652ple.1 for ; Sat, 25 Mar 2023 22:23:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1679808184; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JuyIydhgpL8UArypX6xMRbypFd9wnnNS+58Gghs84yU=; b=d46tvM0v3RZt1eyh4OJHFx2V8jiRbhn/CgAUy1ED7Xlytt6fe7F5y4lk7VV1x45PMW RcmVNtYF3iibnt8I2+XnCHZwSirhLfHXp9i2t9dMxW9etJRx9gFS9/GU+9TJn4qYXZQ3 wgdHt/UOcfgo2i5op2XO+0b6HTatD50xpBAAz3WyTLLHv001ZI+9+nGz5xZLS4HzO9DC POQ076a+uWrJ6WLgQPbnpvkUr1TubnJwfJjJfeQvH3jINbNgejp6R5LCgOZ7NvYI47z0 N6NUkukYnVnrYl4CHoXXIWK0UJqCTSqSxkpXb0jyIbe+mSroCEAarygdNkUgfrMc7foG mppQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679808184; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JuyIydhgpL8UArypX6xMRbypFd9wnnNS+58Gghs84yU=; b=y+reulNpncHUSuD4SnFz6IxsOGCrqJ6tNpBKfOtZmnWAe9oZP/lz6NqvPKsWpT3AGg QPQyluizpSeGapoFiwOjb3hgsDnta4CtqB/hqliLJunltX+EqMdo4OgruLPUYjK17h0h /yzyeLmJ5m2Kx/IQc400D9KN8u0jiyWk6Zp/KwhiTKguHoV1RfIjXNi1dECY3QmK8WK/ 9hO4TQyplsx4V+2h/BGk4QojS+xOb0zuI6niJsA6J0ZaWawgqt8+RTv/x9ORQR75pkUM CjfT/wydevh8LMzCtimJ+5L/Bvx/DzGMb6DdT1an/bmRJ68T7Thuo7ZXn5Up0JFX7iW+ C9Ag== X-Gm-Message-State: AAQBX9d76pF1mUafe5ZGTIC1A/IopxfreUqhfpJPnMTO3dBvfLEtjDeS 0T5wNMzOLv2p51BZv8g+xclPbNokFPOmwg== X-Google-Smtp-Source: AKy350bM1nDRGnHiQ1Vr6to0T6cg11Nv1fVhmIO91Vgq6g9DSwmtz24FiOPTHGydFwxi6LTU94vRRw== X-Received: by 2002:a17:902:c3c3:b0:19e:baa6:5860 with SMTP id j3-20020a170902c3c300b0019ebaa65860mr7234484plj.2.1679808184584; Sat, 25 Mar 2023 22:23:04 -0700 (PDT) Received: from localhost.localdomain ([113.173.97.170]) by smtp.googlemail.com with ESMTPSA id bc9-20020a170902930900b001a20b31a23fsm5020258plb.293.2023.03.25.22.23.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Mar 2023 22:23:04 -0700 (PDT) From: Bui Quang Minh To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Richard Henderson , Eduardo Habkost , "Michael S . Tsirkin" , Marcel Apfelbaum , David Woodhouse , Igor Mammedov , =?utf-8?q?Alex_Benn=C3=A9e?= , Bui Quang Minh Subject: [PATCH v2 3/5] apic, i386/tcg: add x2apic transitions Date: Sun, 26 Mar 2023 12:20:37 +0700 Message-Id: <20230326052039.33717-4-minhquangbui99@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230326052039.33717-1-minhquangbui99@gmail.com> References: <20230326052039.33717-1-minhquangbui99@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::630; envelope-from=minhquangbui99@gmail.com; helo=mail-pl1-x630.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 This commit adds support for x2APIC transitions when writing to MSR_IA32_APICBASE register and finally adds CPUID_EXT_X2APIC to TCG_EXT_FEATURES. Signed-off-by: Bui Quang Minh --- hw/intc/apic.c | 50 ++++++++++++++++++++++++++++ hw/intc/apic_common.c | 7 ++-- target/i386/cpu-sysemu.c | 10 ++++++ target/i386/cpu.c | 5 +-- target/i386/cpu.h | 6 ++++ target/i386/tcg/sysemu/misc_helper.c | 4 +++ 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 159527af30..735412274d 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -308,8 +308,41 @@ bool is_x2apic_mode(DeviceState *dev) return s->apicbase & MSR_IA32_APICBASE_EXTD; } +static void apic_set_base_check(APICCommonState *s, uint64_t val) +{ + /* Enable x2apic when x2apic is not supported by CPU */ + if (!cpu_has_x2apic_feature(&s->cpu->env) && + val & MSR_IA32_APICBASE_EXTD) + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + + /* + * Transition into invalid state + * (s->apicbase & MSR_IA32_APICBASE_ENABLE == 0) && + * (s->apicbase & MSR_IA32_APICBASE_EXTD) == 1 + */ + if (!(val & MSR_IA32_APICBASE_ENABLE) && + (val & MSR_IA32_APICBASE_EXTD)) + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + + /* Invalid transition from disabled mode to x2APIC */ + if (!(s->apicbase & MSR_IA32_APICBASE_ENABLE) && + !(s->apicbase & MSR_IA32_APICBASE_EXTD) && + (val & MSR_IA32_APICBASE_ENABLE) && + (val & MSR_IA32_APICBASE_EXTD)) + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); + + /* Invalid transition from x2APIC to xAPIC */ + if ((s->apicbase & MSR_IA32_APICBASE_ENABLE) && + (s->apicbase & MSR_IA32_APICBASE_EXTD) && + (val & MSR_IA32_APICBASE_ENABLE) && + !(val & MSR_IA32_APICBASE_EXTD)) + raise_exception_ra(&s->cpu->env, EXCP0D_GPF, GETPC()); +} + static void apic_set_base(APICCommonState *s, uint64_t val) { + apic_set_base_check(s, val); + s->apicbase = (val & 0xfffff000) | (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE)); /* if disabled, cannot be enabled again */ @@ -318,6 +351,23 @@ static void apic_set_base(APICCommonState *s, uint64_t val) cpu_clear_apic_feature(&s->cpu->env); s->spurious_vec &= ~APIC_SV_ENABLE; } + + /* Transition from disabled mode to xAPIC */ + if (!(s->apicbase & MSR_IA32_APICBASE_ENABLE) && + (val & MSR_IA32_APICBASE_ENABLE)) { + s->apicbase |= MSR_IA32_APICBASE_ENABLE; + cpu_set_apic_feature(&s->cpu->env); + } + + /* Transition from xAPIC to x2APIC */ + if (cpu_has_x2apic_feature(&s->cpu->env) && + !(s->apicbase & MSR_IA32_APICBASE_EXTD) && + (val & MSR_IA32_APICBASE_EXTD)) { + s->apicbase |= MSR_IA32_APICBASE_EXTD; + + s->log_dest = ((s->initial_apic_id & 0xffff0) << 16) | + (1 << (s->initial_apic_id & 0xf)); + } } static void apic_set_tpr(APICCommonState *s, uint8_t val) diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 39c207bd21..3d249838fc 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -43,11 +43,8 @@ void cpu_set_apic_base(DeviceState *dev, uint64_t val) if (dev) { APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - /* switching to x2APIC, reset possibly modified xAPIC ID */ - if (!(s->apicbase & MSR_IA32_APICBASE_EXTD) && - (val & MSR_IA32_APICBASE_EXTD)) { - s->id = s->initial_apic_id; - } + /* Reset possibly modified xAPIC ID */ + s->id = s->initial_apic_id; info->set_base(s, val); } } diff --git a/target/i386/cpu-sysemu.c b/target/i386/cpu-sysemu.c index 28115edf44..de57892c25 100644 --- a/target/i386/cpu-sysemu.c +++ b/target/i386/cpu-sysemu.c @@ -235,6 +235,16 @@ void cpu_clear_apic_feature(CPUX86State *env) env->features[FEAT_1_EDX] &= ~CPUID_APIC; } +void cpu_set_apic_feature(CPUX86State *env) +{ + env->features[FEAT_1_EDX] |= CPUID_APIC; +} + +bool cpu_has_x2apic_feature(CPUX86State *env) +{ + return env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC; +} + bool cpu_is_bsp(X86CPU *cpu) { return cpu_get_apic_base(cpu->apic_state) & MSR_IA32_APICBASE_BSP; diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6576287e5b..6847b2ae02 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -627,12 +627,13 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, CPUID_EXT_XSAVE | /* CPUID_EXT_OSXSAVE is dynamic */ \ CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR | \ CPUID_EXT_RDRAND | CPUID_EXT_AVX | CPUID_EXT_F16C | \ - CPUID_EXT_FMA) + CPUID_EXT_FMA | CPUID_EXT_X2APIC) /* missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX, CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA, - CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER */ + CPUID_EXT_TSC_DEADLINE_TIMER + */ #ifdef TARGET_X86_64 #define TCG_EXT2_X86_64_FEATURES (CPUID_EXT2_SYSCALL | CPUID_EXT2_LM) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 02165a5ad2..53cd8f01dd 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -379,6 +379,10 @@ typedef enum X86Seg { #define MSR_IA32_APICBASE_ENABLE (1<<11) #define MSR_IA32_APICBASE_EXTD (1 << 10) #define MSR_IA32_APICBASE_BASE (0xfffffU<<12) +#define MSR_IA32_APICBASE_RESERVED \ + (~(uint64_t)(MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE \ + | MSR_IA32_APICBASE_EXTD | MSR_IA32_APICBASE_BASE)) + #define MSR_IA32_FEATURE_CONTROL 0x0000003a #define MSR_TSC_ADJUST 0x0000003b #define MSR_IA32_SPEC_CTRL 0x48 @@ -2158,8 +2162,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); void cpu_clear_apic_feature(CPUX86State *env); +void cpu_set_apic_feature(CPUX86State *env); void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); +bool cpu_has_x2apic_feature(CPUX86State *env); /* helper.c */ void x86_cpu_set_a20(X86CPU *cpu, int a20_state); diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c index 1fce2076a3..91a58d4d97 100644 --- a/target/i386/tcg/sysemu/misc_helper.c +++ b/target/i386/tcg/sysemu/misc_helper.c @@ -159,6 +159,10 @@ void helper_wrmsr(CPUX86State *env) env->sysenter_eip = val; break; case MSR_IA32_APICBASE: + if (val & MSR_IA32_APICBASE_RESERVED) { + goto error; + } + cpu_set_apic_base(env_archcpu(env)->apic_state, val); break; case MSR_EFER: From patchwork Sun Mar 26 05:20:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bui Quang Minh X-Patchwork-Id: 1761218 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=UaptGFFo; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Pkkrn3gD4z1yYB for ; Sun, 26 Mar 2023 16:24:09 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pgIqd-0007kS-L0; Sun, 26 Mar 2023 01:23:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pgIqb-0007jI-O4 for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:17 -0400 Received: from mail-pj1-x1029.google.com ([2607:f8b0:4864:20::1029]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pgIqa-00089Z-8b for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:17 -0400 Received: by mail-pj1-x1029.google.com with SMTP id l7so4965315pjg.5 for ; Sat, 25 Mar 2023 22:23:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1679808195; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hc8u8RCEWRkcWK3lR3VFupEwaZp5j6qGGE9YvB3aeP0=; b=UaptGFFot3fXH0eWVu051t1Jd9fpbOlHoAN6rJyyJwhoRia9GGfMiW68E/olTBY3cx J6Rbx0KUFSHaDK+2JCZjbc96RArIYQDogIFMBRHl9vQXhXY5/HKGfgyvb3989Mw16HKR 4LKbxNv3EXzk5rWtMMGdwGnJ49V7FVnXAAiwzGOrYDX07YUYXPphEuxmID7tHYkq4j1j xTFY6CmNAZ4obTP7vgMWZyO8RNVCueap4sSHTTxyTFiC/r9T/d5gzoK40VPORuNCiXZI B0mTRf2dTe6iJKFq7fJL0yJnqUy7/zxIXLZdZNgrZCzXHczbGoJ4ABJmgB1tD3WrPsF5 oeUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679808195; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hc8u8RCEWRkcWK3lR3VFupEwaZp5j6qGGE9YvB3aeP0=; b=qMpP3vnZWTbyzWzkT1RysCzwLfq6znEggcOBDtzOuN7EaEkFhXzZH7OOyaz8KiZGeM X/9vkg/G3UKwLLCtvW4OlNO9vS/T81lPC7JMW3gNVQrn0VQwrfdDLay165VQTvhaMzHB UxLZpYnyctz99gXiTu8qlvo6PO2B16FJD56uNJMHCtXvu+G3oZNgVN6j0X0xVNu+V73S 2ThT5Mfyxs4dsRD4Jk2feRDJ2dSiPD99NZ+T83V0VRAzx0utYLd2zdaxWgIeQHNGIm0s CokEO0064wL0R/bkCmDotDF9lIr/nsx/lKbymT05YHsYRRA9iO1nMU/P+ce9CoAYFUhZ T+oA== X-Gm-Message-State: AAQBX9dEVg8AO3o+jncva0LjUrINCa7SxriR1+p4cDBaKh3riNcJ1qkc QjMGtEcxF/bO8hx8WDKLbX75nKBzZ3g6MA== X-Google-Smtp-Source: AKy350YVZp+WsqJXhKSxpmlPqcDh90KDVZxBId3xesrix9uc2PrNylP3y4p3Z/h15ZHDbcU38xyISA== X-Received: by 2002:a17:902:ea11:b0:1a1:f06b:f171 with SMTP id s17-20020a170902ea1100b001a1f06bf171mr8221273plg.17.1679808195167; Sat, 25 Mar 2023 22:23:15 -0700 (PDT) Received: from localhost.localdomain ([113.173.97.170]) by smtp.googlemail.com with ESMTPSA id bc9-20020a170902930900b001a20b31a23fsm5020258plb.293.2023.03.25.22.23.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Mar 2023 22:23:14 -0700 (PDT) From: Bui Quang Minh To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Richard Henderson , Eduardo Habkost , "Michael S . Tsirkin" , Marcel Apfelbaum , David Woodhouse , Igor Mammedov , =?utf-8?q?Alex_Benn=C3=A9e?= , Bui Quang Minh Subject: [PATCH v2 4/5] intel_iommu: allow Extended Interrupt Mode when using userspace APIC Date: Sun, 26 Mar 2023 12:20:38 +0700 Message-Id: <20230326052039.33717-5-minhquangbui99@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230326052039.33717-1-minhquangbui99@gmail.com> References: <20230326052039.33717-1-minhquangbui99@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1029; envelope-from=minhquangbui99@gmail.com; helo=mail-pj1-x1029.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 As userspace APIC now supports x2APIC, intel interrupt remapping hardware can be set to EIM mode when userspace local APIC is used. Signed-off-by: Bui Quang Minh --- hw/i386/intel_iommu.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index faade7def8..a34a4c8196 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -4045,17 +4045,6 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) && x86_iommu_ir_supported(x86_iommu) ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; } - if (s->intr_eim == ON_OFF_AUTO_ON && !s->buggy_eim) { - if (!kvm_irqchip_is_split()) { - error_setg(errp, "eim=on requires accel=kvm,kernel-irqchip=split"); - return false; - } - if (!kvm_enable_x2apic()) { - error_setg(errp, "eim=on requires support on the KVM side" - "(X2APIC_API, first shipped in v4.7)"); - return false; - } - } /* Currently only address widths supported are 39 and 48 bits */ if ((s->aw_bits != VTD_HOST_AW_39BIT) && From patchwork Sun Mar 26 05:20:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bui Quang Minh X-Patchwork-Id: 1761219 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=SzG7TL81; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Pkkrs2jDQz1yYB for ; Sun, 26 Mar 2023 16:24:13 +1100 (AEDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pgIqj-0007wa-DR; Sun, 26 Mar 2023 01:23:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pgIqi-0007vC-LT for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:24 -0400 Received: from mail-pj1-x102d.google.com ([2607:f8b0:4864:20::102d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pgIqg-0008Gp-LY for qemu-devel@nongnu.org; Sun, 26 Mar 2023 01:23:24 -0400 Received: by mail-pj1-x102d.google.com with SMTP id d13so5005747pjh.0 for ; Sat, 25 Mar 2023 22:23:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1679808201; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TV10GUJgvLw+0NT1d+ZJRTnL7NF0J6NHPX1SRHZb+IQ=; b=SzG7TL81wDAU92skl8a62ZfC+0uOeuFgaehNPRCRqwixcIFy+h4PoqwqxNkXZrXfPs 9WFDfqeMh1AMbP7R/0/i3sfuIHEUfkrohBkQfSgtBEep6F1/idaNAQZ0fwJvb2h2+s5X 1inl6A/OJRJeCrGVHhI0IqaOQxu32J/ygheolFHg2X3iKnve6+Rofmr/Iizofo2C+STC ws4zjQT+qnQXqTOON0t7EOeswYK/G9rByZ3k8SOpE4M60YLtvH7IG1eaIjvA6sph8AKF q/+wO4WGnJ3YMVG1eVjv7KlmYtyxm8e3nR6ruJkA6AC3K/dK5aoKZ/0vgdoY4zOxK+yV fBGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679808201; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TV10GUJgvLw+0NT1d+ZJRTnL7NF0J6NHPX1SRHZb+IQ=; b=uV4WggVvZtHSgZf5lgZK7511bZiy/NupmAOpSks8V5p+2D5QxmGi3acmGeXVyndKC+ +KtRGQjqZt4cUPvQZf2UFXUzlfEaRUbXpfs/xQ6tDGO1TjjWJgYtmIphZJBP8/Jojg1B MXIKE2tOi5Hf0kOQuKhvxMIPe8aVBA61U17AHKkK+silP8qghngV7Iwn0owtj3eiusA2 7evyjPMlQ++UakAZQ8hEE8xx0cmYEL3nIXqiYNCla4NzKI/xdfR6s2FDjqMmsASy2yx7 6b8GPGRzb9cTPHGNBU1qMTJUPDXw+YU3MGXgC+lSEDUrXo+JoiXNQzoUJQTEMB3OurHL qfdw== X-Gm-Message-State: AAQBX9dPHoULxKonKwRhd8+PrV3s6h8OHC6YlUYEGbQdBBY0BZXFP2gO 2Pg0rHfvgCRewjX55HTtlflMP0gHb4ViZw== X-Google-Smtp-Source: AKy350bLM7np53VdWv+8ppGdq1XoUdpcvmo6L4S1Ii9ly6jO99fl2N111JlKtzzL+fZJ0H+85k969A== X-Received: by 2002:a17:903:28ce:b0:1a0:6852:16e9 with SMTP id kv14-20020a17090328ce00b001a0685216e9mr6312009plb.14.1679808200973; Sat, 25 Mar 2023 22:23:20 -0700 (PDT) Received: from localhost.localdomain ([113.173.97.170]) by smtp.googlemail.com with ESMTPSA id bc9-20020a170902930900b001a20b31a23fsm5020258plb.293.2023.03.25.22.23.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 25 Mar 2023 22:23:20 -0700 (PDT) From: Bui Quang Minh To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Richard Henderson , Eduardo Habkost , "Michael S . Tsirkin" , Marcel Apfelbaum , David Woodhouse , Igor Mammedov , =?utf-8?q?Alex_Benn=C3=A9e?= , Bui Quang Minh Subject: [PATCH v2 5/5] amd_iommu: report x2APIC support to the operating system Date: Sun, 26 Mar 2023 12:20:39 +0700 Message-Id: <20230326052039.33717-6-minhquangbui99@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230326052039.33717-1-minhquangbui99@gmail.com> References: <20230326052039.33717-1-minhquangbui99@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::102d; envelope-from=minhquangbui99@gmail.com; helo=mail-pj1-x102d.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 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 This commit adds XTSup configuration to let user choose to whether enable this feature or not. When XTSup is enabled, additional bytes in IRTE with enabled guest virtual VAPIC are used to support 32-bit destination id. Additionally, this commit changes to use IVHD type 0x11 in ACPI table for feature report to operating system. This is because Linux does not use XTSup in IOMMU Feature Reporting field of IVHD type 0x10 but only use XTSup bit in EFR Register Image of IVHD 0x11 to indicate x2APIC support (see init_iommu_one in linux/drivers/iommu/amd/init.c) Signed-off-by: Bui Quang Minh --- hw/i386/acpi-build.c | 28 ++++++++++++++-------------- hw/i386/amd_iommu.c | 21 +++++++++++++++++++-- hw/i386/amd_iommu.h | 16 +++++++++++----- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index ec857a117e..72d6bb2892 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2339,7 +2339,7 @@ static void build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, const char *oem_table_id) { - int ivhd_table_len = 24; + int ivhd_table_len = 40; AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default()); GArray *ivhd_blob = g_array_new(false, true, 1); AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id, @@ -2349,18 +2349,19 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, /* IVinfo - IO virtualization information common to all * IOMMU units in a system */ - build_append_int_noprefix(table_data, 40UL << 8/* PASize */, 4); + build_append_int_noprefix(table_data, + (1UL << 0) | /* EFRSup */ + (40UL << 8), /* PASize */ + 4); /* reserved */ build_append_int_noprefix(table_data, 0, 8); - /* IVHD definition - type 10h */ - build_append_int_noprefix(table_data, 0x10, 1); + /* IVHD definition - type 11h */ + build_append_int_noprefix(table_data, 0x11, 1); /* virtualization flags */ build_append_int_noprefix(table_data, (1UL << 0) | /* HtTunEn */ - (1UL << 4) | /* iotblSup */ - (1UL << 6) | /* PrefSup */ - (1UL << 7), /* PPRSup */ + (1UL << 4), /* iotblSup */ 1); /* @@ -2404,13 +2405,12 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id, build_append_int_noprefix(table_data, 0, 2); /* IOMMU info */ build_append_int_noprefix(table_data, 0, 2); - /* IOMMU Feature Reporting */ - build_append_int_noprefix(table_data, - (48UL << 30) | /* HATS */ - (48UL << 28) | /* GATS */ - (1UL << 2) | /* GTSup */ - (1UL << 6), /* GASup */ - 4); + /* IOMMU Attributes */ + build_append_int_noprefix(table_data, 0, 4); + /* EFR Register Image */ + build_append_int_noprefix(table_data, s->efr_reg, 8); + /* EFR Register Image 2 */ + build_append_int_noprefix(table_data, 0, 8); /* IVHD entries as found above */ g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len); diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index bcd016f5c5..5dfa93d945 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -31,6 +31,7 @@ #include "hw/i386/apic_internal.h" #include "trace.h" #include "hw/i386/apic-msidef.h" +#include "hw/qdev-properties.h" /* used AMD-Vi MMIO registers */ const char *amdvi_mmio_low[] = { @@ -1155,7 +1156,12 @@ static int amdvi_int_remap_ga(AMDVIState *iommu, irq->vector = irte.hi.fields.vector; irq->dest_mode = irte.lo.fields_remap.dm; irq->redir_hint = irte.lo.fields_remap.rq_eoi; - irq->dest = irte.lo.fields_remap.destination; + if (!iommu->xtsup) { + irq->dest = irte.lo.fields_remap.destination & 0xff; + } else { + irq->dest = irte.lo.fields_remap.destination | + (irte.hi.fields.destination_hi << 24); + } return 0; } @@ -1503,10 +1509,15 @@ static void amdvi_init(AMDVIState *s) s->enabled = false; s->ats_enabled = false; s->cmdbuf_enabled = false; + s->efr_reg = AMDVI_DEFAULT_EXT_FEATURES; + + if (s->xtsup) { + s->efr_reg |= AMDVI_FEATURE_XT; + } /* reset MMIO */ memset(s->mmior, 0, AMDVI_MMIO_SIZE); - amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, AMDVI_EXT_FEATURES, + amdvi_set_quad(s, AMDVI_MMIO_EXT_FEATURES, s->efr_reg, 0xffffffffffffffef, 0); amdvi_set_quad(s, AMDVI_MMIO_STATUS, 0, 0x98, 0x67); @@ -1586,6 +1597,11 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp) amdvi_init(s); } +static Property amdvi_properties[] = { + DEFINE_PROP_BOOL("xtsup", AMDVIState, xtsup, false), + DEFINE_PROP_END_OF_LIST(), +}; + static const VMStateDescription vmstate_amdvi_sysbus = { .name = "amd-iommu", .unmigratable = 1 @@ -1612,6 +1628,7 @@ static void amdvi_sysbus_class_init(ObjectClass *klass, void *data) dc->user_creatable = true; set_bit(DEVICE_CATEGORY_MISC, dc->categories); dc->desc = "AMD IOMMU (AMD-Vi) DMA Remapping device"; + device_class_set_props(dc, amdvi_properties); } static const TypeInfo amdvi_sysbus = { diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h index 79d38a3e41..96df7b0400 100644 --- a/hw/i386/amd_iommu.h +++ b/hw/i386/amd_iommu.h @@ -154,6 +154,7 @@ #define AMDVI_FEATURE_PREFETCH (1ULL << 0) /* page prefetch */ #define AMDVI_FEATURE_PPR (1ULL << 1) /* PPR Support */ +#define AMDVI_FEATURE_XT (1ULL << 2) /* x2APIC Support */ #define AMDVI_FEATURE_GT (1ULL << 4) /* Guest Translation */ #define AMDVI_FEATURE_IA (1ULL << 6) /* inval all support */ #define AMDVI_FEATURE_GA (1ULL << 7) /* guest VAPIC support */ @@ -173,8 +174,9 @@ #define AMDVI_IOTLB_MAX_SIZE 1024 #define AMDVI_DEVID_SHIFT 36 -/* extended feature support */ -#define AMDVI_EXT_FEATURES (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \ +/* default extended feature */ +#define AMDVI_DEFAULT_EXT_FEATURES \ + (AMDVI_FEATURE_PREFETCH | AMDVI_FEATURE_PPR | \ AMDVI_FEATURE_IA | AMDVI_FEATURE_GT | AMDVI_FEATURE_HE | \ AMDVI_GATS_MODE | AMDVI_HATS_MODE | AMDVI_FEATURE_GA) @@ -278,8 +280,8 @@ union irte_ga_lo { dm:1, /* ------ */ guest_mode:1, - destination:8, - rsvd_1:48; + destination:24, + rsvd_1:32; } fields_remap; }; @@ -287,7 +289,8 @@ union irte_ga_hi { uint64_t val; struct { uint64_t vector:8, - rsvd_2:56; + rsvd_2:48, + destination_hi:8; } fields; }; @@ -367,6 +370,9 @@ struct AMDVIState { /* Interrupt remapping */ bool ga_enabled; + bool xtsup; + + uint64_t efr_reg; /* extended feature register */ }; #endif