fix ram offset translation for pc_piix and q35

This commit is contained in:
Sergej Schumilo 2023-01-01 18:52:37 +01:00
parent 96f98e0b8d
commit 37717f5ebf
14 changed files with 166 additions and 33 deletions

View File

@ -61,6 +61,11 @@
#include "migration/misc.h"
#include "sysemu/numa.h"
#ifdef QEMU_NYX
#include "nyx/state/state.h"
#include "nyx/mem_split.h"
#endif
#define MAX_IDE_BUS 2
#ifdef CONFIG_IDE_ISA
@ -147,9 +152,15 @@ static void pc_init1(MachineState *machine,
if (machine->ram_size >= lowmem) {
x86ms->above_4g_mem_size = machine->ram_size - lowmem;
x86ms->below_4g_mem_size = lowmem;
#ifdef QEMU_NYX
GET_GLOBAL_STATE()->mem_mapping_type = PC_PIIX_MEM_TYPE;
#endif
} else {
x86ms->above_4g_mem_size = 0;
x86ms->below_4g_mem_size = machine->ram_size;
#ifdef QEMU_NYX
GET_GLOBAL_STATE()->mem_mapping_type = PC_PIIX_MEM_LOW_TYPE;
#endif
}
}

View File

@ -53,6 +53,11 @@
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/numa.h"
#ifdef QEMU_NYX
#include "nyx/state/state.h"
#include "nyx/mem_split.h"
#endif
/* ICH9 AHCI has 6 ports */
#define MAX_SATA_PORTS 6
@ -145,8 +150,14 @@ static void pc_q35_init(MachineState *machine)
*/
if (machine->ram_size >= 0xb0000000) {
lowmem = 0x80000000;
#ifdef QEMU_NYX
GET_GLOBAL_STATE()->mem_mapping_type = Q35_MEM_MEM_TYPE;
#endif
} else {
lowmem = 0xb0000000;
#ifdef QEMU_NYX
GET_GLOBAL_STATE()->mem_mapping_type = Q35_MEM_MEM_LOW_TYPE;
#endif
}
/* Handle the machine opt max-ram-below-4g. It is basically doing

View File

@ -33,5 +33,6 @@ hypercall/configuration.o \
hypercall/debug.o \
state/state.o \
state/snapshot_state.o \
pt.o
pt.o \
mem_split.o

View File

@ -6,6 +6,7 @@
#include "nyx/fast_vm_reload.h"
#include "nyx/hypercall/debug.h"
#include "nyx/mem_split.h"
#include "nyx/memory_access.h"
#include "nyx/state/state.h"
#include "nyx/synchronization.h"

85
nyx/mem_split.c Normal file
View File

@ -0,0 +1,85 @@
#include "qemu/osdep.h"
#include "nyx/state/state.h"
#include "nyx/mem_split.h"
#define PC_PIIX_LOW_MEM_SPLIT_START 0xe0000000
#define PC_PIIX_MEM_SPLIT_START 0x0C0000000
#define PC_PIXX_MEM_SPLIT_END 0x100000000
#define Q35_MEM_SPLIT_START 0x080000000
#define Q35_MEM_SPLIT_END 0x100000000
#define Q35_LOW_MEM_SPLIT_START 0x0b0000000
bool is_mem_mapping_supported(MemSplitType type){
return type == PC_PIIX_MEM_LOW_TYPE || type == PC_PIIX_MEM_TYPE || type == Q35_MEM_MEM_LOW_TYPE || type == Q35_MEM_MEM_TYPE;
}
uint64_t get_mem_split_start(void){
switch(GET_GLOBAL_STATE()->mem_mapping_type){
case PC_PIIX_MEM_LOW_TYPE:
return PC_PIIX_LOW_MEM_SPLIT_START;
case PC_PIIX_MEM_TYPE:
return PC_PIIX_MEM_SPLIT_START;
case Q35_MEM_MEM_LOW_TYPE:
return Q35_LOW_MEM_SPLIT_START;
case Q35_MEM_MEM_TYPE:
return Q35_MEM_SPLIT_START;
default:
abort();
}
}
uint64_t get_mem_split_end(void){
switch(GET_GLOBAL_STATE()->mem_mapping_type){
case PC_PIIX_MEM_TYPE:
return PC_PIXX_MEM_SPLIT_END;
case Q35_MEM_MEM_TYPE:
return Q35_MEM_SPLIT_END;
default:
abort();
}
}
uint64_t address_to_ram_offset(uint64_t offset){
switch(GET_GLOBAL_STATE()->mem_mapping_type){
case PC_PIIX_MEM_LOW_TYPE:
if(offset >= PC_PIIX_LOW_MEM_SPLIT_START){
abort();
}
return offset;
case PC_PIIX_MEM_TYPE:
return offset >= PC_PIXX_MEM_SPLIT_END ? (offset - PC_PIXX_MEM_SPLIT_END) + PC_PIIX_MEM_SPLIT_START : offset;
case Q35_MEM_MEM_TYPE:
return offset >= Q35_MEM_SPLIT_END ? (offset - Q35_MEM_SPLIT_END) + Q35_MEM_SPLIT_START : offset;
case Q35_MEM_MEM_LOW_TYPE:
if(offset >= Q35_LOW_MEM_SPLIT_START){
abort();
}
return offset;
default:
abort();
}
}
uint64_t ram_offset_to_address(uint64_t offset){
switch(GET_GLOBAL_STATE()->mem_mapping_type){
case PC_PIIX_MEM_LOW_TYPE:
if(offset >= PC_PIIX_LOW_MEM_SPLIT_START){
abort();
}
return offset;
case PC_PIIX_MEM_TYPE:
return offset >= PC_PIIX_MEM_SPLIT_START ? (offset - PC_PIIX_MEM_SPLIT_START) + PC_PIXX_MEM_SPLIT_END : offset;;
case Q35_MEM_MEM_TYPE:
return offset >= Q35_MEM_SPLIT_START ? (offset - Q35_MEM_SPLIT_START) + Q35_MEM_SPLIT_END : offset;
case Q35_MEM_MEM_LOW_TYPE:
if(offset >= Q35_LOW_MEM_SPLIT_START){
abort();
}
return offset;
default:
abort();
}
}

21
nyx/mem_split.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include "nyx/types.h"
#include "stdlib.h"
#include "stdint.h"
typedef enum MemSplitType {
MEM_SPLIT_TYPE_INVALID,
PC_PIIX_MEM_LOW_TYPE,
PC_PIIX_MEM_TYPE,
Q35_MEM_MEM_LOW_TYPE,
Q35_MEM_MEM_TYPE,
} MemSplitType;
bool is_mem_mapping_supported(MemSplitType type);
uint64_t get_mem_split_start(void);
uint64_t get_mem_split_end(void);
uint64_t address_to_ram_offset(uint64_t offset);
uint64_t ram_offset_to_address(uint64_t offset);

View File

@ -34,6 +34,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include "nyx/helpers.h"
#include "nyx/hypercall/hypercall.h"
#include "nyx/state/state.h"
#include "nyx/mem_split.h"
#define INVALID_ADDRESS 0xFFFFFFFFFFFFFFFFULL

View File

@ -27,14 +27,6 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include "nyx/types.h"
#include <linux/kvm.h>
#define MEM_SPLIT_START 0x0C0000000
#define MEM_SPLIT_END 0x100000000
/* i386 pc_piix low_mem address translation */
#define address_to_ram_offset(offset) \
(offset >= MEM_SPLIT_END ? (offset - MEM_SPLIT_END) + MEM_SPLIT_START : offset)
#define ram_offset_to_address(offset) \
(offset >= MEM_SPLIT_START ? (offset - MEM_SPLIT_START) + MEM_SPLIT_END : offset)
mem_mode_t get_current_mem_mode(CPUState *cpu);

View File

@ -11,6 +11,7 @@
#include "nyx/snapshot/helper.h"
#include "nyx/snapshot/memory/block_list.h"
#include "nyx/snapshot/memory/shadow_memory.h"
#include "nyx/mem_split.h"
#define REALLOC_SIZE 0x8000
@ -25,16 +26,16 @@ snapshot_page_blocklist_t *snapshot_page_blocklist_init(void)
snapshot_page_blocklist_t *self = malloc(sizeof(snapshot_page_blocklist_t));
uint64_t ram_size = get_ram_size();
self->phys_area_size = ram_size <= MEM_SPLIT_START ?
self->phys_area_size = ram_size <= get_mem_split_start() ?
ram_size :
ram_size + (MEM_SPLIT_END - MEM_SPLIT_START);
ram_size + (get_mem_split_end() - get_mem_split_start());
self->phys_bitmap = malloc(BITMAP_SIZE(self->phys_area_size));
memset(self->phys_bitmap, 0x0, BITMAP_SIZE(self->phys_area_size));
if (ram_size > MEM_SPLIT_START) {
memset(self->phys_bitmap + BITMAP_SIZE(MEM_SPLIT_START), 0xff,
BITMAP_SIZE((MEM_SPLIT_END - MEM_SPLIT_START)));
if (ram_size > get_mem_split_start()) {
memset(self->phys_bitmap + BITMAP_SIZE(get_mem_split_start()), 0xff,
BITMAP_SIZE((get_mem_split_end() - get_mem_split_start())));
}
self->pages_num = 0;

View File

@ -13,6 +13,7 @@
#include "nyx/snapshot/helper.h"
#include "nyx/snapshot/memory/nyx_fdl_user.h"
#include "nyx/snapshot/memory/shadow_memory.h"
#include "nyx/mem_split.h"
/* debug option */
// #define DEBUG_USER_FDL

View File

@ -13,6 +13,7 @@
#include "nyx/snapshot/helper.h"
#include "nyx/snapshot/memory/shadow_memory.h"
#include "nyx/mem_split.h"
typedef struct fast_reload_dump_head_s {
uint32_t shadow_memory_regions;
@ -95,10 +96,10 @@ shadow_memory_t *shadow_memory_init(void)
for (uint8_t i = 0; i < regions_num; i++) {
block = block_array[i];
if (!block->mr->readonly) {
if (self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START) {
if (self->ram_regions_num == 0 && block->used_length >= get_mem_split_start()) {
self->ram_regions[self->ram_regions_num].ram_region = i;
self->ram_regions[self->ram_regions_num].base = block->mr->addr;
self->ram_regions[self->ram_regions_num].size = MEM_SPLIT_START;
self->ram_regions[self->ram_regions_num].size = get_mem_split_start();
self->ram_regions[self->ram_regions_num].offset =
snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
@ -113,16 +114,14 @@ shadow_memory_t *shadow_memory_init(void)
self->ram_regions_num++;
self->ram_regions[self->ram_regions_num].ram_region = i;
self->ram_regions[self->ram_regions_num].base =
MEM_SPLIT_END
;
self->ram_regions[self->ram_regions_num].size = block->used_length - MEM_SPLIT_START;
self->ram_regions[self->ram_regions_num].base = get_mem_split_end();
self->ram_regions[self->ram_regions_num].size = block->used_length - get_mem_split_start();
self->ram_regions[self->ram_regions_num].offset =
(snapshot_ptr_offset_array[i] + MEM_SPLIT_START) - snapshot_ptr_offset_array[0];
(snapshot_ptr_offset_array[i] + get_mem_split_start()) - snapshot_ptr_offset_array[0];
self->ram_regions[self->ram_regions_num].host_region_ptr =
block->host + MEM_SPLIT_START;
block->host + get_mem_split_start();
self->ram_regions[self->ram_regions_num].snapshot_region_ptr =
snapshot_ptr_offset_array[i] + MEM_SPLIT_START;
snapshot_ptr_offset_array[i] + get_mem_split_start();
self->ram_regions[self->ram_regions_num].idstr = malloc(strlen(block->idstr) + 1);
memset(self->ram_regions[self->ram_regions_num].idstr, 0, strlen(block->idstr) + 1);
strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
@ -169,7 +168,7 @@ shadow_memory_t *shadow_memory_init_from_snapshot(const char *snapshot_folder,
/* count number of ram regions */
QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
if (!block->mr->readonly) {
if (self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START) {
if (self->ram_regions_num == 0 && block->used_length >= get_mem_split_start()) {
self->ram_regions_num++;
}
self->ram_regions_num++;
@ -240,10 +239,10 @@ shadow_memory_t *shadow_memory_init_from_snapshot(const char *snapshot_folder,
for (uint8_t i = 0; i < regions_num; i++) {
block = block_array[i];
if (!block->mr->readonly) {
if (self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START) {
if (self->ram_regions_num == 0 && block->used_length >= get_mem_split_start()) {
self->ram_regions[self->ram_regions_num].ram_region = i;
self->ram_regions[self->ram_regions_num].base = block->mr->addr;
self->ram_regions[self->ram_regions_num].size = MEM_SPLIT_START;
self->ram_regions[self->ram_regions_num].size = get_mem_split_start();
self->ram_regions[self->ram_regions_num].offset =
snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
@ -258,16 +257,14 @@ shadow_memory_t *shadow_memory_init_from_snapshot(const char *snapshot_folder,
self->ram_regions_num++;
self->ram_regions[self->ram_regions_num].ram_region = i;
self->ram_regions[self->ram_regions_num].base =
MEM_SPLIT_END
;
self->ram_regions[self->ram_regions_num].size = block->used_length - MEM_SPLIT_START;
self->ram_regions[self->ram_regions_num].base = get_mem_split_end();
self->ram_regions[self->ram_regions_num].size = block->used_length - get_mem_split_start();
self->ram_regions[self->ram_regions_num].offset =
(snapshot_ptr_offset_array[i] + MEM_SPLIT_START) - snapshot_ptr_offset_array[0];
(snapshot_ptr_offset_array[i] + get_mem_split_start()) - snapshot_ptr_offset_array[0];
self->ram_regions[self->ram_regions_num].host_region_ptr =
block->host + MEM_SPLIT_START;
block->host + get_mem_split_start();
self->ram_regions[self->ram_regions_num].snapshot_region_ptr =
snapshot_ptr_offset_array[i] + MEM_SPLIT_START;
snapshot_ptr_offset_array[i] + get_mem_split_start();
self->ram_regions[self->ram_regions_num].idstr = malloc(strlen(block->idstr) + 1);
memset(self->ram_regions[self->ram_regions_num].idstr, 0, strlen(block->idstr) + 1);
strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);

View File

@ -117,6 +117,8 @@ void state_init_global(void)
global_state.get_host_config_done = false;
global_state.set_agent_config_done = false;
global_state.mem_mapping_type = MEM_SPLIT_TYPE_INVALID;
global_state.sharedir = sharedir_new();

View File

@ -30,6 +30,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include "nyx/sharedir.h"
#include "nyx/synchronization.h"
#include "nyx/types.h"
#include "nyx/mem_split.h"
#include <libxdc.h>
@ -137,6 +138,8 @@ typedef struct qemu_nyx_state_s {
bool get_host_config_done;
bool set_agent_config_done;
MemSplitType mem_mapping_type;
/* capabilites */
uint8_t cap_timeout_detection;
uint8_t cap_only_reload_mode;

6
vl.c
View File

@ -143,6 +143,7 @@ int main(int argc, char **argv)
#include "nyx/pt.h"
#include "nyx/state/state.h"
#include "nyx/synchronization.h"
#include "nyx/mem_split.h"
// clang-format off
#endif
@ -4588,6 +4589,11 @@ int main(int argc, char **argv, char **envp)
#ifdef QEMU_NYX
// clang-format on
if(is_mem_mapping_supported(GET_GLOBAL_STATE()->mem_mapping_type) == false){
nyx_error("Unsupported memory mapping type (only q35 and pc_piix are supported)\n");
exit(1);
}
fast_reload_init(GET_GLOBAL_STATE()->fast_reload_snapshot);
if (fast_vm_reload) {