-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SEV-SNP support #1269
base: cc_quark_amd_sev_snp
Are you sure you want to change the base?
SEV-SNP support #1269
Conversation
It will cause failure when tracking readonly pages and then writing back before unmapping.
This is the start of the SEV-SNP series update, the support will include several parts: 1.SEV-SNP VM Creation 2.KVM VMGEXIT handling 3.qkernel SEV-SNP related initialization 4.qkernel #VC interrupt handling Since this branch is based on cc_quark branch, the private and shared memory isolation is done, do not need to change here.
If cc is enabled then check cpuid for snp support. Switch to the vm creation flow to the snp machine creation
SEV-SNP need to update cpuid page before launching
The vcpu regsiters should be initialized before SNP_LAUNCH_FINISH in InitSevSnp, but not before vcpu.run(). So extract the process to a function x86_init.
Add c bit to inital page table.
Add support for vmgexit
If sev-snp is enabled, parse the page table including c bit. Add a function smash, smash a big page table entry to a smaller page size.
1.Add ghcb protocol related functions. 2.Add ghcb init functions.
1.Add a new crate to disassemble input instruction in #VC Handler 2.Add an atomic bool to check whether log is available, avoiding loop in the interrupt.
If it is SEV-SNP, do the following setup: 1.Accpet unvalidated memory. 2.GHCB and then shared memory initialization. 3.Set registers which not set automatically by kvm.
@@ -127,12 +129,23 @@ impl PageTables { | |||
} | |||
|
|||
pub fn SwitchTo(&self) { | |||
#[cfg(feature = "cc")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally prefer having two SwitchTo with different config terms, instead of one SwitchTo with two different behaviors. But this makes no difference, just personal opinion.
@@ -364,6 +417,13 @@ impl PageTables { | |||
flags: PageTableFlags, | |||
pagePool: &Allocator, | |||
) -> Result<bool> { | |||
#[cfg(feature = "cc")] | |||
if ENABLE_CC.load(Ordering::Acquire) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was confused earlier because of the ENABLE_CC naming. I think in this context it's a flag variable that means "whether CC is enabled", the ENABLE_CC
name sounds like a (rather static) configuration term.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is configurable via config file now
thanks for doing clear commit messages. To be picky, perhaps consider using conventional commit messages, that is, use
instead of
|
I see, will reword them later. |
|
||
unsafe { | ||
if self.vmgexit(SVM_VMGEXIT_PSC, 0, 0).is_err() { | ||
early_panic(4, 0x33); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a note that you have some hardcoded values (which is fine)
|
||
for i in desc.cur_entry..=desc.end_entry { | ||
let entry = &mut desc.entries[i as usize]; | ||
let operation = (entry.entry >> 52) & 0xF; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as above, maybe have some defs later. This could be error prone.
@@ -0,0 +1,1447 @@ | |||
pub use super::linux_def::*; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be better to have a cc directory, instead of having files suffixed "cc"? There should be more such files I suppose? (like Kernel_cc.rs
, and maybe there are more to come in the future).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I can move Kernel_cc.rs
and pagetable_cc.rs
into the cc folder which already exists. But I am not sure that I should put all the cc related codes into that folder, or it might be easy to add support for cc if you put them together in one folder. You can easily realize there is a related cc file without opening the cc folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also since the *_cc.rs are already their own files, there is no need to suffix the functions within with _cc
. The namespace already tells the difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then how to differ from the normal ones? For example, they are both functions of Pagetable struct, and I need to decide which to run in the runtime.
This comment was marked as resolved.
This comment was marked as resolved.
sf.ss |= 3; | ||
currTask.SaveFp(); | ||
} | ||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please remove this. And also any leftover commented code that you don't need. Also consider using debug!()
or error!()
depending on situation...
@@ -474,6 +482,32 @@ fn InitLoader() { | |||
LOADER.InitKernel(process).unwrap(); | |||
} | |||
|
|||
#[cfg(feature = "cc")] | |||
//Need to initialize PAGEMGR(pagepool for page allcator) and kernel page table in advance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: *allocator :)
#[cfg(feature = "cc")] | ||
//Need to initialize PAGEMGR(pagepool for page allcator) and kernel page table in advance | ||
fn InitShareMemory() { | ||
*GHCB[0].lock() = Some(GhcbHandle::default()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this is a repeated pattern. Maybe have some accessor methods for GHCB elements, that way you can also do sanity check on indexes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sanity check on indexes.
an assert would do, but that rust runtime will panic on out-of-bound anyways, that's the same effect. I think this depends on whether you consider this operation failiable.
|
||
//Different from normal vm, mxcsr will not be set by kvm, should set it mannualy | ||
if IS_SEV_SNP.load(Ordering::Acquire){ | ||
let mxcsr_value = 0x1f80; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a short comment to explain what the mask means... for readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually all these masks and hardcoded values should be constant defs.
@@ -3021,8 +3021,11 @@ impl MemoryDef { | |||
const GUEST_HOST_SHARED_HEAP_OFFEST: u64 = MemoryDef::GUEST_PRIVATE_HEAP_END; | |||
const GUEST_HOST_SHARED_HEAP_END: u64 = MemoryDef::GUEST_HOST_SHARED_HEAP_OFFEST + MemoryDef::GUEST_HOST_SHARED_HEAP_SIZE; | |||
|
|||
const GHCB_OFFSET: u64 = MemoryDef::GUEST_HOST_SHARED_HEAP_OFFEST + MemoryDef::PAGE_SIZE*2; | |||
const HYPERCALL_PARA_PAGE_OFFSET :u64 = MemoryDef::GUEST_HOST_SHARED_HEAP_OFFEST + MemoryDef::PAGE_SIZE*3; | |||
// Reuse RDMA area for sev-snp special pages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this cause conflict with RDMA?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it was commented elsewhere that RDMA stuffs are not supported under cc context.
cpuid_page | ||
.FillCpuidPage(&kvm_cpuid) | ||
.expect("Fail to fill cpuid page"); | ||
//cpuid_page.dump_cpuid(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleanups :)
@@ -0,0 +1,31 @@ | |||
pub mod sev_snp; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cc needs an arch directory...
@@ -0,0 +1,46 @@ | |||
use core::sync::atomic::{AtomicU64, Ordering}; | |||
|
|||
/// The C-Bit mask indicating encrypted physical addresses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Three slashes are meant for documentation. Is that your intention?
@@ -28,6 +28,14 @@ use super::super::threadmgr::task_sched::*; | |||
use super::super::MainRun; | |||
use super::super::SignalDef::*; | |||
use super::super::SHARESPACE; | |||
cfg_cc! { | |||
use super::super::qlib::cc::sev_snp::{VCResult,SVMExitDef,snp_active,C_BIT_MASK}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using relative paths was a mistake and will be fixed later. Perhaps consider ditch this pattern in new code already.
#kvm-ioctls = "0.11.0" | ||
kvm-ioctls = { git = "https://github.com/QuarkContainer/kvm-ioctls.git" } | ||
#kvm-ioctls = { git = "https://github.com/QuarkContainer/kvm-ioctls.git" } | ||
kvm-ioctls = { git = "https://github.com/123abcpp/kvm-ioctls.git" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can your changes be merged to QC/kvm-ioctls.git?
@@ -483,20 +517,47 @@ cfg_if::cfg_if! { | |||
vdsoParamAddr: u64, | |||
vcpuCnt: u64, | |||
autoStart: bool, | |||
vm_type: u64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a feeling this will cause too much runtime dependency (also the case for IS_SEV_SNP
and ENABLE_CC
etc). In other words you will have check these flags quite frequently. I don't know what's an alternative though, maybe we can discuss this at some point.
//check msr to see if sev-snp enabled | ||
ENABLE_CC.store(true,Ordering::Release); | ||
// ghcb convert shared memory | ||
|
||
GLOBAL_ALLOCATOR.InitSharedAllocator(MemoryDef::guest_host_shared_heap_offest_gpa()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not related to this PR, but I'm still not convinced of having getters for static constant values. This only makes code reading harder for me.
|
||
SingletonInit(); | ||
LOG_AVAILABLE.store(true, Ordering::Release); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you may need a comment here, like,
///// LOGGING NOT AVAILABLE BEFORE THIS POINT /////
XD
|
||
GLOBAL_ALLOCATOR.InitPrivateAllocator(MemoryDef::guest_private_running_heap_offset_gpa()); | ||
|
||
unsafe {KERNEL_PAGETABLE.Init(PageTables::Init(CurrentKernelTable()&0xffff_ffff_ffff));} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is somewhat cryptic to me...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't understand this part. @123abcpp could you explan why you do this? thank you
On Thu May 23, 2024 at 1:03 PM CEST, Tianhao Wang wrote:
@shrik3 commented on this pull request.
> @@ -3021,8 +3021,11 @@ impl MemoryDef {
const GUEST_HOST_SHARED_HEAP_OFFEST: u64 = MemoryDef::GUEST_PRIVATE_HEAP_END;
const GUEST_HOST_SHARED_HEAP_END: u64 = MemoryDef::GUEST_HOST_SHARED_HEAP_OFFEST + MemoryDef::GUEST_HOST_SHARED_HEAP_SIZE;
- const GHCB_OFFSET: u64 = MemoryDef::GUEST_HOST_SHARED_HEAP_OFFEST + MemoryDef::PAGE_SIZE*2;
- const HYPERCALL_PARA_PAGE_OFFSET :u64 = MemoryDef::GUEST_HOST_SHARED_HEAP_OFFEST + MemoryDef::PAGE_SIZE*3;
+ // Reuse RDMA area for sev-snp special pages
it was commented elsewhere that RDMA stuffs are not supported under cc context.
I have missed it then. Sorry for the noise=)
|
} | ||
let ghcb_option: &mut Option<GhcbHandle<'_>> = &mut *GHCB[vcpuid].lock(); | ||
let ghcb = ghcb_option.as_mut().unwrap(); | ||
ghcb.invalidate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we need to do ghcb.invalidate
twice? I thought you already did it before vm exit
|
||
GLOBAL_ALLOCATOR.InitPrivateAllocator(MemoryDef::guest_private_running_heap_offset_gpa()); | ||
|
||
unsafe {KERNEL_PAGETABLE.Init(PageTables::Init(CurrentKernelTable()&0xffff_ffff_ffff));} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't understand this part. @123abcpp could you explan why you do this? thank you
@@ -0,0 +1,593 @@ | |||
use core::ptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may need to add a header here to clarify where you got the code, and who modified the code
@@ -0,0 +1,274 @@ | |||
use self::Error::{FailInput, FailSizeMismatch, Unknown}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need header to clarify where you get the code, for example
// Copyright (c) 2021 The Enarx Authors.
// Original code source: link to Enarx
// Code modifier: yiliang
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
let sharedSpace = unsafe { &mut (*shareSpaceAddr) }; | ||
let sharedSpace = unsafe { &mut (*shareSpaceAddr) }; | ||
|
||
// note: in CC mdoe, host can't access PAGE_MGR because it is on private memory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: *mode
// note: in CC mdoe, host can't access PAGE_MGR because it is on private memory | ||
// in non-cc case, host require PAGE_MGR to support hibernate mode | ||
// check pub fn SwapOut(&self, start: u64, len: u64) -> Result<()> | ||
// check pub fn SwapOut(&self, start: u64, len: u64) -> Result<()> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"check foo() in path" would be enough, no need for the foo()'s signature.
MemoryDef::FILE_MAP_SIZE / MemoryDef::PAGE_SIZE_2M, | ||
); | ||
ghcb.set_memory_shared_2mb( | ||
VirtAddr::new(MemoryDef::guest_host_shared_heap_offest_gpa()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: *offset
No description provided.