diff mbox

[RFC,v1,15/22] i386: sev: register RAM read/write ops for BIOS and PC.RAM region

Message ID 147377816100.11859.1924921034992764815.stgit@brijesh-build-machine
State New
Headers show

Commit Message

Brijesh Singh Sept. 13, 2016, 2:49 p.m. UTC
If guest is launched into SEV-enabled mode then read/write to the
BIOS and RAM memory regions should be performed using the SEV commands.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 hw/i386/pc.c       |    5 +++++
 hw/i386/pc_sysfw.c |    6 ++++++
 2 files changed, 11 insertions(+)

Comments

Paolo Bonzini Sept. 13, 2016, 11:05 p.m. UTC | #1
On 13/09/2016 16:49, Brijesh Singh wrote:
>  
> +    /* Register SEV read/write ops for the guest RAM */
> +    if (kvm_sev_enabled())
> +        memory_region_set_ram_ops(ram, kvm_sev_get_ram_ops());

If you don't actually need this one except for -kernel it would be very
nice, because then the hooks could be limited to cpu_memory_rw_debug.

address_space_write and address_space_read are the central entry point
for device DMA, and calling mr->ram_ops->write from there seems very
wrong.  I'd rather make those hooks *ROM* read/write ops rather than RAM
read/write ops.

Paolo
Brijesh Singh Sept. 14, 2016, 8:59 p.m. UTC | #2
Hi Paolo,

On 09/13/2016 06:05 PM, Paolo Bonzini wrote:
>
>
> On 13/09/2016 16:49, Brijesh Singh wrote:
>>
>> +    /* Register SEV read/write ops for the guest RAM */
>> +    if (kvm_sev_enabled())
>> +        memory_region_set_ram_ops(ram, kvm_sev_get_ram_ops());
>
> If you don't actually need this one except for -kernel it would be very
> nice, because then the hooks could be limited to cpu_memory_rw_debug.
>

Yes so far i see that we needing this only for -kernel option.

> address_space_write and address_space_read are the central entry point
> for device DMA, and calling mr->ram_ops->write from there seems very
> wrong.  I'd rather make those hooks *ROM* read/write ops rather than RAM
> read/write ops.
>

I will look into hooking up the callback into ROM read/write ops. I was 
thinking about adding a new argument in 
cpu_physical_memory_write_rom_internal()

void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
                                    const uint8_t *buf, int len,
                                    WriteCB *cb)
{
    ....
    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);

    if (cb)
      cb(ptr, buf, len)
    else
      memcpy(ptr, buf, len)
....

}

In case of SEV, we pass a CB function pointer which calls SEV API's to 
encrypt memory. Does this make sense?

-Brijesh
Paolo Bonzini Sept. 14, 2016, 9 p.m. UTC | #3
On 14/09/2016 22:59, Brijesh Singh wrote:
> I will look into hooking up the callback into ROM read/write ops. I was
> thinking about adding a new argument in
> cpu_physical_memory_write_rom_internal()
> 
> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>                                    const uint8_t *buf, int len,
>                                    WriteCB *cb)
> {
>    ....
>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
> 
>    if (cb)
>      cb(ptr, buf, len)
>    else
>      memcpy(ptr, buf, len)
> ....
> 
> }
> 
> In case of SEV, we pass a CB function pointer which calls SEV API's to
> encrypt memory. Does this make sense?

I think a global as you have it in this series is just fine---just don't
hook it into address_space_read and address_space_write.

Paolo
Brijesh Singh Sept. 14, 2016, 9:47 p.m. UTC | #4
On 09/14/2016 04:00 PM, Paolo Bonzini wrote:
>
>
> On 14/09/2016 22:59, Brijesh Singh wrote:
>> I will look into hooking up the callback into ROM read/write ops. I was
>> thinking about adding a new argument in
>> cpu_physical_memory_write_rom_internal()
>>
>> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>>                                    const uint8_t *buf, int len,
>>                                    WriteCB *cb)
>> {
>>    ....
>>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
>>
>>    if (cb)
>>      cb(ptr, buf, len)
>>    else
>>      memcpy(ptr, buf, len)
>> ....
>>
>> }
>>
>> In case of SEV, we pass a CB function pointer which calls SEV API's to
>> encrypt memory. Does this make sense?
>
> I think a global as you have it in this series is just fine---just don't
> hook it into address_space_read and address_space_write.
>

Actually in SEV RAM callback I check the Attrs, if attr.sev_debug flag 
set then use SEV debug command otherwise default to memcpy so that DMA 
and everything else works. I guest the main reason why i choose to hook 
this up in address_space_read/write was that I found that 
address_space_write and address_space_read is used in debug path. e.g

cpu_memory_rw_debug
   address_space_rw
     address_space_write/read

cpu_physical_memory_rw
  address_space_rw
    address_space_write/read

How do you want me to handle these cases? Having SEV RAM callback taking 
care this internally was my simplest solution,  I am certainly open to 
new ideas.
Paolo Bonzini Sept. 14, 2016, 9:52 p.m. UTC | #5
On 14/09/2016 23:47, Brijesh Singh wrote:
> 
> 
> On 09/14/2016 04:00 PM, Paolo Bonzini wrote:
>>
>>
>> On 14/09/2016 22:59, Brijesh Singh wrote:
>>> I will look into hooking up the callback into ROM read/write ops. I was
>>> thinking about adding a new argument in
>>> cpu_physical_memory_write_rom_internal()
>>>
>>> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>>>                                    const uint8_t *buf, int len,
>>>                                    WriteCB *cb)
>>> {
>>>    ....
>>>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
>>>
>>>    if (cb)
>>>      cb(ptr, buf, len)
>>>    else
>>>      memcpy(ptr, buf, len)
>>> ....
>>>
>>> }
>>>
>>> In case of SEV, we pass a CB function pointer which calls SEV API's to
>>> encrypt memory. Does this make sense?
>>
>> I think a global as you have it in this series is just fine---just don't
>> hook it into address_space_read and address_space_write.
>>
> 
> Actually in SEV RAM callback I check the Attrs, if attr.sev_debug flag
> set then use SEV debug command otherwise default to memcpy so that DMA
> and everything else works. I guest the main reason why i choose to hook
> this up in address_space_read/write was that I found that
> address_space_write and address_space_read is used in debug path. e.g
> 
> cpu_memory_rw_debug
>   address_space_rw
>     address_space_write/read

Right, but if you change this to a ROM hook only, cpu_memory_rw_debug
will go through cpu_physical_memory_write_rom instead.  This will invoke
the hook properly, won't it?  It will break -kernel unless fw_cfg DMA is
disabled, of course.

Paolo
Brijesh Singh Sept. 14, 2016, 10:06 p.m. UTC | #6
On 09/14/2016 04:52 PM, Paolo Bonzini wrote:
>
>
> On 14/09/2016 23:47, Brijesh Singh wrote:
>>
>>
>> On 09/14/2016 04:00 PM, Paolo Bonzini wrote:
>>>
>>>
>>> On 14/09/2016 22:59, Brijesh Singh wrote:
>>>> I will look into hooking up the callback into ROM read/write ops. I was
>>>> thinking about adding a new argument in
>>>> cpu_physical_memory_write_rom_internal()
>>>>
>>>> void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
>>>>                                    const uint8_t *buf, int len,
>>>>                                    WriteCB *cb)
>>>> {
>>>>    ....
>>>>    ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
>>>>
>>>>    if (cb)
>>>>      cb(ptr, buf, len)
>>>>    else
>>>>      memcpy(ptr, buf, len)
>>>> ....
>>>>
>>>> }
>>>>
>>>> In case of SEV, we pass a CB function pointer which calls SEV API's to
>>>> encrypt memory. Does this make sense?
>>>
>>> I think a global as you have it in this series is just fine---just don't
>>> hook it into address_space_read and address_space_write.
>>>
>>
>> Actually in SEV RAM callback I check the Attrs, if attr.sev_debug flag
>> set then use SEV debug command otherwise default to memcpy so that DMA
>> and everything else works. I guest the main reason why i choose to hook
>> this up in address_space_read/write was that I found that
>> address_space_write and address_space_read is used in debug path. e.g
>>
>> cpu_memory_rw_debug
>>   address_space_rw
>>     address_space_write/read
>
> Right, but if you change this to a ROM hook only, cpu_memory_rw_debug
> will go through cpu_physical_memory_write_rom instead.  This will invoke
> the hook properly, won't it?  It will break -kernel unless fw_cfg DMA is
> disabled, of course.
>

maybe I am missing something.

here is what I see:

int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
                         uint8_t *buf, int len, int is_write)
{
   ............

    if (is_write)
        cpu_physical_memory_write_rom_internal()
     else
        address_space_rw()

    .....

}

So looking at code, i have impression that write will go through the 
cpu_physical_memory_write_rom but the read will still go through 
address_space_rw which will eventually invoke address_space_read.

Also when user tries to read or write to a physical address through qemu 
monitor then it will invoke cpu_physical_memory_rw which will eventually 
use address_space_write and address_space_read to read/write the guest 
memory.
diff mbox

Patch

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 022dd1b..1471df4 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -46,6 +46,7 @@ 
 #include "sysemu/sysemu.h"
 #include "sysemu/numa.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sev.h"
 #include "sysemu/qtest.h"
 #include "kvm_i386.h"
 #include "hw/xen/xen.h"
@@ -1387,6 +1388,10 @@  void pc_memory_init(PCMachineState *pcms,
         e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
     }
 
+    /* Register SEV read/write ops for the guest RAM */
+    if (kvm_sev_enabled())
+        memory_region_set_ram_ops(ram, kvm_sev_get_ram_ops());
+
     if (!pcmc->has_reserved_memory &&
         (machine->ram_slots ||
          (machine->maxram_size > machine->ram_size))) {
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index f915ad0..95b1006 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -35,6 +35,7 @@ 
 #include "sysemu/sysemu.h"
 #include "hw/block/flash.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sev.h"
 
 #define BIOS_FILENAME "bios.bin"
 
@@ -228,6 +229,11 @@  static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
     memory_region_add_subregion(rom_memory,
                                 (uint32_t)(-bios_size),
                                 bios);
+
+    /* Register SEV read/write callback */
+    if (kvm_sev_enabled()) {
+        memory_region_set_ram_ops(bios, kvm_sev_get_ram_ops());
+    }
 }
 
 void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw)