@@ -2234,6 +2234,7 @@ static int kvm_init(MachineState *ms)
kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
kvm_state->memcrypt_debug_ops_memory_region =
sev_set_debug_ops_memory_region;
+ kvm_state->memcrypt_debug_ops_cpu_state = sev_set_debug_ops_cpu_state;
}
ret = kvm_arch_init(ms, s);
@@ -19,6 +19,10 @@ void sev_set_debug_ops_memory_region(void *handle, MemoryRegion *mr)
{
}
+void sev_set_debug_ops_cpu_state(void *handle, CPUState *cpu)
+{
+}
+
int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
{
abort();
@@ -19,4 +19,15 @@
void *sev_guest_init(const char *id);
int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
void sev_set_debug_ops_memory_region(void *handle, MemoryRegion *mr);
+void sev_set_debug_ops_cpu_state(void *handle, CPUState *cpu);
+hwaddr sev_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
+ MemTxAttrs *attrs);
+MemTxResult sev_address_space_read_debug(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, void *ptr,
+ hwaddr len);
+MemTxResult sev_address_space_write_rom_debug(AddressSpace *as,
+ hwaddr addr,
+ MemTxAttrs attrs,
+ const void *ptr,
+ hwaddr len);
#endif
@@ -1838,6 +1838,10 @@ int kvm_arch_init_vcpu(CPUState *cs)
kvm_init_msrs(cpu);
+ if (kvm_memcrypt_enabled()) {
+ kvm_memcrypt_set_debug_ops_cpu_state(cs);
+ }
+
r = hyperv_init_vcpu(cpu);
if (r) {
goto fail;
@@ -843,6 +843,191 @@ sev_set_debug_ops_memory_region(void *handle, MemoryRegion *mr)
memory_region_set_ram_debug_ops(mr, &sev_ops);
}
+hwaddr sev_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
+ MemTxAttrs *attrs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ target_ulong pde_addr, pte_addr;
+ uint64_t pte;
+ int32_t a20_mask;
+ uint32_t page_offset;
+ int page_size;
+ uint64_t me_mask;
+
+ me_mask = sev_get_me_mask();
+
+ *attrs = cpu_get_mem_attrs(env);
+
+ a20_mask = x86_get_a20_mask(env);
+ if (!(env->cr[0] & CR0_PG_MASK)) {
+ pte = addr & a20_mask;
+ page_size = 4096;
+ } else if (env->cr[4] & CR4_PAE_MASK) {
+ target_ulong pdpe_addr;
+ uint64_t pde, pdpe;
+
+#ifdef TARGET_X86_64
+ if (env->hflags & HF_LMA_MASK) {
+ bool la57 = env->cr[4] & CR4_LA57_MASK;
+ uint64_t pml5e_addr, pml5e;
+ uint64_t pml4e_addr, pml4e;
+ int32_t sext;
+
+ /* test virtual address sign extension */
+ sext = la57 ? (int64_t)addr >> 56 : (int64_t)addr >> 47;
+ if (sext != 0 && sext != -1) {
+ return -1;
+ }
+
+ if (la57) {
+ pml5e_addr = ((env->cr[3] & ~0xfff & me_mask) +
+ (((addr >> 48) & 0x1ff) << 3)) & a20_mask;
+ pml5e = ldq_phys_debug(cs, pml5e_addr) & me_mask;
+ if (!(pml5e & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ } else {
+ pml5e = env->cr[3] & me_mask;
+ }
+
+ pml4e_addr = ((pml5e & PG_ADDRESS_MASK) +
+ (((addr >> 39) & 0x1ff) << 3)) & a20_mask;
+ pml4e = ldq_phys_debug(cs, pml4e_addr) & me_mask;
+ if (!(pml4e & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ pdpe_addr = ((pml4e & PG_ADDRESS_MASK) +
+ (((addr >> 30) & 0x1ff) << 3)) & a20_mask;
+ pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
+ if (!(pdpe & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ if (pdpe & PG_PSE_MASK) {
+ page_size = 1024 * 1024 * 1024;
+ pte = pdpe;
+ goto out;
+ }
+
+ } else
+#endif
+ {
+ pdpe_addr = ((env->cr[3] & ~0x1f & me_mask) +
+ ((addr >> 27) & 0x18)) & a20_mask;
+ pdpe = ldq_phys_debug(cs, pdpe_addr) & me_mask;
+ if (!(pdpe & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ }
+
+ pde_addr = ((pdpe & PG_ADDRESS_MASK) +
+ (((addr >> 21) & 0x1ff) << 3)) & a20_mask;
+ pde = ldq_phys_debug(cs, pde_addr) & me_mask;
+ if (!(pde & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ if (pde & PG_PSE_MASK) {
+ /* 2 MB page */
+ page_size = 2048 * 1024;
+ pte = pde;
+ } else {
+ /* 4 KB page */
+ pte_addr = ((pde & PG_ADDRESS_MASK) +
+ (((addr >> 12) & 0x1ff) << 3)) & a20_mask;
+ page_size = 4096;
+ pte = ldq_phys_debug(cs, pte_addr) & me_mask;
+ }
+ if (!(pte & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ } else {
+ uint32_t pde;
+
+ /* page directory entry */
+ pde_addr = ((env->cr[3] & ~0xfff & me_mask) +
+ ((addr >> 20) & 0xffc)) & a20_mask;
+ pde = x86_ldl_phys(cs, pde_addr) & me_mask;
+ if (!(pde & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {
+ pte = pde | ((pde & 0x1fe000LL) << (32 - 13));
+ page_size = 4096 * 1024;
+ } else {
+ /* page directory entry */
+ pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask;
+ pte = ldl_phys_debug(cs, pte_addr) & me_mask;
+ if (!(pte & PG_PRESENT_MASK)) {
+ return -1;
+ }
+ page_size = 4096;
+ }
+ pte = pte & a20_mask;
+ }
+
+#ifdef TARGET_X86_64
+out:
+#endif
+ pte &= PG_ADDRESS_MASK & ~(page_size - 1);
+ page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);
+ return pte | page_offset;
+}
+
+MemTxResult sev_address_space_write_rom_debug(AddressSpace *as,
+ hwaddr addr,
+ MemTxAttrs attrs,
+ const void *ptr,
+ hwaddr len)
+{
+ /* set debug attrs to indicate memory access is from the debugger */
+ attrs.debug = 1;
+
+ /*
+ * Invoke address_space_rw debug helper
+ */
+ return address_space_write_rom_debug(as, addr, attrs, ptr, len);
+}
+
+MemTxResult sev_address_space_read_debug(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, void *ptr,
+ hwaddr len)
+{
+ /* set debug attrs to indicate memory access is from the debugger */
+ attrs.debug = 1;
+
+ /*
+ * Invoke address_space_rw debug helper
+ */
+ return address_space_read_debug(as, addr, attrs, ptr, len);
+}
+
+static const MemoryDebugOps sev_debug_ops = {
+ .read = sev_address_space_read_debug,
+ .write = sev_address_space_write_rom_debug
+};
+
+void
+sev_set_debug_ops_cpu_state(void *handle, CPUState *cs)
+{
+ SevGuestState *s = handle;
+ CPUClass *cc;
+
+ /* If policy does not allow debug then no need to register ops */
+ if (s->policy & SEV_POLICY_NODBG) {
+ return;
+ }
+
+ cc = CPU_GET_CLASS(cs);
+
+ /*
+ * Override guest MMU lookup/page-table-walker with SEV specific
+ * callback to handle encrypted memory.
+ */
+ cc->get_phys_page_attrs_debug = sev_cpu_get_phys_page_attrs_debug;
+
+ address_space_set_debug_ops(&sev_debug_ops);
+}
+
static void
sev_register_types(void)
{