From patchwork Mon Feb 26 14:35:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jiangshan X-Patchwork-Id: 206740 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:a81b:b0:108:e6aa:91d0 with SMTP id bq27csp2143866dyb; Mon, 26 Feb 2024 07:18:19 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUWEdVUDJiCFvxfZLxwf5WAdS9MVsVJgBgGDKeX7e6SLBJLac3grK6Ip+JB3lAbRhR9eS7o6ypBf9I3sHcI2Ql4lJ/QdQ== X-Google-Smtp-Source: AGHT+IEi6u8jWyIqTlGiqnAieu9zhghYTGZks66uxmmSQ+9qko9PRw6ke57JyXqvvHktO9CemKuw X-Received: by 2002:a92:c530:0:b0:365:7614:dc78 with SMTP id m16-20020a92c530000000b003657614dc78mr8679891ili.10.1708960698994; Mon, 26 Feb 2024 07:18:18 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708960698; cv=pass; d=google.com; s=arc-20160816; b=kqX+XYGNCWo7S4iHyTcH2vfwSeX7Ko7PhQc13z6yX9e1ottMzPyTekqnhR5VYuEUvg L1ruRZm3GEc2kGGBSC+dW1+8KLHyoywl3cdkEDZGQyMqTjDZ1biOAUab7ueCU/No52+r Km035ucNP91vujS2RcMBGrU9GGdZCQFZ9ku8RviT5DoNrvqeAKvyFz9NK0nNhGUejQOX n0XgfjKF6J0P+wqz+pk9dzlqcPftX6KCMSizX/oH0xWgVN6HyLGBqhWwS/3GYobHpdg6 IXR16gV+38jGzQrJExtX7dQPmh/mfMOOA3BXftkoXg8TJ7VoqqkIqBV60T20fEPKsDRy 6ybA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=0en7LuGGPdtEWR7o0ZKkW7B0C/vkNLQUW7iYqtMdnKQ=; fh=AEzGuI1rb+m5zowIpq020Kjo7697wU5eK04ocJLtyyc=; b=LgahjHvfQafcYT+hk/ZGXIpcp5RwR2kUQmnu/Gf2Ywh9ahLLcH+6TaogQDZv2chy5f 7+jmU8T1h1XhCsVtUYBWdobQkVBD7PmmD0dmbSxTYStGxaics5Y4NHgS9TjDr7XhhEHM dRHwthsHscpGeL7TaFwx9Yg68XSYUYnu74I+nTG60SedrUy8SYBSBp+WQ1zREAxv53zG Odqx0riM3uGx3VAcw9jcYiCaW2ejGilbeJNn6tsGJn9lDs9VF8S+o6tta0XKHFUXMbxy 95A3NoKyC7rRKBJ13+sFPqs1hGrnSppe4wpZRWrog1oOzRlmvW4hyfPgTxwgSYTEoieB QSew==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=FHwQt2Gv; arc=pass (i=1 spf=pass spfdomain=gmail.com dkim=pass dkdomain=gmail.com dmarc=pass fromdomain=gmail.com); spf=pass (google.com: domain of linux-kernel+bounces-81676-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-81676-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id a16-20020a63e850000000b005dc6d159424si3844297pgk.235.2024.02.26.07.18.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 07:18:18 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-81676-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=FHwQt2Gv; arc=pass (i=1 spf=pass spfdomain=gmail.com dkim=pass dkdomain=gmail.com dmarc=pass fromdomain=gmail.com); spf=pass (google.com: domain of linux-kernel+bounces-81676-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-81676-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id E4F2AB2EA1C for ; Mon, 26 Feb 2024 14:48:30 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1859A136987; Mon, 26 Feb 2024 14:36:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FHwQt2Gv" Received: from mail-il1-f177.google.com (mail-il1-f177.google.com [209.85.166.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1B32113664A; Mon, 26 Feb 2024 14:36:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708958178; cv=none; b=cLEp03nAn0kXbJ5HgGIyu46zOmVfiljzg9a4QoqNRRwb3pXcG707rsIsQvOdE+2x3OtrmW8iA18S/tEB2GroXzisnGh99hBnW8drvN3GBxOaqNv/BlnFh3G5fyxLJwzO+QbjTNmRMW3VBLjDA78/iFK6FSoRuhUIqBW4UDz1IR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708958178; c=relaxed/simple; bh=8gFP5rvdzZxmykD3GgHFtUmnYj+RZy2c2VA4Es1YSSs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cT0TDclyEUJaN2VFlVaxH1zLZHmShxOoAuEI/98RUBOMpyQAzucjzV0E4q/tcA0uYWXfHdCQvq4CoAQS1QBSEysWmofAySgs36mhqGOAZic2Rze2spE+PkghE/yebhDz1dTtX37YFItD0di7HQQ9QTYJ7uoAlgQjxJ9CmPb4uNM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FHwQt2Gv; arc=none smtp.client-ip=209.85.166.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-il1-f177.google.com with SMTP id e9e14a558f8ab-3657dbe2008so10162675ab.1; Mon, 26 Feb 2024 06:36:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1708958176; x=1709562976; darn=vger.kernel.org; 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=0en7LuGGPdtEWR7o0ZKkW7B0C/vkNLQUW7iYqtMdnKQ=; b=FHwQt2GvLmnD7J+9eoMsAbHRGZkOiBEAZis4BhscMz/pGSjYyHVNfqKjrXHgdZ0t1P Cb06XDtr1W2LunueSHxwSNb7SAgF5vPj20rqpYmOtY8bFdS82wxxf2o81uG/86sCFfue 1LdCSwhInuJr/iKmL7oVI/xJdRMBZU9SGlkOQPymKBUECbWrWyUGfUh6nBQKlUUyKIAz 44SzK6TyVJDckFK8YEvGYG9TPoZ67LGZvTBJzE4nksOhiE5GpxT5ZbEuFUn7n+UnIWQY a5JQLZ/mHdfxNHJCdW2ec0eQ5Y8RG3bppdkw6DX+U+0fsVBoDupS5XV1m1Q9fOdlks3C 3e0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708958176; x=1709562976; 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=0en7LuGGPdtEWR7o0ZKkW7B0C/vkNLQUW7iYqtMdnKQ=; b=E+2MsHlclWUf0jxwMKDfG01yKENkS23Ni4bw8CHTAWlLpKCwjP38bsUrTk2fOdm+DZ 1qyugHprBRwwpMVVYP8dDNTtPJ49mItK87J9JMcJvyVx27cD+tmCTzgaNImSmJsATxSX z4c2upcQh0ksCwU+7mF/tfCrTkxtf7it6Dwvad9HDl1L0rv2d49vAFnmrNJbkcwLpDV4 0KRjM7clfyP6kBPjNFSAx/H0ALHRRXoTcqJ9lu4uMK5GNuYz8xA55cP8AMXsFhEKtBGw 9D7p01QFv4X+H7nPJFS+4CMONDXOE0wof8eadzSkT530u5vRFIV5VbTHId4sQNioSz7l 4nHg== X-Forwarded-Encrypted: i=1; AJvYcCWpA0XHxGf/hT2m40OU26xLcc1QDbxyxE9PrHklLG+2tlESybpRtnCo6P56vfKw518FeMBOz6alEn+0D7XgeC8qTzfh X-Gm-Message-State: AOJu0YyGIELOvZaGCLXBzSuYsi9TOfJivskvNA21SUR0AN5ryjzlzXlm yzOh52WDfhG6FePogWuRVqj3ocA6sPvENkqAFpIuA8NjUScYA0emHcXh/ZVU X-Received: by 2002:a05:6e02:2166:b0:365:13a8:4090 with SMTP id s6-20020a056e02216600b0036513a84090mr9791278ilv.27.1708958175892; Mon, 26 Feb 2024 06:36:15 -0800 (PST) Received: from localhost ([47.89.225.180]) by smtp.gmail.com with ESMTPSA id s35-20020a634523000000b005cfb6e7b0c7sm4049086pga.39.2024.02.26.06.36.14 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Feb 2024 06:36:15 -0800 (PST) From: Lai Jiangshan To: linux-kernel@vger.kernel.org Cc: Lai Jiangshan , Hou Wenlong , Linus Torvalds , Peter Zijlstra , Sean Christopherson , Thomas Gleixner , Borislav Petkov , Ingo Molnar , kvm@vger.kernel.org, Paolo Bonzini , x86@kernel.org, Kees Cook , Juergen Gross , Dave Hansen , "H. Peter Anvin" Subject: [RFC PATCH 30/73] KVM: x86/PVM: Implement segment related callbacks Date: Mon, 26 Feb 2024 22:35:47 +0800 Message-Id: <20240226143630.33643-31-jiangshanlai@gmail.com> X-Mailer: git-send-email 2.19.1.6.gb485710b In-Reply-To: <20240226143630.33643-1-jiangshanlai@gmail.com> References: <20240226143630.33643-1-jiangshanlai@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791975174249561256 X-GMAIL-MSGID: 1791975174249561256 From: Lai Jiangshan Segmentation in PVM guest is generally disabled and is only available for instruction emulation. The segment descriptors of segment registers are just cached and do not take effect in hardware. Since the PVM guest is only allowed to run in x86 long mode, the value of guest CS/SS is fixed and depends on the current mode. Signed-off-by: Lai Jiangshan Signed-off-by: Hou Wenlong --- arch/x86/kvm/pvm/pvm.c | 128 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/arch/x86/kvm/pvm/pvm.c b/arch/x86/kvm/pvm/pvm.c index 26b2201f7dde..6f91dffb6c50 100644 --- a/arch/x86/kvm/pvm/pvm.c +++ b/arch/x86/kvm/pvm/pvm.c @@ -630,6 +630,52 @@ static int pvm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return ret; } +static void pvm_get_segment(struct kvm_vcpu *vcpu, + struct kvm_segment *var, int seg) +{ + struct vcpu_pvm *pvm = to_pvm(vcpu); + + // Update CS or SS to reflect the current mode. + if (seg == VCPU_SREG_CS) { + if (is_smod(pvm)) { + pvm->segments[seg].selector = kernel_cs_by_msr(pvm->msr_star); + pvm->segments[seg].dpl = 0; + pvm->segments[seg].l = 1; + pvm->segments[seg].db = 0; + } else { + pvm->segments[seg].selector = pvm->hw_cs >> 3; + pvm->segments[seg].dpl = 3; + if (pvm->hw_cs == __USER_CS) { + pvm->segments[seg].l = 1; + pvm->segments[seg].db = 0; + } else { // __USER32_CS + pvm->segments[seg].l = 0; + pvm->segments[seg].db = 1; + } + } + } else if (seg == VCPU_SREG_SS) { + if (is_smod(pvm)) { + pvm->segments[seg].dpl = 0; + pvm->segments[seg].selector = kernel_ds_by_msr(pvm->msr_star); + } else { + pvm->segments[seg].dpl = 3; + pvm->segments[seg].selector = pvm->hw_ss >> 3; + } + } + + // Update DS/ES/FS/GS states from the hardware when the states are loaded. + pvm_switch_to_host(pvm); + *var = pvm->segments[seg]; +} + +static u64 pvm_get_segment_base(struct kvm_vcpu *vcpu, int seg) +{ + struct kvm_segment var; + + pvm_get_segment(vcpu, &var, seg); + return var.base; +} + static int pvm_get_cpl(struct kvm_vcpu *vcpu) { if (is_smod(to_pvm(vcpu))) @@ -637,6 +683,80 @@ static int pvm_get_cpl(struct kvm_vcpu *vcpu) return 3; } +static void pvm_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg) +{ + struct vcpu_pvm *pvm = to_pvm(vcpu); + int cpl = pvm_get_cpl(vcpu); + + // Unload DS/ES/FS/GS states from hardware before changing them. + // It also has to unload the VCPU when leaving PVM mode. + pvm_switch_to_host(pvm); + pvm->segments[seg] = *var; + + switch (seg) { + case VCPU_SREG_CS: + if (var->dpl == 1 || var->dpl == 2) + goto invalid_change; + if (!kvm_vcpu_has_run(vcpu)) { + // CPL changing is only valid for the first changed + // after the vcpu is created (vm-migration). + if (cpl != var->dpl) + pvm_switch_flags_toggle_mod(pvm); + } else { + if (cpl != var->dpl) + goto invalid_change; + if (cpl == 0 && !var->l) + goto invalid_change; + } + break; + case VCPU_SREG_LDTR: + // pvm doesn't support LDT + if (var->selector) + goto invalid_change; + break; + default: + break; + } + + return; + +invalid_change: + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); +} + +static void pvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) +{ + struct vcpu_pvm *pvm = to_pvm(vcpu); + + if (pvm->hw_cs == __USER_CS) { + *db = 0; + *l = 1; + } else { + *db = 1; + *l = 0; + } +} + +static void pvm_get_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt) +{ + *dt = to_pvm(vcpu)->idt_ptr; +} + +static void pvm_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt) +{ + to_pvm(vcpu)->idt_ptr = *dt; +} + +static void pvm_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt) +{ + *dt = to_pvm(vcpu)->gdt_ptr; +} + +static void pvm_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt) +{ + to_pvm(vcpu)->gdt_ptr = *dt; +} + static void pvm_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode, int trig_mode, int vector) { @@ -1545,8 +1665,16 @@ static struct kvm_x86_ops pvm_x86_ops __initdata = { .get_msr_feature = pvm_get_msr_feature, .get_msr = pvm_get_msr, .set_msr = pvm_set_msr, + .get_segment_base = pvm_get_segment_base, + .get_segment = pvm_get_segment, + .set_segment = pvm_set_segment, .get_cpl = pvm_get_cpl, + .get_cs_db_l_bits = pvm_get_cs_db_l_bits, .load_mmu_pgd = pvm_load_mmu_pgd, + .get_gdt = pvm_get_gdt, + .set_gdt = pvm_set_gdt, + .get_idt = pvm_get_idt, + .set_idt = pvm_set_idt, .get_rflags = pvm_get_rflags, .set_rflags = pvm_set_rflags, .get_if_flag = pvm_get_if_flag,