From 2ca220961a5094afc9b6c3d2d6c6ed6dba323395 Mon Sep 17 00:00:00 2001 From: Zed Date: Sat, 2 Nov 2024 08:50:31 -0400 Subject: [PATCH] Virtualization: Update clock and syscon vitualization code Signed-off-by: Zed --- subsys/virtualization/vdev/CMakeLists.txt | 2 +- .../{virt_clock_syscon.c => virt_clock.c} | 162 +++++++++++++----- subsys/virtualization/vdev/virt_syscon.c | 104 +++++++++-- 3 files changed, 213 insertions(+), 55 deletions(-) rename subsys/virtualization/vdev/{virt_clock_syscon.c => virt_clock.c} (36%) diff --git a/subsys/virtualization/vdev/CMakeLists.txt b/subsys/virtualization/vdev/CMakeLists.txt index 429460f80..4cd12c728 100644 --- a/subsys/virtualization/vdev/CMakeLists.txt +++ b/subsys/virtualization/vdev/CMakeLists.txt @@ -37,7 +37,7 @@ zephyr_sources_ifdef( zephyr_sources_ifdef( CONFIG_VM_CLOCK_SYSTEM_CONTROLLER - virt_clock_syscon.c + virt_clock.c ) zephyr_sources_ifdef( diff --git a/subsys/virtualization/vdev/virt_clock_syscon.c b/subsys/virtualization/vdev/virt_clock.c similarity index 36% rename from subsys/virtualization/vdev/virt_clock_syscon.c rename to subsys/virtualization/vdev/virt_clock.c index 0490968cc..dab435ba3 100644 --- a/subsys/virtualization/vdev/virt_clock_syscon.c +++ b/subsys/virtualization/vdev/virt_clock.c @@ -15,48 +15,89 @@ #include #include #include -#include +#include #include +#include LOG_MODULE_DECLARE(ZVM_MODULE_NAME); +#define CRU_REG(offset) (CRU_BASE + (offset)) -#define VM_CLKCON_NAME vm_clock_syscon +#define VM_CLKCON_NAME vm_clock #define DEV_DATA(dev) \ ((struct virt_device_data *)(dev)->data) -struct virt_clk_syscon_list overall_clock_syscons; +struct virt_clk_list overall_clocks; static const struct virtual_device_instance *clk_virtual_device_instance; static bool first_entry_flag = false; +uint32_t zephyr_cru_space[20] = { + CRU_REG(CRU_CLKSEL_CON72_OFFSET), + CRU_REG(CRU_CLKSEL_CON71_OFFSET), + CRU_REG(CRU_GATE_CON30_OFFSET), + CRU_REG(CRU_GATE_CON31_OFFSET), + CRU_REG(CRU_GATE_CON32_OFFSET), +}; + +static uint32_t fake_write_addr = 0; +static uint32_t fake_write_value = 0; + +/** + * @brief Defines an enum type to represent different virtual machine types. + */ +static enum vm_type { + VM_TYPE_UNKNOWN = 0, + VM_TYPE_ZEPHYR, + VM_TYPE_LINUX, + /* More virtual machine types can be added in the future */ +}; + +/** + * @brief Returns the corresponding enum value based on the virtual machine name. + * + * @param vm_name A string representing the name of the virtual machine. + * + * @return The enum value of the virtual machine type. Returns VM_TYPE_UNKNOWN if + * the name does not match any known virtual machine type. + */ +enum vm_type get_vm_type(const char *vm_name) { + if (strcmp(vm_name, "zephyr_os-0") == 0) { + return VM_TYPE_ZEPHYR; + } else if (strcmp(vm_name, "linux_os-1") == 0) { + return VM_TYPE_LINUX; + } else { + return VM_TYPE_UNKNOWN; + } +} + int z_info_sys_clkcon(const char *name, uint32_t addr_base, uint32_t addr_size, void *priv) { ARG_UNUSED(priv); k_spinlock_key_t key; - struct virt_clk_syscon *clk_syscon; + struct virt_clk *clk; - clk_syscon = (struct virt_clk_syscon *)k_malloc(sizeof(struct virt_clk_syscon)); - if (!clk_syscon) { - ZVM_LOG_ERR("Allocate memory for clk_syscon Error.\n"); + clk = (struct virt_clk *)k_malloc(sizeof(struct virt_clk)); + if (!clk) { + ZVM_LOG_ERR("Allocate memory for clk Error.\n"); return -ENOMEM; } - clk_syscon->reg_base = addr_base; - clk_syscon->reg_size = addr_size; - clk_syscon->name = name; + clk->reg_base = addr_base; + clk->reg_size = addr_size; + clk->name = name; - /* Add clock syscon info to overall lists. */ - key = k_spin_lock(&overall_clock_syscons.vclk_lock); - /*dlist must be init to address to itself.*/ + /* Add clock info to overall lists. */ + key = k_spin_lock(&overall_clocks.vclk_lock); + /* dlist must be init to address to itself.*/ if(!first_entry_flag){ - sys_dlist_init(&overall_clock_syscons.clk_syscon_list); + sys_dlist_init(&overall_clocks.clk_list); first_entry_flag = true; } - sys_dlist_append(&overall_clock_syscons.clk_syscon_list, &clk_syscon->clk_node); - overall_clock_syscons.clk_num++; - k_spin_unlock(&overall_clock_syscons.vclk_lock, key); + sys_dlist_append(&overall_clocks.clk_list, &clk->clk_node); + overall_clocks.clk_num++; + k_spin_unlock(&overall_clocks.vclk_lock, key); return 0; } @@ -65,7 +106,7 @@ int z_info_sys_clkcon(const char *name, uint32_t addr_base, * @brief: Get the virtual clock controller, and set a * pre_kernel configuration for the virtual clock. */ -static int virt_clock_syscon_init(const struct device *dev) +static int virt_clock_init(const struct device *dev) { ARG_UNUSED(dev); int i; @@ -82,27 +123,27 @@ static int virt_clock_syscon_init(const struct device *dev) return 0; } -static struct virt_device_config virt_clock_syscon_cfg = { +static struct virt_device_config virt_clock_cfg = { .hirq_num = VM_DEVICE_INVALID_VIRQ, }; -static struct virt_device_data virt_clock_syscon_data_port = { +static struct virt_device_data virt_clock_data_port = { .device_data = NULL, }; /** - * @brief init vm clock syscon device for each vm. + * @brief init vm clock device for each vm. */ -static int vm_clock_syscons_init(const struct device *dev, struct vm *vm, struct virt_dev *vdev_desc) +static int vm_clock_init(const struct device *dev, struct vm *vm, struct virt_dev *vdev_desc) { ARG_UNUSED(dev); struct virt_dev *vm_dev; - struct virt_clk_syscon *virt_clk_dev; + struct virt_clk *virt_clk_dev; struct _dnode *d_node, *ds_node; /* scan the system clock list and get the clock device */ - SYS_DLIST_FOR_EACH_NODE_SAFE(&overall_clock_syscons.clk_syscon_list, d_node, ds_node){ - virt_clk_dev = CONTAINER_OF(d_node, struct virt_clk_syscon, clk_node); + SYS_DLIST_FOR_EACH_NODE_SAFE(&overall_clocks.clk_list, d_node, ds_node){ + virt_clk_dev = CONTAINER_OF(d_node, struct virt_clk, clk_node); vm_dev = vm_virt_dev_add(vm, virt_clk_dev->name, false, false, virt_clk_dev->reg_base, virt_clk_dev->reg_base, virt_clk_dev->reg_size, VM_DEVICE_INVALID_VIRQ, @@ -116,37 +157,76 @@ static int vm_clock_syscons_init(const struct device *dev, struct vm *vm, struct return 0; } -static int clk_syscon_vdev_mem_read(struct virt_dev *vdev, uint64_t addr, uint64_t *value, uint16_t size) +int clk_vdev_mem_read(struct virt_dev *vdev, uint64_t addr, uint64_t *value) { uint32_t read_value; + + if(addr == fake_write_addr){ + *(uint32_t *)value = fake_write_value; + return 0; + } + read_value = sys_read32(addr); *(uint32_t *)value = read_value; return 0; } -static int clk_syscon_vdev_mem_write(struct virt_dev *vdev, uint64_t addr, uint64_t *value, uint16_t size) +static void fake_write(uint64_t addr,uint64_t value){ + fake_write_addr = addr; + fake_write_value = value; + ZVM_LOG_INFO("^^Invalid cru_addr =%x,value=%x\n",addr,value); + return; +} + +int clk_vdev_mem_write(struct virt_dev *vdev, uint64_t addr, uint64_t *value) { uint32_t be_write_value, write_value, af_write_value; - - write_value = *(uint32_t *)value; - be_write_value = sys_read32(addr); - sys_write32(write_value, addr); - af_write_value = sys_read32(addr); + enum vm_type vm_type_id; + + /* Get the virtual machine type */ + vm_type_id = get_vm_type(vdev->vm->vm_name); + + /* Switch to handle different types of virtual machines */ + switch (vm_type_id) { + case VM_TYPE_ZEPHYR: + write_value = *(uint32_t *)value; + be_write_value = sys_read32(addr); + sys_write32(write_value, addr); + af_write_value = sys_read32(addr); + break; + + case VM_TYPE_LINUX: + for (int i = 0; i < ARRAY_SIZE(zephyr_cru_space); i++) { + if (addr == zephyr_cru_space[i]) { + fake_write(addr, value); + return 0; + } + } + write_value = *(uint32_t *)value; + be_write_value = sys_read32(addr); + sys_write32(write_value, addr); + af_write_value = sys_read32(addr); + break; + + default: + /* Handle unknown virtual machine type */ + return -1; + } return 0; } -static const struct virt_device_api virt_clock_syscon_api = { - .init_fn = vm_clock_syscons_init, - .virt_device_read = clk_syscon_vdev_mem_read, - .virt_device_write = clk_syscon_vdev_mem_write, +static const struct virt_device_api virt_clock_api = { + .init_fn = vm_clock_init, + .virt_device_read = clk_vdev_mem_read, + .virt_device_write = clk_vdev_mem_write, }; -/* Init after soc's clock syscon. */ -ZVM_VIRTUAL_DEVICE_DEFINE(virt_clock_syscon_init, +/* Init after soc's clock. */ +ZVM_VIRTUAL_DEVICE_DEFINE(virt_clock_init, POST_KERNEL, CONFIG_VM_CLOCK_SYSTEM_CONTROLLER_INIT_PRIORITY, VM_CLKCON_NAME, - virt_clock_syscon_data_port, - virt_clock_syscon_cfg, - virt_clock_syscon_api); + virt_clock_data_port, + virt_clock_cfg, + virt_clock_api); diff --git a/subsys/virtualization/vdev/virt_syscon.c b/subsys/virtualization/vdev/virt_syscon.c index 32d0f2c74..b04c493a1 100644 --- a/subsys/virtualization/vdev/virt_syscon.c +++ b/subsys/virtualization/vdev/virt_syscon.c @@ -16,11 +16,33 @@ #include #include #include - +#include LOG_MODULE_DECLARE(ZVM_MODULE_NAME); #define VIRT_SYSCON_NAME vm_syscon +#define SYSCON_REG(offset) (SYSGRF_BASE + (offset)) + +/* Zephyr syscon space */ +uint32_t zephyr_syscon_space[20] = { + SYSCON_REG(GRF_GPIO3B_IOMUX_L_OFFSET), + SYSCON_REG(GRF_GPIO3B_IOMUX_L_OFFSET), + SYSCON_REG(GRF_GPIO3B_P_OFFSET), + SYSCON_REG(GRF_GPIO3B_IE_OFFSET), + SYSCON_REG(GRF_GPIO3B_DS_0_OFFSET), + SYSCON_REG(GRF_GPIO3B_DS_1_OFFSET), + SYSCON_REG(GRF_GPIO3B_DS_2_OFFSET) +}; + +/** + * @brief Defines an enum type to represent different virtual machine types. + */ +enum vm_type { + VM_TYPE_UNKNOWN = 0, + VM_TYPE_ZEPHYR, + VM_TYPE_LINUX, + /* More virtual machine types can be added in the future */ +}; struct virt_syscon_list overall_syscons; @@ -30,6 +52,28 @@ static const struct virtual_device_instance *syscon_virtual_device_instance; #define DEV_DATA(dev) \ ((struct virt_device_data *)(dev)->data) +static uint32_t fake_write_addr = 0; +static uint32_t fake_write_value = 0; + +/** + * @brief Returns the corresponding enum value based on the virtual machine name. + * + * @param vm_name A string representing the name of the virtual machine. + * + * @return The enum value of the virtual machine type. Returns VM_TYPE_UNKNOWN if + * the name does not match any known virtual machine type. + */ +static enum vm_type get_vm_type(const char *vm_name) +{ + if (strcmp(vm_name, "zephyr_os-0") == 0) { + return VM_TYPE_ZEPHYR; + } else if (strcmp(vm_name, "linux_os-1") == 0) { + return VM_TYPE_LINUX; + } else { + return VM_TYPE_UNKNOWN; + } +} + int z_info_syscon(const char *name, uint32_t addr_base, uint32_t addr_size, void *priv) { @@ -48,6 +92,7 @@ int z_info_syscon(const char *name, uint32_t addr_base, /* Add clock syscon info to overall lists. */ key = k_spin_lock(&overall_syscons.vsyscon_lock); + /*dlist must be init to address to itself.*/ if(!first_entry_flag){ sys_dlist_init(&overall_syscons.syscon_list); first_entry_flag = true; @@ -79,29 +124,62 @@ static int virt_syscon_init(const struct device *dev) return 0; } - -static int syscon_vdev_mem_read(struct virt_dev *vdev, uint64_t addr, uint64_t *value, uint16_t size) +int syscon_vdev_mem_read(struct virt_dev *vdev, uint64_t addr, uint64_t *value) { + if(addr == fake_write_addr){ + *(uint32_t *)value = fake_write_value; + return 0; + } uint32_t read_value; read_value = sys_read32(addr); *(uint32_t *)value = read_value; - ZVM_LOG_INFO("Syscon-%s Read:addr is %llx, value is %x\n", vdev->name, addr, read_value); - return 0; } -static int syscon_vdev_mem_write(struct virt_dev *vdev, uint64_t addr, uint64_t *value, uint16_t size) +static void fake_write(uint64_t addr,uint64_t value) { - uint32_t be_write_value, write_value, af_write_value; + fake_write_addr = addr; + fake_write_value = value; + ZVM_LOG_INFO("###Invalid addr=%x,value=%x\n",addr,value); - write_value = *(uint32_t *)value; - be_write_value = sys_read32(addr); - sys_write32(write_value, addr); - af_write_value = sys_read32(addr); + return; +} - ZVM_LOG_INFO("Syscon-%s Write:addr is %llx, be_value is %x, ne_value is %x, af_value is %x\n", - vdev->name, addr, be_write_value, write_value, af_write_value); +int syscon_vdev_mem_write(struct virt_dev *vdev, uint64_t addr, uint64_t *value) +{ + uint32_t be_write_value, write_value, af_write_value; + enum vm_type vm_type_id; + + /* Get the virtual machine type */ + vm_type_id = get_vm_type(vdev->vm->vm_name); + + /* Switch to handle different types of virtual machines */ + switch (vm_type_id) { + case VM_TYPE_ZEPHYR: + write_value = *(uint32_t *)value; + be_write_value = sys_read32(addr); + sys_write32(write_value, addr); + af_write_value = sys_read32(addr); + break; + + case VM_TYPE_LINUX: + for (int i = 0; i < ARRAY_SIZE(zephyr_syscon_space); i++) { + if (addr == zephyr_syscon_space[i]) { + fake_write(addr, value); + return 0; + } + } + write_value = *(uint32_t *)value; + be_write_value = sys_read32(addr); + sys_write32(write_value, addr); + af_write_value = sys_read32(addr); + break; + + default: + /* Handle unknown virtual machine type */ + return -1; + } return 0; } -- Gitee