Skip to content
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

Open
wants to merge 19 commits into
base: cc_quark_amd_sev_snp
Choose a base branch
from

Conversation

123abcpp
Copy link

No description provided.

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")]
Copy link
Collaborator

@shrik3 shrik3 May 21, 2024

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) {
Copy link
Collaborator

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.

Copy link
Collaborator

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

@shrik3
Copy link
Collaborator

shrik3 commented May 21, 2024

thanks for doing clear commit messages. To be picky, perhaps consider using conventional commit messages, that is, use

SEV-SNP: does xyz

instead of

[SEV-SNP]Does xyz

@123abcpp
Copy link
Author

thanks for doing clear commit messages. To be picky, perhaps consider using conventional commit messages, that is, use

SEV-SNP: does xyz

instead of

[SEV-SNP]Does xyz

I see, will reword them later.


unsafe {
if self.vmgexit(SVM_VMGEXIT_PSC, 0, 0).is_err() {
early_panic(4, 0x33);
Copy link
Collaborator

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;
Copy link
Collaborator

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::*;
Copy link
Collaborator

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).

Copy link
Author

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.

Copy link
Collaborator

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.

Copy link
Author

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.

@shrik3

This comment was marked as resolved.

@123abcpp
Copy link
Author

image

there are a lot of redundant spaces in the code (red blocks), I think they were added from previous cc commits. Consider clearing them towards the end.

fixed

sf.ss |= 3;
currTask.SaveFp();
}
/*
Copy link
Collaborator

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
Copy link
Collaborator

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());
Copy link
Collaborator

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.

Copy link
Collaborator

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;
Copy link
Collaborator

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.

Copy link
Collaborator

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
Copy link
Collaborator

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?

Copy link
Collaborator

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();
Copy link
Collaborator

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;
Copy link
Collaborator

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
Copy link
Collaborator

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};
Copy link
Collaborator

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" }
Copy link
Collaborator

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
Copy link
Collaborator

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());
Copy link
Collaborator

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);
Copy link
Collaborator

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));}
Copy link
Collaborator

@chl337 chl337 May 23, 2024

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...

Copy link
Collaborator

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

@chl337
Copy link
Collaborator

chl337 commented May 23, 2024 via email

}
let ghcb_option: &mut Option<GhcbHandle<'_>> = &mut *GHCB[vcpuid].lock();
let ghcb = ghcb_option.as_mut().unwrap();
ghcb.invalidate();
Copy link
Collaborator

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));}
Copy link
Collaborator

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;
Copy link
Collaborator

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};
Copy link
Collaborator

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
Copy link
Collaborator

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<()>
Copy link
Collaborator

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()),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: *offset

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants