RE: [PATCH V5 1/3] net/filter: Optimize transfer protocol for filter-mirror/redirector
> -Original Message- > From: Jason Wang > Sent: Monday, November 1, 2021 11:46 AM > To: Zhang, Chen > Cc: qemu-dev ; Markus Armbruster > ; Li Zhijian > Subject: Re: [PATCH V5 1/3] net/filter: Optimize transfer protocol for filter- > mirror/redirector > > On Fri, Oct 29, 2021 at 4:08 PM Zhang, Chen wrote: > > > > > > > > > -Original Message- > > > From: Jason Wang > > > Sent: Friday, October 29, 2021 11:11 AM > > > To: Zhang, Chen > > > Cc: qemu-dev ; Markus Armbruster > > > ; Li Zhijian > > > Subject: Re: [PATCH V5 1/3] net/filter: Optimize transfer protocol > > > for filter- mirror/redirector > > > > > > > > > 在 2021/10/28 下午5:05, Zhang Chen 写道: > > > > Make the vnet header a necessary part of filter transfer protocol. > > > > It make other modules(like another > > > > filter-redirector,colo-compare...) > > > > know how to parse net packet correctly. If local device is not the > > > > virtio-net-pci, vnet_hdr_len will be 0. > > > > > > > > Signed-off-by: Zhang Chen > > > > --- > > > > net/filter-mirror.c | 34 -- > > > > 1 file changed, 16 insertions(+), 18 deletions(-) > > > > > > > > diff --git a/net/filter-mirror.c b/net/filter-mirror.c index > > > > f20240cc9f..24d3e498e9 100644 > > > > --- a/net/filter-mirror.c > > > > +++ b/net/filter-mirror.c > > > > @@ -39,6 +39,7 @@ struct MirrorState { > > > > CharBackend chr_in; > > > > CharBackend chr_out; > > > > SocketReadState rs; > > > > +/* Keep compatibility for the management layer */ > > > > bool vnet_hdr; > > > > }; > > > > > > > > @@ -48,7 +49,7 @@ static int filter_send(MirrorState *s, > > > > { > > > > NetFilterState *nf = NETFILTER(s); > > > > int ret = 0; > > > > -ssize_t size = 0; > > > > +ssize_t size = 0, vnet_hdr_len = 0; > > > > uint32_t len = 0; > > > > char *buf; > > > > > > > > @@ -63,21 +64,18 @@ static int filter_send(MirrorState *s, > > > > goto err; > > > > } > > > > > > > > -if (s->vnet_hdr) { > > > > -/* > > > > - * If vnet_hdr = on, we send vnet header len to make other > > > > - * module(like colo-compare) know how to parse net > > > > - * packet correctly. > > > > - */ > > > > -ssize_t vnet_hdr_len; > > > > - > > > > -vnet_hdr_len = nf->netdev->vnet_hdr_len; > > > > +/* > > > > + * The vnet header is the necessary part of filter transfer > > > > protocol. > > > > + * It make other module(like colo-compare) know how to parse net > > > > + * packet correctly. If device is not the virtio-net-pci, > > > > + * vnet_hdr_len will be 0. > > > > + */ > > > > +vnet_hdr_len = nf->netdev->vnet_hdr_len; > > > > > > > > -len = htonl(vnet_hdr_len); > > > > -ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, > > > sizeof(len)); > > > > -if (ret != sizeof(len)) { > > > > -goto err; > > > > -} > > > > +len = htonl(vnet_hdr_len); > > > > +ret = qemu_chr_fe_write_all(&s->chr_out, (uint8_t *)&len, > > > > + sizeof(len)); > > > > > > > > > I wonder if we need to introduce new parameter, e.g force_vnet_hdr > > > here, then we can always send vnet_hdr when it is enabled. > > > > > > Otherwise the "vnet_hdr_support" seems meaningless. > > > > Yes, Current "vnet_hdr_support" default enabled, and vnet_hdr_len > already forced from attached nf->netdev. > > Maybe we can introduce a new parameter "force_no_vnet_hdr" here to > make the vnet_hdr_len always keep 0. > > If you think OK, I will update it in next version. > > Let me explain, if I was not wrong: > > "vnet_hdr_support" means whether or not to send vnet header length. If > vnet_hdr_support=false, we won't send the vnet header. This looks the > same as you "force_no_vent_hdr" above. Yes, It was. But this series changed it. Current "vnet_hdr_support" can't decide whether send vnet header length, we always send it even 0. It will avoid sender/receiver transfer protocol parse issues: When sender data with the vnet header length, but receiver can't enable the "vnet_hdr_support". Filters will auto setup vnet_hdr_len as local nf->netdev and found the issue when get different vnet_hdr_len from other filters. > > And my "force_vnet_hdr" seems duplicated with vnet_hdr_support=true. > So it looks to me we can leave the mirror code as is and just change the > compare? (depends on the mgmt to set a correct vnet_hdr_support) OK, I will keep the filter-mirror/filter-redirector/filter-rewriter same as this version. For the colo-compare module, It will get primary node's filter data's vnet_hdr_len as the local value, And compare with secondary node's, because it is not attached any nf->netdev. So, it looks compare module's "vnet_hdr_support" been auto configuration from the filter transport protocol. If the "force_vnet_hdr" means hard code a compare's local vnet_hdr_len rather than come from input filter's data? Tha
[PATCH v3 2/5] monitor: Support 'info numa' command
Add the MEMORY_DEVICE_INFO_KIND_SGX_EPC case for SGX numa info with 'info numa' command in the monitor. Signed-off-by: Yang Zhong --- hw/core/numa.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/hw/core/numa.c b/hw/core/numa.c index 510d096a88..1aa05dcf42 100644 --- a/hw/core/numa.c +++ b/hw/core/numa.c @@ -756,6 +756,7 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[]) PCDIMMDeviceInfo *pcdimm_info; VirtioPMEMDeviceInfo *vpi; VirtioMEMDeviceInfo *vmi; +SgxEPCDeviceInfo *se; for (info = info_list; info; info = info->next) { MemoryDeviceInfo *value = info->value; @@ -781,6 +782,11 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[]) node_mem[vmi->node].node_mem += vmi->size; node_mem[vmi->node].node_plugged_mem += vmi->size; break; +case MEMORY_DEVICE_INFO_KIND_SGX_EPC: +se = value->u.sgx_epc.data; +node_mem[se->node].node_mem += se->size; +node_mem[se->node].node_plugged_mem = 0; +break; default: g_assert_not_reached(); }
[PATCH v3 0/5] SGX NUMA support plus vepc reset
The basic SGX patches were merged into Qemu release, the left NUMA function for SGX should be enabled. The patch1 implemented the SGX NUMA ACPI to enable NUMA in the SGX guest. Since Libvirt need detailed host SGX EPC sections info to decide how to allocate EPC sections for SGX NUMA guest, the SGXEPCSection list is introduced to show detailed sections info in the monitor or HMP interface. This version also plus the vEPC reset support because the related kernel patches were merged into tip tree master branch, please ref below link: https://lore.kernel.org/all/20211021201155.1523989-1-pbonz...@redhat.com/ or the tip tree master branch. Thanks! Yang Changes from V2: - Updated the reset patch(patch 5), reduced to 2 pass.(Paolo) Changes from V1: - added documents for new members.(Eric) - changed the "index" to "node" in struct SGXEPCSection.(Eric, Paolo) - squashed the previous patch 4 and patch 5 into patch 3.(Paolo) - added reset patch(patch 5) into this version. Yang Zhong (5): numa: Enable numa for SGX EPC sections monitor: Support 'info numa' command numa: Support SGX numa in the monitor and Libvirt interfaces doc: Add the SGX numa description sgx: Reset the vEPC regions during VM reboot docs/system/i386/sgx.rst | 31 +++-- qapi/machine.json | 10 ++- qapi/misc-target.json | 19 +- include/hw/i386/sgx-epc.h | 3 + include/hw/i386/x86.h | 1 + linux-headers/linux/kvm.h | 6 ++ hw/core/numa.c| 6 ++ hw/i386/acpi-build.c | 4 ++ hw/i386/sgx-epc.c | 3 + hw/i386/sgx.c | 137 +++--- hw/i386/x86.c | 4 ++ monitor/hmp-cmds.c| 1 + qemu-options.hx | 4 +- 13 files changed, 211 insertions(+), 18 deletions(-)
[PATCH v3 1/5] numa: Enable numa for SGX EPC sections
The basic SGX did not enable numa for SGX EPC sections, which result in all EPC sections located in numa node 0. This patch enable SGX numa function in the guest and the EPC section can work with RAM as one numa node. The Guest kernel related log: [0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x18000-0x183ff] [0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x18400-0x185bf] The SRAT table can normally show SGX EPC sections menory info in different numa nodes. The SGX EPC numa related command: .. -m 4G,maxmem=20G \ -smp sockets=2,cores=2 \ -cpu host,+sgx-provisionkey \ -object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \ -object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \ -numa node,nodeid=0,cpus=0-1,memdev=node0 \ -object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \ -object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \ -numa node,nodeid=1,cpus=2-3,memdev=node1 \ -M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1 \ .. Signed-off-by: Yang Zhong --- qapi/machine.json | 10 - include/hw/i386/sgx-epc.h | 3 +++ hw/i386/acpi-build.c | 4 hw/i386/sgx-epc.c | 3 +++ hw/i386/sgx.c | 44 +++ monitor/hmp-cmds.c| 1 + qemu-options.hx | 4 ++-- 7 files changed, 66 insertions(+), 3 deletions(-) diff --git a/qapi/machine.json b/qapi/machine.json index 5db54df298..38a1e3438f 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1207,12 +1207,15 @@ # # @memdev: memory backend linked with device # +# @node: the numa node +# # Since: 6.2 ## { 'struct': 'SgxEPCDeviceInfo', 'data': { '*id': 'str', 'memaddr': 'size', 'size': 'size', +'node': 'int', 'memdev': 'str' } } @@ -1285,10 +1288,15 @@ # # @memdev: memory backend linked with device # +# @node: the numa node +# # Since: 6.2 ## { 'struct': 'SgxEPC', - 'data': { 'memdev': 'str' } } + 'data': { 'memdev': 'str', +'node': 'int' + } +} ## # @SgxEPCProperties: diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h index a6a65be854..581fac389a 100644 --- a/include/hw/i386/sgx-epc.h +++ b/include/hw/i386/sgx-epc.h @@ -25,6 +25,7 @@ #define SGX_EPC_ADDR_PROP "addr" #define SGX_EPC_SIZE_PROP "size" #define SGX_EPC_MEMDEV_PROP "memdev" +#define SGX_EPC_NUMA_NODE_PROP "node" /** * SGXEPCDevice: @@ -38,6 +39,7 @@ typedef struct SGXEPCDevice { /* public */ uint64_t addr; +uint32_t node; HostMemoryBackendEpc *hostmem; } SGXEPCDevice; @@ -56,6 +58,7 @@ typedef struct SGXEPCState { } SGXEPCState; bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size); +void sgx_epc_build_srat(GArray *table_data); static inline uint64_t sgx_epc_above_4g_end(SGXEPCState *sgx_epc) { diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 81418b7911..563a38992f 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2062,6 +2062,10 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) nvdimm_build_srat(table_data); } +if (pcms->sgx_epc.size != 0) { +sgx_epc_build_srat(table_data); +} + /* * TODO: this part is not in ACPI spec and current linux kernel boots fine * without these entries. But I recall there were issues the last time I diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c index 55e2217eae..e5cd2789be 100644 --- a/hw/i386/sgx-epc.c +++ b/hw/i386/sgx-epc.c @@ -21,6 +21,7 @@ static Property sgx_epc_properties[] = { DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0), +DEFINE_PROP_UINT32(SGX_EPC_NUMA_NODE_PROP, SGXEPCDevice, node, 0), DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem, TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *), DEFINE_PROP_END_OF_LIST(), @@ -139,6 +140,8 @@ static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md, se->memaddr = epc->addr; se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP, NULL); +se->node = object_property_get_uint(OBJECT(epc), SGX_EPC_NUMA_NODE_PROP, +NULL); se->memdev = object_get_canonical_path(OBJECT(epc->hostmem)); info->u.sgx_epc.data = se; diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index 11607568b6..9a77519609 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -21,6 +21,7 @@ #include "qapi/qapi-commands-misc-target.h" #include "exec/address-spaces.h" #include "sysemu/hw_accel.h" +#include "hw/acpi/aml-build.h" #define SGX_MAX_EPC_SECTIONS8 #define SGX_CPUID_EPC_INVALID 0x0 @@ -29,6 +30,46 @@ #define SGX_CPUID_EPC_SECTION 0x1 #define SGX_CPUID_EPC_MASK 0xF +static int sgx_epc_devic
[PATCH v3 3/5] numa: Support SGX numa in the monitor and Libvirt interfaces
Add the SGXEPCSection list into SGXInfo to show the multiple SGX EPC sections detailed info, not the total size like before. This patch can enable numa support for 'info sgx' command and QMP interfaces. The new interfaces show each EPC section info in one numa node. Libvirt can use QMP interface to get the detailed host SGX EPC capabilities to decide how to allocate host EPC sections to guest. (qemu) info sgx SGX support: enabled SGX1 support: enabled SGX2 support: enabled FLC support: enabled NUMA node #0: size=67108864 NUMA node #1: size=29360128 The QMP interface show: (QEMU) query-sgx {"return": {"sgx": true, "sgx2": true, "sgx1": true, "sections": \ [{"node": 0, "size": 67108864}, {"node": 1, "size": 29360128}], "flc": true}} (QEMU) query-sgx-capabilities {"return": {"sgx": true, "sgx2": true, "sgx1": true, "sections": \ [{"node": 0, "size": 17070817280}, {"node": 1, "size": 17079205888}], "flc": true}} Signed-off-by: Yang Zhong --- qapi/misc-target.json | 19 ++-- hw/i386/sgx.c | 51 +++ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/qapi/misc-target.json b/qapi/misc-target.json index 5aa2b95b7d..1022aa0184 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -337,6 +337,21 @@ 'if': 'TARGET_ARM' } +## +# @SGXEPCSection: +# +# Information about intel SGX EPC section info +# +# @node: the numa node +# +# @size: the size of epc section +# +# Since: 6.2 +## +{ 'struct': 'SGXEPCSection', + 'data': { 'node': 'int', +'size': 'uint64'}} + ## # @SGXInfo: # @@ -350,7 +365,7 @@ # # @flc: true if FLC is supported # -# @section-size: The EPC section size for guest +# @sections: The EPC sections info for guest # # Since: 6.2 ## @@ -359,7 +374,7 @@ 'sgx1': 'bool', 'sgx2': 'bool', 'flc': 'bool', -'section-size': 'uint64'}, +'sections': ['SGXEPCSection']}, 'if': 'TARGET_I386' } ## diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index 9a77519609..b5b710a556 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -76,11 +76,13 @@ static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high) ((high & MAKE_64BIT_MASK(0, 20)) << 32); } -static uint64_t sgx_calc_host_epc_section_size(void) +static SGXEPCSectionList *sgx_calc_host_epc_sections(void) { +SGXEPCSectionList *head = NULL, **tail = &head; +SGXEPCSection *section; uint32_t i, type; uint32_t eax, ebx, ecx, edx; -uint64_t size = 0; +uint32_t j = 0; for (i = 0; i < SGX_MAX_EPC_SECTIONS; i++) { host_cpuid(0x12, i + 2, &eax, &ebx, &ecx, &edx); @@ -94,10 +96,13 @@ static uint64_t sgx_calc_host_epc_section_size(void) break; } -size += sgx_calc_section_metric(ecx, edx); +section = g_new0(SGXEPCSection, 1); +section->node = j++; +section->size = sgx_calc_section_metric(ecx, edx); +QAPI_LIST_APPEND(tail, section); } -return size; +return head; } SGXInfo *qmp_query_sgx_capabilities(Error **errp) @@ -121,13 +126,35 @@ SGXInfo *qmp_query_sgx_capabilities(Error **errp) info->sgx1 = eax & (1U << 0) ? true : false; info->sgx2 = eax & (1U << 1) ? true : false; -info->section_size = sgx_calc_host_epc_section_size(); +info->sections = sgx_calc_host_epc_sections(); close(fd); return info; } +static SGXEPCSectionList *sgx_get_epc_sections_list(void) +{ +GSList *device_list = sgx_epc_get_device_list(); +SGXEPCSectionList *head = NULL, **tail = &head; +SGXEPCSection *section; + +for (; device_list; device_list = device_list->next) { +DeviceState *dev = device_list->data; +Object *obj = OBJECT(dev); + +section = g_new0(SGXEPCSection, 1); +section->node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP, + &error_abort); +section->size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP, + &error_abort); +QAPI_LIST_APPEND(tail, section); +} +g_slist_free(device_list); + +return head; +} + SGXInfo *qmp_query_sgx(Error **errp) { SGXInfo *info = NULL; @@ -146,14 +173,13 @@ SGXInfo *qmp_query_sgx(Error **errp) return NULL; } -SGXEPCState *sgx_epc = &pcms->sgx_epc; info = g_new0(SGXInfo, 1); info->sgx = true; info->sgx1 = true; info->sgx2 = true; info->flc = true; -info->section_size = sgx_epc->size; +info->sections = sgx_get_epc_sections_list(); return info; } @@ -161,6 +187,7 @@ SGXInfo *qmp_query_sgx(Error **errp) void hmp_info_sgx(Monitor *mon, const QDict *qdict) { Error *err = NULL; +SGXEPCSectionList *section_list, *section; g_autoptr(SGXInfo) info = qmp_query_sgx(&err); if (err) { @@ -175,8 +202,14 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict)
[PATCH v3 4/5] doc: Add the SGX numa description
Add the SGX numa reference command and how to check if SGX numa is support or not with multiple EPC sections. Signed-off-by: Yang Zhong --- docs/system/i386/sgx.rst | 31 +++ 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/system/i386/sgx.rst b/docs/system/i386/sgx.rst index f103ae2a2f..9e4ada761f 100644 --- a/docs/system/i386/sgx.rst +++ b/docs/system/i386/sgx.rst @@ -141,8 +141,7 @@ To launch a SGX guest: |qemu_system_x86| \\ -cpu host,+sgx-provisionkey \\ -object memory-backend-epc,id=mem1,size=64M,prealloc=on \\ - -object memory-backend-epc,id=mem2,size=28M \\ - -M sgx-epc.0.memdev=mem1,sgx-epc.1.memdev=mem2 + -M sgx-epc.0.memdev=mem1,sgx-epc.0.node=0 Utilizing SGX in the guest requires a kernel/OS with SGX support. The support can be determined in guest by:: @@ -152,8 +151,32 @@ The support can be determined in guest by:: and SGX epc info by:: $ dmesg | grep sgx - [1.242142] sgx: EPC section 0x18000-0x181bf - [1.242319] sgx: EPC section 0x181c0-0x1837f + [0.182807] sgx: EPC section 0x14000-0x143ff + [0.183695] sgx: [Firmware Bug]: Unable to map EPC section to online node. Fallback to the NUMA node 0. + +To launch a SGX numa guest: + +.. parsed-literal:: + + |qemu_system_x86| \\ + -cpu host,+sgx-provisionkey \\ + -object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \\ + -object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \\ + -numa node,nodeid=0,cpus=0-1,memdev=node0 \\ + -object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \\ + -object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \\ + -numa node,nodeid=1,cpus=2-3,memdev=node1 \\ + -M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1 + +and SGX epc numa info by:: + + $ dmesg | grep sgx + [0.369937] sgx: EPC section 0x18000-0x183ff + [0.370259] sgx: EPC section 0x18400-0x185bf + + $ dmesg | grep SRAT + [0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x18000-0x183ff] + [0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x18400-0x185bf] References --
[PATCH v3 5/5] sgx: Reset the vEPC regions during VM reboot
For bare-metal SGX on real hardware, the hardware provides guarantees SGX state at reboot. For instance, all pages start out uninitialized. The vepc driver provides a similar guarantee today for freshly-opened vepc instances, but guests such as Windows expect all pages to be in uninitialized state on startup, including after every guest reboot. Qemu can invoke the ioctl to bring its vEPC pages back to uninitialized state. There is a possibility that some pages fail to be removed if they are SECS pages, and the child and SECS pages could be in separate vEPC regions. Therefore, the ioctl returns the number of EREMOVE failures, telling Qemu to try the ioctl again after it's done with all vEPC regions. The related kernel patches: Link: https://lkml.kernel.org/r/20211021201155.1523989-3-pbonz...@redhat.com Signed-off-by: Yang Zhong --- include/hw/i386/x86.h | 1 + linux-headers/linux/kvm.h | 6 ++ hw/i386/sgx.c | 42 +++ hw/i386/x86.c | 4 4 files changed, 53 insertions(+) diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 23267a3674..e78ca6c156 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -141,5 +141,6 @@ qemu_irq x86_allocate_cpu_irq(void); void gsi_handler(void *opaque, int n, int level); void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); DeviceState *ioapic_init_secondary(GSIState *gsi_state); +void sgx_epc_reset(void *opaque); #endif diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index bcaf66cc4d..ee110e660b 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -887,6 +887,12 @@ struct kvm_ppc_resize_hpt { #define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) #define KVM_GET_MSR_FEATURE_INDEX_LIST_IOWR(KVMIO, 0x0a, struct kvm_msr_list) +/* + * ioctl for /dev/sgx_vepc + */ +#define SGX_MAGIC 0xA4 +#define SGX_IOC_VEPC_REMOVE_ALL _IO(SGX_MAGIC, 0x04) + /* * Extension capability list. */ diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index b5b710a556..640bd4198f 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -22,6 +22,8 @@ #include "exec/address-spaces.h" #include "sysemu/hw_accel.h" #include "hw/acpi/aml-build.h" +#include "hw/i386/x86.h" +#include #define SGX_MAX_EPC_SECTIONS8 #define SGX_CPUID_EPC_INVALID 0x0 @@ -29,6 +31,7 @@ /* A valid EPC section. */ #define SGX_CPUID_EPC_SECTION 0x1 #define SGX_CPUID_EPC_MASK 0xF +#define RETRY_NUM 2 static int sgx_epc_device_list(Object *obj, void *opaque) { @@ -70,6 +73,45 @@ void sgx_epc_build_srat(GArray *table_data) g_slist_free(device_list); } +void sgx_epc_reset(void *opaque) +{ +PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); +HostMemoryBackend *hostmem; +SGXEPCDevice *epc; +int failures; +int fd, i, j, r; + +/* + * The second pass is needed to remove SECS pages that could not + * be removed during the first. + */ +for (i = 0; i < RETRY_NUM; i++) { +failures = 0; +for (j = 0; j < pcms->sgx_epc.nr_sections; j++) { +epc = pcms->sgx_epc.sections[j]; +hostmem = MEMORY_BACKEND(epc->hostmem); +fd = memory_region_get_fd(host_memory_backend_get_memory(hostmem)); + +r = ioctl(fd, SGX_IOC_VEPC_REMOVE_ALL); +if (r < 0) { +if (r == -ENOTTY) { +error_report("use the error ioctl number"); +break; +} +} else if (r > 0) { +/* SECS pages remain */ +failures++; +if (i == 1) { +error_report("cannot reset vEPC section %d", j); +} +} +} +if (!failures) { +break; +} + } +} + static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high) { return (low & MAKE_64BIT_MASK(12, 20)) + diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 76de7e2265..03d30a487a 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -39,6 +39,7 @@ #include "sysemu/replay.h" #include "sysemu/sysemu.h" #include "sysemu/cpu-timers.h" +#include "sysemu/reset.h" #include "trace.h" #include "hw/i386/x86.h" @@ -1307,6 +1308,9 @@ static void machine_set_sgx_epc(Object *obj, Visitor *v, const char *name, visit_type_SgxEPCList(v, name, &x86ms->sgx_epc_list, errp); qapi_free_SgxEPCList(list); + +/* register the reset callback for sgx reset */ +qemu_register_reset(sgx_epc_reset, NULL); } static void x86_machine_initfn(Object *obj)
Re: [PATCH v4 07/22] target/riscv: Add defines for AIA CSRs
On Mon, Nov 1, 2021 at 12:26 PM Alistair Francis wrote: > > On Tue, Oct 26, 2021 at 5:01 PM Anup Patel wrote: > > > > The RISC-V AIA specification extends RISC-V local interrupts and > > introduces new CSRs. This patch adds defines for the new AIA CSRs. > > > > Signed-off-by: Anup Patel > > What's the status of these CSR addresses being finalised? These CSR addresses have not changed since the past 2 months. Overall, the AIA spec has been in stable state for quite some time without much changes or objections. Regards, Anup > > Alistair
Re: [PATCH v3 2/4] qemu-img: make --block-size optional for compare --stat
29.10.2021 23:32, Eric Blake wrote: On Thu, Oct 28, 2021 at 12:24:39PM +0200, Vladimir Sementsov-Ogievskiy wrote: Let's detect block-size automatically if not specified by user: If both files define cluster-size, use minimum to be more precise. If both files don't specify cluster-size, use default of 64K If only one file specify cluster-size, just use it. Signed-off-by: Vladimir Sementsov-Ogievskiy --- docs/tools/qemu-img.rst | 7 +++- qemu-img.c | 71 + qemu-img-cmds.hx| 4 +-- 3 files changed, 72 insertions(+), 10 deletions(-) Reviewed-by: Eric Blake +if (cluster_size1 > 0 && cluster_size2 > 0) { +if (cluster_size1 == cluster_size2) { +block_size = cluster_size1; +} else { +block_size = MIN(cluster_size1, cluster_size2); +qprintf(quiet, "%s and %s have different cluster sizes: %d and %d " +"respectively. Using minimum as block-size for " +"accuracy: %d. %s\n", +fname1, fname2, cluster_size1, +cluster_size2, block_size, note); Results in a long line; I don't know if it's worth trying to wrap it (if we had a generic utility function that took arbitrary text, then outputs it wrapped to the user's current terminal column width, I'd suggest using that instead - but that's NOT something I expect you to write, and I don't know if glib has such a utility). Hmm. But long lines printed to the terminal are wrapped by terminal automatically, so we don't need to wrap to terminal width by hand.. -- Best regards, Vladimir
[PATCH v2 2/7] Fixed qemu crash when guest power off in COLO mode
From: "Rao, Lei" This patch fixes the following: qemu-system-x86_64: invalid runstate transition: 'shutdown' -> 'running' Aborted (core dumped) The gdb bt as following: 0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 1 0x7faa3d613859 in __GI_abort () at abort.c:79 2 0x55c5a21268fd in runstate_set (new_state=RUN_STATE_RUNNING) at vl.c:723 3 0x55c5a1f8cae4 in vm_prepare_start () at /home/workspace/colo-qemu/cpus.c:2206 4 0x55c5a1f8cb1b in vm_start () at /home/workspace/colo-qemu/cpus.c:2213 5 0x55c5a2332bba in migration_iteration_finish (s=0x55c5a4658810) at migration/migration.c:3376 6 0x55c5a2332f3b in migration_thread (opaque=0x55c5a4658810) at migration/migration.c:3527 7 0x55c5a251d68a in qemu_thread_start (args=0x55c5a5491a70) at util/qemu-thread-posix.c:519 8 0x7faa3d7e9609 in start_thread (arg=) at pthread_create.c:477 9 0x7faa3d710293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 Signed-off-by: Lei Rao --- migration/migration.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/migration/migration.c b/migration/migration.c index 9172686b89..e5b38a492f 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -3616,7 +3616,9 @@ static void migration_iteration_finish(MigrationState *s) case MIGRATION_STATUS_CANCELLED: case MIGRATION_STATUS_CANCELLING: if (s->vm_was_running) { -vm_start(); +if (!runstate_check(RUN_STATE_SHUTDOWN)) { +vm_start(); +} } else { if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { runstate_set(RUN_STATE_POSTMIGRATE); -- 2.30.2
[PATCH v2 1/7] Some minor optimizations for COLO
From: "Rao, Lei" Signed-off-by: Lei Rao Reviewed-by: Dr. David Alan Gilbert --- migration/colo.c | 2 +- net/colo-compare.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/colo.c b/migration/colo.c index 79fa1f6619..616dc00af7 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -152,7 +152,7 @@ static void primary_vm_do_failover(void) * kick COLO thread which might wait at * qemu_sem_wait(&s->colo_checkpoint_sem). */ -colo_checkpoint_notify(migrate_get_current()); +colo_checkpoint_notify(s); /* * Wake up COLO thread which may blocked in recv() or send(), diff --git a/net/colo-compare.c b/net/colo-compare.c index b100e7b51f..4a64a5d386 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -170,7 +170,7 @@ static bool packet_matches_str(const char *str, return false; } -return !memcmp(str, buf, strlen(str)); +return !memcmp(str, buf, packet_len); } static void notify_remote_frame(CompareState *s) -- 2.30.2
[PATCH v2 0/7] Fixed some bugs and optimized some codes for COLO
Changes since v1: --Move the s->rp_state.from_dst_file = NULL behind qemu_close(). The series of patches include: Fixed some bugs of qemu crash and segment fault. Optimized the function of fill_connection_key. Remove some unnecessary code to improve COLO. Rao, Lei (7): Some minor optimizations for COLO Fixed qemu crash when guest power off in COLO mode Fixed SVM hang when do failover before PVM crash colo: fixed 'Segmentation fault' when the simplex mode PVM poweroff Removed the qemu_fclose() in colo_process_incoming_thread Changed the last-mode to none of first start COLO Optimized the function of fill_connection_key. migration/colo.c | 16 +--- migration/migration.c | 6 +- net/colo-compare.c| 4 ++-- net/colo.c| 31 --- net/colo.h| 6 +++--- net/filter-rewriter.c | 10 +- 6 files changed, 28 insertions(+), 45 deletions(-) -- 2.30.2
[PATCH v2 4/7] colo: fixed 'Segmentation fault' when the simplex mode PVM poweroff
From: "Rao, Lei" The GDB statck is as follows: Program terminated with signal SIGSEGV, Segmentation fault. 0 object_class_dynamic_cast (class=0x55c8f5d2bf50, typename=0x55c8f2f7379e "qio-channel") at qom/object.c:832 if (type->class->interfaces && [Current thread is 1 (Thread 0x7f756e97eb00 (LWP 1811577))] (gdb) bt 0 object_class_dynamic_cast (class=0x55c8f5d2bf50, typename=0x55c8f2f7379e "qio-channel") at qom/object.c:832 1 0x55c8f2c3dd14 in object_dynamic_cast (obj=0x55c8f543ac00, typename=0x55c8f2f7379e "qio-channel") at qom/object.c:763 2 0x55c8f2c3ddce in object_dynamic_cast_assert (obj=0x55c8f543ac00, typename=0x55c8f2f7379e "qio-channel", file=0x55c8f2f73780 "migration/qemu-file-channel.c", line=117, func=0x55c8f2f73800 <__func__.18724> "channel_shutdown") at qom/object.c:786 3 0x55c8f2bbc6ac in channel_shutdown (opaque=0x55c8f543ac00, rd=true, wr=true, errp=0x0) at migration/qemu-file-channel.c:117 4 0x55c8f2bba56e in qemu_file_shutdown (f=0x7f7558070f50) at migration/qemu-file.c:67 5 0x55c8f2ba5373 in migrate_fd_cancel (s=0x55c8f4ccf3f0) at migration/migration.c:1699 6 0x55c8f2ba1992 in migration_shutdown () at migration/migration.c:187 7 0x55c8f29a5b77 in main (argc=69, argv=0x7fff3e9e8c08, envp=0x7fff3e9e8e38) at vl.c:4512 The root cause is that we still want to shutdown the from_dst_file in migrate_fd_cancel() after qemu_close in colo_process_checkpoint(). So, we should set the s->rp_state.from_dst_file = NULL after qemu_close(). Signed-off-by: Lei Rao --- migration/colo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/migration/colo.c b/migration/colo.c index 616dc00af7..907241ab5c 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -640,6 +640,7 @@ out: */ if (s->rp_state.from_dst_file) { qemu_fclose(s->rp_state.from_dst_file); +s->rp_state.from_dst_file = NULL; } } -- 2.30.2
[PATCH v2 5/7] Removed the qemu_fclose() in colo_process_incoming_thread
From: "Rao, Lei" After the live migration, the related fd will be cleanup in migration_incoming_state_destroy(). So, the qemu_close() in colo_process_incoming_thread is not necessary. Signed-off-by: Lei Rao --- migration/colo.c | 5 - 1 file changed, 5 deletions(-) diff --git a/migration/colo.c b/migration/colo.c index 907241ab5c..71fc82a040 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -919,11 +919,6 @@ out: /* Hope this not to be too long to loop here */ qemu_sem_wait(&mis->colo_incoming_sem); qemu_sem_destroy(&mis->colo_incoming_sem); -/* Must be called after failover BH is completed */ -if (mis->to_src_file) { -qemu_fclose(mis->to_src_file); -mis->to_src_file = NULL; -} rcu_unregister_thread(); return NULL; -- 2.30.2
[PATCH v2 3/7] Fixed SVM hang when do failover before PVM crash
From: "Rao, Lei" This patch fixed as follows: Thread 1 (Thread 0x7f34ee738d80 (LWP 11212)): #0 __pthread_clockjoin_ex (threadid=139847152957184, thread_return=0x7f30b1febf30, clockid=, abstime=, block=) at pthread_join_common.c:145 #1 0x563401998e36 in qemu_thread_join (thread=0x563402d66610) at util/qemu-thread-posix.c:587 #2 0x5634017a79fa in process_incoming_migration_co (opaque=0x0) at migration/migration.c:502 #3 0x5634019b59c9 in coroutine_trampoline (i0=63395504, i1=22068) at util/coroutine-ucontext.c:115 #4 0x7f34ef860660 in ?? () at ../sysdeps/unix/sysv/linux/x86_64/__start_context.S:91 from /lib/x86_64-linux-gnu/libc.so.6 #5 0x7f30b21ee730 in ?? () #6 0x in ?? () Thread 13 (Thread 0x7f30b3dff700 (LWP 11747)): #0 __lll_lock_wait (futex=futex@entry=0x56340218ffa0 , private=0) at lowlevellock.c:52 #1 0x7f34efa000a3 in _GI__pthread_mutex_lock (mutex=0x56340218ffa0 ) at ../nptl/pthread_mutex_lock.c:80 #2 0x563401997f99 in qemu_mutex_lock_impl (mutex=0x56340218ffa0 , file=0x563401b7a80e "migration/colo.c", line=806) at util/qemu-thread-posix.c:78 #3 0x563401407144 in qemu_mutex_lock_iothread_impl (file=0x563401b7a80e "migration/colo.c", line=806) at /home/workspace/colo-qemu/cpus.c:1899 #4 0x5634017ba8e8 in colo_process_incoming_thread (opaque=0x563402d664c0) at migration/colo.c:806 #5 0x563401998b72 in qemu_thread_start (args=0x5634039f8370) at util/qemu-thread-posix.c:519 #6 0x7f34ef9fd609 in start_thread (arg=) at pthread_create.c:477 #7 0x7f34ef924293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 The QEMU main thread is holding the lock: (gdb) p qemu_global_mutex $1 = {lock = {_data = {lock = 2, __count = 0, __owner = 11212, __nusers = 9, __kind = 0, __spins = 0, __elision = 0, __list = {_prev = 0x0, __next = 0x0}}, __size = "\002\000\000\000\000\000\000\000\314+\000\000\t", '\000' , __align = 2}, file = 0x563401c07e4b "util/main-loop.c", line = 240, initialized = true} >From the call trace, we can see it is a deadlock bug. and the QEMU main thread >holds the global mutex to wait until the COLO thread ends. and the colo thread wants to acquire the global mutex, which will cause a deadlock. So, we should release the qemu_global_mutex before waiting colo thread ends. Signed-off-by: Lei Rao Reviewed-by: Li Zhijian --- migration/migration.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/migration/migration.c b/migration/migration.c index e5b38a492f..811097c423 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -587,8 +587,10 @@ static void process_incoming_migration_co(void *opaque) mis->have_colo_incoming_thread = true; qemu_coroutine_yield(); +qemu_mutex_unlock_iothread(); /* Wait checkpoint incoming thread exit before free resource */ qemu_thread_join(&mis->colo_incoming_thread); +qemu_mutex_lock_iothread(); /* We hold the global iothread lock, so it is safe here */ colo_release_ram_cache(); } -- 2.30.2
[PATCH v2 6/7] Changed the last-mode to none of first start COLO
From: "Rao, Lei" When we first stated the COLO, the last-mode is as follows: { "execute": "query-colo-status" } {"return": {"last-mode": "primary", "mode": "primary", "reason": "none"}} The last-mode is unreasonable. After the patch, will be changed to the following: { "execute": "query-colo-status" } {"return": {"last-mode": "none", "mode": "primary", "reason": "none"}} Signed-off-by: Lei Rao --- migration/colo.c | 8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/migration/colo.c b/migration/colo.c index 71fc82a040..e3b1f136f4 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -205,7 +205,7 @@ void colo_do_failover(void) vm_stop_force_state(RUN_STATE_COLO); } -switch (get_colo_mode()) { +switch (last_colo_mode = get_colo_mode()) { case COLO_MODE_PRIMARY: primary_vm_do_failover(); break; @@ -530,8 +530,7 @@ static void colo_process_checkpoint(MigrationState *s) Error *local_err = NULL; int ret; -last_colo_mode = get_colo_mode(); -if (last_colo_mode != COLO_MODE_PRIMARY) { +if (get_colo_mode() != COLO_MODE_PRIMARY) { error_report("COLO mode must be COLO_MODE_PRIMARY"); return; } @@ -830,8 +829,7 @@ void *colo_process_incoming_thread(void *opaque) migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_COLO); -last_colo_mode = get_colo_mode(); -if (last_colo_mode != COLO_MODE_SECONDARY) { +if (get_colo_mode() != COLO_MODE_SECONDARY) { error_report("COLO mode must be COLO_MODE_SECONDARY"); return NULL; } -- 2.30.2
[PATCH v2 7/7] Optimized the function of fill_connection_key.
From: "Rao, Lei" Remove some unnecessary code to improve the performance of the filter-rewriter module. Signed-off-by: Lei Rao Reviewed-by: Zhang Chen --- net/colo-compare.c| 2 +- net/colo.c| 31 --- net/colo.h| 6 +++--- net/filter-rewriter.c | 10 +- 4 files changed, 17 insertions(+), 32 deletions(-) diff --git a/net/colo-compare.c b/net/colo-compare.c index 4a64a5d386..6a1354dcb1 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -264,7 +264,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) pkt = NULL; return -1; } -fill_connection_key(pkt, &key); +fill_connection_key(pkt, &key, 0); conn = connection_get(s->connection_track_table, &key, diff --git a/net/colo.c b/net/colo.c index 3a3e6e89a0..5e7232ce47 100644 --- a/net/colo.c +++ b/net/colo.c @@ -83,19 +83,26 @@ int parse_packet_early(Packet *pkt) return 0; } -void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, Packet *pkt) +void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, + Packet *pkt, int reverse) { +if (reverse) { +key->src = pkt->ip->ip_dst; +key->dst = pkt->ip->ip_src; +key->src_port = ntohs(tmp_ports & 0x); +key->dst_port = ntohs(tmp_ports >> 16); +} else { key->src = pkt->ip->ip_src; key->dst = pkt->ip->ip_dst; key->src_port = ntohs(tmp_ports >> 16); key->dst_port = ntohs(tmp_ports & 0x); +} } -void fill_connection_key(Packet *pkt, ConnectionKey *key) +void fill_connection_key(Packet *pkt, ConnectionKey *key, int reverse) { -uint32_t tmp_ports; +uint32_t tmp_ports = 0; -memset(key, 0, sizeof(*key)); key->ip_proto = pkt->ip->ip_p; switch (key->ip_proto) { @@ -106,29 +113,15 @@ void fill_connection_key(Packet *pkt, ConnectionKey *key) case IPPROTO_SCTP: case IPPROTO_UDPLITE: tmp_ports = *(uint32_t *)(pkt->transport_header); -extract_ip_and_port(tmp_ports, key, pkt); break; case IPPROTO_AH: tmp_ports = *(uint32_t *)(pkt->transport_header + 4); -extract_ip_and_port(tmp_ports, key, pkt); break; default: break; } -} - -void reverse_connection_key(ConnectionKey *key) -{ -struct in_addr tmp_ip; -uint16_t tmp_port; - -tmp_ip = key->src; -key->src = key->dst; -key->dst = tmp_ip; -tmp_port = key->src_port; -key->src_port = key->dst_port; -key->dst_port = tmp_port; +extract_ip_and_port(tmp_ports, key, pkt, reverse); } Connection *connection_new(ConnectionKey *key) diff --git a/net/colo.h b/net/colo.h index d91cd245c4..5f4d502df3 100644 --- a/net/colo.h +++ b/net/colo.h @@ -89,9 +89,9 @@ typedef struct Connection { uint32_t connection_key_hash(const void *opaque); int connection_key_equal(const void *opaque1, const void *opaque2); int parse_packet_early(Packet *pkt); -void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, Packet *pkt); -void fill_connection_key(Packet *pkt, ConnectionKey *key); -void reverse_connection_key(ConnectionKey *key); +void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, + Packet *pkt, int reverse); +void fill_connection_key(Packet *pkt, ConnectionKey *key, int reverse); Connection *connection_new(ConnectionKey *key); void connection_destroy(void *opaque); Connection *connection_get(GHashTable *connection_track_table, diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c index cb3a96cde1..bf05023dc3 100644 --- a/net/filter-rewriter.c +++ b/net/filter-rewriter.c @@ -279,15 +279,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf, */ if (pkt && is_tcp_packet(pkt)) { -fill_connection_key(pkt, &key); - -if (sender == nf->netdev) { -/* - * We need make tcp TX and RX packet - * into one connection. - */ -reverse_connection_key(&key); -} +fill_connection_key(pkt, &key, sender == nf->netdev); /* After failover we needn't change new TCP packet */ if (s->failover_mode && -- 2.30.2
Re: [RFC PATCH v5 01/26] util: Make some iova_tree parameters const
On Sun, Oct 31, 2021 at 7:59 PM Juan Quintela wrote: > > Eugenio Pérez wrote: > > As qemu guidelines: > > Unless a pointer is used to modify the pointed-to storage, give it the > > "const" attribute. > > > > In the particular case of iova_tree_find it allows to enforce what is > > requested by its comment, since the compiler would shout in case of > > modifying or freeing the const-qualified returned pointer. > > > > Signed-off-by: Eugenio Pérez > > Acked-by: Peter Xu > > Reviewed-by: Philippe Mathieu-Daudé > > Reviewed-by: Juan Quintela > > This patch can go in already, whose tree should this go through? > Hi Juan, Sorry for being unclear, this patch has been already queued in Bonzini's tree [1]. I included it here because it is still not in the master branch. Thanks! [1] https://lists.nongnu.org/archive/html/qemu-devel/2021-10/msg03407.html > Later, Juan. >
Re: [PATCH v3 3/4] qemu-img: add --shallow option for qemu-img compare
29.10.2021 23:44, Eric Blake wrote: On Thu, Oct 28, 2021 at 12:24:40PM +0200, Vladimir Sementsov-Ogievskiy wrote: Allow compare only top images of backing chains. This is useful to Allow the comparison of only the top image of backing chains. compare images with same backing file or to compare incremental images from the chain of incremental backups with "--stat" option. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Hanna Reitz --- docs/tools/qemu-img.rst | 9 - qemu-img.c | 8 ++-- qemu-img-cmds.hx| 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index 9bfdd93d6c..c6e9306c70 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -176,6 +176,13 @@ Parameters to compare subcommand: - If both files don't specify cluster-size, use default of 64K - If only one file specifies cluster-size, just use that. +.. option:: --shallow + + This option prevents opening and comparing any backing files. + This is useful to compare images with same backing file or to compare + incremental images from the chain of incremental backups with + ``--stat`` option. If I understand correctly, your implementation makes --shallow an all-or-none option (either both images are compared shallow, or neither is). Does it make sense to make it a per-image option (--shallow-source, --shallow-dest), where --shallow is a synonym for the more verbose --shallow-source --shallow-dest? Usable, to compare incremental image with "everything below it". But I'm not sure about source/dest terms in context of compare, where image roles are symmetrical. I even start to thing, that it should be an option, used together with --image-opts, applied to image in person.. And actually we already have it, like --image-opts ... driver=qcow2,file.filename=file.qcow2,backing= At least this works with qemu-io. But prints warning: qemu-io: warning: Use of "backing": "" is deprecated; use "backing": null instead And of course, "null" doesn't work here. May be we should drop the warning, keeping backing= syntax at least for --image-opts of qemu utilities. Or, another way, support json for --image-opts. What do you think? driver=qcow2,file.filename=a.qcow2,backing= doesn't look better than --shallow. But if we want to make shallow option per-image, we can't ignore the fact that we already have a way to specify per-image options. -- Best regards, Vladimir
[PULL 0/6] Trivial branch for 6.2 patches
The following changes since commit af531756d25541a1b3b3d9a14e72e7fedd941a2e: Merge remote-tracking branch 'remotes/philmd/tags/renesas-20211030' into staging (2021-10-30 11:31:41 -0700) are available in the Git repository at: git://github.com/vivier/qemu.git tags/trivial-branch-for-6.2-pull-request for you to fetch changes up to c3f93230df9ad1d3260f03655faa8f9f23c90a52: hw/input/lasips2: QOM'ify the Lasi PS/2 (2021-10-31 21:05:40 +0100) Trivial patches branch pull request 20211101 Markus Armbruster (1): monitor: Trim some trailing space from human-readable output Philippe Mathieu-Daudé (4): MAINTAINERS: Split HPPA TCG vs HPPA machines/hardware hw/input/lasips2: Fix typos in function names hw/input/lasips2: Move LASIPS2State declaration to 'hw/input/lasips2.h' hw/input/lasips2: QOM'ify the Lasi PS/2 Yanan Wang (1): hw/core/machine: Add the missing delimiter in cpu_slot_to_string() MAINTAINERS| 5 ++- hw/core/machine.c | 3 ++ hw/hppa/lasi.c | 10 +- hw/input/lasips2.c | 64 +++--- include/hw/input/lasips2.h | 31 -- monitor/hmp-cmds.c | 2 +- target/i386/cpu-dump.c | 4 +-- target/i386/cpu.c | 2 +- target/ppc/cpu_init.c | 2 +- target/s390x/cpu_models.c | 4 +-- target/xtensa/mmu_helper.c | 2 +- 11 files changed, 83 insertions(+), 46 deletions(-) -- 2.31.1
[PULL 1/6] monitor: Trim some trailing space from human-readable output
From: Markus Armbruster I noticed -cpu help printing enough trailing spaces to make the output at least 84 characters wide. Looks ugly unless the terminal is wider. Ugly or not, trailing spaces are stupid. The culprit is this line in x86_cpu_list_entry(): qemu_printf("x86 %-20s %-58s\n", name, desc); This prints a string with minimum field left-justified right before a newline. Change it to qemu_printf("x86 %-20s %s\n", name, desc); which avoids the trailing spaces and is simpler to boot. A search for the pattern with "git-grep -E '%-[0-9]+s\\n'" found a few more instances. Change them similarly. Signed-off-by: Markus Armbruster Reviewed-by: Richard Henderson Acked-by: Greg Kurz Reviewed-by: Philippe Mathieu-Daudé Acked-by: Max Filippov Message-Id: <20211009152401.2982862-1-arm...@redhat.com> Signed-off-by: Laurent Vivier --- monitor/hmp-cmds.c | 2 +- target/i386/cpu-dump.c | 4 ++-- target/i386/cpu.c | 2 +- target/ppc/cpu_init.c | 2 +- target/s390x/cpu_models.c | 4 ++-- target/xtensa/mmu_helper.c | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index bcaa41350e9a..9e45a138a505 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1945,7 +1945,7 @@ void hmp_rocker_ports(Monitor *mon, const QDict *qdict) monitor_printf(mon, " port linkduplex neg?\n"); for (port = list; port; port = port->next) { -monitor_printf(mon, "%10s %-4s %-3s %2s %-3s\n", +monitor_printf(mon, "%10s %-4s %-3s %2s %s\n", port->value->name, port->value->enabled ? port->value->link_up ? "up" : "down" : "!ena", diff --git a/target/i386/cpu-dump.c b/target/i386/cpu-dump.c index 02b635a52cff..08ac957e99cf 100644 --- a/target/i386/cpu-dump.c +++ b/target/i386/cpu-dump.c @@ -464,13 +464,13 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags) snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); #ifdef TARGET_X86_64 if (env->hflags & HF_CS64_MASK) { -qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%-8s\n", +qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%s\n", env->cc_src, env->cc_dst, cc_op_name); } else #endif { -qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n", +qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%s\n", (uint32_t)env->cc_src, (uint32_t)env->cc_dst, cc_op_name); } diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 598d451dcf04..c5744ce08cf9 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4878,7 +4878,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) desc = g_strdup_printf("%s", model_id); } -qemu_printf("x86 %-20s %-58s\n", name, desc); +qemu_printf("x86 %-20s %s\n", name, desc); } /* list available CPU models and flags */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 65545ba9ca8d..ba384a592bc1 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -8734,7 +8734,7 @@ void ppc_cpu_list(void) #ifdef CONFIG_KVM qemu_printf("\n"); -qemu_printf("PowerPC %-16s\n", "host"); +qemu_printf("PowerPC %s\n", "host"); #endif } diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 4e4598cc774c..11e06cc51fab 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -398,14 +398,14 @@ void s390_cpu_list(void) for (feat = 0; feat < S390_FEAT_MAX; feat++) { const S390FeatDef *def = s390_feat_def(feat); -qemu_printf("%-20s %-50s\n", def->name, def->desc); +qemu_printf("%-20s %s\n", def->name, def->desc); } qemu_printf("\nRecognized feature groups:\n"); for (group = 0; group < S390_FEAT_GROUP_MAX; group++) { const S390FeatGroupDef *def = s390_feat_group_def(group); -qemu_printf("%-20s %-50s\n", def->name, def->desc); +qemu_printf("%-20s %s\n", def->name, def->desc); } } diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c index b01ff9399ae6..57e319a1af3a 100644 --- a/target/xtensa/mmu_helper.c +++ b/target/xtensa/mmu_helper.c @@ -1098,7 +1098,7 @@ static void dump_tlb(CPUXtensaState *env, bool dtlb) qemu_printf("\tVaddr Paddr ASID Attr RWX Cache\n" "\t-- -- --- ---\n"); } -qemu_printf("\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c %-7s\n", +qemu_printf("\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c %s\n", entry->vaddr, entry->paddr, entry->asid, -- 2.31.1
[PULL 5/6] hw/input/lasips2: Move LASIPS2State declaration to 'hw/input/lasips2.h'
From: Philippe Mathieu-Daudé We want to use the OBJECT_DECLARE_SIMPLE_TYPE() macro to QOM'ify this device in the next commit. To make its review simpler, as a first step move the LASIPS2State and LASIPS2Port declarations to 'hw/input/lasips2.h' Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Damien Hedde Message-Id: <20210920064048.2729397-3-f4...@amsat.org> Signed-off-by: Laurent Vivier --- hw/input/lasips2.c | 18 -- include/hw/input/lasips2.h | 18 ++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hw/input/lasips2.c b/hw/input/lasips2.c index 68d741d34215..0f8362f17bc1 100644 --- a/hw/input/lasips2.c +++ b/hw/input/lasips2.c @@ -33,24 +33,6 @@ #include "hw/irq.h" -struct LASIPS2State; -typedef struct LASIPS2Port { -struct LASIPS2State *parent; -MemoryRegion reg; -void *dev; -uint8_t id; -uint8_t control; -uint8_t buf; -bool loopback_rbne; -bool irq; -} LASIPS2Port; - -typedef struct LASIPS2State { -LASIPS2Port kbd; -LASIPS2Port mouse; -qemu_irq irq; -} LASIPS2State; - static const VMStateDescription vmstate_lasips2 = { .name = "lasips2", .version_id = 0, diff --git a/include/hw/input/lasips2.h b/include/hw/input/lasips2.h index 0cd7b59064a9..c88f1700162a 100644 --- a/include/hw/input/lasips2.h +++ b/include/hw/input/lasips2.h @@ -11,6 +11,24 @@ #define TYPE_LASIPS2 "lasips2" +struct LASIPS2State; +typedef struct LASIPS2Port { +struct LASIPS2State *parent; +MemoryRegion reg; +void *dev; +uint8_t id; +uint8_t control; +uint8_t buf; +bool loopback_rbne; +bool irq; +} LASIPS2Port; + +typedef struct LASIPS2State { +LASIPS2Port kbd; +LASIPS2Port mouse; +qemu_irq irq; +} LASIPS2State; + void lasips2_init(MemoryRegion *address_space, hwaddr base, qemu_irq irq); #endif /* HW_INPUT_LASIPS2_H */ -- 2.31.1
[PULL 3/6] MAINTAINERS: Split HPPA TCG vs HPPA machines/hardware
From: Philippe Mathieu-Daudé Hardware emulated models don't belong to the TCG MAINTAINERS section. Move them to the 'HP-PARISC Machines' section. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Helge Deller Message-Id: <20211004083835.3802961-1-f4...@amsat.org> Signed-off-by: Laurent Vivier --- MAINTAINERS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 894dc4310526..6f2b20078032 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -205,10 +205,7 @@ HPPA (PA-RISC) TCG CPUs M: Richard Henderson S: Maintained F: target/hppa/ -F: hw/hppa/ F: disas/hppa.c -F: hw/net/*i82596* -F: include/hw/net/lasi_82596.h M68K TCG CPUs M: Laurent Vivier @@ -1099,6 +1096,8 @@ R: Helge Deller S: Odd Fixes F: configs/devices/hppa-softmmu/default.mak F: hw/hppa/ +F: hw/net/*i82596* +F: include/hw/net/lasi_82596.h F: pc-bios/hppa-firmware.img M68K Machines -- 2.31.1
[PULL 2/6] hw/core/machine: Add the missing delimiter in cpu_slot_to_string()
From: Yanan Wang The expected output string from cpu_slot_to_string() ought to be like "socket-id: *, die-id: *, core-id: *, thread-id: *", so add the missing ", " before "die-id". This affects the readability of the error message. Fixes: 176d2cda0d ("i386/cpu: Consolidate die-id validity in smp context") Signed-off-by: Yanan Wang Reviewed-by: Laurent Vivier Message-Id: <20211008075040.18028-1-wangyana...@huawei.com> Signed-off-by: Laurent Vivier --- hw/core/machine.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/core/machine.c b/hw/core/machine.c index b8d95eec32d4..0a23ae310606 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1157,6 +1157,9 @@ static char *cpu_slot_to_string(const CPUArchId *cpu) g_string_append_printf(s, "socket-id: %"PRId64, cpu->props.socket_id); } if (cpu->props.has_die_id) { +if (s->len) { +g_string_append_printf(s, ", "); +} g_string_append_printf(s, "die-id: %"PRId64, cpu->props.die_id); } if (cpu->props.has_core_id) { -- 2.31.1
[PULL 6/6] hw/input/lasips2: QOM'ify the Lasi PS/2
From: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Damien Hedde Message-Id: <20210920064048.2729397-4-f4...@amsat.org> Signed-off-by: Laurent Vivier --- hw/hppa/lasi.c | 10 +- hw/input/lasips2.c | 38 -- include/hw/input/lasips2.h | 17 + 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/hw/hppa/lasi.c b/hw/hppa/lasi.c index 88c3791eb683..91414748b70d 100644 --- a/hw/hppa/lasi.c +++ b/hw/hppa/lasi.c @@ -297,6 +297,7 @@ static int lasi_get_irq(unsigned long hpa) DeviceState *lasi_init(MemoryRegion *address_space) { DeviceState *dev; +SysBusDevice *sbd; LasiState *s; dev = qdev_new(TYPE_LASI_CHIP); @@ -340,7 +341,14 @@ DeviceState *lasi_init(MemoryRegion *address_space) /* PS/2 Keyboard/Mouse */ qemu_irq ps2kbd_irq = qemu_allocate_irq(lasi_set_irq, s, lasi_get_irq(LASI_PS2KBD_HPA)); -lasips2_init(address_space, LASI_PS2KBD_HPA, ps2kbd_irq); + +sbd = SYS_BUS_DEVICE(qdev_new(TYPE_LASIPS2)); +sysbus_realize_and_unref(sbd, &error_fatal); +memory_region_add_subregion(address_space, LASI_PS2KBD_HPA, +sysbus_mmio_get_region(sbd, 0)); +memory_region_add_subregion(address_space, LASI_PS2MOU_HPA, +sysbus_mmio_get_region(sbd, 1)); +sysbus_connect_irq(sbd, 0, ps2kbd_irq); return dev; } diff --git a/hw/input/lasips2.c b/hw/input/lasips2.c index 0f8362f17bc1..46cd32316dac 100644 --- a/hw/input/lasips2.c +++ b/hw/input/lasips2.c @@ -243,28 +243,46 @@ static void ps2dev_update_irq(void *opaque, int level) lasips2_update_irq(port->parent); } -void lasips2_init(MemoryRegion *address_space, - hwaddr base, qemu_irq irq) +static void lasips2_init(Object *obj) { -LASIPS2State *s; +LASIPS2State *s = LASIPS2(obj); +SysBusDevice *sbd = SYS_BUS_DEVICE(obj); -s = g_malloc0(sizeof(LASIPS2State)); - -s->irq = irq; +sysbus_init_irq(sbd, &s->irq); s->mouse.id = 1; s->kbd.parent = s; s->mouse.parent = s; -vmstate_register(NULL, base, &vmstate_lasips2, s); - s->kbd.dev = ps2_kbd_init(ps2dev_update_irq, &s->kbd); s->mouse.dev = ps2_mouse_init(ps2dev_update_irq, &s->mouse); memory_region_init_io(&s->kbd.reg, NULL, &lasips2_reg_ops, &s->kbd, "lasips2-kbd", 0x100); -memory_region_add_subregion(address_space, base, &s->kbd.reg); +sysbus_init_mmio(sbd, &s->kbd.reg); memory_region_init_io(&s->mouse.reg, NULL, &lasips2_reg_ops, &s->mouse, "lasips2-mouse", 0x100); -memory_region_add_subregion(address_space, base + 0x100, &s->mouse.reg); +sysbus_init_mmio(sbd, &s->mouse.reg); +} + +static void lasips2_class_init(ObjectClass *oc, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(oc); + +dc->vmsd = &vmstate_lasips2; } + +static const TypeInfo lasips2_info = { +.name = TYPE_LASIPS2, +.parent= TYPE_SYS_BUS_DEVICE, +.instance_size = sizeof(LASIPS2State), +.instance_init = lasips2_init, +.class_init= lasips2_class_init, +}; + +static void lasips2_register_types(void) +{ +type_register_static(&lasips2_info); +} + +type_init(lasips2_register_types) diff --git a/include/hw/input/lasips2.h b/include/hw/input/lasips2.h index c88f1700162a..834b6d867d9d 100644 --- a/include/hw/input/lasips2.h +++ b/include/hw/input/lasips2.h @@ -7,11 +7,11 @@ #ifndef HW_INPUT_LASIPS2_H #define HW_INPUT_LASIPS2_H -#include "exec/hwaddr.h" +#include "hw/sysbus.h" #define TYPE_LASIPS2 "lasips2" +OBJECT_DECLARE_SIMPLE_TYPE(LASIPS2State, LASIPS2) -struct LASIPS2State; typedef struct LASIPS2Port { struct LASIPS2State *parent; MemoryRegion reg; @@ -23,12 +23,21 @@ typedef struct LASIPS2Port { bool irq; } LASIPS2Port; +/* + * QEMU interface: + * + sysbus MMIO region 0 is the keyboard port interface + * + sysbus MMIO region 1 is the mouse port interface + * + sysbus IRQ 0 is the interrupt line shared between + *keyboard and mouse ports + */ typedef struct LASIPS2State { +/*< private >*/ +SysBusDevice parent_obj; + +/*< public >*/ LASIPS2Port kbd; LASIPS2Port mouse; qemu_irq irq; } LASIPS2State; -void lasips2_init(MemoryRegion *address_space, hwaddr base, qemu_irq irq); - #endif /* HW_INPUT_LASIPS2_H */ -- 2.31.1
[PULL 4/6] hw/input/lasips2: Fix typos in function names
From: Philippe Mathieu-Daudé Artist is another device, this one is the Lasi PS/2. Rename the functions accordingly. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Damien Hedde Message-Id: <20210920064048.2729397-2-f4...@amsat.org> Signed-off-by: Laurent Vivier --- hw/input/lasips2.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/input/lasips2.c b/hw/input/lasips2.c index e7faf24058b4..68d741d34215 100644 --- a/hw/input/lasips2.c +++ b/hw/input/lasips2.c @@ -96,7 +96,7 @@ typedef enum { LASIPS2_STATUS_CLKSHD = 0x80, } lasips2_status_reg_t; -static const char *artist_read_reg_name(uint64_t addr) +static const char *lasips2_read_reg_name(uint64_t addr) { switch (addr & 0xc) { case REG_PS2_ID: @@ -116,7 +116,7 @@ static const char *artist_read_reg_name(uint64_t addr) } } -static const char *artist_write_reg_name(uint64_t addr) +static const char *lasips2_write_reg_name(uint64_t addr) { switch (addr & 0x0c) { case REG_PS2_RESET: @@ -145,7 +145,7 @@ static void lasips2_reg_write(void *opaque, hwaddr addr, uint64_t val, LASIPS2Port *port = opaque; trace_lasips2_reg_write(size, port->id, addr, -artist_write_reg_name(addr), val); +lasips2_write_reg_name(addr), val); switch (addr & 0xc) { case REG_PS2_CONTROL: @@ -239,7 +239,7 @@ static uint64_t lasips2_reg_read(void *opaque, hwaddr addr, unsigned size) break; } trace_lasips2_reg_read(size, port->id, addr, - artist_read_reg_name(addr), ret); + lasips2_read_reg_name(addr), ret); return ret; } -- 2.31.1
[PATCH v6 1/2] vhost-user: remove VirtQ notifier restore
When vhost-user vdpa client suspend, backend may close all resources, VQ notifier mmap address become invalid, restore MR which contains the invalid address is wrong. vdpa client will set VQ notifier after reconnect. This patch removes VQ notifier restore and related flags to avoid reusing invalid address. Fixes: 44866521bd6e ("vhost-user: support registering external host notifiers") Cc: qemu-sta...@nongnu.org Cc: Yuwei Zhang Signed-off-by: Xueming Li --- hw/virtio/vhost-user.c | 19 +-- include/hw/virtio/vhost-user.h | 1 - 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index bf6e50223c..c671719e9b 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -1143,19 +1143,6 @@ static int vhost_user_set_vring_num(struct vhost_dev *dev, return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring); } -static void vhost_user_host_notifier_restore(struct vhost_dev *dev, - int queue_idx) -{ -struct vhost_user *u = dev->opaque; -VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; -VirtIODevice *vdev = dev->vdev; - -if (n->addr && !n->set) { -virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true); -n->set = true; -} -} - static void vhost_user_host_notifier_remove(struct vhost_dev *dev, int queue_idx) { @@ -1163,17 +1150,14 @@ static void vhost_user_host_notifier_remove(struct vhost_dev *dev, VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; VirtIODevice *vdev = dev->vdev; -if (n->addr && n->set) { +if (n->addr) { virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); -n->set = false; } } static int vhost_user_set_vring_base(struct vhost_dev *dev, struct vhost_vring_state *ring) { -vhost_user_host_notifier_restore(dev, ring->index); - return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring); } @@ -1538,7 +1522,6 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, } n->addr = addr; -n->set = true; return 0; } diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h index a9abca3288..f6012b2078 100644 --- a/include/hw/virtio/vhost-user.h +++ b/include/hw/virtio/vhost-user.h @@ -14,7 +14,6 @@ typedef struct VhostUserHostNotifier { MemoryRegion mr; void *addr; -bool set; } VhostUserHostNotifier; typedef struct VhostUserState { -- 2.33.0
[PATCH v6 0/2] Improve vhost-user VQ notifier unmap
When vDPA applicaiton in client mode shutdown, unmapped VQ notifier might being accessed by vCPU thread under high tx traffic, it will crash VM in rare conditon. This patch try to fix it with better RCU sychronization of new flatview. v2: no RCU draining on vCPU thread v3: minor fix on coding style and comments https://lists.nongnu.org/archive/html/qemu-devel/2021-10/msg01764.html v4: fix first patch compilation https://lists.nongnu.org/archive/html/qemu-devel/2021-10/msg04060.html v5: update 2/2 commit message https://lists.nongnu.org/archive/html/qemu-devel/2021-10/msg04115.html v6: use call_rcu to avoid dead lock in rcu reader Xueming Li (2): vhost-user: remove VirtQ notifier restore vhost-user: fix VirtQ notifier cleanup hw/virtio/vhost-user.c | 63 -- include/hw/virtio/vhost-user.h | 3 +- 2 files changed, 31 insertions(+), 35 deletions(-) -- 2.33.0
[PATCH v6 2/2] vhost-user: fix VirtQ notifier cleanup
When vhost-user device cleanup is executed and un-mmaps notifier address, VM cpu thread writing the notifier fails by accessing invalid address error. To avoid this concurrent issue, call RCU and wait for a memory flatview update, then un-mmap notifiers in callback. Fixes: 44866521bd6e ("vhost-user: support registering external host notifiers") Cc: qemu-sta...@nongnu.org Cc: Yuwei Zhang Signed-off-by: Xueming Li --- hw/virtio/vhost-user.c | 50 +- include/hw/virtio/vhost-user.h | 2 ++ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index c671719e9b..5adad4d029 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -25,6 +25,7 @@ #include "migration/migration.h" #include "migration/postcopy-ram.h" #include "trace.h" +#include "exec/ramblock.h" #include #include @@ -1143,15 +1144,27 @@ static int vhost_user_set_vring_num(struct vhost_dev *dev, return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring); } -static void vhost_user_host_notifier_remove(struct vhost_dev *dev, -int queue_idx) +static void vhost_user_host_notifier_free(VhostUserHostNotifier *n) { -struct vhost_user *u = dev->opaque; -VhostUserHostNotifier *n = &u->user->notifier[queue_idx]; -VirtIODevice *vdev = dev->vdev; +assert(n && n->old_addr); +munmap(n->old_addr, qemu_real_host_page_size); +n->old_addr = NULL; +} + +static void vhost_user_host_notifier_remove(VhostUserState *user, +VirtIODevice *vdev, int queue_idx) +{ +VhostUserHostNotifier *n = &user->notifier[queue_idx]; if (n->addr) { -virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); +if (vdev) { +virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); +} +assert(n->addr); +assert(!n->old_addr); +n->old_addr = n->addr; +n->addr = NULL; +call_rcu(n, vhost_user_host_notifier_free, rcu); } } @@ -1190,8 +1203,9 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev, .payload.state = *ring, .hdr.size = sizeof(msg.payload.state), }; +struct vhost_user *u = dev->opaque; -vhost_user_host_notifier_remove(dev, ring->index); +vhost_user_host_notifier_remove(u->user, dev->vdev, ring->index); if (vhost_user_write(dev, &msg, NULL, 0) < 0) { return -1; @@ -1486,12 +1500,7 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, n = &user->notifier[queue_idx]; -if (n->addr) { -virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false); -object_unparent(OBJECT(&n->mr)); -munmap(n->addr, page_size); -n->addr = NULL; -} +vhost_user_host_notifier_remove(user, vdev, queue_idx); if (area->u64 & VHOST_USER_VRING_NOFD_MASK) { return 0; @@ -1510,9 +1519,12 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]", user, queue_idx); -if (!n->mr.ram) /* Don't init again after suspend. */ +if (!n->mr.ram) { /* Don't init again after suspend. */ memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name, page_size, addr); +} else { +n->mr.ram_block->host = addr; +} g_free(name); if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) { @@ -2460,17 +2472,17 @@ bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) void vhost_user_cleanup(VhostUserState *user) { int i; +VhostUserHostNotifier *n; if (!user->chr) { return; } memory_region_transaction_begin(); for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { -if (user->notifier[i].addr) { -object_unparent(OBJECT(&user->notifier[i].mr)); -munmap(user->notifier[i].addr, qemu_real_host_page_size); -user->notifier[i].addr = NULL; -} +n = &user->notifier[i]; +assert(!n->addr); +vhost_user_host_notifier_remove(user, NULL, i); +object_unparent(OBJECT(&n->mr)); } memory_region_transaction_commit(); user->chr = NULL; diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h index f6012b2078..03aa22d450 100644 --- a/include/hw/virtio/vhost-user.h +++ b/include/hw/virtio/vhost-user.h @@ -12,8 +12,10 @@ #include "hw/virtio/virtio.h" typedef struct VhostUserHostNotifier { +struct rcu_head rcu; MemoryRegion mr; void *addr; +void *old_addr; } VhostUserHostNotifier; typedef struct VhostUserState { -- 2.33.0
Re: [PATCH v2] hw/arm/virt: Expose empty NUMA nodes through ACPI
On Thu, 28 Oct 2021 22:32:09 +1100 Gavin Shan wrote: > On 10/28/21 2:40 AM, Igor Mammedov wrote: > > On Wed, 27 Oct 2021 13:29:58 +0800 > > Gavin Shan wrote: > > > >> The empty NUMA nodes, where no memory resides, aren't exposed > >> through ACPI SRAT table. It's not user preferred behaviour because > >> the corresponding memory node devices are missed from the guest > >> kernel as the following example shows. It means the guest kernel > >> doesn't have the node information as user specifies. However, > >> memory can be still hot added to these empty NUMA nodes when > >> they're not exposed. > >> > >>/home/gavin/sandbox/qemu.main/build/qemu-system-aarch64 \ > >>-accel kvm -machine virt,gic-version=host \ > >>-cpu host -smp 4,sockets=2,cores=2,threads=1\ > >>-m 1024M,slots=16,maxmem=64G\ > >>-object memory-backend-ram,id=mem0,size=512M\ > >>-object memory-backend-ram,id=mem1,size=512M\ > >>-numa node,nodeid=0,cpus=0-1,memdev=mem0\ > >>-numa node,nodeid=1,cpus=2-3,memdev=mem1\ > >>-numa node,nodeid=2 \ > >>-numa node,nodeid=3 \ > >> : > >>guest# ls /sys/devices/system/node | grep node > >>node0 > >>node1 > >>(qemu) object_add memory-backend-ram,id=hp-mem0,size=1G > >>(qemu) device_add pc-dimm,id=hp-dimm0,node=3,memdev=hp-mem0 > >>guest# ls /sys/devices/system/node | grep node > >>node0 > >>node1 > >>node2 > >>guest# cat /sys/devices/system/node/node2/meminfo | grep MemTotal > >>Node 2 MemTotal:1048576 kB > >> > >> This exposes these empty NUMA nodes through ACPI SRAT table. With > >> this applied, the corresponding memory node devices can be found > >> from the guest. Note that the hotpluggable capability is explicitly > >> given to these empty NUMA nodes for sake of completeness. > >> > >>guest# ls /sys/devices/system/node | grep node > >>node0 > >>node1 > >>node2 > >>node3 > >>guest# cat /sys/devices/system/node/node3/meminfo | grep MemTotal > >>Node 3 MemTotal:0 kB > >>(qemu) object_add memory-backend-ram,id=hp-mem0,size=1G > >>(qemu) device_add pc-dimm,id=hp-dimm0,node=3,memdev=hp-mem0 > >>guest# cat /sys/devices/system/node/node3/meminfo | grep MemTotal > >>Node 3 MemTotal:1048576 kB > > > > I'm still not sure why this is necessary and if it's a good idea, > > is there a real hardware that have such nodes? > > > > SRAT is used to assign resources to nodes, I haven't seen it being > > used as means to describe an empty node anywhere in the spec. > > (perhaps we should not allow empty nodes on QEMU CLI at all). > > > > Then if we really need this, why it's done for ARM only > > and not for x86? > > > > I think this case exists in real hardware where the memory DIMM > isn't plugged, but the node is still probed. Then please, provide SRAT table from such hw (a lot of them (to justify it as defacto 'standard')? since such hw firmware could be buggy as well). BTW, fake memory node doesn't have to be present to make guest notice an existing numa node. it can be represented by affinity entries as well (see chapter:System Resource Affinity Table (SRAT) in the spec). At the moment, I'm totally unconvinced that empty numa nodes are valid to provide. > Besides, this patch > addresses two issues: > > (1) To make the information contained in guest kernel consistent > to the command line as the user expects. It means the sysfs > entries for these empty NUMA nodes in guest kernel reflects > what user provided. -numa/SRAT describe boot time configuration. So if you do not specify empty nodes on CLI, then number of nodes would be consistent. > (2) Without this patch, the node number can be twisted from user's > perspective. As the example included in the commit log, node3 > should be created, but node2 is actually created. The patch > reserves the NUMA node IDs in advance to avoid the issue. > > /home/gavin/sandbox/qemu.main/build/qemu-system-aarch64 \ > : > -numa node,nodeid=0,cpus=0-1,memdev=mem0\ > -numa node,nodeid=1,cpus=2-3,memdev=mem1\ > -numa node,nodeid=2 \ > -numa node,nodeid=3 \ > guest# ls /sys/devices/system/node | grep node > node0 node1 > (qemu) object_add memory-backend-ram,id=hp-mem0,size=1G > (qemu) device_add pc-dimm,id=hp-dimm0,node=3,memdev=hp-mem0 > guest# ls /sys/devices/system/node | grep node > node0 node1 node2 The same node numbering on guest side and QEMU CLI works only by accident not by design. In short numbers may not match (in linux kernel case it depends on the order the nodes are enumerated), if you really want numbers to match then fix guest ker
Re: [PATCH 00/31] passage: Define a standard for firmware data flow
Hi Simon, this seems a great endeavor. I'd like to better understand the scope of it. Is it to be used as part of what could become a U-Boot entry ABI scheme? By that I mean giving some fixed aspects to U-Boot entry while letting boards to have flexibility (say for instance that the first 5 architecture ABI parameter registers are reserved for U-Boot), and the Passage is about specifying either those reserved registers or one of them? Thinking entry ABI, here is what I observed on Arm: Linux has two entry ABIs: - plain: x0 = dtb; command line = dtb:/chosen/bootargs; initrd = dtb:/chosen/linux,initrd-* - EFI: x0=handle, x1=systemtable, x30=return address; dtb = EFI_UUID config table; initrd = efi:, x2-x5 = , other registers are per platform, SMC calls allowed too - EFI: x0=handle, x1=systemtable, x30=return address; (when U-Boot is launched as an EFI app) dtb = EFI_UUID config table, + Passage = Passage UUID config table We could further leverage Passage to pass Operating Systems parameters that could be removed from device tree (migration of /chosen to Passage). Memory inventory would still be in DT but allocations for CMA or GPUs would be in Passage. This idea is to reach a point where device tree is a "pristine" hardware description. Cheers PS: as Ilias mentions, this patch set contains bug fixes, non immediately related additional functions (DM stats). It would be great to carve those out to fast path them and keep this one with the very core of your idea. On Mon, 1 Nov 2021 at 02:17, Simon Glass wrote: > > This series adds a standard way of passing information between different > firmware phases. This already exists in U-Boot at a very basic level, in > the form of a bloblist containing an spl_handoff structure, but the intent > here is to define something useful across projects. > > The need for this is growing as firmware fragments into multiple binaries > each with its own purpose. Without any run-time connection, we must rely > on build-time settings which are brittle and painful to keep in sync. > > This feature is named 'standard passage' since the name is more unique > than many others that could be chosen, it is a passage in the sense that > information is flowing from one place to another and it is standard, > because that is what we want to create. > > The implementation is simply a pointer to a bloblist in a register, with > an extra register to point to a devicetree, for more complex data, if one > is present in the bloblist. This should cover all cases (small memory > footprint as well as complex data flow) and be easy enough to implement on > all architectures. > > The core bloblist code is relicensed to BSD-3-Clause in case it is useful > in non-GPL projects but there is no requirement to use the same code. > > This series includes tweaks to the bloblist implementation in U-Boot to > make it more suitable for the task, including: > >- Allocate tags explicitly in the enum >- Put the magic number first >- Define a process for adding tags > > The emphasis is on enabling open communcation between binaries, not > enabling passage of secret, undocumented data, although this is possible > in a private environment. > > This series is built on the OF_BOARD series It is available at > u-boot-dm/pass-working or: > > > https://source.denx.de/u-boot/custodians/u-boot-dm/-/commit/073b5c156f222c69a98b8ebcaa563d1ff10eb217 > > > Simon Glass (31): > Makefile: Correct TPL rule for OF_REAL > kconfig: Add support for conditional values > dm: core: Allow getting some basic stats > stddef: Avoid warning with clang with offsetof() > fdt: Drop SPL_BUILD macro > bloblist: Put the magic number first > bloblist: Rename the SPL tag > bloblist: Drop unused tags > bloblist: Use explicit numbering for the tags > bloblist: Support allocating the bloblist > bloblist: Use LOG_CATEGORY to simply logging > bloblist: Use 'phase' consistently for bloblists > bloblist: Refactor Kconfig to support alloc or fixed > arm: qemu: Add an SPL build > bloblist: Add functions to obtain base address and size > passage: Support an incoming passage > passage: Support a control devicetree > passage: arm: Accept a passage from the previous phase > passage: spl: Support adding the dtb to the passage bloblist > passage: spl: Support passing the passage to U-Boot > passage: Record where the devicetree came from > passage: Report the devicetree source > passage: Add a qemu test for ARM > bloblist: doc: Bring in the API documentation > bloblist: Relicense to allow BSD-3-Clause > sandbox: Add a way of checking structs for standard passage > passage: Add documentation > passage: Add docs for spl_handoff > x86: Move Intel GNVS file into the common include directory > passage: Add checks for pre-existing blobs > WIP: RFC: Add a gitlab test > > .gitlab-ci.yml| 6 + > MAINTAINERS
Re: [PATCH] vhost: Fix last queue index of devices with no cvq
On Mon, Nov 1, 2021 at 4:34 AM Jason Wang wrote: > > On Fri, Oct 29, 2021 at 10:16 PM Eugenio Pérez wrote: > > > > The -1 assumes that all devices with no cvq have an spare vq allocated > > for them, but with no offer of VIRTIO_NET_F_CTRL_VQ. This may not be the > > case, and the device may have a pair number of queues. > > > > To fix this, just resort to the lower even number of queues. > > > > Fixes: 049eb15b5fc9 ("vhost: record the last virtqueue index for the virtio > > device") > > Signed-off-by: Eugenio Pérez > > --- > > hw/net/vhost_net.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c > > index 0d888f29a6..edf56a597f 100644 > > --- a/hw/net/vhost_net.c > > +++ b/hw/net/vhost_net.c > > @@ -330,7 +330,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState > > *ncs, > > NetClientState *peer; > > > > if (!cvq) { > > -last_index -= 1; > > +last_index &= ~1ULL; > > } > > The math here looks correct but we need to fix vhost_vdpa_dev_start() instead? > > if (dev->vq_index + dev->nvqs - 1 != dev->last_index) { > ... > } > If we just do that, devices that offer an odd number of queues but do not offer ctrl vq would never enable the last vq pair, isn't it? Also, I would say that the right place for the solution of this problem should not be virtio/vhost-vdpa: This is highly dependent on having cvq, and this implies a knowledge about the use of each virtqueue. Another kind of device could have an odd number of virtqueues naturally, and that (-1) would not work for them, isn't it? Thanks! > Thanks > > > > > if (!k->set_guest_notifiers) { > > -- > > 2.27.0 > > >
Re: [PATCH v4 01/22] target/riscv: Fix trap cause for RV32 HS-mode CSR access from RV64 HS-mode
On Tue, Oct 26, 2021 at 2:43 PM Anup Patel wrote: > > We should be returning illegal instruction trap when RV64 HS-mode tries > to access RV32 HS-mode CSR. > > Fixes: d6f20dacea51 ("target/riscv: Fix 32-bit HS mode access permissions") > Signed-off-by: Anup Patel > Reviewed-by: Alistair Francis > --- > target/riscv/csr.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > Reviewed-by: Bin Meng
Re: [PATCH] vhost: Fix last queue index of devices with no cvq
On Sun, Oct 31, 2021 at 10:47 PM Michael S. Tsirkin wrote: > > On Fri, Oct 29, 2021 at 04:16:08PM +0200, Eugenio Pérez wrote: > > The -1 assumes that all devices with no cvq have an spare vq allocated > > for them, but with no offer of VIRTIO_NET_F_CTRL_VQ. This may not be the > > case, and the device may have a pair number of queues. > > > > To fix this, just resort to the lower even number of queues. > > > > Fixes: 049eb15b5fc9 ("vhost: record the last virtqueue index for the virtio > > device") > > Signed-off-by: Eugenio Pérez > > --- > > hw/net/vhost_net.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c > > index 0d888f29a6..edf56a597f 100644 > > --- a/hw/net/vhost_net.c > > +++ b/hw/net/vhost_net.c > > @@ -330,7 +330,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState > > *ncs, > > NetClientState *peer; > > > > if (!cvq) { > > -last_index -= 1; > > +last_index &= ~1ULL; > > } > > > > if (!k->set_guest_notifiers) { > > could this code be made clearer? > I can expand both for sure, but do you mean clearer because the operation is obscure (to remove the last bit to make last_index even) or because the need of that operation is not clear enough? Thanks! > > -- > > 2.27.0 >
Re: [RFC PATCH v5 00/26] vDPA shadow virtqueue
On Fri, Oct 29, 2021 at 8:41 PM Eugenio Pérez wrote: > > This series enable shadow virtqueue (SVQ) for vhost-vdpa devices. This > is intended as a new method of tracking the memory the devices touch > during a migration process: Instead of relay on vhost device's dirty > logging capability, SVQ intercepts the VQ dataplane forwarding the > descriptors between VM and device. This way qemu is the effective > writer of guests memory, like in qemu's virtio device operation. > > When SVQ is enabled qemu offers a new virtual address space to the > device to read and write into, and it maps new vrings and the guest > memory in it. SVQ also intercepts kicks and calls between the device > and the guest. Used buffers relay would cause dirty memory being > tracked, but at this RFC SVQ is not enabled on migration automatically. > > Thanks of being a buffers relay system, SVQ can be used also to > communicate devices and drivers with different capabilities, like > devices that only supports packed vring and not split and old guest > with no driver packed support. > > It is based on the ideas of DPDK SW assisted LM, in the series of > DPDK's https://patchwork.dpdk.org/cover/48370/ . However, these does > not map the shadow vq in guest's VA, but in qemu's. > > For qemu to use shadow virtqueues the guest virtio driver must not use > features like event_idx. > > SVQ needs to be enabled with QMP command: > > { "execute": "x-vhost-set-shadow-vq", > "arguments": { "name": "vhost-vdpa0", "enable": true } } > > This series includes some patches to delete in the final version that > helps with its testing. The first two of the series have been sent > sepparately but they haven't been included in qemu main branch. > > The two after them adds the feature to stop the device and be able to > set and get its status. It's intended to be used with vp_vpda driver in > a nested environment, so they are also external to this series. The > vp_vdpa driver also need modifications to forward the new status bit, > they will be proposed sepparately > > Patches 5-12 prepares the SVQ and QMP command to support guest to host > notifications forwarding. If the SVQ is enabled with these ones > applied and the device supports it, that part can be tested in > isolation (for example, with networking), hopping through SVQ. > > Same thing is true with patches 13-17, but with device to guest > notifications. > > Based on them, patches from 18 to 22 implement the actual buffer > forwarding, using some features already introduced in previous. > However, they will need a host device with no iommu, something that > is not available at the moment. > > The last part of the series uses properly the host iommu, so the driver > can access this new virtual address space created. > > Comments are welcome. > > TODO: > * Event, indirect, packed, and others features of virtio. > * To sepparate buffers forwarding in its own AIO context, so we can > throw more threads to that task and we don't need to stop the main > event loop. > * Support multiqueue virtio-net vdpa. > * Proper documentation. > > Changes from v4 RFC: > * Support of allocating / freeing iova ranges in IOVA tree. Extending > already present iova-tree for that. > * Proper validation of guest features. Now SVQ can negotiate a > different set of features with the device when enabled. > * Support of host notifiers memory regions > * Handling of SVQ full queue in case guest's descriptors span to > different memory regions (qemu's VA chunks). > * Flush pending used buffers at end of SVQ operation. > * QMP command now looks by NetClientState name. Other devices will need > to implement it's way to enable vdpa. > * Rename QMP command to set, so it looks more like a way of working > * Better use of qemu error system > * Make a few assertions proper error-handling paths. > * Add more documentation > * Less coupling of virtio / vhost, that could cause friction on changes > * Addressed many other small comments and small fixes. > > Changes from v3 RFC: > * Move everything to vhost-vdpa backend. A big change, this allowed > some cleanup but more code has been added in other places. > * More use of glib utilities, especially to manage memory. > v3 link: > https://lists.nongnu.org/archive/html/qemu-devel/2021-05/msg06032.html > > Changes from v2 RFC: > * Adding vhost-vdpa devices support > * Fixed some memory leaks pointed by different comments > v2 link: > https://lists.nongnu.org/archive/html/qemu-devel/2021-03/msg05600.html > > Changes from v1 RFC: > * Use QMP instead of migration to start SVQ mode. > * Only accepting IOMMU devices, closer behavior with target devices > (vDPA) > * Fix invalid masking/unmasking of vhost call fd. > * Use of proper methods for synchronization. > * No need to modify VirtIO device code, all of the changes are > contained in vhost code. > * Delete superfluous code. > * An intermediate RFC was sent with only the notifications forwarding >
Re: [PATCH] vhost: Fix last queue index of devices with no cvq
On Mon, Nov 01, 2021 at 10:03:19AM +0100, Eugenio Perez Martin wrote: > On Sun, Oct 31, 2021 at 10:47 PM Michael S. Tsirkin wrote: > > > > On Fri, Oct 29, 2021 at 04:16:08PM +0200, Eugenio Pérez wrote: > > > The -1 assumes that all devices with no cvq have an spare vq allocated > > > for them, but with no offer of VIRTIO_NET_F_CTRL_VQ. This may not be the > > > case, and the device may have a pair number of queues. > > > > > > To fix this, just resort to the lower even number of queues. > > > > > > Fixes: 049eb15b5fc9 ("vhost: record the last virtqueue index for the > > > virtio device") > > > Signed-off-by: Eugenio Pérez > > > --- > > > hw/net/vhost_net.c | 2 +- > > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c > > > index 0d888f29a6..edf56a597f 100644 > > > --- a/hw/net/vhost_net.c > > > +++ b/hw/net/vhost_net.c > > > @@ -330,7 +330,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState > > > *ncs, > > > NetClientState *peer; > > > > > > if (!cvq) { > > > -last_index -= 1; > > > +last_index &= ~1ULL; > > > } > > > > > > if (!k->set_guest_notifiers) { > > > > could this code be made clearer? > > > > I can expand both for sure, but do you mean clearer because the > operation is obscure (to remove the last bit to make last_index even) > or because the need of that operation is not clear enough? > > Thanks! I'm not sure ... both? > > > -- > > > 2.27.0 > >
Re: [PATCH v2] failover: specify an alternate MAC address
On Wed, Oct 27, 2021 at 11:59:45AM +0200, Laurent Vivier wrote: > If the guest driver doesn't support the STANDBY feature, by default > we keep the virtio-net device and don't hotplug the VFIO device, > but in some cases, user can prefer to use the VFIO device rather > than the virtio-net one. We can't unplug the virtio-net device > (because on migration it is expected on the destination side) but > we can keep both interfaces if the MAC addresses are different > (to have the same MAC address can cause kernel crash with old > kernel). The VFIO device will be unplugged before the migration > like in the normal failover migration but without a failover device. > > This patch adds a new property to the virtio-net device: > "failover-legacy-mac" > > If an alternate MAC address is provided with "failover-legacy-mac" and > the STANDBY feature is not supported, both interfaces are plugged > but the standby interface (virtio-net) MAC address is set to the > value provided by the "failover-legacy-mac" parameter. > > If the STANDBY feature is supported by guest and QEMU, the virtio-net > failover acts as usual. > > Signed-off-by: Laurent Vivier Wait a second. What if config is read before features are set? Are we going to provide a legacy or a new mac? I guess current guests do not do this, but the spec does allow this, and then the mac will apparently change for the guests. It might be cleaner to just add a PRIMARY_MAC feature - would need guest work though ... > --- > > Notes: > v2: rename alt-mac to failover-legacy-mac > update doc with text provided by MST > > docs/system/virtio-net-failover.rst | 10 ++ > hw/net/virtio-net.c | 48 +++-- > include/hw/virtio/virtio-net.h | 6 > 3 files changed, 55 insertions(+), 9 deletions(-) > > diff --git a/docs/system/virtio-net-failover.rst > b/docs/system/virtio-net-failover.rst > index 6002dc5d96e4..99f21cd55ef7 100644 > --- a/docs/system/virtio-net-failover.rst > +++ b/docs/system/virtio-net-failover.rst > @@ -51,6 +51,16 @@ Usage >is only for pairing the devices within QEMU. The guest kernel module >net_failover will match devices with identical MAC addresses. > > + For legacy guests (including bios/EUFI) not supporting > VIRTIO_NET_F_STANDBY, > + two options exist: > + > + 1. if failover-legacy-mac has not been configured (default) > + only the standby virtio-net device is visible to the guest > + > + 2. if failover-legacy-mac has been configured, virtio and vfio devices will > + be presented to guest as two NIC devices, with virtio using the > + failover-legacy-mac address. > + > Hotplug > --- > > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c > index f2014d5ea0b3..0d47d287de14 100644 > --- a/hw/net/virtio-net.c > +++ b/hw/net/virtio-net.c > @@ -45,6 +45,9 @@ > #include "net_rx_pkt.h" > #include "hw/virtio/vhost.h" > > +/* zero MAC address to check with */ > +static const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } }; > + > #define VIRTIO_NET_VM_VERSION11 > > #define MAC_TABLE_ENTRIES64 > @@ -126,7 +129,6 @@ static void virtio_net_get_config(VirtIODevice *vdev, > uint8_t *config) > VirtIONet *n = VIRTIO_NET(vdev); > struct virtio_net_config netcfg; > NetClientState *nc = qemu_get_queue(n->nic); > -static const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } }; > > int ret = 0; > memset(&netcfg, 0 , sizeof(struct virtio_net_config)); > @@ -871,10 +873,21 @@ static void failover_add_primary(VirtIONet *n, Error > **errp) > error_propagate(errp, err); > } > > +static void failover_plug_primary(VirtIONet *n) > +{ > +Error *err = NULL; > + > +qapi_event_send_failover_negotiated(n->netclient_name); > +qatomic_set(&n->failover_primary_hidden, false); > +failover_add_primary(n, &err); > +if (err) { > +warn_report_err(err); > +} > +} > + > static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) > { > VirtIONet *n = VIRTIO_NET(vdev); > -Error *err = NULL; > int i; > > if (n->mtu_bypass_backend && > @@ -921,12 +934,22 @@ static void virtio_net_set_features(VirtIODevice *vdev, > uint64_t features) > memset(n->vlans, 0xff, MAX_VLAN >> 3); > } > > -if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { > -qapi_event_send_failover_negotiated(n->netclient_name); > -qatomic_set(&n->failover_primary_hidden, false); > -failover_add_primary(n, &err); > -if (err) { > -warn_report_err(err); > +if (n->failover) { > +if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { > +if (memcmp(&n->legacy_mac, &zero, sizeof(zero)) != 0 && > +memcmp(n->mac, &n->legacy_mac, ETH_ALEN) == 0) { > +/* > + * set_features can be called twice, without & with > F_STANDBY, > + * so restore original MAC address R
[PATCH v8 01/29] target/loongarch: Add README
This patch gives an introduction to the LoongArch target. Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- MAINTAINERS | 5 target/loongarch/README | 76 + 2 files changed, 81 insertions(+) create mode 100644 target/loongarch/README diff --git a/MAINTAINERS b/MAINTAINERS index 894dc43..7a3c190 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -210,6 +210,11 @@ F: disas/hppa.c F: hw/net/*i82596* F: include/hw/net/lasi_82596.h +LoongArch TCG CPUS +M: Song Gao +S: Maintained +F: target/loongarch/ + M68K TCG CPUs M: Laurent Vivier S: Maintained diff --git a/target/loongarch/README b/target/loongarch/README new file mode 100644 index 000..09f809c --- /dev/null +++ b/target/loongarch/README @@ -0,0 +1,76 @@ +- Introduction + + LoongArch is the general processor architecture of Loongson. + + The following versions of the LoongArch core are supported +core: 3A5000 + https://github.com/loongson/LoongArch-Documentation/releases/download/2021.08.17/LoongArch-Vol1-v1.00-EN.pdf + + We can get the latest loongarch documents at https://github.com/loongson/LoongArch-Documentation/tags. + + +- Linux-user emulation + + We already support Linux user emulation. We can use LoongArch cross-tools to build LoongArch executables on X86 machines, + and We can also use qemu-loongarch64 to run LoongArch executables. + + 1. Install LoongArch cross-tools on X86 machines. + +Download cross-tools. + + wget https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20210831-cross-tools.tar.xz + + tar -vxf loongarch64-clfs-20210831-cross-tools.tar.xz -C /opt + +Config cross-tools env. + + . setenv.sh + + setenv.sh: + + #!/bin/sh + set -x + CC_PREFIX=/opt/cross-tools + + export PATH=$CC_PREFIX/bin:$PATH + export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH + export LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH + set +x + + 2. Test tests/tcg/multiarch. + +./configure --disable-rdma --disable-pvrdma --prefix=/usr \ +--target-list="loongarch64-linux-user" \ +--disable-libiscsi --disable-libnfs --disable-libpmem \ +--disable-glusterfs --enable-libusb --enable-usb-redir \ +--disable-opengl --disable-xen --enable-spice --disable-werror \ +--enable-debug --disable-capstone --disable-kvm --enable-profiler + +cd build/ + +make && make check-tcg + + 3. Run LoongArch system basic command with loongarch-clfs-system. + +Download clfs-system. + + wget https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-system-2021-08-31.tar.bz2 + + tar -vxf loongarch64-clfs-system-2021-08-31.tar.bz2 -C /opt/clfs + +Config env. + + cp /opt/clfs/lib64/ld-linux-loongarch64.so.1 /lib64 + + export LD_LIBRARY_PATH="/opt/clfs/lib64" + +Run LoongArch system basic command. + + ./qemu-loongarch64 /opt/clfs/usr/bin/bash + ./qemu-loongarch64 /opt/clfs/usr/bin/ls + ./qemu-loongarch64 /opt/clfs/usr/bin/pwd + ... + + +- Note. + We can get the latest LoongArch documents or LoongArch tools at https://github.com/loongson/ -- 1.8.3.1
[PATCH v8 00/29] Add LoongArch linux-user emulation support
Hi all, This series only support linux-user emulation. More about LoongArch at: https://github.com/loongson/ The latest kernel: * https://github.com/loongson/linux/tree/loongarch-next Patches need review: * 0002-target-loongarch-Add-core-definition.patch * 0016-target-loongarch-Add-disassembler.patch * 0017-linux-user-Add-LoongArch-generic-header-files.patch * 0018-linux-user-Add-LoongArch-specific-structures.patch * 0019-linux-user-Add-LoongArch-signal-support.patch * 0020-linux-user-Add-LoongArch-elf-support.patch * 0021-linux-user-Add-LoongArch-syscall-support.patch * 0022-linux-user-Add-LoongArch-cpu_loop-support.patch * 0023-linux-user-Add-host-dependency-for-LoongArch-64-bit.patch * 0028-accel-tcg-user-exec-Implement-CPU-specific-signal-ha.patch * 0029-linux-user-Add-safe-syscall-handling-for-loongarch64.patch Changes for v8: * Use the FIELD functions to define cpucfg[i]. * Re-use the decodetree to disassembler description. * Split v7 patch(0017-LoongArch-Linux-User-Emulation.patch). Changes for v7: * scripts/gensyscalls.sh support loongarch64 if we use gensyscalls.sh, we need disable __BITS_PER_LONG at arch/loongarch/include/uapi/asm/bitsperlong.h Changes for v6: * Resolve patch10 and patch6 code issues. Changes for v5: * Follow Richard's code review comments [1]. * Use force_sig_fault(). * Implement setup_sigtramp. [1]: https://patchew.org/QEMU/1630586467-22463-1-git-send-email-gaos...@loongson.cn/ Changes for v4: * Update README,add LoongArch linux-user emulation Introduction. * Add 'make check-tcg' support(patch 20). * Add binfmt config(patch 21). * Fix bugs when running loongarch basic commands. Changes for v3: * Split trans.inc.c. * Remove csr registers. * Delete patchs 2, 4, 5. * Follow Richard's code review comments [1]. * Follow Richard's riscv patches [2]. [1]: https://patchew.org/QEMU/1626861198-6133-1-git-send-email-gaos...@loongson.cn/ [2]: https://patchew.org/QEMU/20210823195529.560295-1-richard.hender...@linaro.org/ Changes for v2: * Patch 1, remove unnecessary introduction; * Patch 3, follow the ARM/AVR pattern to add new CPU features; * Patch 6, remove decode_lsx(); * Patches 7-18, delete opcode definition, modify translation function; * Patches 20-22, split V1 patch20 to V2 patch20-22. v7: https://patchew.org/QEMU/1634561247-25499-1-git-send-email-gaos...@loongson.cn/ V6: https://patchew.org/QEMU/1631866380-31017-1-git-send-email-gaos...@loongson.cn/ V5: https://patchew.org/QEMU/1631624431-30658-1-git-send-email-gaos...@loongson.cn/ V4: https://patchew.org/QEMU/1630586467-22463-1-git-send-email-gaos...@loongson.cn/ V3: https://patchew.org/QEMU/1630048494-2143-1-git-send-email-gaos...@loongson.cn/ V2: https://patchew.org/QEMU/1626861198-6133-1-git-send-email-gaos...@loongson.cn/ V1: https://patchew.org/QEMU/1624881885-31692-1-git-send-email-gaos...@loongson.cn/ Please review! Thanks. Song Gao (29): target/loongarch: Add README target/loongarch: Add core definition target/loongarch: Add main translation routines target/loongarch: Add fixed point arithmetic instruction translation target/loongarch: Add fixed point shift instruction translation target/loongarch: Add fixed point bit instruction translation target/loongarch: Add fixed point load/store instruction translation target/loongarch: Add fixed point atomic instruction translation target/loongarch: Add fixed point extra instruction translation target/loongarch: Add floating point arithmetic instruction translation target/loongarch: Add floating point comparison instruction translation target/loongarch: Add floating point conversion instruction translation target/loongarch: Add floating point move instruction translation target/loongarch: Add floating point load/store instruction translation target/loongarch: Add branch instruction translation target/loongarch: Add disassembler linux-user: Add LoongArch generic header files linux-user: Add LoongArch specific structures linux-user: Add LoongArch signal support linux-user: Add LoongArch elf support linux-user: Add LoongArch syscall support linux-user: Add LoongArch cpu_loop support linux-user: Add host dependency for LoongArch 64-bit default-configs: Add loongarch linux-user support target/loongarch: Add target build suport target/loongarch: 'make check-tcg' support scripts: add loongarch64 binfmt config accel/tcg/user-exec: Implement CPU-specific signal handler for loongarch64 hosts linux-user: Add safe syscall handling for loongarch64 hosts MAINTAINERS| 5 + accel/tcg/user-exec.c | 73 ++ configs/targets/loongarch64-linux-user.mak | 3 + configure | 5 + include/disas/dis-asm.h| 2 + include/elf.h | 2 + linux-user/elfload.c
[PATCH v8 10/29] target/loongarch: Add floating point arithmetic instruction translation
This includes: - F{ADD/SUB/MUL/DIV}.{S/D} - F{MADD/MSUB/NMADD/NMSUB}.{S/D} - F{MAX/MIN}.{S/D} - F{MAXA/MINA}.{S/D} - F{ABS/NEG}.{S/D} - F{SQRT/RECIP/RSQRT}.{S/D} - F{SCALEB/LOGB/COPYSIGN}.{S/D} - FCLASS.{S/D} Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/cpu.c | 1 + target/loongarch/fpu_helper.c | 406 + target/loongarch/helper.h | 37 +++ target/loongarch/insn_trans/trans_farith.c | 108 target/loongarch/insns.decode | 56 target/loongarch/internals.h | 2 + target/loongarch/translate.c | 11 + 7 files changed, 621 insertions(+) create mode 100644 target/loongarch/fpu_helper.c create mode 100644 target/loongarch/insn_trans/trans_farith.c diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 0c39d6e..f9329d5 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -210,6 +210,7 @@ static void loongarch_cpu_reset(DeviceState *dev) env->fcsr0_mask = 0x1f1f031f; env->fcsr0 = 0x0; +restore_fp_status(env); cs->exception_index = EXCP_NONE; } diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c new file mode 100644 index 000..f5c32e4 --- /dev/null +++ b/target/loongarch/fpu_helper.c @@ -0,0 +1,406 @@ +/* + * LoongArch float point emulation helpers for QEMU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "fpu/softfloat.h" +#include "internals.h" + +#define FLOAT_TO_INT32_OVERFLOW 0x7fff +#define FLOAT_TO_INT64_OVERFLOW 0x7fffULL + +static inline uint64_t nanbox_s(float32 fp) +{ +return fp | MAKE_64BIT_MASK(32, 32); +} + +/* Convert loongarch rounding mode in fcsr0 to IEEE library */ +static const FloatRoundMode ieee_rm[4] = { +float_round_nearest_even, +float_round_to_zero, +float_round_up, +float_round_down +}; + +void restore_fp_status(CPULoongArchState *env) +{ +set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], +&env->fp_status); +set_flush_to_zero(0, &env->fp_status); +} + +static int ieee_ex_to_loongarch(int xcpt) +{ +int ret = 0; +if (xcpt & float_flag_invalid) { +ret |= FP_INVALID; +} +if (xcpt & float_flag_overflow) { +ret |= FP_OVERFLOW; +} +if (xcpt & float_flag_underflow) { +ret |= FP_UNDERFLOW; +} +if (xcpt & float_flag_divbyzero) { +ret |= FP_DIV0; +} +if (xcpt & float_flag_inexact) { +ret |= FP_INEXACT; +} +return ret; +} + +static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask) +{ +int flags = get_float_exception_flags(&env->fp_status); + +set_float_exception_flags(0, &env->fp_status); + +if (~mask) { +flags = flags & (~mask); +} + +if (!flags) { +SET_FP_CAUSE(env->fcsr0, flags); +return; +} + +flags = ieee_ex_to_loongarch(flags); +SET_FP_CAUSE(env->fcsr0, flags); + +if (GET_FP_ENABLES(env->fcsr0) & flags) { +do_raise_exception(env, EXCP_FPE, pc); +} else { +UPDATE_FP_FLAGS(env->fcsr0, flags); +} +} + +static void update_fcsr0(CPULoongArchState *env, uintptr_t pc) +{ +update_fcsr0_mask(env, pc, 0); +} + +uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ +uint64_t fd; + +fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status)); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ +uint64_t fd; + +fd = float64_add(fj, fk, &env->fp_status); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ +uint64_t fd; + +fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status)); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ +uint64_t fd; + +fd = float64_sub(fj, fk, &env->fp_status); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ +uint64_t fd; + +fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status)); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ +uint64_t fd; + +fd = float64_mul(fj, fk, &env->fp_status); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) +{ +uint64_t fd; + +fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status)); +
[PATCH v8 04/29] target/loongarch: Add fixed point arithmetic instruction translation
This includes: - ADD.{W/D}, SUB.{W/D} - ADDI.{W/D}, ADDU16ID - ALSL.{W[U]/D} - LU12I.W, LU32I.D LU52I.D - SLT[U], SLT[U]I - PCADDI, PCADDU12I, PCADDU18I, PCALAU12I - AND, OR, NOR, XOR, ANDN, ORN - MUL.{W/D}, MULH.{W[U]/D[U]} - MULW.D.W[U] - DIV.{W[U]/D[U]}, MOD.{W[U]/D[U]} - ANDI, ORI, XORI Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/insn_trans/trans_arith.c | 322 ++ target/loongarch/insns.decode | 89 + target/loongarch/translate.c | 78 target/loongarch/translate.h | 19 ++ 4 files changed, 508 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_arith.c create mode 100644 target/loongarch/insns.decode diff --git a/target/loongarch/insn_trans/trans_arith.c b/target/loongarch/insn_trans/trans_arith.c new file mode 100644 index 000..4e8b9dd --- /dev/null +++ b/target/loongarch/insn_trans/trans_arith.c @@ -0,0 +1,322 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_r3(DisasContext *ctx, arg_fmt_rdrjrk *a, + DisasExtend src1_ext, DisasExtend src2_ext, + DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv)) +{ +TCGv dest = gpr_dst(ctx, a->rd, dst_ext); +TCGv src1 = gpr_src(ctx, a->rj, src1_ext); +TCGv src2 = gpr_src(ctx, a->rk, src2_ext); + +func(dest, src1, src2); + +/* dst_ext is EXT_NONE and input is dest, We don't run gen_set_gpr. */ +if (dst_ext) { +gen_set_gpr(a->rd, dest, dst_ext); +} +return true; +} + +static bool gen_r2_si12(DisasContext *ctx, arg_fmt_rdrjsi12 *a, +DisasExtend src_ext, DisasExtend dst_ext, +void (*func)(TCGv, TCGv, TCGv)) +{ +TCGv dest = gpr_dst(ctx, a->rd, dst_ext); +TCGv src1 = gpr_src(ctx, a->rj, src_ext); +TCGv src2 = tcg_constant_tl(a->si12); + +func(dest, src1, src2); + +if (dst_ext) { +gen_set_gpr(a->rd, dest, dst_ext); +} +return true; +} + +static bool gen_r3_sa2(DisasContext *ctx, arg_fmt_rdrjrksa2 *a, + DisasExtend src_ext, DisasExtend dst_ext, + void (*func)(TCGv, TCGv, TCGv, TCGv, target_long)) +{ +TCGv dest = gpr_dst(ctx, a->rd, dst_ext); +TCGv src1 = gpr_src(ctx, a->rj, src_ext); +TCGv src2 = gpr_src(ctx, a->rk, src_ext); +TCGv temp = tcg_temp_new(); + +func(dest, src1, src2, temp, a->sa2); + +if (dst_ext) { +gen_set_gpr(a->rd, dest, dst_ext); +} +tcg_temp_free(temp); +return true; +} + +static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + +tcg_gen_movi_tl(dest, a->si20 << 12); +return true; +} + +static bool gen_pc(DisasContext *ctx, arg_fmt_rdsi20 *a, + target_ulong (*func)(target_ulong, int)) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +target_ulong addr = func(ctx->base.pc_next, a->si20); + +tcg_gen_movi_tl(dest, addr); +return true; +} + +static bool gen_r2_ui12(DisasContext *ctx, arg_fmt_rdrjui12 *a, +void (*func)(TCGv, TCGv, target_long)) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +func(dest, src1, a->ui12); +return true; +} + +static void gen_slt(TCGv dest, TCGv src1, TCGv src2) +{ +tcg_gen_setcond_tl(TCG_COND_LT, dest, src1, src2); +} + +static void gen_sltu(TCGv dest, TCGv src1, TCGv src2) +{ +tcg_gen_setcond_tl(TCG_COND_LTU, dest, src1, src2); +} + +static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2) +{ +tcg_gen_mul_i64(dest, src1, src2); +tcg_gen_sari_i64(dest, dest, 32); +} + +static void gen_mulh_wu(TCGv dest, TCGv src1, TCGv src2) +{ +tcg_gen_mul_i64(dest, src1, src2); +tcg_gen_sari_i64(dest, dest, 32); +} + +static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv discard = tcg_temp_new(); +tcg_gen_muls2_tl(discard, dest, src1, src2); +tcg_temp_free(discard); +} + +static void gen_mulh_du(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv discard = tcg_temp_new(); +tcg_gen_mulu2_tl(discard, dest, src1, src2); +tcg_temp_free(discard); +} + +static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +TCGv t1 = tcg_temp_new(); +TCGv zero = tcg_constant_tl(0); + +/* + * If min / -1, set the divisor to 1. + * This avoids potential host overflow trap and produces min. + * If x / 0, set the divisor to 1. + * This avoids potential host overflow trap; + * the required result is undefined. + */ +tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN); +tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1); +tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0); +tcg_gen_and_tl(ret, ret, t0); +tcg_gen_or_tl(ret
[PATCH v8 03/29] target/loongarch: Add main translation routines
This patch adds main translation routines and basic functions for translation. Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/helper.h| 9 +++ target/loongarch/op_helper.c | 22 ++ target/loongarch/translate.c | 160 +++ target/loongarch/translate.h | 27 4 files changed, 218 insertions(+) create mode 100644 target/loongarch/helper.h create mode 100644 target/loongarch/op_helper.c create mode 100644 target/loongarch/translate.c create mode 100644 target/loongarch/translate.h diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h new file mode 100644 index 000..09bfcfd --- /dev/null +++ b/target/loongarch/helper.h @@ -0,0 +1,9 @@ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +DEF_HELPER_2(raise_exception, noreturn, env, i32) diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c new file mode 100644 index 000..c22bdee --- /dev/null +++ b/target/loongarch/op_helper.c @@ -0,0 +1,22 @@ +/* + * LoongArch emulation helpers for QEMU. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "cpu.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "internals.h" + +/* Exceptions helpers */ +void helper_raise_exception(CPULoongArchState *env, uint32_t exception) +{ +do_raise_exception(env, exception, GETPC()); +} diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c new file mode 100644 index 000..b449af7 --- /dev/null +++ b/target/loongarch/translate.c @@ -0,0 +1,160 @@ +/* + * LoongArch emulation for QEMU - main translation routines. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "tcg/tcg-op.h" +#include "exec/translator.h" +#include "exec/helper-proto.h" +#include "exec/helper-gen.h" + +#include "exec/translator.h" +#include "exec/log.h" +#include "qemu/qemu-print.h" +#include "translate.h" +#include "internals.h" + +/* Global register indices */ +TCGv cpu_gpr[32], cpu_pc; +static TCGv cpu_lladdr, cpu_llval; +TCGv_i32 cpu_fcsr0; +TCGv_i64 cpu_fpr[32]; + +#define DISAS_STOP DISAS_TARGET_0 + +void generate_exception(DisasContext *ctx, int excp) +{ +tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); +gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); +ctx->base.is_jmp = DISAS_NORETURN; +} + +static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) +{ +if (translator_use_goto_tb(&ctx->base, dest)) { +tcg_gen_goto_tb(n); +tcg_gen_movi_tl(cpu_pc, dest); +tcg_gen_exit_tb(ctx->base.tb, n); +} else { +tcg_gen_movi_tl(cpu_pc, dest); +tcg_gen_lookup_and_goto_ptr(); +} +} + +static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, +CPUState *cs) +{ +int64_t bound; +DisasContext *ctx = container_of(dcbase, DisasContext, base); + +ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK; +ctx->mem_idx = MMU_USER_IDX; + +/* Bound the number of insns to execute to those left on the page. */ +bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; +ctx->base.max_insns = MIN(ctx->base.max_insns, bound); +} + +static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) +{ +} + +static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) +{ +DisasContext *ctx = container_of(dcbase, DisasContext, base); + +tcg_gen_insn_start(ctx->base.pc_next); +} + +static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) +{ +CPULoongArchState *env = cs->env_ptr; +DisasContext *ctx = container_of(dcbase, DisasContext, base); + +ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); + +if (!decode(ctx, ctx->opcode)) { +qemu_log_mask(LOG_UNIMP, "Error: unkown opcode. 0x%lx: 0x%x\n", + ctx->base.pc_next, ctx->opcode); +generate_exception(ctx, EXCP_INE); +} + +ctx->base.pc_next += 4; +} + +static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) +{ +DisasContext *ctx = container_of(dcbase, DisasContext, base); + +switch (ctx->base.is_jmp) { +case DISAS_STOP: +tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); +tcg_gen_lookup_and_goto_ptr(); +break; +case DISAS_TOO_MANY: +gen_goto_tb(ctx, 0, ctx->base.pc_next); +break; +case DISAS_NORETURN: +break; +default: +g_assert_not_reached(); +} +} + +static void loongarch_tr_disas_log(const DisasContextBase *dcbase, CPUState *c
[PATCH v8 02/29] target/loongarch: Add core definition
This patch adds target state header, target definitions and initialization routines. Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/cpu-param.h | 19 +++ target/loongarch/cpu.c | 352 +++ target/loongarch/cpu.h | 254 +++ target/loongarch/internals.h | 22 +++ 4 files changed, 647 insertions(+) create mode 100644 target/loongarch/cpu-param.h create mode 100644 target/loongarch/cpu.c create mode 100644 target/loongarch/cpu.h create mode 100644 target/loongarch/internals.h diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h new file mode 100644 index 000..099d6fa --- /dev/null +++ b/target/loongarch/cpu-param.h @@ -0,0 +1,19 @@ +/* + * LoongArch CPU parameters for QEMU. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_CPU_PARAM_H +#define LOONGARCH_CPU_PARAM_H + +#define TARGET_LONG_BITS 64 +#define TARGET_PHYS_ADDR_SPACE_BITS 48 +#define TARGET_VIRT_ADDR_SPACE_BITS 48 + +#define TARGET_PAGE_BITS 14 +#define NB_MMU_MODES 4 + +#endif diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c new file mode 100644 index 000..0c39d6e --- /dev/null +++ b/target/loongarch/cpu.c @@ -0,0 +1,352 @@ +/* + * QEMU LoongArch CPU + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu/qemu-print.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "sysemu/qtest.h" +#include "exec/exec-all.h" +#include "qapi/qapi-commands-machine-target.h" +#include "cpu.h" +#include "internals.h" +#include "fpu/softfloat-helpers.h" + +const char * const regnames[] = { +"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", +"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", +"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", +"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", +}; + +const char * const fregnames[] = { +"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", +"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", +"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", +"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", +}; + +static const char * const excp_names[EXCP_LAST + 1] = { +[EXCP_ADE] = "Address error", +[EXCP_SYSCALL] = "Syscall", +[EXCP_BREAK] = "Break", +[EXCP_INE] = "Instruction Non-existent", +[EXCP_FPE] = "Floating Point Exception", +}; + +const char *loongarch_exception_name(int32_t exception) +{ +return excp_names[exception]; +} + +void QEMU_NORETURN do_raise_exception(CPULoongArchState *env, + uint32_t exception, + uintptr_t pc) +{ +CPUState *cs = env_cpu(env); + +qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n", + __func__, + exception, + loongarch_exception_name(exception)); +cs->exception_index = exception; + +cpu_loop_exit_restore(cs, pc); +} + +static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) +{ +LoongArchCPU *cpu = LOONGARCH_CPU(cs); +CPULoongArchState *env = &cpu->env; + +env->pc = value; +} + +#ifdef CONFIG_TCG +static void loongarch_cpu_synchronize_from_tb(CPUState *cs, + const TranslationBlock *tb) +{ +LoongArchCPU *cpu = LOONGARCH_CPU(cs); +CPULoongArchState *env = &cpu->env; + +env->pc = tb->pc; +} +#endif /* CONFIG_TCG */ + +static bool loongarch_cpu_has_work(CPUState *cs) +{ +return true; +} + +static void set_loongarch_cpucfg(CPULoongArchState *env) +{ +int i; + +for (i = 0; i < 49; i++) { +env->cpucfg[i] = 0x0; +} + +env->cpucfg[0] = 0x14c010; /* PRID */ + +uint32_t data = 0; +data = FIELD_DP32(data, CPUCFG1, ARCH, 2); +data = FIELD_DP32(data, CPUCFG1, PGMMU, 1); +data = FIELD_DP32(data, CPUCFG1, IOCSR, 1); +data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f); +data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f); +data = FIELD_DP32(data, CPUCFG1, UAL, 1); +data = FIELD_DP32(data, CPUCFG1, RI, 1); +data = FIELD_DP32(data, CPUCFG1, EP, 1); +data = FIELD_DP32(data, CPUCFG1, RPLV, 1); +data = FIELD_DP32(data, CPUCFG1, HP, 1); +data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1); +env->cpucfg[1] = data; + +data = 0; +data = FIELD_DP32(data, CPUCFG2, FP, 1); +data = FIELD_DP32(data, CPUCFG2, FP_SP, 1); +data = FIELD_DP32(data, CPUCFG2, FP_DP, 1); +data = FIELD_DP32(data, CPUCFG2, FP_VER, 1); +data = FIELD_DP32(data, CPUCFG2, LSX, 1); +data = FIELD_DP32(data, CPUCFG2, LASX, 1); +data = FIELD_DP32(data, CPUCFG2, COMPLEX, 1); +data = FIELD_DP32(data, CPUCFG2, CRYPTO, 1); +data = FIELD_DP32(data, CPUCFG2, LLFTP, 1); +data = FIELD_DP32(data, CPUCFG2, LLF
[PATCH v8 06/29] target/loongarch: Add fixed point bit instruction translation
This includes: - EXT.W.{B/H} - CL{O/Z}.{W/D}, CT{O/Z}.{W/D} - BYTEPICK.{W/D} - REVB.{2H/4H/2W/D} - REVH.{2W/D} - BITREV.{4B/8B}, BITREV.{W/D} - BSTRINS.{W/D}, BSTRPICK.{W/D} - MASKEQZ, MASKNEZ Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/helper.h | 4 + target/loongarch/insn_trans/trans_bit.c | 255 target/loongarch/insns.decode | 45 ++ target/loongarch/op_helper.c| 22 +++ target/loongarch/translate.c| 1 + 5 files changed, 327 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_bit.c diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 09bfcfd..e39574e 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -7,3 +7,7 @@ */ DEF_HELPER_2(raise_exception, noreturn, env, i32) + +DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl) +DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) diff --git a/target/loongarch/insn_trans/trans_bit.c b/target/loongarch/insn_trans/trans_bit.c new file mode 100644 index 000..b0bee95 --- /dev/null +++ b/target/loongarch/insn_trans/trans_bit.c @@ -0,0 +1,255 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_r2(DisasContext *ctx, arg_fmt_rdrj *a, + DisasExtend src_ext, DisasExtend dst_ext, + void (*func)(TCGv, TCGv)) +{ +TCGv dest = gpr_dst(ctx, a->rd, dst_ext); +TCGv src1 = gpr_src(ctx, a->rj, src_ext); + +func(dest, src1); + +if (dst_ext) { +gen_set_gpr(a->rd, dest, dst_ext); +} +return true; +} + +static bool trans_bytepick_w(DisasContext *ctx, arg_bytepick_w *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + +tcg_gen_concat_tl_i64(dest, src1, src2); +tcg_gen_sextract_i64(dest, dest, (32 - (a->sa2) * 8), 32); + +return true; +} + +static bool trans_bytepick_d(DisasContext *ctx, arg_bytepick_d *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + +tcg_gen_extract2_i64(dest, src1, src2, (64 - (a->sa3) * 8)); +return true; +} + +static bool trans_bstrins_w(DisasContext *ctx, arg_bstrins_w *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +if (a->lsbw > a->msbw) { +return false; +} + +tcg_gen_deposit_tl(dest, dest, src1, a->lsbw, a->msbw - a->lsbw + 1); +tcg_gen_ext32s_tl(dest, dest); + +return true; +} + +static bool trans_bstrins_d(DisasContext *ctx, arg_bstrins_d *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +if (a->lsbd > a->msbd) { +return false; +} + +tcg_gen_deposit_tl(dest, dest, src1, a->lsbd, a->msbd - a->lsbd + 1); +return true; +} + +static bool trans_bstrpick_w(DisasContext *ctx, arg_bstrpick_w *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +if (a->lsbw > a->msbw) { +return false; +} + +tcg_gen_extract_tl(dest, src1, a->lsbw, a->msbw - a->lsbw + 1); +tcg_gen_ext32s_tl(dest, dest); +return true; +} + +static bool trans_bstrpick_d(DisasContext *ctx, arg_bstrpick_d *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +if (a->lsbd > a->msbd) { +return false; +} + +tcg_gen_extract_tl(dest, src1, a->lsbd, a->msbd - a->lsbd + 1); +return true; +} + +static void gen_clz_w(TCGv dest, TCGv src1) +{ +tcg_gen_clzi_tl(dest, src1, TARGET_LONG_BITS); +tcg_gen_subi_tl(dest, dest, TARGET_LONG_BITS - 32); +} + +static void gen_clo_w(TCGv dest, TCGv src1) +{ +tcg_gen_not_tl(dest, src1); +tcg_gen_ext32u_tl(dest, dest); +gen_clz_w(dest, dest); +} + +static void gen_ctz_w(TCGv dest, TCGv src1) +{ +tcg_gen_ori_tl(dest, src1, (target_ulong)MAKE_64BIT_MASK(32, 32)); +tcg_gen_ctzi_tl(dest, dest, 32); +} + +static void gen_cto_w(TCGv dest, TCGv src1) +{ +tcg_gen_not_tl(dest, src1); +tcg_gen_ext32u_tl(dest, dest); +gen_ctz_w(dest, dest); +} + +static void gen_clz_d(TCGv dest, TCGv src1) +{ +tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS); +} + +static void gen_clo_d(TCGv dest, TCGv src1) +{ +tcg_gen_not_tl(dest, src1); +gen_clz_d(dest, dest); +} + +static void gen_ctz_d(TCGv dest, TCGv src1) +{ +tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS); +} + +static void gen_cto_d(TCGv dest, TCGv src1) +{ +tcg_gen_not_tl(dest, src1); +gen_ctz_d(dest, dest); +} + +static void gen_revb_2w(TCGv dest, TCGv src1) +{ +tcg_gen_bswap64_i6
[PATCH v8 13/29] target/loongarch: Add floating point move instruction translation
This includes: - FMOV.{S/D} - FSEL - MOVGR2FR.{W/D}, MOVGR2FRH.W - MOVFR2GR.{S/D}, MOVFRH2GR.S - MOVGR2FCSR, MOVFCSR2GR - MOVFR2CF, MOVCF2FR - MOVGR2CF, MOVCF2GR Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/fpu_helper.c| 6 ++ target/loongarch/helper.h| 2 + target/loongarch/insn_trans/trans_fmov.c | 153 +++ target/loongarch/insns.decode| 41 + target/loongarch/translate.c | 1 + 5 files changed, 203 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fmov.c diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c index 6f1b9c8..a013022 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -857,3 +857,9 @@ uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj) update_fcsr0(env, GETPC()); return fd; } + +void helper_set_rounding_mode(CPULoongArchState *env, uint32_t fcsr0) +{ +set_float_rounding_mode(ieee_rm[(fcsr0 >> FCSR0_RM) & 0x3], +&env->fp_status); +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index ab0e9d8..c19220a 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -93,3 +93,5 @@ DEF_HELPER_2(ftint_w_s, i64, env, i64) DEF_HELPER_2(ftint_w_d, i64, env, i64) DEF_HELPER_2(frint_s, i64, env, i64) DEF_HELPER_2(frint_d, i64, env, i64) + +DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32) diff --git a/target/loongarch/insn_trans/trans_fmov.c b/target/loongarch/insn_trans/trans_fmov.c new file mode 100644 index 000..0024c0d --- /dev/null +++ b/target/loongarch/insn_trans/trans_fmov.c @@ -0,0 +1,153 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static const uint32_t fcsr_mask[4] = { +UINT32_MAX, FCSR0_M1, FCSR0_M2, FCSR0_M3 +}; + +static bool trans_fsel(DisasContext *ctx, arg_fsel *a) +{ +TCGv zero = tcg_constant_tl(0); +TCGv cond = tcg_temp_new(); + +tcg_gen_ld8u_tl(cond, cpu_env, offsetof(CPULoongArchState, cf[a->ca])); +tcg_gen_movcond_tl(TCG_COND_EQ, cpu_fpr[a->fd], cond, zero, + cpu_fpr[a->fj], cpu_fpr[a->fk]); +tcg_temp_free(cond); +return true; +} + +static bool gen_f2f(DisasContext *ctx, arg_fmt_fdfj *a, +void (*func)(TCGv, TCGv), bool nanbox) +{ +TCGv dest = cpu_fpr[a->fd]; +TCGv src = cpu_fpr[a->fj]; + +func(dest, src); +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} +return true; +} + +static bool gen_r2f(DisasContext *ctx, arg_fmt_fdrj *a, +void (*func)(TCGv, TCGv)) +{ +TCGv src = gpr_src(ctx, a->rj, EXT_NONE); + +func(cpu_fpr[a->fd], src); +return true; +} + +static bool gen_f2r(DisasContext *ctx, arg_fmt_rdfj *a, +void (*func)(TCGv, TCGv)) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + +func(dest, cpu_fpr[a->fj]); +return true; +} + +static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) +{ +uint32_t mask = fcsr_mask[a->fcsrd]; +TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE); + +if (mask == UINT32_MAX) { +tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj); +} else { +TCGv_i32 temp = tcg_temp_new_i32(); + +tcg_gen_extrl_i64_i32(temp, Rj); +tcg_gen_andi_i32(temp, temp, mask); +tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask); +tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp); +tcg_temp_free_i32(temp); + +/* + * Install the new rounding mode to fpu_status, if changed. + * Note that FCSR3 is exactly the rounding mode field. + */ +if (mask != FCSR0_M3) { +return true; +} +} +gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0); +return true; +} + +static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) +{ +TCGv_i32 temp = tcg_temp_new_i32(); +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); + +tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]); +tcg_gen_ext_i32_i64(dest, temp); +tcg_temp_free_i32(temp); +return true; +} + +static void gen_movgr2fr_w(TCGv dest, TCGv src) +{ +tcg_gen_deposit_i64(dest, dest, src, 0, 32); +} + +static void gen_movgr2frh_w(TCGv dest, TCGv src) +{ +tcg_gen_deposit_i64(dest, dest, src, 32, 32); +} + +static void gen_movfrh2gr_s(TCGv dest, TCGv src) +{ +tcg_gen_sextract_tl(dest, src, 32, 32); +} + +static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a) +{ +TCGv t0 = tcg_temp_new(); + +tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1); +tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); + +tcg_temp_free(t0); +return true; +} + +static bool trans_movcf2fr(DisasContext *ctx, arg_movcf2fr *a) +{ +tcg_gen_ld8u_tl(cpu_fpr[a->fd], cpu_
[PATCH v8 07/29] target/loongarch: Add fixed point load/store instruction translation
This includes: - LD.{B[U]/H[U]/W[U]/D}, ST.{B/H/W/D} - LDX.{B[U]/H[U]/W[U]/D}, STX.{B/H/W/D} - LDPTR.{W/D}, STPTR.{W/D} - PRELD - LD{GT/LE}.{B/H/W/D}, ST{GT/LE}.{B/H/W/D} - DBAR, IBAR Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/helper.h | 3 + target/loongarch/insn_trans/trans_memory.c | 235 + target/loongarch/insns.decode | 58 +++ target/loongarch/op_helper.c | 15 ++ target/loongarch/translate.c | 30 5 files changed, 341 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_memory.c diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index e39574e..09b5a3d 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -11,3 +11,6 @@ DEF_HELPER_2(raise_exception, noreturn, env, i32) DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) + +DEF_HELPER_3(asrtle_d, void, env, tl, tl) +DEF_HELPER_3(asrtgt_d, void, env, tl, tl) diff --git a/target/loongarch/insn_trans/trans_memory.c b/target/loongarch/insn_trans/trans_memory.c new file mode 100644 index 000..343d51c --- /dev/null +++ b/target/loongarch/insn_trans/trans_memory.c @@ -0,0 +1,235 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_load(DisasContext *ctx, arg_fmt_rdrjsi12 *a, MemOp mop) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); +TCGv temp = NULL; + +if (a->si12) { +temp = tcg_temp_new(); +tcg_gen_addi_tl(temp, addr, a->si12); +addr = temp; +} + +tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + +if (temp) { +tcg_temp_free(temp); +} +return true; +} + +static bool gen_store(DisasContext *ctx, arg_fmt_rdrjsi12 *a, MemOp mop) +{ +TCGv data = gpr_src(ctx, a->rd, EXT_NONE); +TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); +TCGv temp = NULL; + +if (a->si12) { +temp = tcg_temp_new(); +tcg_gen_addi_tl(temp, addr, a->si12); +addr = temp; +} + +tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + +if (temp) { +tcg_temp_free(temp); +} +return true; +} + +static bool gen_loadx(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + +tcg_temp_free(addr); +return true; +} + +static bool gen_storex(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ +TCGv data = gpr_src(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + +tcg_temp_free(addr); +return true; +} + +static bool gen_load_gt(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtgt_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + +tcg_temp_free(addr); +return true; +} + +static bool gen_load_le(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtle_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop); + +tcg_temp_free(addr); +return true; +} + +static bool gen_store_gt(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ +TCGv data = gpr_src(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtgt_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop); + +tcg_temp_free(addr); +return true; +} + +static bool gen_store_le(DisasContext *ctx, arg_fmt_rdrjrk *a, MemOp mop) +{ +TCGv data = gpr_src(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtle_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_st_tl(data, addr,
[PATCH v8 08/29] target/loongarch: Add fixed point atomic instruction translation
This includes: - LL.{W/D}, SC.{W/D} - AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[_DB].{W/D} - AM{MAX/MIN}[_DB].{WU/DU} Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/insn_trans/trans_atomic.c | 133 + target/loongarch/insns.decode | 44 ++ target/loongarch/translate.c | 1 + 3 files changed, 178 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_atomic.c diff --git a/target/loongarch/insn_trans/trans_atomic.c b/target/loongarch/insn_trans/trans_atomic.c new file mode 100644 index 000..7613f21 --- /dev/null +++ b/target/loongarch/insn_trans/trans_atomic.c @@ -0,0 +1,133 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_ll(DisasContext *ctx, arg_fmt_rdrjsi14 *a, + void (*func)(TCGv, TCGv, int)) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv t0 = tcg_temp_new(); + +tcg_gen_addi_tl(t0, src1, a->si14 << 2); +func(dest, t0, ctx->mem_idx); +tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr)); +tcg_gen_st_tl(dest, cpu_env, offsetof(CPULoongArchState, llval)); +tcg_temp_free(t0); +return true; +} + +static bool gen_sc(DisasContext *ctx, arg_fmt_rdrjsi14 *a, MemOp mop) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE); +TCGv t0 = tcg_temp_new(); +TCGv val = tcg_temp_new(); + +TCGLabel *l1 = gen_new_label(); +TCGLabel *done = gen_new_label(); + +tcg_gen_addi_tl(t0, src1, a->si14 << 2); +tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lladdr, l1); +tcg_gen_movi_tl(dest, 0); +tcg_gen_br(done); + +gen_set_label(l1); +tcg_gen_mov_tl(val, src2); +/* generate cmpxchg */ +tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, + val, ctx->mem_idx, mop); +tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval); +gen_set_label(done); +tcg_temp_free(t0); +tcg_temp_free(val); +return true; +} + +static bool gen_am(DisasContext *ctx, arg_fmt_rdrjrk *a, + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), + MemOp mop) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); +TCGv val = gpr_src(ctx, a->rk, EXT_NONE); + +if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { +qemu_log_mask(LOG_GUEST_ERROR, + "Warning: source register overlaps destination register" + "in atomic insn at pc=0x" TARGET_FMT_lx "\n", + ctx->base.pc_next - 4); +return false; +} + +func(dest, addr, val, ctx->mem_idx, mop); +return true; +} + +static bool gen_am_db(DisasContext *ctx, arg_fmt_rdrjrk *a, + void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), + MemOp mop) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); +TCGv val = gpr_src(ctx, a->rk, EXT_NONE); + +if ((a->rd != 0) && ((a->rj == a->rd) || (a->rk == a->rd))) { +qemu_log_mask(LOG_GUEST_ERROR, + "Warning: source register overlaps destination register" + "in atomic insn at pc=0x" TARGET_FMT_lx "\n", + ctx->base.pc_next - 4); +return false; +} + +gen_loongarch_sync(0x10); +func(dest, addr, val, ctx->mem_idx, mop); + +return true; +} + +TRANS(ll_w, gen_ll, tcg_gen_qemu_ld32s) +TRANS(sc_w, gen_sc, MO_TESL) +TRANS(ll_d, gen_ll, tcg_gen_qemu_ld64) +TRANS(sc_d, gen_sc, MO_TEQ) +TRANS(amswap_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL) +TRANS(amswap_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEQ) +TRANS(amadd_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL) +TRANS(amadd_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEQ) +TRANS(amand_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL) +TRANS(amand_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEQ) +TRANS(amor_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL) +TRANS(amor_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEQ) +TRANS(amxor_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL) +TRANS(amxor_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEQ) +TRANS(ammax_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL) +TRANS(ammax_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEQ) +TRANS(ammin_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL) +TRANS(ammin_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEQ) +TRANS(ammax_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL) +TRANS(ammax_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEQ) +TRANS(ammin_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL) +TRANS(ammin_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEQ) +TRANS(amswap_db_w, gen_am_db,
[PATCH v8 11/29] target/loongarch: Add floating point comparison instruction translation
This includes: - FCMP.cond.{S/D} Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/fpu_helper.c| 60 target/loongarch/helper.h| 9 + target/loongarch/insn_trans/trans_fcmp.c | 59 +++ target/loongarch/insns.decode| 10 ++ target/loongarch/internals.h | 5 +++ target/loongarch/translate.c | 1 + 6 files changed, 144 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fcmp.c diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c index f5c32e4..d2c4fff 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -404,3 +404,63 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj, update_fcsr0(env, GETPC()); return fd; } + +static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp, +uint32_t flags) +{ +bool ret; + +switch (cmp) { +case float_relation_less: +ret = (flags & FCMP_LT); +break; +case float_relation_equal: +ret = (flags & FCMP_EQ); +break; +case float_relation_greater: +ret = (flags & FCMP_GT); +break; +case float_relation_unordered: +ret = (flags & FCMP_UN); +break; +default: +g_assert_not_reached(); +} +update_fcsr0(env, GETPC()); + +return ret; +} + +/* fcmp_cXXX_s */ +uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ +FloatRelation cmp = float32_compare_quiet((uint32_t)fj, + (uint32_t)fk, &env->fp_status); +return fcmp_common(env, cmp, flags); +} + +/* fcmp_sXXX_s */ +uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ +FloatRelation cmp = float32_compare((uint32_t)fj, +(uint32_t)fk, &env->fp_status); +return fcmp_common(env, cmp, flags); +} + +/* fcmp_cXXX_d */ +uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ +FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status); +return fcmp_common(env, cmp, flags); +} + +/* fcmp_sXXX_d */ +uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, + uint64_t fk, uint32_t flags) +{ +FloatRelation cmp = float64_compare(fj, fk, &env->fp_status); +return fcmp_common(env, cmp, flags); +} diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 901ab27..e0ab735 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -55,3 +55,12 @@ DEF_HELPER_2(frecip_d, i64, env, i64) DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64) DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64) + +/* fcmp.cXXX.s */ +DEF_HELPER_4(fcmp_c_s, i64, env, i64, i64, i32) +/* fcmp.sXXX.s */ +DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32) +/* fcmp.cXXX.d */ +DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32) +/* fcmp.sXXX.d */ +DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32) diff --git a/target/loongarch/insn_trans/trans_fcmp.c b/target/loongarch/insn_trans/trans_fcmp.c new file mode 100644 index 000..1c5945b --- /dev/null +++ b/target/loongarch/insn_trans/trans_fcmp.c @@ -0,0 +1,59 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +/* bit0(signaling/quiet) bit1(lt) bit2(eq) bit3(un) bit4(neq) */ +static uint32_t get_fcmp_flags(int cond) +{ +uint32_t flags = 0; + +if (cond & 0x1) { +flags |= FCMP_LT; +} +if (cond & 0x2) { +flags |= FCMP_EQ; +} +if (cond & 0x4) { +flags |= FCMP_UN; +} +if (cond & 0x8) { +flags |= FCMP_GT | FCMP_LT; +} +return flags; +} + +static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a) +{ +TCGv var = tcg_temp_new(); +uint32_t flags; +void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32); + +fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s); +flags = get_fcmp_flags(a->fcond >> 1); + +fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags)); + +tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd & 0x7])); +tcg_temp_free(var); +return true; +} + +static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a) +{ +TCGv var = tcg_temp_new(); +uint32_t flags; +void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32); +fn = (a->fcond & 1 ? gen_helper_fcmp_s_d : gen_helper_fcmp_c_d); +flags = get_fcmp_flags(a->fcond >> 1); + +fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags)); + +tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoong
[PATCH v8 12/29] target/loongarch: Add floating point conversion instruction translation
This includes: - FCVT.S.D, FCVT.D.S - FFINT.{S/D}.{W/L}, FTINT.{W/L}.{S/D} - FTINT{RM/RP/RZ/RNE}.{W/L}.{S/D} - FRINT.{S/D} Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/fpu_helper.c| 393 +++ target/loongarch/helper.h| 29 +++ target/loongarch/insn_trans/trans_fcnv.c | 36 +++ target/loongarch/insns.decode| 32 +++ target/loongarch/translate.c | 1 + 5 files changed, 491 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fcnv.c diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c index d2c4fff..6f1b9c8 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -464,3 +464,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, FloatRelation cmp = float64_compare(fj, fk, &env->fp_status); return fcmp_common(env, cmp, flags); } + +/* floating point conversion */ +uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = nanbox_s(float64_to_float32(fj, &env->fp_status)); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = float32_to_float64((uint32_t)fj, &env->fp_status); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status)); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = nanbox_s(int64_to_float32(fj, &env->fp_status)); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = int32_to_float64((int32_t)fj, &env->fp_status); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = int64_to_float64(fj, &env->fp_status); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status)); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; + +fd = float64_round_to_int(fj, &env->fp_status); +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; +FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + +set_float_rounding_mode(float_round_down, &env->fp_status); +fd = float64_to_int64(fj, &env->fp_status); +set_float_rounding_mode(old_mode, &env->fp_status); + +if (get_float_exception_flags(&env->fp_status) & +(float_flag_invalid | float_flag_overflow)) { +fd = FLOAT_TO_INT64_OVERFLOW; +} +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; +FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + +set_float_rounding_mode(float_round_down, &env->fp_status); +fd = float32_to_int64((uint32_t)fj, &env->fp_status); +set_float_rounding_mode(old_mode, &env->fp_status); + +if (get_float_exception_flags(&env->fp_status) & +(float_flag_invalid | float_flag_overflow)) { +fd = FLOAT_TO_INT64_OVERFLOW; +} +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; +FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + +set_float_rounding_mode(float_round_down, &env->fp_status); +fd = (uint64_t)float64_to_int32(fj, &env->fp_status); +set_float_rounding_mode(old_mode, &env->fp_status); + +if (get_float_exception_flags(&env->fp_status) & +(float_flag_invalid | float_flag_overflow)) { +fd = FLOAT_TO_INT32_OVERFLOW; +} +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; +FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + +set_float_rounding_mode(float_round_down, &env->fp_status); +fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); +set_float_rounding_mode(old_mode, &env->fp_status); + +if (get_float_exception_flags(&env->fp_status) & +(float_flag_invalid | float_flag_overflow)) { +fd = FLOAT_TO_INT32_OVERFLOW; +} +update_fcsr0(env, GETPC()); +return fd; +} + +uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj) +{ +uint64_t fd; +FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); + +se
[PATCH v8 19/29] linux-user: Add LoongArch signal support
Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- accel/tcg/user-exec.c | 15 +++ linux-user/loongarch64/signal.c| 163 + linux-user/loongarch64/target_signal.h | 30 ++ 3 files changed, 208 insertions(+) create mode 100644 linux-user/loongarch64/signal.c create mode 100644 linux-user/loongarch64/target_signal.h diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index e6bb29b..7604b0a 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -803,6 +803,21 @@ int cpu_signal_handler(int host_signum, void *pinfo, return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } +#elif defined(__loongarch64__) + +int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) +{ +siginfo_t *info = pinfo; +ucontext_t *uc = puc; +greg_t pc = uc->uc_mcontext.__pc; +int is_write; + +/* XXX: compute is_write */ +is_write = 0; +return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); +} + #elif defined(__riscv) int cpu_signal_handler(int host_signum, void *pinfo, diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c new file mode 100644 index 000..4f289e1 --- /dev/null +++ b/linux-user/loongarch64/signal.c @@ -0,0 +1,163 @@ +/* + * LoongArch emulation of Linux signals + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu.h" +#include "signal-common.h" +#include "user-internals.h" +#include "linux-user/trace.h" + +struct target_sigcontext { +uint64_t sc_pc; +uint64_t sc_gpr[32]; +uint64_t sc_fpr[32]; +uint64_t sc_fcc; +uint32_t sc_fcsr; +uint32_t sc_flags; +}; + +struct target_ucontext { +target_ulong tuc_flags; +target_ulong tuc_link; +target_stack_t tuc_stack; +target_ulong pad0; +struct target_sigcontext tuc_mcontext; +target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { +struct target_siginfo rs_info; +struct target_ucontext rs_uc; +}; + +static inline void setup_sigcontext(CPULoongArchState *env, +struct target_sigcontext *sc) +{ +int i; + +__put_user(env->pc, &sc->sc_pc); + +__put_user(0, &sc->sc_gpr[0]); +for (i = 1; i < 32; ++i) { +__put_user(env->gpr[i], &sc->sc_gpr[i]); +} + +for (i = 0; i < 32; ++i) { +__put_user(env->fpr[i], &sc->sc_fpr[i]); +} +} + +static inline void +restore_sigcontext(CPULoongArchState *env, struct target_sigcontext *sc) +{ +int i; + +__get_user(env->pc, &sc->sc_pc); + +for (i = 1; i < 32; ++i) { +__get_user(env->gpr[i], &sc->sc_gpr[i]); +} + +for (i = 0; i < 32; ++i) { +__get_user(env->fpr[i], &sc->sc_fpr[i]); +} +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPULoongArchState *env, + size_t frame_size) +{ +unsigned long sp; + +sp = target_sigsp(get_sp_from_cpustate(env) - 32, ka); + +return (sp - frame_size) & ~7; +} + +void setup_rt_frame(int sig, struct target_sigaction *ka, +target_siginfo_t *info, +target_sigset_t *set, CPULoongArchState *env) +{ +struct target_rt_sigframe *frame; +abi_ulong frame_addr; +int i; + +frame_addr = get_sigframe(ka, env, sizeof(*frame)); +trace_user_setup_rt_frame(env, frame_addr); +if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +goto give_sigsegv; +} + +tswap_siginfo(&frame->rs_info, info); + +__put_user(0, &frame->rs_uc.tuc_flags); +__put_user(0, &frame->rs_uc.tuc_link); +target_save_altstack(&frame->rs_uc.tuc_stack, env); + +setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); + +for (i = 0; i < TARGET_NSIG_WORDS; i++) { +__put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); +} + +env->gpr[4] = sig; +env->gpr[5] = frame_addr + offsetof(struct target_rt_sigframe, rs_info); +env->gpr[6] = frame_addr + offsetof(struct target_rt_sigframe, rs_uc); +env->gpr[3] = frame_addr; +env->gpr[1] = default_rt_sigreturn; + +env->pc = env->gpr[20] = ka->_sa_handler; +unlock_user_struct(frame, frame_addr, 1); +return; + +give_sigsegv: +unlock_user_struct(frame, frame_addr, 1); +force_sigsegv(sig); +} + +long do_rt_sigreturn(CPULoongArchState *env) +{ +struct target_rt_sigframe *frame; +abi_ulong frame_addr; +sigset_t blocked; + +frame_addr = env->gpr[3]; +trace_user_do_rt_sigreturn(env, frame_addr); +if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { +goto badframe; +} + +target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); +set_sigmask(&blocked); + +restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); +target_restore_altstack(&frame->rs_uc.tuc_stack, env);
[PATCH v8 22/29] linux-user: Add LoongArch cpu_loop support
Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- configure | 5 ++ linux-user/loongarch64/cpu_loop.c | 98 + linux-user/loongarch64/target_cpu.h | 35 + 3 files changed, 138 insertions(+) create mode 100644 linux-user/loongarch64/cpu_loop.c create mode 100644 linux-user/loongarch64/target_cpu.h diff --git a/configure b/configure index 039467c..9563595 100755 --- a/configure +++ b/configure @@ -579,6 +579,8 @@ elif check_define __arm__ ; then cpu="arm" elif check_define __aarch64__ ; then cpu="aarch64" +elif check_define __loongarch64__ ; then + cpu="loongarch64" else cpu=$(uname -m) fi @@ -610,6 +612,9 @@ case "$cpu" in sparc|sun4[cdmuv]) cpu="sparc" ;; + loongarch) +cpu="loongarch" + ;; *) # This will result in either an error or falling back to TCI later ARCH=unknown diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c new file mode 100644 index 000..2529683 --- /dev/null +++ b/linux-user/loongarch64/cpu_loop.c @@ -0,0 +1,98 @@ +/* + * QEMU LoongArch user cpu_loop. + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "qemu.h" +#include "qemu-common.h" +#include "user-internals.h" +#include "cpu_loop-common.h" +#include "signal-common.h" + +void cpu_loop(CPULoongArchState *env) +{ +CPUState *cs = env_cpu(env); +int trapnr, si_code; +abi_long ret; + +for (;;) { +cpu_exec_start(cs); +trapnr = cpu_exec(cs); +cpu_exec_end(cs); +process_queued_cpu_work(cs); + +switch (trapnr) { +case EXCP_INTERRUPT: +/* just indicate that signals should be handled asap */ +break; +case EXCP_SYSCALL: +env->pc += 4; +ret = do_syscall(env, env->gpr[11], + env->gpr[4], env->gpr[5], + env->gpr[6], env->gpr[7], + env->gpr[8], env->gpr[9], + -1, -1); +if (ret == -TARGET_ERESTARTSYS) { +env->pc -= 4; +break; +} +if (ret == -TARGET_QEMU_ESIGRETURN) { +/* + * Returning from a successful sigreturn syscall. + * Avoid clobbering register state. + */ +break; +} +env->gpr[4] = ret; +break; +case EXCP_ADE: +force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->badaddr); +break; +case EXCP_INE: +force_sig_fault(TARGET_SIGILL, 0, env->pc); +break; +case EXCP_FPE: +si_code = TARGET_FPE_FLTUNK; +if (GET_FP_CAUSE(env->fcsr0) & FP_INVALID) { +si_code = TARGET_FPE_FLTINV; +} else if (GET_FP_CAUSE(env->fcsr0) & FP_DIV0) { +si_code = TARGET_FPE_FLTDIV; +} else if (GET_FP_CAUSE(env->fcsr0) & FP_OVERFLOW) { +si_code = TARGET_FPE_FLTOVF; +} else if (GET_FP_CAUSE(env->fcsr0) & FP_UNDERFLOW) { +si_code = TARGET_FPE_FLTUND; +} else if (GET_FP_CAUSE(env->fcsr0) & FP_INEXACT) { +si_code = TARGET_FPE_FLTRES; +} +force_sig_fault(TARGET_SIGFPE, si_code, env->pc); +break; +case EXCP_DEBUG: +case EXCP_BREAK: +force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); +break; +case EXCP_ATOMIC: +cpu_exec_step_atomic(cs); +break; +default: +EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", + trapnr); +exit(EXIT_FAILURE); +} +process_pending_signals(env); +} +} + +void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) +{ +int i; + +for (i = 0; i < 32; i++) { +env->gpr[i] = regs->regs[i]; +} +env->pc = regs->csr_era; + +} diff --git a/linux-user/loongarch64/target_cpu.h b/linux-user/loongarch64/target_cpu.h new file mode 100644 index 000..5bd13a7 --- /dev/null +++ b/linux-user/loongarch64/target_cpu.h @@ -0,0 +1,35 @@ +/* + * LoongArch specific CPU ABI and functions for linux-user + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_CPU_H +#define LOONGARCH_TARGET_CPU_H + +static inline void cpu_clone_regs_child(CPULoongArchState *env, +target_ulong newsp, unsigned flags) +{ +if (newsp) { +env->gpr[3] = newsp; +} +env->gpr[4] = 0; +} + +static inline void cpu_clone_regs_parent(CPULoongArchState *env, + unsigned flags) +{ +} + +static inline void
[PATCH v8 05/29] target/loongarch: Add fixed point shift instruction translation
This includes: - SLL.W, SRL.W, SRA.W, ROTR.W - SLLI.W, SRLI.W, SRAI.W, ROTRI.W - SLL.D, SRL.D, SRA.D, ROTR.D - SLLI.D, SRLI.D, SRAI.D, ROTRI.D Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/insn_trans/trans_shift.c | 131 ++ target/loongarch/insns.decode | 26 ++ target/loongarch/translate.c | 1 + 3 files changed, 158 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_shift.c diff --git a/target/loongarch/insn_trans/trans_shift.c b/target/loongarch/insn_trans/trans_shift.c new file mode 100644 index 000..759d22b --- /dev/null +++ b/target/loongarch/insn_trans/trans_shift.c @@ -0,0 +1,131 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_r2_ui5(DisasContext *ctx, arg_slli_w *a, + void(*func)(TCGv, TCGv, TCGv)) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN); +TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO); +TCGv src2 = tcg_constant_tl(a->ui5); + +func(dest, src1, src2); +gen_set_gpr(a->rd, dest, EXT_SIGN); + +return true; +} + +static bool gen_r2_ui6(DisasContext *ctx, arg_slli_d *a, + void(*func)(TCGv, TCGv, target_long)) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +func(dest, src1, a->ui6); + +return true; +} + +static void gen_sll_w(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +tcg_gen_andi_tl(t0, src2, 0x1f); +tcg_gen_shl_tl(dest, src1, t0); +tcg_temp_free(t0); +} + +static void gen_srl_w(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +tcg_gen_andi_tl(t0, src2, 0x1f); +tcg_gen_shr_tl(dest, src1, t0); +tcg_temp_free(t0); +} + +static void gen_sra_w(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +tcg_gen_andi_tl(t0, src2, 0x1f); +tcg_gen_sar_tl(dest, src1, t0); +tcg_temp_free(t0); +} + +static void gen_sll_d(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +tcg_gen_andi_tl(t0, src2, 0x3f); +tcg_gen_shl_tl(dest, src1, t0); +tcg_temp_free(t0); +} + +static void gen_srl_d(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +tcg_gen_andi_tl(t0, src2, 0x3f); +tcg_gen_shr_tl(dest, src1, t0); +tcg_temp_free(t0); +} + +static void gen_sra_d(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +tcg_gen_andi_tl(t0, src2, 0x3f); +tcg_gen_sar_tl(dest, src1, t0); +tcg_temp_free(t0); +} + +static void gen_rotr_w(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv_i32 t1 = tcg_temp_new_i32(); +TCGv_i32 t2 = tcg_temp_new_i32(); +TCGv t0 = tcg_temp_new(); + +tcg_gen_andi_tl(t0, src2, 0x1f); + +tcg_gen_trunc_tl_i32(t1, src1); +tcg_gen_trunc_tl_i32(t2, t0); + +tcg_gen_rotr_i32(t1, t1, t2); +tcg_gen_ext_i32_tl(dest, t1); + +tcg_temp_free_i32(t1); +tcg_temp_free_i32(t2); +tcg_temp_free(t0); +} + +static void gen_rotr_d(TCGv dest, TCGv src1, TCGv src2) +{ +TCGv t0 = tcg_temp_new(); +tcg_gen_andi_tl(t0, src2, 0x3f); +tcg_gen_rotr_tl(dest, src1, t0); +tcg_temp_free(t0); +} + +static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO); + +tcg_gen_sextract_tl(dest, src1, a->ui5, 32 - a->ui5); +return true; +} + +TRANS(sll_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w) +TRANS(srl_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w) +TRANS(sra_w, gen_r3, EXT_SIGN, EXT_NONE, EXT_SIGN, gen_sra_w) +TRANS(sll_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d) +TRANS(srl_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d) +TRANS(sra_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d) +TRANS(rotr_w, gen_r3, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w) +TRANS(rotr_d, gen_r3, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d) +TRANS(slli_w, gen_r2_ui5, tcg_gen_shl_tl) +TRANS(slli_d, gen_r2_ui6, tcg_gen_shli_tl) +TRANS(srli_w, gen_r2_ui5, tcg_gen_shr_tl) +TRANS(srli_d, gen_r2_ui6, tcg_gen_shri_tl) +TRANS(srai_d, gen_r2_ui6, tcg_gen_sari_tl) +TRANS(rotri_w, gen_r2_ui5, gen_rotr_w) +TRANS(rotri_d, gen_r2_ui6, tcg_gen_rotri_tl) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 1e0b755..9302576 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -17,6 +17,8 @@ %ui1210:12 %si1610:s16 %si205:s20 +%ui5 10:5 +%ui6 10:6 # # Argument sets @@ -27,6 +29,8 @@ &fmt_rdrjsi16 rd rj si16 &fmt_rdrjui12 rd rj ui12 &fmt_rdsi20 rd si20 +&fmt_rdrjui5rd rj ui5 +&fmt_rdrjui6rd rj ui6 # # Formats @@ -37,6 +41,8 @@ @fmt_rdrjrksa2 ... .. . . . &fmt_rdrjrksa2 %rd %rj %rk %sa2 @fmt_rdrj
[PATCH v8 20/29] linux-user: Add LoongArch elf support
Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- include/elf.h | 2 ++ linux-user/elfload.c| 58 + linux-user/loongarch64/target_elf.h | 14 + 3 files changed, 74 insertions(+) create mode 100644 linux-user/loongarch64/target_elf.h diff --git a/include/elf.h b/include/elf.h index 811bf4a..3a4bcb6 100644 --- a/include/elf.h +++ b/include/elf.h @@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ +#define EM_LOONGARCH258 /* LoongArch */ + /* * This is an interim value that we will use until the committee comes * up with a final number. diff --git a/linux-user/elfload.c b/linux-user/elfload.c index f9b8261..b703300 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -914,6 +914,64 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en #endif +#ifdef TARGET_LOONGARCH64 + +#define ELF_START_MMAP 0x8000 + +#define ELF_CLASS ELFCLASS64 +#define ELF_ARCHEM_LOONGARCH + +#define elf_check_arch(x) ((x) == EM_LOONGARCH) +static inline void init_thread(struct target_pt_regs *regs, + struct image_info *infop) +{ +regs->csr_crmd = 2 << 3; +regs->csr_era = infop->entry; +regs->regs[3] = infop->start_stack; +} + +/* See linux kernel: arch/loongarch/include/asm/elf.h. */ +#define ELF_NREG 45 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +/* See linux kernel: arch/loongarch/include/asm/reg.h. */ +enum { +TARGET_EF_R0 = 0, +TARGET_EF_CSR_ERA = TARGET_EF_R0 + 32, +TARGET_EF_CSR_BADVADDR = TARGET_EF_R0 + 33, +}; + +/* See linux kernel: arch/loongarch/kernel/process.c:loongarch_dump_regs64. */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, + const CPULoongArchState *env) +{ +int i; + +for (i = 0; i < TARGET_EF_R0; i++) { +(*regs)[i] = 0; +} +(*regs)[TARGET_EF_R0] = 0; + +for (i = 1; i < ARRAY_SIZE(env->gpr); i++) { +(*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]); +} + +(*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc); +(*regs)[TARGET_EF_CSR_BADVADDR] = tswapreg(env->badaddr); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE4096 + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ +return 0; +} + +#endif /* TARGET_LOONGARCH64 */ + #ifdef TARGET_MIPS #define ELF_START_MMAP 0x8000 diff --git a/linux-user/loongarch64/target_elf.h b/linux-user/loongarch64/target_elf.h new file mode 100644 index 000..7c88394 --- /dev/null +++ b/linux-user/loongarch64/target_elf.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + + +#ifndef LOONGARCH_TARGET_ELF_H +#define LOONGARCH_TARGET_ELF_H +static inline const char *cpu_get_model(uint32_t eflags) +{ +return "Loongson-3A5000"; +} +#endif -- 1.8.3.1
[PATCH v8 26/29] target/loongarch: 'make check-tcg' support
Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- tests/tcg/configure.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index 1f985cc..d8f677d 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -51,6 +51,7 @@ fi : ${cross_cc_cflags_armeb="-mbig-endian"} : ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"} : ${cross_cc_cflags_hexagon="-mv67 -O2 -static"} +: ${cross_cc_loongarch64="loongarch64-unknown-linux-gnu-gcc"} : ${cross_cc_hppa="hppa-linux-gnu-gcc"} : ${cross_cc_i386="i686-linux-gnu-gcc"} : ${cross_cc_cflags_i386="-m32"} -- 1.8.3.1
[PATCH v8 09/29] target/loongarch: Add fixed point extra instruction translation
This includes: - CRC[C].W.{B/H/W/D}.W - SYSCALL - BREAK - ASRT{LE/GT}.D - RDTIME{L/H}.W, RDTIME.D - CPUCFG Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/helper.h | 4 ++ target/loongarch/insn_trans/trans_extra.c | 87 +++ target/loongarch/insns.decode | 25 + target/loongarch/op_helper.c | 26 + target/loongarch/translate.c | 1 + 5 files changed, 143 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_extra.c diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index 09b5a3d..e4b4595 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -14,3 +14,7 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_3(asrtle_d, void, env, tl, tl) DEF_HELPER_3(asrtgt_d, void, env, tl, tl) + +DEF_HELPER_3(crc32, tl, tl, tl, tl) +DEF_HELPER_3(crc32c, tl, tl, tl, tl) +DEF_HELPER_2(cpucfg, tl, env, tl) diff --git a/target/loongarch/insn_trans/trans_extra.c b/target/loongarch/insn_trans/trans_extra.c new file mode 100644 index 000..8da3b40 --- /dev/null +++ b/target/loongarch/insn_trans/trans_extra.c @@ -0,0 +1,87 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool trans_break(DisasContext *ctx, arg_break *a) +{ +generate_exception(ctx, EXCP_BREAK); +return true; +} + +static bool trans_syscall(DisasContext *ctx, arg_syscall *a) +{ +generate_exception(ctx, EXCP_SYSCALL); +return true; +} + +static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + +gen_helper_asrtle_d(cpu_env, src1, src2); +return true; +} + +static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + +gen_helper_asrtgt_d(cpu_env, src1, src2); +return true; +} + +static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a) +{ +tcg_gen_movi_tl(cpu_gpr[a->rd], 0); +return true; +} + +static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a) +{ +tcg_gen_movi_tl(cpu_gpr[a->rd], 0); +return true; +} + +static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) +{ +tcg_gen_movi_tl(cpu_gpr[a->rd], 0); +return true; +} + +static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +gen_helper_cpucfg(dest, cpu_env, src1); +return true; +} + +static bool gen_crc(DisasContext *ctx, arg_fmt_rdrjrk *a, +void (*func)(TCGv, TCGv, TCGv, TCGv), +TCGv tsz) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); + +func(dest, src2, src1, tsz); + +gen_set_gpr(a->rd, dest, EXT_SIGN); +return true; +} + +TRANS(crc_w_b_w, gen_crc, gen_helper_crc32, tcg_constant_tl(1)) +TRANS(crc_w_h_w, gen_crc, gen_helper_crc32, tcg_constant_tl(2)) +TRANS(crc_w_w_w, gen_crc, gen_helper_crc32, tcg_constant_tl(4)) +TRANS(crc_w_d_w, gen_crc, gen_helper_crc32, tcg_constant_tl(8)) +TRANS(crcc_w_b_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(1)) +TRANS(crcc_w_h_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(2)) +TRANS(crcc_w_w_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(4)) +TRANS(crcc_w_d_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(8)) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index 574c055..66bc314 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -27,6 +27,7 @@ %si1410:s14 %hint0:5 %whint 0:15 +%code0:15 # # Argument sets @@ -46,6 +47,8 @@ &fmt_rdrjsi14 rd rj si14 &fmt_hintrjsi12 hint rj si12 &fmt_whint whint +&fmt_rjrk rj rk +&fmt_code code # # Formats @@ -65,6 +68,8 @@ @fmt_hintrjsi12 .. . . &fmt_hintrjsi12 %hint %rj %si12 @fmt_whint . ... &fmt_whint %whint @fmt_rdrjsi14 .. . . &fmt_rdrjsi14 %rd %rj %si14 +@fmt_rjrk . . . .&fmt_rjrk %rj %rk +@fmt_code . ... &fmt_code %code # # Fixed point arithmetic operation instruction @@ -260,3 +265,23 @@ ammax_db_wu 0011 1111 0 . . . @fmt_rdrjrk ammax_db_du 0011 1111 1 . . .@fmt_rdrjrk ammin_db_wu 0011 1111 00010 . . .@fmt_rdrjrk ammin_db_du 0011 1111 00011 . . .@fmt_rdrjrk + +#
[PATCH v8 17/29] linux-user: Add LoongArch generic header files
This includes: - sockbits.h - target_errno_defs.h - target_fcntl.h - termbits.h Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- linux-user/loongarch64/sockbits.h | 1 + linux-user/loongarch64/target_errno_defs.h | 7 +++ linux-user/loongarch64/target_fcntl.h | 12 linux-user/loongarch64/termbits.h | 1 + 4 files changed, 21 insertions(+) create mode 100644 linux-user/loongarch64/sockbits.h create mode 100644 linux-user/loongarch64/target_errno_defs.h create mode 100644 linux-user/loongarch64/target_fcntl.h create mode 100644 linux-user/loongarch64/termbits.h diff --git a/linux-user/loongarch64/sockbits.h b/linux-user/loongarch64/sockbits.h new file mode 100644 index 000..0e4c8f0 --- /dev/null +++ b/linux-user/loongarch64/sockbits.h @@ -0,0 +1 @@ +#include "../generic/sockbits.h" diff --git a/linux-user/loongarch64/target_errno_defs.h b/linux-user/loongarch64/target_errno_defs.h new file mode 100644 index 000..17165c1 --- /dev/null +++ b/linux-user/loongarch64/target_errno_defs.h @@ -0,0 +1,7 @@ +#ifndef LOONGARCH_TARGET_ERRNO_DEFS_H +#define LOONGARCH_TARGET_ERRNO_DEFS_H + +/* Target uses generic errno */ +#include "../generic/target_errno_defs.h" + +#endif diff --git a/linux-user/loongarch64/target_fcntl.h b/linux-user/loongarch64/target_fcntl.h new file mode 100644 index 000..b810293 --- /dev/null +++ b/linux-user/loongarch64/target_fcntl.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_FCNTL_H +#define LOONGARCH_TARGET_FCNTL_H + +#include "../generic/fcntl.h" + +#endif /* LOONGARCH_TARGET_FCNTL_H */ diff --git a/linux-user/loongarch64/termbits.h b/linux-user/loongarch64/termbits.h new file mode 100644 index 000..b1d4f4f --- /dev/null +++ b/linux-user/loongarch64/termbits.h @@ -0,0 +1 @@ +#include "../generic/termbits.h" -- 1.8.3.1
[PATCH v8 28/29] accel/tcg/user-exec: Implement CPU-specific signal handler for loongarch64 hosts
Base-on: <20210925173032.2434906-30-...@xen0n.name> Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- accel/tcg/user-exec.c | 64 --- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 7604b0a..ec887c4 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -811,10 +811,68 @@ int cpu_signal_handler(int host_signum, void *pinfo, siginfo_t *info = pinfo; ucontext_t *uc = puc; greg_t pc = uc->uc_mcontext.__pc; -int is_write; +uint32_t insn = *(uint32_t *)pc; +int is_write = 0; + +/* Detect store by reading the instruction at the program counter. */ +switch ((insn >> 26) & 0b11) { +case 0b001000: /* {ll,sc}.[wd] */ +switch ((insn >> 24) & 0b11) { +case 0b01: /* sc.w */ +case 0b11: /* sc.d */ +is_write = 1; +break; +} +break; +case 0b001001: /* {ld,st}ox4.[wd] ({ld,st}ptr.[wd]) */ +switch ((insn >> 24) & 0b11) { +case 0b01: /* stox4.w (stptr.w) */ +case 0b11: /* stox4.d (stptr.d) */ +is_write = 1; +break; +} +break; +case 0b001010: /* {ld,st}.* family */ +switch ((insn >> 22) & 0b) { +case 0b0100: /* st.b */ +case 0b0101: /* st.h */ +case 0b0110: /* st.w */ +case 0b0111: /* st.d */ +case 0b1101: /* fst.s */ +case 0b: /* fst.d */ +is_write = 1; +break; +} +break; +case 0b001110: /* indexed, atomic, bounds-checking memory operations */ +uint32_t sel = (insn >> 15) & 0b111; + +switch (sel) { +case 0b010: /* stx.b */ +case 0b0101000: /* stx.h */ +case 0b011: /* stx.w */ +case 0b0111000: /* stx.d */ +case 0b111: /* fstx.s */ +case 0b000: /* fstx.d */ +case 0b00011101100: /* fstgt.s */ +case 0b00011101101: /* fstgt.d */ +case 0b00011101110: /* fstle.s */ +case 0b0001110: /* fstle.d */ +case 0b0001000: /* stgt.b */ +case 0b0001001: /* stgt.h */ +case 0b0001010: /* stgt.w */ +case 0b0001011: /* stgt.d */ +case 0b0001100: /* stle.b */ +case 0b0001101: /* stle.h */ +case 0b0001110: /* stle.w */ +case 0b000: /* stle.d */ +case 0b0001100 ... 0b00011100011: /* am* insns */ +is_write = 1; +break; +} +break; +} -/* XXX: compute is_write */ -is_write = 0; return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask); } -- 1.8.3.1
[PATCH v8 24/29] default-configs: Add loongarch linux-user support
This patch adds loongarch64 linux-user default configs file. Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- configs/targets/loongarch64-linux-user.mak | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 configs/targets/loongarch64-linux-user.mak diff --git a/configs/targets/loongarch64-linux-user.mak b/configs/targets/loongarch64-linux-user.mak new file mode 100644 index 000..5b0acfa --- /dev/null +++ b/configs/targets/loongarch64-linux-user.mak @@ -0,0 +1,3 @@ +# Default configuration for loongson64-linux-user +TARGET_ARCH=loongarch64 +TARGET_BASE_ARCH=loongarch -- 1.8.3.1
[PATCH v8 29/29] linux-user: Add safe syscall handling for loongarch64 hosts
Base-on: <20210925173032.2434906-29-...@xen0n.name> Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- linux-user/host/loongarch64/hostdep.h | 23 linux-user/host/loongarch64/safe-syscall.inc.S | 80 ++ 2 files changed, 103 insertions(+) create mode 100644 linux-user/host/loongarch64/safe-syscall.inc.S diff --git a/linux-user/host/loongarch64/hostdep.h b/linux-user/host/loongarch64/hostdep.h index 4e55695..e3d5fa7 100644 --- a/linux-user/host/loongarch64/hostdep.h +++ b/linux-user/host/loongarch64/hostdep.h @@ -8,4 +8,27 @@ #ifndef LOONGARCH64_HOSTDEP_H #define LOONGARCH64_HOSTDEP_H +/* We have a safe-syscall.inc.S */ +#define HAVE_SAFE_SYSCALL + +#ifndef __ASSEMBLER__ + +/* These are defined by the safe-syscall.inc.S file */ +extern char safe_syscall_start[]; +extern char safe_syscall_end[]; + +/* Adjust the signal context to rewind out of safe-syscall if we're in it */ +static inline void rewind_if_in_safe_syscall(void *puc) +{ +ucontext_t *uc = puc; +unsigned long long *pcreg = &uc->uc_mcontext.__pc; + +if (*pcreg > (uintptr_t)safe_syscall_start +&& *pcreg < (uintptr_t)safe_syscall_end) { +*pcreg = (uintptr_t)safe_syscall_start; +} +} + +#endif /* __ASSEMBLER__ */ + #endif diff --git a/linux-user/host/loongarch64/safe-syscall.inc.S b/linux-user/host/loongarch64/safe-syscall.inc.S new file mode 100644 index 000..bb53024 --- /dev/null +++ b/linux-user/host/loongarch64/safe-syscall.inc.S @@ -0,0 +1,80 @@ +/* + * safe-syscall.inc.S : host-specific assembly fragment + * to handle signals occurring at the same time as system calls. + * This is intended to be included by linux-user/safe-syscall.S + * + * Ported to LoongArch by WANG Xuerui + * + * Based on safe-syscall.inc.S code for every other architecture, + * originally written by Richard Henderson + * Copyright (C) 2018 Linaro, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + + .global safe_syscall_base + .global safe_syscall_start + .global safe_syscall_end + .type safe_syscall_base, @function + .type safe_syscall_start, @function + .type safe_syscall_end, @function + + /* +* This is the entry point for making a system call. The calling +* convention here is that of a C varargs function with the +* first argument an 'int *' to the signal_pending flag, the +* second one the system call number (as a 'long'), and all further +* arguments being syscall arguments (also 'long'). +* We return a long which is the syscall's return value, which +* may be negative-errno on failure. Conversion to the +* -1-and-errno-set convention is done by the calling wrapper. +*/ +safe_syscall_base: + .cfi_startproc + /* +* The syscall calling convention is nearly the same as C: +* we enter with a0 == *signal_pending +* a1 == syscall number +* a2 ... a7 == syscall arguments +* and return the result in a0 +* and the syscall instruction needs +* a7 == syscall number +* a0 ... a5 == syscall arguments +* and returns the result in a0 +* Shuffle everything around appropriately. +*/ + move$t0, $a0/* signal_pending pointer */ + move$t1, $a1/* syscall number */ + move$a0, $a2/* syscall arguments */ + move$a1, $a3 + move$a2, $a4 + move$a3, $a5 + move$a4, $a6 + move$a5, $a7 + move$a7, $t1 + + /* +* This next sequence of code works in conjunction with the +* rewind_if_safe_syscall_function(). If a signal is taken +* and the interrupted PC is anywhere between 'safe_syscall_start' +* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. +* The code sequence must therefore be able to cope with this, and +* the syscall instruction must be the final one in the sequence. +*/ +safe_syscall_start: + /* If signal_pending is non-zero, don't do the call */ + ld.w$t1, $t0, 0 + bnez$t1, 0f + syscall 0 +safe_syscall_end: + /* code path for having successfully executed the syscall */ + jr $ra + +0: + /* code path when we didn't execute the syscall */ + li.w$a0, -TARGET_ERESTARTSYS + jr $ra + .cfi_endproc + + .size safe_syscall_base, .-safe_syscall_base -- 1.8.3.1
[PATCH v8 14/29] target/loongarch: Add floating point load/store instruction translation
This includes: - FLD.{S/D}, FST.{S/D} - FLDX.{S/D}, FSTX.{S/D} - FLD{GT/LE}.{S/D}, FST{GT/LE}.{S/D} Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/insn_trans/trans_fmemory.c | 187 target/loongarch/insns.decode | 24 target/loongarch/translate.c| 1 + 3 files changed, 212 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_fmemory.c diff --git a/target/loongarch/insn_trans/trans_fmemory.c b/target/loongarch/insn_trans/trans_fmemory.c new file mode 100644 index 000..eca2b8b --- /dev/null +++ b/target/loongarch/insn_trans/trans_fmemory.c @@ -0,0 +1,187 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool gen_fload_imm(DisasContext *ctx, arg_fmt_fdrjsi12 *a, + MemOp mop, bool nanbox) +{ +TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); +TCGv temp = NULL; + +if (a->si12) { +temp = tcg_temp_new(); +tcg_gen_addi_tl(temp, addr, a->si12); +addr = temp; +} + +tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +if (temp) { +tcg_temp_free(temp); +} +return true; +} + +static bool gen_fstore_imm(DisasContext *ctx, arg_fmt_fdrjsi12 *a, + MemOp mop, bool nanbox) +{ +TCGv addr = gpr_src(ctx, a->rj, EXT_NONE); +TCGv temp = NULL; + +if (a->si12) { +temp = tcg_temp_new(); +tcg_gen_addi_tl(temp, addr, a->si12); +addr = temp; +} + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + +if (temp) { +tcg_temp_free(temp); +} +return true; +} + +static bool gen_fload_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +tcg_temp_free(addr); +return true; +} + +static bool gen_fstore_tl(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +tcg_gen_add_tl(addr, src1, src2); + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + +tcg_temp_free(addr); +return true; +} + +static bool gen_fload_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtgt_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +tcg_temp_free(addr); +return true; +} + +static bool gen_fstore_gt(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtgt_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + +tcg_temp_free(addr); +return true; +} + +static bool gen_fload_le(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtle_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); +tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop); + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +tcg_temp_free(addr); +return true; +} + +static bool gen_fstore_le(DisasContext *ctx, arg_fmt_fdrjrk *a, + MemOp mop, bool nanbox) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE); +TCGv addr = tcg_temp_new(); + +gen_helper_asrtle_d(cpu_env, src1, src2); +tcg_gen_add_tl(addr, src1, src2); + +if (nanbox) { +gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]); +} + +tcg_gen_qemu_st_
[PATCH 03/13] target/riscv: Ignore the pc bits above XLEN
The read from PC for translation is in cpu_get_tb_cpu_state, before translation. Signed-off-by: LIU Zhiwei --- target/riscv/cpu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 7d0aee6769..eb425d74d2 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -71,7 +71,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, { uint32_t flags = 0; -*pc = env->pc; +*pc = cpu_get_xl(env) == MXL_RV32 ? env->pc & UINT32_MAX : env->pc; *cs_base = 0; if (riscv_has_ext(env, RVV)) { -- 2.25.1
[PATCH v8 23/29] linux-user: Add host dependency for LoongArch 64-bit
Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- linux-user/host/loongarch64/hostdep.h | 11 +++ 1 file changed, 11 insertions(+) create mode 100644 linux-user/host/loongarch64/hostdep.h diff --git a/linux-user/host/loongarch64/hostdep.h b/linux-user/host/loongarch64/hostdep.h new file mode 100644 index 000..4e55695 --- /dev/null +++ b/linux-user/host/loongarch64/hostdep.h @@ -0,0 +1,11 @@ +/* + * hostdep.h : things which are dependent on the host architecture + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef LOONGARCH64_HOSTDEP_H +#define LOONGARCH64_HOSTDEP_H + +#endif -- 1.8.3.1
[PATCH v8 18/29] linux-user: Add LoongArch specific structures
Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- linux-user/loongarch64/target_structs.h | 49 + 1 file changed, 49 insertions(+) create mode 100644 linux-user/loongarch64/target_structs.h diff --git a/linux-user/loongarch64/target_structs.h b/linux-user/loongarch64/target_structs.h new file mode 100644 index 000..818e8d6 --- /dev/null +++ b/linux-user/loongarch64/target_structs.h @@ -0,0 +1,49 @@ +/* + * LoongArch specific structures for linux-user + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#ifndef LOONGARCH_TARGET_STRUCTS_H +#define LOONGARCH_TARGET_STRUCTS_H + +struct target_ipc_perm { +abi_int __key; /* Key. */ +abi_uint uid; /* Owner's user ID. */ +abi_uint gid; /* Owner's group ID. */ +abi_uint cuid; /* Creator's user ID. */ +abi_uint cgid; /* Creator's group ID. */ +abi_uint mode; /* Read/write permission. */ +abi_ushort __seq; /* Sequence number. */ +abi_ushort __pad1; +abi_ulong __unused1; +abi_ulong __unused2; +}; + +struct target_shmid_ds { +struct target_ipc_perm shm_perm;/* operation permission struct */ +abi_long shm_segsz; /* size of segment in bytes */ +abi_ulong shm_atime;/* time of last shmat() */ +abi_ulong shm_dtime;/* time of last shmdt() */ +abi_ulong shm_ctime;/* time of last change by shmctl() */ +abi_int shm_cpid; /* pid of creator */ +abi_int shm_lpid; /* pid of last shmop */ +abi_ulong shm_nattch; /* number of current attaches */ +abi_ulong __unused1; +abi_ulong __unused2; +}; + +#define TARGET_SEMID64_DS + +struct target_semid64_ds { +struct target_ipc_perm sem_perm; +abi_ulong sem_otime; +abi_ulong sem_ctime; +abi_ulong sem_nsems; +abi_ulong __unused1; +abi_ulong __unused2; +}; + +#endif -- 1.8.3.1
Re: [PATCH v3 02/12] vfio-user: build library
On Fri, Oct 29, 2021 at 02:17:43PM +, Jag Raman wrote: > Hi Stefan, > > > On Oct 27, 2021, at 11:17 AM, Stefan Hajnoczi wrote: > > > > On Mon, Oct 11, 2021 at 01:31:07AM -0400, Jagannathan Raman wrote: > >> diff --git a/hw/remote/Kconfig b/hw/remote/Kconfig > >> index 08c16e235f..f9e512d44a 100644 > >> --- a/hw/remote/Kconfig > >> +++ b/hw/remote/Kconfig > >> @@ -1,4 +1,9 @@ > >> +config VFIO_USER_SERVER > >> +bool > >> +default n > > > > Does VFIO_USER_SERVER depend on MULTIPROCESS? > > Yes, VFIO_USER_SERVER presently depends on MULTIPROCESS. > > This is because it needs some object and functions implemented by multiprocess > such as TYPE_REMOTE_MACHINE and TYPE_REMOTE_PCIHOST. I wonder if it's necessary to specify that dependency in the Kconfig file? If someone disables MULTIPROCESS but enables VFIO_USER_SERVER then there should probably be an error (or MULTIPROCESS becomes enabled again automatically). Stefan signature.asc Description: PGP signature
[PATCH 01/13] target/riscv: Sign extend pc for different ol
When pc is written, it is sign-extended to fill the widest supported XLEN. Signed-off-by: LIU Zhiwei --- target/riscv/translate.c | 23 +++ 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 1d57bc97b5..7d78a3561e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -150,16 +150,31 @@ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in) tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan); } +static void gen_set_pc(DisasContext *ctx, target_ulong dest) +{ +TCGv t = tcg_constant_tl(dest); +switch (get_ol(ctx)) { +case MXL_RV32: +tcg_gen_ext32s_tl(cpu_pc, t); +break; +case MXL_RV64: +tcg_gen_mov_tl(cpu_pc, t); +break; +default: +g_assert_not_reached(); +} +} + static void generate_exception(DisasContext *ctx, int excp) { -tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); +gen_set_pc(ctx, ctx->base.pc_next); gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; } static void generate_exception_mtval(DisasContext *ctx, int excp) { -tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); +gen_set_pc(ctx, ctx->base.pc_next); tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr)); gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; @@ -179,10 +194,10 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) { if (translator_use_goto_tb(&ctx->base, dest)) { tcg_gen_goto_tb(n); -tcg_gen_movi_tl(cpu_pc, dest); +gen_set_pc(ctx, dest); tcg_gen_exit_tb(ctx->base.tb, n); } else { -tcg_gen_movi_tl(cpu_pc, dest); +gen_set_pc(ctx, dest); tcg_gen_lookup_and_goto_ptr(); } } -- 2.25.1
[PATCH 10/13] target/riscv: Adjust scalar reg in vector with ol
When sew <= 32bits, not need to extend scalar reg. When sew > 32bits, if xlen is less that sew, we should sign extend the scalar register, except explicitly specified by the spec. Signed-off-by: LIU Zhiwei --- target/riscv/insn_trans/trans_rvv.c.inc | 5 +++-- target/riscv/vector_helper.c| 6 -- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 5cd9b802df..947a58d7ca 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -853,7 +853,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); -src1 = get_gpr(s, rs1, EXT_NONE); +src1 = get_gpr(s, rs1, EXT_SIGN); data = FIELD_DP32(data, VDATA, MLEN, s->mlen); data = FIELD_DP32(data, VDATA, VM, vm); @@ -2677,6 +2677,7 @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) /* This instruction ignores LMUL and vector register groups */ int maxsz = s->vlen >> 3; TCGv_i64 t1; +TCGv src1 = get_gpr(s, a->rs1, EXT_ZERO); TCGLabel *over = gen_new_label(); tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); @@ -2686,7 +2687,7 @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) } t1 = tcg_temp_new_i64(); -tcg_gen_extu_tl_i64(t1, cpu_gpr[a->rs1]); +tcg_gen_extu_tl_i64(t1, src1); vec_element_storei(s, a->rd, 0, t1); tcg_temp_free_i64(t1); done: diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 451688c328..5bdbbf7c71 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -4763,6 +4763,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t mlen = vext_mlen(desc); \ uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ uint32_t vm = vext_vm(desc); \ +uint32_t olen = 16 << vext_ol(desc); \ uint32_t vl = env->vl;\ uint32_t i; \ \ @@ -4771,7 +4772,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ continue; \ } \ if (i == 0) { \ -*((ETYPE *)vd + H(i)) = s1; \ +*((ETYPE *)vd + H(i)) = adjust_addr(s1, olen);\ } else { \ *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - 1)); \ } \ @@ -4792,6 +4793,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t mlen = vext_mlen(desc); \ uint32_t vlmax = env_archcpu(env)->cfg.vlen / mlen; \ uint32_t vm = vext_vm(desc); \ +uint32_t olen = 16 << vext_ol(desc); \ uint32_t vl = env->vl;\ uint32_t i; \ \ @@ -4800,7 +4802,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ continue; \ } \ if (i == vl - 1) {\ -*((ETYPE *)vd + H(i)) = s1; \ +*((ETYPE *)vd + H(i)) = adjust_addr(s1, olen);\ } else { \ *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i + 1)); \ } \ -- 2.25.1
[PATCH v8 16/29] target/loongarch: Add disassembler
This patch adds support for disassembling via option '-d in_asm'. Acked-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- include/disas/dis-asm.h | 2 + meson.build | 1 + target/loongarch/disas.c | 919 +++ 3 files changed, 922 insertions(+) create mode 100644 target/loongarch/disas.c diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index 08e1bee..aeab30f 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -253,6 +253,7 @@ enum bfd_architecture #define bfd_mach_rx0x75 #define bfd_mach_rx_v2 0x76 #define bfd_mach_rx_v3 0x77 + bfd_arch_loongarch, bfd_arch_last }; #define bfd_mach_s390_31 31 @@ -461,6 +462,7 @@ int print_insn_riscv32 (bfd_vma, disassemble_info*); int print_insn_riscv64 (bfd_vma, disassemble_info*); int print_insn_rx(bfd_vma, disassemble_info *); int print_insn_hexagon(bfd_vma, disassemble_info *); +int print_insn_loongarch(bfd_vma, disassemble_info *); #ifdef CONFIG_CAPSTONE bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size); diff --git a/meson.build b/meson.build index b092728..77efb25 100644 --- a/meson.build +++ b/meson.build @@ -1812,6 +1812,7 @@ disassemblers = { 'sh4' : ['CONFIG_SH4_DIS'], 'sparc' : ['CONFIG_SPARC_DIS'], 'xtensa' : ['CONFIG_XTENSA_DIS'], + 'loongarch' : ['CONFIG_LOONGARCH_DIS'], } if link_language == 'cpp' disassemblers += { diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c new file mode 100644 index 000..01649a4 --- /dev/null +++ b/target/loongarch/disas.c @@ -0,0 +1,919 @@ +/* + * QEMU LoongArch Disassembler + * + * Copyright (c) 2021 Loongson Technology Corporation Limited. + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "qemu/osdep.h" +#include "disas/dis-asm.h" +#include "qemu/bitops.h" +#include "cpu.h" + +typedef disassemble_info DisasContext; + +#define INSNLEN 4 + +typedef enum { +la_codec_2r, +la_codec_2r_u5, +la_codec_2r_u6, +la_codec_2r_2bw, +la_codec_2r_2bd, +la_codec_3r, +la_codec_3r_rd0, +la_codec_3r_sa, +la_codec_4r, +la_codec_r_im20, +la_codec_2r_im16, +la_codec_2r_im14, +la_codec_2r_im12, +la_codec_r_cd, +la_codec_r_cj, +la_codec_code, +la_codec_whint, +la_codec_r_ofs21, +la_codec_cj_ofs21, +la_codec_ofs26, +la_codec_cond, +la_codec_sel, + +} la_codec; + +#define la_fmt_rd_rj "nt0,1" +#define la_fmt_rj_rk "nt1,2" +#define la_fmt_rd_si20 "nt0,i(x)" +#define la_fmt_rd_rj_ui"nt0,1,C" +#define la_fmt_rd_rj_bs"nt0,1,C,D" +#define la_fmt_rd_rj_si"nt0,1,i(x)" +#define la_fmt_hint_rj_si12"ntE,1,i(x)" +#define la_fmt_rd_rj_rk"nt0,1,2" +#define la_fmt_fd_rj_rk"nt3,1,2" +#define la_fmt_rd_rj_rk_sa "nt0,1,2,D" +#define la_fmt_fd_fj "nt3,4" +#define la_fmt_fd_fj_si12 "nt3,4,i(x)" +#define la_fmt_fcsrd_rj"ntF,1" +#define la_fmt_rd_fcsrs"nt0,G" +#define la_fmt_cd_fj "ntH,4" +#define la_fmt_fd_cj "nt3,I" +#define la_fmt_fd_fj_fk"nt3,4,5" +#define la_fmt_code"ntJ" +#define la_fmt_whint "ntx" +#define la_fmt_offs26 "nto(X)p" +#define la_fmt_rj_offs21 "nt1,o(X)p" +#define la_fmt_cj_offs21 "ntQ,o(X)p" +#define la_fmt_rd_rj_offs16"nt0,1,o(X)" +#define la_fmt_rj_rd_offs16"nt1,0,o(X)p" +#define la_fmt_s_cd_fj_fk "K.stH,4,5" +#define la_fmt_d_cd_fj_fk "K.dtH,4,5" +#define la_fmt_fd_fj_fk_fa "nt3,4,5,6" +#define la_fmt_fd_fj_fk_ca "nt3,4,5,L" + +typedef struct { +uint32_t pc; +uint32_t insn; +int32_t imm; +int32_t imm2; +uint16_t code; +uint8_t codec; +uint8_t r1; +uint8_t r2; +uint8_t r3; +uint8_t r4; +uint8_t bit; +} la_decode; + +const char * const fccregnames[8] = { + "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7", +}; + +/* operand extractors */ +#define IM_12 12 +#define IM_14 14 +#define IM_15 15 +#define IM_16 16 +#define IM_20 20 +#define IM_21 21 +#define IM_26 26 + +static uint32_t operand_r1(uint32_t insn) +{ +return insn & 0x1f; +} + +static uint32_t operand_r2(uint32_t insn) +{ +return (insn >> 5) & 0x1f; +} + +static uint32_t operand_r3(uint32_t insn) +{ +return (insn >> 10) & 0x1f; +} + +static uint32_t operand_r4(uint32_t insn) +{ +return (insn >> 15) & 0x1f; +} + +static uint32_t operand_u6(uint32_t insn) +{ +return (insn >> 10) & 0x3f; +} + +static uint32_t operand_bw1(uint32_t insn) +{ +return (insn >> 10) & 0x1f; +} + +static uint32_t operand_bw2(uint32_t insn) +{ +return (insn >> 16) & 0x1f; +} + +static uint32_t operand_bd1(uint32_t insn) +{ +return (insn >> 10) & 0x3f; +} + +static uint32_t operand_bd2(uint32_t insn) +{ +return (insn >> 16) & 0x3f; +} + +static uint32_t operand_sa(uint32_t insn) +{ +re
[PATCH v8 27/29] scripts: add loongarch64 binfmt config
Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- scripts/qemu-binfmt-conf.sh | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh index 7de996d..da6a937 100755 --- a/scripts/qemu-binfmt-conf.sh +++ b/scripts/qemu-binfmt-conf.sh @@ -4,7 +4,7 @@ qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \ ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \ sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \ -microblaze microblazeel or1k x86_64 hexagon" +microblaze microblazeel or1k x86_64 hexagon loongarch64" i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00' i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' @@ -140,6 +140,10 @@ hexagon_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x hexagon_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' hexagon_family=hexagon +loongarch64_magic='\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02\x01' +loongarch64_mask='\xff\xff\xff\xff\xff\xff\xff\xfc\x00\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff' +loongarch64_family=loongarch + qemu_get_family() { cpu=${HOST_ARCH:-$(uname -m)} case "$cpu" in -- 1.8.3.1
[PATCH 00/13] Support UXL filed in xstatus.
In this patch set, we process the pc reigsters writes, gdb reads and writes, and address calculation under different UXLEN settings. LIU Zhiwei (13): target/riscv: Sign extend pc for different ol target/riscv: Extend pc for runtime pc write target/riscv: Ignore the pc bits above XLEN target/riscv: Use gdb xml according to max mxlen target/riscv: Calculate address according to ol target/riscv: Adjust vsetvl according to ol target/riscv: Ajdust vector atomic check with ol target/riscv: Fix check range for first fault only target/riscv: Adjust vector address with ol target/riscv: Adjust scalar reg in vector with ol target/riscv: Switch context in exception return target/riscv: Don't save pc when exception return target/riscv: Enable uxl field write target/riscv/cpu.c| 20 - target/riscv/cpu.h| 4 + target/riscv/cpu_helper.c | 4 +- target/riscv/csr.c| 6 +- target/riscv/gdbstub.c| 73 - target/riscv/helper.h | 7 +- target/riscv/insn_trans/trans_privileged.c.inc| 9 +-- target/riscv/insn_trans/trans_rvd.c.inc | 20 ++--- target/riscv/insn_trans/trans_rvf.c.inc | 21 ++--- target/riscv/insn_trans/trans_rvi.c.inc | 23 +++--- target/riscv/insn_trans/trans_rvv.c.inc | 19 +++-- target/riscv/internals.h | 1 + target/riscv/op_helper.c | 30 ++- target/riscv/translate.c | 23 +- target/riscv/vector_helper.c | 81 +-- 15 files changed, 233 insertions(+), 108 deletions(-) -- 2.25.1
[PATCH 09/13] target/riscv: Adjust vector address with ol
Signed-off-by: LIU Zhiwei --- target/riscv/insn_trans/trans_rvv.c.inc | 8 target/riscv/internals.h| 1 + target/riscv/vector_helper.c| 54 + 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index ed042f7bb9..5cd9b802df 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -233,6 +233,7 @@ static bool ld_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, NF, a->nf); +data = FIELD_DP32(data, VDATA, OL, s->ol); return ldst_us_trans(a->rd, a->rs1, data, fn, s); } @@ -286,6 +287,7 @@ static bool st_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, NF, a->nf); +data = FIELD_DP32(data, VDATA, OL, s->ol); return ldst_us_trans(a->rd, a->rs1, data, fn, s); } @@ -365,6 +367,7 @@ static bool ld_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, NF, a->nf); +data = FIELD_DP32(data, VDATA, OL, s->ol); return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s); } @@ -404,6 +407,7 @@ static bool st_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, NF, a->nf); +data = FIELD_DP32(data, VDATA, OL, s->ol); fn = fns[seq][s->sew]; if (fn == NULL) { return false; @@ -490,6 +494,7 @@ static bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, NF, a->nf); +data = FIELD_DP32(data, VDATA, OL, s->ol); return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s); } @@ -542,6 +547,7 @@ static bool st_index_op(DisasContext *s, arg_rnfvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, NF, a->nf); +data = FIELD_DP32(data, VDATA, OL, s->ol); return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s); } @@ -617,6 +623,7 @@ static bool ldff_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, NF, a->nf); +data = FIELD_DP32(data, VDATA, OL, s->ol); return ldff_trans(a->rd, a->rs1, data, fn, s); } @@ -724,6 +731,7 @@ static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, WD, a->wd); +data = FIELD_DP32(data, VDATA, OL, s->ol); return amo_trans(a->rd, a->rs1, a->rs2, data, fn, s); } /* diff --git a/target/riscv/internals.h b/target/riscv/internals.h index b15ad394bb..f74b8291e4 100644 --- a/target/riscv/internals.h +++ b/target/riscv/internals.h @@ -27,6 +27,7 @@ FIELD(VDATA, VM, 8, 1) FIELD(VDATA, LMUL, 9, 2) FIELD(VDATA, NF, 11, 4) FIELD(VDATA, WD, 11, 1) +FIELD(VDATA, OL, 15, 2) /* float point classify helpers */ target_ulong fclass_h(uint64_t frs1); diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 535420ee66..451688c328 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -112,6 +112,11 @@ static uint32_t vext_wd(uint32_t desc) return (simd_data(desc) >> 11) & 0x1; } +static inline uint32_t vext_ol(uint32_t desc) +{ +return FIELD_EX32(simd_data(desc), VDATA, OL); +} + /* * Get vector group length in bytes. Its range is [64, 2048]. * @@ -123,6 +128,14 @@ static inline uint32_t vext_maxsz(uint32_t desc) return simd_maxsz(desc) << vext_lmul(desc); } +static inline target_ulong adjust_addr(target_ulong addr, uint32_t olen) +{ +if (olen < TARGET_LONG_BITS) { +addr &= UINT32_MAX; +} +return addr; +} + /* * This function checks watchpoint before real load operation. * @@ -135,17 +148,17 @@ static inline uint32_t vext_maxsz(uint32_t desc) */ static void probe_pages(CPURISCVState *env, target_ulong addr, target_ulong len, uintptr_t ra, -MMUAccessType access_type) +MMUAccessType access_type, uint32_t olen) { target_ulong pagelen = -(addr | TARGET_PAGE_MASK); target_ulong curlen = MIN(pagelen, len); -probe_access(env, addr, curlen, access_type, +probe_access(env, adjust_
[PATCH v8 15/29] target/loongarch: Add branch instruction translation
This includes: - BEQ, BNE, BLT[U], BGE[U] - BEQZ, BNEZ - B - BL - JIRL - BCEQZ, BCNEZ Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- target/loongarch/insn_trans/trans_branch.c | 85 ++ target/loongarch/insns.decode | 30 +++ target/loongarch/translate.c | 1 + 3 files changed, 116 insertions(+) create mode 100644 target/loongarch/insn_trans/trans_branch.c diff --git a/target/loongarch/insn_trans/trans_branch.c b/target/loongarch/insn_trans/trans_branch.c new file mode 100644 index 000..77a6ae6 --- /dev/null +++ b/target/loongarch/insn_trans/trans_branch.c @@ -0,0 +1,85 @@ +/* + * LoongArch translate functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +static bool trans_b(DisasContext *ctx, arg_b *a) +{ +gen_goto_tb(ctx, 0, ctx->base.pc_next + (a->offs << 2)); +ctx->base.is_jmp = DISAS_NORETURN; +return true; +} + +static bool trans_bl(DisasContext *ctx, arg_bl *a) +{ +tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4); +gen_goto_tb(ctx, 0, ctx->base.pc_next + (a->offs << 2)); +ctx->base.is_jmp = DISAS_NORETURN; +return true; +} + +static bool trans_jirl(DisasContext *ctx, arg_jirl *a) +{ +TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); + +tcg_gen_addi_tl(cpu_pc, src1, (a->offs16) << 2); +tcg_gen_movi_tl(dest, ctx->base.pc_next + 4); +tcg_gen_lookup_and_goto_ptr(); +ctx->base.is_jmp = DISAS_NORETURN; +return true; +} + +static void gen_bc(DisasContext *ctx, TCGv src1, TCGv src2, + target_long offs, TCGCond cond) +{ +TCGLabel *l = gen_new_label(); +tcg_gen_brcond_tl(cond, src1, src2, l); +gen_goto_tb(ctx, 1, ctx->base.pc_next + 4); +gen_set_label(l); +gen_goto_tb(ctx, 0, ctx->base.pc_next + offs); +ctx->base.is_jmp = DISAS_NORETURN; +} + +static bool gen_r2_bc(DisasContext *ctx, arg_fmt_rjrdoffs16 *a, TCGCond cond) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE); + +gen_bc(ctx, src1, src2, (a->offs16 << 2), cond); +return true; +} + +static bool gen_rz_bc(DisasContext *ctx, arg_fmt_rjoffs21 *a, TCGCond cond) +{ +TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE); +TCGv src2 = tcg_constant_tl(0); + +gen_bc(ctx, src1, src2, (a->offs21 << 2), cond); +return true; +} + +static bool gen_cz_bc(DisasContext *ctx, arg_fmt_cjoffs21 *a, TCGCond cond) +{ +TCGv src1 = tcg_temp_new(); +TCGv src2 = tcg_constant_tl(0); + +tcg_gen_ld8u_tl(src1, cpu_env, +offsetof(CPULoongArchState, cf[a->cj & 0x7])); +gen_bc(ctx, src1, src2, (a->offs21 << 2), cond); +return true; +} + +TRANS(beq, gen_r2_bc, TCG_COND_EQ) +TRANS(bne, gen_r2_bc, TCG_COND_NE) +TRANS(blt, gen_r2_bc, TCG_COND_LT) +TRANS(bge, gen_r2_bc, TCG_COND_GE) +TRANS(bltu, gen_r2_bc, TCG_COND_LTU) +TRANS(bgeu, gen_r2_bc, TCG_COND_GEU) +TRANS(beqz, gen_rz_bc, TCG_COND_EQ) +TRANS(bnez, gen_rz_bc, TCG_COND_NE) +TRANS(bceqz, gen_cz_bc, TCG_COND_EQ) +TRANS(bcnez, gen_cz_bc, TCG_COND_NE) diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode index ea776c2..077063e 100644 --- a/target/loongarch/insns.decode +++ b/target/loongarch/insns.decode @@ -38,6 +38,9 @@ %ca 15:3 %fcsrd 0:5 %fcsrs 5:5 +%offs21 0:s5 10:16 +%offs16 10:s16 +%offs0:s10 10:16 # # Argument sets @@ -74,6 +77,11 @@ &fmt_rdcj rd cj &fmt_fdrjrk fd rj rk &fmt_fdrjsi12 fd rj si12 +&fmt_rjoffs21 rj offs21 +&fmt_cjoffs21 cj offs21 +&fmt_rdrjoffs16 rd rj offs16 +&fmt_offs offs +&fmt_rjrdoffs16 rj rd offs16 # # Formats @@ -110,6 +118,11 @@ @fmt_rdcj . . .. ... . &fmt_rdcj %rd %cj @fmt_fdrjrk . . . .&fmt_fdrjrk %fd %rj %rk @fmt_fdrjsi12 .. . . &fmt_fdrjsi12 %fd %rj %si12 +@fmt_rjoffs21 .. . . &fmt_rjoffs21 %rj %offs21 +@fmt_cjoffs21 .. .. ... .&fmt_cjoffs21 %cj %offs21 +@fmt_rdrjoffs16 .. . . &fmt_rdrjoffs16 %rd %rj %offs16 +@fmt_offs .. .. &fmt_offs %offs +@fmt_rjrdoffs16 .. . . &fmt_rjrdoffs16 %rj %rd %offs16 # # Fixed point arithmetic operation instruction @@ -448,3 +461,20 @@ fstgt_s 0011 1111 01100 . . . @fmt_fdrjrk fstgt_d 0011 1111 01101 . . .@fmt_fdrjrk fstle_s 0011 1111 01110 . . .@fmt_fdrjrk fstle_d 0011 1111 0 . . .@fmt_fdrjrk + +# +# Branch instructions +# +beqz 0100 0
[PATCH 05/13] target/riscv: Calculate address according to ol
Signed-off-by: LIU Zhiwei --- target/riscv/insn_trans/trans_rvd.c.inc | 20 ++-- target/riscv/insn_trans/trans_rvf.c.inc | 21 - target/riscv/insn_trans/trans_rvi.c.inc | 21 ++--- 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index 64fb0046f7..70317691c9 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -20,17 +20,13 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) { -TCGv addr; +TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv addr = temp_new(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); -addr = get_gpr(ctx, a->rs1, EXT_NONE); -if (a->imm) { -TCGv temp = temp_new(ctx); -tcg_gen_addi_tl(temp, addr, a->imm); -addr = temp; -} +tcg_gen_addi_tl(addr, src1, a->imm); addr = gen_pm_adjust_address(ctx, addr); tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEQ); @@ -41,17 +37,13 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) static bool trans_fsd(DisasContext *ctx, arg_fsd *a) { -TCGv addr; +TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv addr = temp_new(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); -addr = get_gpr(ctx, a->rs1, EXT_NONE); -if (a->imm) { -TCGv temp = temp_new(ctx); -tcg_gen_addi_tl(temp, addr, a->imm); -addr = temp; -} +tcg_gen_addi_tl(addr, src1, a->imm); addr = gen_pm_adjust_address(ctx, addr); tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEQ); diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index b5459249c4..08fa83df7e 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -26,16 +26,15 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) { TCGv_i64 dest; -TCGv addr; +TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv addr = temp_new(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); -addr = get_gpr(ctx, a->rs1, EXT_NONE); -if (a->imm) { -TCGv temp = temp_new(ctx); -tcg_gen_addi_tl(temp, addr, a->imm); -addr = temp; +tcg_gen_addi_tl(addr, src1, a->imm); +if (ctx->ol == MXL_RV32) { +tcg_gen_ext32u_tl(addr, addr); } addr = gen_pm_adjust_address(ctx, addr); @@ -49,17 +48,13 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) static bool trans_fsw(DisasContext *ctx, arg_fsw *a) { -TCGv addr; +TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv addr = temp_new(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); -addr = get_gpr(ctx, a->rs1, EXT_NONE); -if (a->imm) { -TCGv temp = tcg_temp_new(); -tcg_gen_addi_tl(temp, addr, a->imm); -addr = temp; -} +tcg_gen_addi_tl(addr, src1, a->imm); addr = gen_pm_adjust_address(ctx, addr); tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL); diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index e51dbc41c5..bd9d50bb94 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -137,12 +137,12 @@ static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a) static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) { TCGv dest = dest_gpr(ctx, a->rd); -TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv addr = temp_new(ctx); -if (a->imm) { -TCGv temp = temp_new(ctx); -tcg_gen_addi_tl(temp, addr, a->imm); -addr = temp; +tcg_gen_addi_tl(addr, src1, a->imm); +if (ctx->ol == MXL_RV32) { +tcg_gen_ext32u_tl(addr, addr); } addr = gen_pm_adjust_address(ctx, addr); @@ -178,16 +178,15 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a) static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { -TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv addr = temp_new(ctx); +TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); TCGv data = get_gpr(ctx, a->rs2, EXT_NONE); -if (a->imm) { -TCGv temp = temp_new(ctx); -tcg_gen_addi_tl(temp, addr, a->imm); -addr = temp; +tcg_gen_addi_tl(addr, src1, a->imm); +if (ctx->ol == MXL_RV32) { +tcg_gen_ext32u_tl(addr, addr); } addr = gen_pm_adjust_address(ctx, addr); - tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); return true; } -- 2.25.1
[PATCH 06/13] target/riscv: Adjust vsetvl according to ol
Signed-off-by: LIU Zhiwei --- target/riscv/cpu.h | 2 ++ target/riscv/helper.h | 2 +- target/riscv/insn_trans/trans_rvv.c.inc | 4 ++-- target/riscv/vector_helper.c| 19 +++ 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 8befff0166..7163ac1f4c 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -107,6 +107,8 @@ FIELD(VTYPE, VSEW, 2, 3) FIELD(VTYPE, VEDIV, 5, 2) FIELD(VTYPE, RESERVED, 7, sizeof(target_ulong) * 8 - 9) FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1) +FIELD(VTYPE, RESERVED_OLEN32, 7, 23) +FIELD(VTYPE, VILL_OLEN32, 31, 1) struct CPURISCVState { target_ulong gpr[32]; diff --git a/target/riscv/helper.h b/target/riscv/helper.h index c7a5376227..e198d43981 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -82,7 +82,7 @@ DEF_HELPER_2(hyp_hlvx_wu, tl, env, tl) #endif /* Vector functions */ -DEF_HELPER_3(vsetvl, tl, env, tl, tl) +DEF_HELPER_4(vsetvl, tl, env, tl, tl, tl) DEF_HELPER_5(vlb_v_b, void, ptr, ptr, tl, env, i32) DEF_HELPER_5(vlb_v_b_mask, void, ptr, ptr, tl, env, i32) DEF_HELPER_5(vlb_v_h, void, ptr, ptr, tl, env, i32) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 17ee3babef..01da065710 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -37,7 +37,7 @@ static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a) } else { s1 = get_gpr(ctx, a->rs1, EXT_ZERO); } -gen_helper_vsetvl(dst, cpu_env, s1, s2); +gen_helper_vsetvl(dst, cpu_env, s1, s2, tcg_constant_tl(get_olen(ctx))); gen_set_gpr(ctx, a->rd, dst); tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); @@ -64,7 +64,7 @@ static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a) } else { s1 = get_gpr(ctx, a->rs1, EXT_ZERO); } -gen_helper_vsetvl(dst, cpu_env, s1, s2); +gen_helper_vsetvl(dst, cpu_env, s1, s2, tcg_constant_tl(get_olen(ctx))); gen_set_gpr(ctx, a->rd, dst); gen_goto_tb(ctx, 0, ctx->pc_succ_insn); diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 12c31aa4b4..09e76229bc 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -27,18 +27,29 @@ #include target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, -target_ulong s2) +target_ulong s2, target_ulong olen) { int vlmax, vl; RISCVCPU *cpu = env_archcpu(env); uint16_t sew = 8 << FIELD_EX64(s2, VTYPE, VSEW); uint8_t ediv = FIELD_EX64(s2, VTYPE, VEDIV); -bool vill = FIELD_EX64(s2, VTYPE, VILL); -target_ulong reserved = FIELD_EX64(s2, VTYPE, RESERVED); +bool vill; +target_ulong reserved; +if (olen < TARGET_LONG_BITS) { +vill = FIELD_EX64(s2, VTYPE, VILL_OLEN32); +reserved = FIELD_EX64(s2, VTYPE, RESERVED_OLEN32); +} else { +vill = FIELD_EX64(s2, VTYPE, VILL); +reserved = FIELD_EX64(s2, VTYPE, RESERVED); +} if ((sew > cpu->cfg.elen) || vill || (ediv != 0) || (reserved != 0)) { /* only set vill bit. */ -env->vtype = FIELD_DP64(0, VTYPE, VILL, 1); +if (olen < TARGET_LONG_BITS) { +env->vtype = FIELD_DP64(0, VTYPE, VILL_OLEN32, 1); +} else { +env->vtype = FIELD_DP64(0, VTYPE, VILL, 1); +} env->vl = 0; env->vstart = 0; return 0; -- 2.25.1
[PATCH v8 21/29] linux-user: Add LoongArch syscall support
We should disable '__BITS_PER_LONG' at [1] before run gensyscalls.sh [1] arch/loongarch/include/uapi/asm/bitsperlong.h Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- linux-user/loongarch64/syscall_nr.h | 312 linux-user/loongarch64/target_syscall.h | 46 + linux-user/syscall_defs.h | 10 +- scripts/gensyscalls.sh | 1 + 4 files changed, 365 insertions(+), 4 deletions(-) create mode 100644 linux-user/loongarch64/syscall_nr.h create mode 100644 linux-user/loongarch64/target_syscall.h diff --git a/linux-user/loongarch64/syscall_nr.h b/linux-user/loongarch64/syscall_nr.h new file mode 100644 index 000..8fbf287 --- /dev/null +++ b/linux-user/loongarch64/syscall_nr.h @@ -0,0 +1,312 @@ +/* + * This file contains the system call numbers. + * Do not modify. + * This file is generated by scripts/gensyscalls.sh + */ +#ifndef LINUX_USER_LOONGARCH_SYSCALL_NR_H +#define LINUX_USER_LOONGARCH_SYSCALL_NR_H + +#define TARGET_NR_io_setup 0 +#define TARGET_NR_io_destroy 1 +#define TARGET_NR_io_submit 2 +#define TARGET_NR_io_cancel 3 +#define TARGET_NR_io_getevents 4 +#define TARGET_NR_setxattr 5 +#define TARGET_NR_lsetxattr 6 +#define TARGET_NR_fsetxattr 7 +#define TARGET_NR_getxattr 8 +#define TARGET_NR_lgetxattr 9 +#define TARGET_NR_fgetxattr 10 +#define TARGET_NR_listxattr 11 +#define TARGET_NR_llistxattr 12 +#define TARGET_NR_flistxattr 13 +#define TARGET_NR_removexattr 14 +#define TARGET_NR_lremovexattr 15 +#define TARGET_NR_fremovexattr 16 +#define TARGET_NR_getcwd 17 +#define TARGET_NR_lookup_dcookie 18 +#define TARGET_NR_eventfd2 19 +#define TARGET_NR_epoll_create1 20 +#define TARGET_NR_epoll_ctl 21 +#define TARGET_NR_epoll_pwait 22 +#define TARGET_NR_dup 23 +#define TARGET_NR_dup3 24 +#define TARGET_NR_fcntl 25 +#define TARGET_NR_inotify_init1 26 +#define TARGET_NR_inotify_add_watch 27 +#define TARGET_NR_inotify_rm_watch 28 +#define TARGET_NR_ioctl 29 +#define TARGET_NR_ioprio_set 30 +#define TARGET_NR_ioprio_get 31 +#define TARGET_NR_flock 32 +#define TARGET_NR_mknodat 33 +#define TARGET_NR_mkdirat 34 +#define TARGET_NR_unlinkat 35 +#define TARGET_NR_symlinkat 36 +#define TARGET_NR_linkat 37 +#define TARGET_NR_umount2 39 +#define TARGET_NR_mount 40 +#define TARGET_NR_pivot_root 41 +#define TARGET_NR_nfsservctl 42 +#define TARGET_NR_statfs 43 +#define TARGET_NR_fstatfs 44 +#define TARGET_NR_truncate 45 +#define TARGET_NR_ftruncate 46 +#define TARGET_NR_fallocate 47 +#define TARGET_NR_faccessat 48 +#define TARGET_NR_chdir 49 +#define TARGET_NR_fchdir 50 +#define TARGET_NR_chroot 51 +#define TARGET_NR_fchmod 52 +#define TARGET_NR_fchmodat 53 +#define TARGET_NR_fchownat 54 +#define TARGET_NR_fchown 55 +#define TARGET_NR_openat 56 +#define TARGET_NR_close 57 +#define TARGET_NR_vhangup 58 +#define TARGET_NR_pipe2 59 +#define TARGET_NR_quotactl 60 +#define TARGET_NR_getdents64 61 +#define TARGET_NR_lseek 62 +#define TARGET_NR_read 63 +#define TARGET_NR_write 64 +#define TARGET_NR_readv 65 +#define TARGET_NR_writev 66 +#define TARGET_NR_pread64 67 +#define TARGET_NR_pwrite64 68 +#define TARGET_NR_preadv 69 +#define TARGET_NR_pwritev 70 +#define TARGET_NR_sendfile 71 +#define TARGET_NR_pselect6 72 +#define TARGET_NR_ppoll 73 +#define TARGET_NR_signalfd4 74 +#define TARGET_NR_vmsplice 75 +#define TARGET_NR_splice 76 +#define TARGET_NR_tee 77 +#define TARGET_NR_readlinkat 78 +#define TARGET_NR_newfstatat 79 +#define TARGET_NR_fstat 80 +#define TARGET_NR_sync 81 +#define TARGET_NR_fsync 82 +#define TARGET_NR_fdatasync 83 +#define TARGET_NR_sync_file_range 84 +#define TARGET_NR_timerfd_create 85 +#define TARGET_NR_timerfd_settime 86 +#define TARGET_NR_timerfd_gettime 87 +#define TARGET_NR_utimensat 88 +#define TARGET_NR_acct 89 +#define TARGET_NR_capget 90 +#define TARGET_NR_capset 91 +#define TARGET_NR_personality 92 +#define TARGET_NR_exit 93 +#define TARGET_NR_exit_group 94 +#define TARGET_NR_waitid 95 +#define TARGET_NR_set_tid_address 96 +#define TARGET_NR_unshare 97 +#define TARGET_NR_futex 98 +#define TARGET_NR_set_robust_list 99 +#define TARGET_NR_get_robust_list 100 +#define TARGET_NR_nanosleep 101 +#define TARGET_NR_getitimer 102 +#define TARGET_NR_setitimer 103 +#define TARGET_NR_kexec_load 104 +#define TARGET_NR_init_module 105 +#define TARGET_NR_delete_module 106 +#define TARGET_NR_timer_create 107 +#define TARGET_NR_timer_gettime 108 +#define TARGET_NR_timer_getoverrun 109 +#define TARGET_NR_timer_settime 110 +#define TARGET_NR_timer_delete 111 +#define TARGET_NR_clock_settime 112 +#define TARGET_NR_clock_gettime 113 +#define TARGET_NR_clock_getres 114 +#define TARGET_NR_clock_nanosleep 115 +#define TARGET_NR_syslog 116 +#define TARGET_NR_ptrace 117 +#define TARGET_NR_sched_setparam 118 +#define TARGET_NR_sched_setscheduler 119 +#define TARGET_NR_sched_getscheduler 120 +#define TARGET_NR_sched_getparam 121 +#define TARGET_NR_sched_setaffinity 122 +#define TARGET_NR_sched_getaffinity 123 +#define TARGET_NR_sched_yield
[PATCH v8 25/29] target/loongarch: Add target build suport
This patch adds build loongarch-linux-user target support. Reviewed-by: Richard Henderson Signed-off-by: Song Gao Signed-off-by: Xiaojuan Yang --- meson.build | 2 +- target/loongarch/meson.build | 19 +++ target/meson.build | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 target/loongarch/meson.build diff --git a/meson.build b/meson.build index 77efb25..97e459f 100644 --- a/meson.build +++ b/meson.build @@ -56,7 +56,7 @@ python = import('python').find_installation() supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64', - 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] + 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64', 'loongarch64'] cpu = host_machine.cpu_family() targetos = host_machine.system() diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build new file mode 100644 index 000..bcb076e --- /dev/null +++ b/target/loongarch/meson.build @@ -0,0 +1,19 @@ +gen = decodetree.process('insns.decode') + +loongarch_ss = ss.source_set() +loongarch_ss.add(files( + 'cpu.c', + 'disas.c', +)) +loongarch_tcg_ss = ss.source_set() +loongarch_tcg_ss.add(gen) +loongarch_tcg_ss.add(files( + 'fpu_helper.c', + 'op_helper.c', + 'translate.c', +)) +loongarch_tcg_ss.add(zlib) + +loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss]) + +target_arch += {'loongarch': loongarch_ss} diff --git a/target/meson.build b/target/meson.build index 2f69402..a53a604 100644 --- a/target/meson.build +++ b/target/meson.build @@ -5,6 +5,7 @@ subdir('cris') subdir('hexagon') subdir('hppa') subdir('i386') +subdir('loongarch') subdir('m68k') subdir('microblaze') subdir('mips') -- 1.8.3.1
[PATCH 08/13] target/riscv: Fix check range for first fault only
Only check the range that has passed the address translation. Signed-off-by: LIU Zhiwei --- target/riscv/vector_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 09e76229bc..535420ee66 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -638,12 +638,12 @@ vext_ldff(void *vd, void *v0, target_ulong base, cpu_mmu_index(env, false)); if (host) { #ifdef CONFIG_USER_ONLY -if (page_check_range(addr, nf * msz, PAGE_READ) < 0) { +if (page_check_range(addr, offset, PAGE_READ) < 0) { vl = i; goto ProbeSuccess; } #else -probe_pages(env, addr, nf * msz, ra, MMU_DATA_LOAD); +probe_pages(env, addr, offset, ra, MMU_DATA_LOAD); #endif } else { vl = i; -- 2.25.1
[PATCH 02/13] target/riscv: Extend pc for runtime pc write
In some cases, we must restore the guest PC to the address of the start of the TB, such as when the instruction counter hit zero. So extend pc register according to current xlen for these cases. Signed-off-by: LIU Zhiwei --- target/riscv/cpu.c| 20 +--- target/riscv/cpu.h| 2 ++ target/riscv/cpu_helper.c | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7d53125dbc..7eefd4f6a6 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -319,7 +319,12 @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; -env->pc = value; + +if (cpu_get_xl(env) == MXL_RV32) { +env->pc = (int32_t)value; +} else { +env->pc = value; +} } static void riscv_cpu_synchronize_from_tb(CPUState *cs, @@ -327,7 +332,12 @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs, { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; -env->pc = tb->pc; + +if (cpu_get_xl(env) == MXL_RV32) { +env->pc = (int32_t)tb->pc; +} else { +env->pc = tb->pc; +} } static bool riscv_cpu_has_work(CPUState *cs) @@ -348,7 +358,11 @@ static bool riscv_cpu_has_work(CPUState *cs) void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb, target_ulong *data) { -env->pc = data[0]; + if (cpu_get_xl(env) == MXL_RV32) { +env->pc = (int32_t)data[0]; +} else { +env->pc = data[0]; +} } static void riscv_cpu_reset(DeviceState *dev) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0760c0af93..8befff0166 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -420,6 +420,8 @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env) } #endif +RISCVMXL cpu_get_xl(CPURISCVState *env); + /* * A simplification for VLMAX * = (1 << LMUL) * VLEN / (8 * (1 << SEW)) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index f30ff672f8..7d0aee6769 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -35,7 +35,7 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) #endif } -static RISCVMXL cpu_get_xl(CPURISCVState *env) +RISCVMXL cpu_get_xl(CPURISCVState *env) { #if defined(TARGET_RISCV32) return MXL_RV32; -- 2.25.1
[PATCH 04/13] target/riscv: Use gdb xml according to max mxlen
Signed-off-by: LIU Zhiwei --- target/riscv/gdbstub.c | 73 +++--- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 23429179e2..15abbbdb54 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -24,11 +24,25 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; +target_ulong tmp; if (n < 32) { -return gdb_get_regl(mem_buf, env->gpr[n]); +tmp = env->gpr[n]; } else if (n == 32) { -return gdb_get_regl(mem_buf, env->pc); +tmp = env->pc; +} else { +return 0; +} + +switch (env->misa_mxl_max) { +case MXL_RV32: +gdb_get_reg32(mem_buf, tmp); +break; +case MXL_RV64: +gdb_get_reg64(mem_buf, tmp); +break; +default: +g_assert_not_reached(); } return 0; } @@ -37,18 +51,32 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; - -if (n == 0) { -/* discard writes to x0 */ -return sizeof(target_ulong); -} else if (n < 32) { -env->gpr[n] = ldtul_p(mem_buf); -return sizeof(target_ulong); +int length = 0; +target_ulong tmp; + +switch (env->misa_mxl_max) { +case MXL_RV32: +tmp = (uint32_t)ldl_p(mem_buf); +length = 4; +break; +case MXL_RV64: +if (cpu_get_xl(env) < MXL_RV64) { +tmp = (int32_t)ldq_p(mem_buf); +} else { +tmp = ldq_p(mem_buf); +} +length = 8; +break; +default: +g_assert_not_reached(); +} +if (n > 0 && n < 32) { +env->gpr[n] = tmp; } else if (n == 32) { -env->pc = ldtul_p(mem_buf); -return sizeof(target_ulong); +env->pc = tmp; } -return 0; + +return length; } static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n) @@ -198,13 +226,20 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, 36, "riscv-32bit-fpu.xml", 0); } -#if defined(TARGET_RISCV32) -gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, - 1, "riscv-32bit-virtual.xml", 0); -#elif defined(TARGET_RISCV64) -gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, - 1, "riscv-64bit-virtual.xml", 0); -#endif +switch (env->misa_mxl_max) { +case MXL_RV32: +gdb_register_coprocessor(cs, riscv_gdb_get_virtual, + riscv_gdb_set_virtual, + 1, "riscv-32bit-virtual.xml", 0); +break; +case MXL_RV64: +gdb_register_coprocessor(cs, riscv_gdb_get_virtual, + riscv_gdb_set_virtual, + 1, "riscv-64bit-virtual.xml", 0); +break; +default: +g_assert_not_reached(); +} gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs), -- 2.25.1
[PATCH 13/13] target/riscv: Enable uxl field write
Signed-off-by: LIU Zhiwei --- target/riscv/csr.c | 6 -- target/riscv/insn_trans/trans_rvi.c.inc | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9f41954894..471c10acf6 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -543,14 +543,16 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, * add them to mstatush. For now, we just don't support it. */ mask |= MSTATUS_MPV | MSTATUS_GVA; +if ((val ^ mstatus) & MSTATUS64_UXL) { +mask |= MSTATUS64_UXL; +} } mstatus = (mstatus & ~mask) | (val & mask); if (riscv_cpu_mxl(env) == MXL_RV64) { -/* SXL and UXL fields are for now read only */ +/* SXL fields are for now read only */ mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64); -mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64); } env->mstatus = mstatus; diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index bd9d50bb94..880026f13d 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -475,7 +475,7 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask) static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a) { -TCGv src = get_gpr(ctx, a->rs1, EXT_NONE); +TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO); /* * If rd == 0, the insn shall not read the csr, nor cause any of the -- 2.25.1
[PATCH 11/13] target/riscv: Switch context in exception return
After excpetion return, we should give a xlen view of context in new priveledge, including the general registers, pc, and CSRs. Signed-off-by: LIU Zhiwei --- target/riscv/helper.h | 1 + .../riscv/insn_trans/trans_privileged.c.inc | 2 ++ target/riscv/op_helper.c | 26 +++ 3 files changed, 29 insertions(+) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index e198d43981..9b379d7232 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -71,6 +71,7 @@ DEF_HELPER_2(sret, tl, env, tl) DEF_HELPER_2(mret, tl, env, tl) DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(tlb_flush, void, env) +DEF_HELPER_1(switch_context_xl, void, env) #endif /* Hypervisor functions */ diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc index 75c6ef80a6..6e39632f83 100644 --- a/target/riscv/insn_trans/trans_privileged.c.inc +++ b/target/riscv/insn_trans/trans_privileged.c.inc @@ -78,6 +78,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a) if (has_ext(ctx, RVS)) { gen_helper_sret(cpu_pc, cpu_env, cpu_pc); +gen_helper_switch_context_xl(cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; } else { @@ -94,6 +95,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a) #ifndef CONFIG_USER_ONLY tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); gen_helper_mret(cpu_pc, cpu_env, cpu_pc); +gen_helper_switch_context_xl(cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; return true; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index ee7c24efe7..20cf8ad883 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -70,6 +70,32 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr, } #ifndef CONFIG_USER_ONLY +void helper_switch_context_xl(CPURISCVState *env) +{ +RISCVMXL xl = cpu_get_xl(env); +if (xl == env->misa_mxl_max) { +return; +} +assert(xl < env->misa_mxl_max); +switch (xl) { +case MXL_RV32: +for (int i = 1; i < 32; i++) { +env->gpr[i] = (int32_t)env->gpr[i]; +} +env->pc = (int32_t)env->pc; +/* + * For the read-only bits of the previous-width CSR, the bits at the + * same positions in the temporary register are set to zeros. + */ +if ((env->priv == PRV_U) && (env->misa_ext & RVV)) { +env->vl = 0; +env->vtype = 0; +} +break; +default: +break; +} +} target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) { -- 2.25.1
[PATCH 12/13] target/riscv: Don't save pc when exception return
As pc will be written by the xepc in exception return, just ignore pc in translation. Signed-off-by: LIU Zhiwei --- target/riscv/helper.h | 4 ++-- target/riscv/insn_trans/trans_privileged.c.inc | 7 ++- target/riscv/op_helper.c | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 9b379d7232..34c57a6083 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -67,8 +67,8 @@ DEF_HELPER_2(csrr, tl, env, int) DEF_HELPER_3(csrw, void, env, int, tl) DEF_HELPER_4(csrrw, tl, env, int, tl, tl) #ifndef CONFIG_USER_ONLY -DEF_HELPER_2(sret, tl, env, tl) -DEF_HELPER_2(mret, tl, env, tl) +DEF_HELPER_1(sret, tl, env) +DEF_HELPER_1(mret, tl, env) DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(tlb_flush, void, env) DEF_HELPER_1(switch_context_xl, void, env) diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc index 6e39632f83..cf6dc9 100644 --- a/target/riscv/insn_trans/trans_privileged.c.inc +++ b/target/riscv/insn_trans/trans_privileged.c.inc @@ -74,10 +74,8 @@ static bool trans_uret(DisasContext *ctx, arg_uret *a) static bool trans_sret(DisasContext *ctx, arg_sret *a) { #ifndef CONFIG_USER_ONLY -tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); - if (has_ext(ctx, RVS)) { -gen_helper_sret(cpu_pc, cpu_env, cpu_pc); +gen_helper_sret(cpu_pc, cpu_env); gen_helper_switch_context_xl(cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; @@ -93,8 +91,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a) static bool trans_mret(DisasContext *ctx, arg_mret *a) { #ifndef CONFIG_USER_ONLY -tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); -gen_helper_mret(cpu_pc, cpu_env, cpu_pc); +gen_helper_mret(cpu_pc, cpu_env); gen_helper_switch_context_xl(cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 20cf8ad883..3ce2767ccf 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -97,7 +97,7 @@ void helper_switch_context_xl(CPURISCVState *env) } } -target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) +target_ulong helper_sret(CPURISCVState *env) { uint64_t mstatus; target_ulong prev_priv, prev_virt; @@ -158,7 +158,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) return retpc; } -target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) +target_ulong helper_mret(CPURISCVState *env) { if (!(env->priv >= PRV_M)) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); -- 2.25.1
[PATCH 07/13] target/riscv: Ajdust vector atomic check with ol
Signed-off-by: LIU Zhiwei --- target/riscv/insn_trans/trans_rvv.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 01da065710..ed042f7bb9 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -739,7 +739,7 @@ static bool amo_check(DisasContext *s, arg_rwdvm* a) (!a->wd || vext_check_overlap_mask(s, a->rd, a->vm, false)) && vext_check_reg(s, a->rd, false) && vext_check_reg(s, a->rs2, false) && -((1 << s->sew) <= sizeof(target_ulong)) && +((1 << s->sew) <= (get_olen(s) / 8)) && ((1 << s->sew) >= 4)); } -- 2.25.1
[PATCH 3/3] sev/i386: Perform padding calculations at compile-time
In sev_add_kernel_loader_hashes, the sizes of structs are known at compile-time, so calculate needed padding at compile-time. No functional change intended. Signed-off-by: Dov Murik --- target/i386/sev.c | 28 ++-- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index a20ddb545e..c09de9c6f0 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -109,9 +109,19 @@ typedef struct QEMU_PACKED SevHashTable { SevHashTableEntry cmdline; SevHashTableEntry initrd; SevHashTableEntry kernel; -uint8_t padding[]; } SevHashTable; +/* + * Data encrypted by sev_encrypt_flash() must be padded to a multiple of + * 16 bytes. + */ +typedef struct QEMU_PACKED PaddedSevHashTable { +SevHashTable ht; +uint8_t padding[ROUND_UP(sizeof(SevHashTable), 16) - sizeof(SevHashTable)]; +} PaddedSevHashTable; + +QEMU_BUILD_BUG_ON(sizeof(PaddedSevHashTable) % 16 != 0); + static SevGuestState *sev_guest; static Error *sev_mig_blocker; @@ -1196,19 +1206,19 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) uint8_t *data; SevHashTableDescriptor *area; SevHashTable *ht; +PaddedSevHashTable *padded_ht; uint8_t cmdline_hash[HASH_SIZE]; uint8_t initrd_hash[HASH_SIZE]; uint8_t kernel_hash[HASH_SIZE]; uint8_t *hashp; size_t hash_len = HASH_SIZE; -int aligned_len = ROUND_UP(sizeof(SevHashTable), 16); if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) { warn_report("SEV: kernel specified but OVMF has no hash table guid"); return false; } area = (SevHashTableDescriptor *)data; -if (!area->base || area->size < aligned_len) { +if (!area->base || area->size < sizeof(PaddedSevHashTable)) { warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)", area->base, area->size); return false; @@ -1253,7 +1263,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) * Populate the hashes table in the guest's memory at the OVMF-designated * area for the SEV hashes table */ -ht = qemu_map_ram_ptr(NULL, area->base); +padded_ht = qemu_map_ram_ptr(NULL, area->base); +ht = &padded_ht->ht; ht->guid = sev_hash_table_header_guid; ht->len = sizeof(*ht); @@ -1270,13 +1281,10 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) ht->kernel.len = sizeof(ht->kernel); memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash)); -/* When calling sev_encrypt_flash, the length has to be 16 byte aligned */ -if (aligned_len != ht->len) { -/* zero the excess data so the measurement can be reliably calculated */ -memset(ht->padding, 0, aligned_len - ht->len); -} +/* zero the excess data so the measurement can be reliably calculated */ +memset(padded_ht->padding, 0, sizeof(padded_ht->padding)); -if (sev_encrypt_flash((uint8_t *)ht, aligned_len, errp) < 0) { +if (sev_encrypt_flash((uint8_t *)padded_ht, sizeof(*padded_ht), errp) < 0) { return false; } -- 2.25.1
[PATCH 0/3] SEV: fixes for -kernel launch with incompatible OVMF
Tom Lendacky and Brijesh Singh reported two issues with launching SEV guests with the -kernel QEMU option when an old [1] or wrongly configured [2] OVMF images are used. The fixes in patches 1 and 2 allow such guests to boot by skipping the kernel/initrd/cmdline hashes addition to the initial guest memory (and warning the user). Patch 3 is a refactoring of parts of the same function sev_add_kernel_loader_hashes() to calculate all padding sizes at compile-time. This patch is not required to fix the issues above, but is suggested as an improvement (no functional change intended). Note that launch measurement security is not harmed by these fixes: a Guest Owner that wants to use measured Linux boot with -kernel, must use (and measure) an OVMF image that designates a proper hashes table area, and that verifies those hashes when loading the binaries from QEMU via fw_cfg. The old OVMFs which don't publish the hashes table GUID or don't reserve a valid area for it in MEMFD cannot support these hashes verification in any case (for measured boot with -kernel). [1] https://lore.kernel.org/qemu-devel/3b9d10d9-5d9c-da52-f18c-cd93c1931...@amd.com/ [2] https://lore.kernel.org/qemu-devel/001dd81a-282d-c307-a657-e228480d4...@amd.com/ Dov Murik (3): sev/i386: Allow launching with -kernel if no OVMF hashes table found sev/i386: Warn if using -kernel with invalid OVMF hashes table area sev/i386: Perform padding calculations at compile-time target/i386/sev.c | 34 +++--- 1 file changed, 23 insertions(+), 11 deletions(-) base-commit: af531756d25541a1b3b3d9a14e72e7fedd941a2e -- 2.25.1
Re: [PATCH v2] hw: Add a 'Sensor devices' qdev category
ping? On 10/27/21 07:06, Philippe Mathieu-Daudé wrote: > Sensors models are listed in the 'Misc devices' category. > Move them to their own category. > > Reviewed-by: Cédric Le Goater > Reviewed-by: Hao Wu > Signed-off-by: Philippe Mathieu-Daudé > --- > v2: Only include hw/sensor/, removed AER915 device from hw/arm/z2.c > --- > include/hw/qdev-core.h | 1 + > hw/sensor/adm1272.c| 1 + > hw/sensor/dps310.c | 1 + > hw/sensor/emc141x.c| 1 + > hw/sensor/max34451.c | 2 ++ > hw/sensor/tmp105.c | 1 + > hw/sensor/tmp421.c | 1 + > softmmu/qdev-monitor.c | 1 + > 8 files changed, 9 insertions(+) > > diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h > index 1bad07002df..2fd6b73bd8b 100644 > --- a/include/hw/qdev-core.h > +++ b/include/hw/qdev-core.h > @@ -26,6 +26,7 @@ typedef enum DeviceCategory { > DEVICE_CATEGORY_SOUND, > DEVICE_CATEGORY_MISC, > DEVICE_CATEGORY_CPU, > +DEVICE_CATEGORY_SENSOR, > DEVICE_CATEGORY_MAX > } DeviceCategory; > > diff --git a/hw/sensor/adm1272.c b/hw/sensor/adm1272.c > index 7310c769be2..2942ac75f90 100644 > --- a/hw/sensor/adm1272.c > +++ b/hw/sensor/adm1272.c > @@ -518,6 +518,7 @@ static void adm1272_class_init(ObjectClass *klass, void > *data) > DeviceClass *dc = DEVICE_CLASS(klass); > PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass); > > +set_bit(DEVICE_CATEGORY_SENSOR, dc->categories); > dc->desc = "Analog Devices ADM1272 Hot Swap controller"; > dc->vmsd = &vmstate_adm1272; > k->write_data = adm1272_write_data; > diff --git a/hw/sensor/dps310.c b/hw/sensor/dps310.c > index d60a18ac41b..1e24a499b38 100644 > --- a/hw/sensor/dps310.c > +++ b/hw/sensor/dps310.c > @@ -208,6 +208,7 @@ static void dps310_class_init(ObjectClass *klass, void > *data) > k->send = dps310_tx; > dc->reset = dps310_reset; > dc->vmsd = &vmstate_dps310; > +set_bit(DEVICE_CATEGORY_SENSOR, dc->categories); > } > > static const TypeInfo dps310_info = { > diff --git a/hw/sensor/emc141x.c b/hw/sensor/emc141x.c > index 7ce8f4e9794..4202d8f185a 100644 > --- a/hw/sensor/emc141x.c > +++ b/hw/sensor/emc141x.c > @@ -270,6 +270,7 @@ static void emc141x_class_init(ObjectClass *klass, void > *data) > DeviceClass *dc = DEVICE_CLASS(klass); > I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); > > +set_bit(DEVICE_CATEGORY_SENSOR, dc->categories); > dc->reset = emc141x_reset; > k->event = emc141x_event; > k->recv = emc141x_rx; > diff --git a/hw/sensor/max34451.c b/hw/sensor/max34451.c > index a91d8bd487c..8300bf4ff43 100644 > --- a/hw/sensor/max34451.c > +++ b/hw/sensor/max34451.c > @@ -751,6 +751,8 @@ static void max34451_class_init(ObjectClass *klass, void > *data) > ResettableClass *rc = RESETTABLE_CLASS(klass); > DeviceClass *dc = DEVICE_CLASS(klass); > PMBusDeviceClass *k = PMBUS_DEVICE_CLASS(klass); > + > +set_bit(DEVICE_CATEGORY_SENSOR, dc->categories); > dc->desc = "Maxim MAX34451 16-Channel V/I monitor"; > dc->vmsd = &vmstate_max34451; > k->write_data = max34451_write_data; > diff --git a/hw/sensor/tmp105.c b/hw/sensor/tmp105.c > index 20564494899..43d79b9eeec 100644 > --- a/hw/sensor/tmp105.c > +++ b/hw/sensor/tmp105.c > @@ -305,6 +305,7 @@ static void tmp105_class_init(ObjectClass *klass, void > *data) > DeviceClass *dc = DEVICE_CLASS(klass); > I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); > > +set_bit(DEVICE_CATEGORY_SENSOR, dc->categories); > dc->realize = tmp105_realize; > k->event = tmp105_event; > k->recv = tmp105_rx; > diff --git a/hw/sensor/tmp421.c b/hw/sensor/tmp421.c > index a3db57dcb5a..c328978af9c 100644 > --- a/hw/sensor/tmp421.c > +++ b/hw/sensor/tmp421.c > @@ -343,6 +343,7 @@ static void tmp421_class_init(ObjectClass *klass, void > *data) > I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); > TMP421Class *sc = TMP421_CLASS(klass); > > +set_bit(DEVICE_CATEGORY_SENSOR, dc->categories); > dc->realize = tmp421_realize; > k->event = tmp421_event; > k->recv = tmp421_rx; > diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c > index 4851de51a5c..a411af03c5c 100644 > --- a/softmmu/qdev-monitor.c > +++ b/softmmu/qdev-monitor.c > @@ -164,6 +164,7 @@ static void qdev_print_devinfos(bool show_no_user) > [DEVICE_CATEGORY_SOUND] = "Sound", > [DEVICE_CATEGORY_MISC]= "Misc", > [DEVICE_CATEGORY_CPU] = "CPU", > +[DEVICE_CATEGORY_SENSOR] = "Sensor", > [DEVICE_CATEGORY_MAX] = "Uncategorized", > }; > GSList *list, *elt; >
[PATCH 1/3] sev/i386: Allow launching with -kernel if no OVMF hashes table found
Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes for measured linux boot", 2021-09-30) introduced measured direct boot with -kernel, using an OVMF-designated hashes table which QEMU fills. However, if OVMF doesn't designate such an area, QEMU would completely abort the VM launch. This breaks launching with -kernel using older OVMF images which don't publish the SEV_HASH_TABLE_RV_GUID. Instead, just warn the user that -kernel was supplied by OVMF doesn't specify the GUID for the hashes table. The following warning will be displayed during VM launch: qemu-system-x86_64: warning: SEV: kernel specified but OVMF has no hash table guid Signed-off-by: Dov Murik Reported-by: Tom Lendacky --- target/i386/sev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index eede07f11d..682b8ccf6c 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -1204,7 +1204,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) int aligned_len; if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) { -error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid"); +warn_report("SEV: kernel specified but OVMF has no hash table guid"); return false; } area = (SevHashTableDescriptor *)data; -- 2.25.1
gitlab-ci: clang-user job failed with run-tcg-tests-sh4-linux-user
Build failed running the 'clang-user' job: TESTlinux-test on sh4 ../linux-user/syscall.c:10373:34: runtime error: member access within misaligned address 0x0048af34 for type 'struct linux_dirent64', which requires 8 byte alignment 0x0048af34: note: pointer points here 00 00 00 00 00 40 0c 00 00 00 00 00 7b e2 f5 de fc d8 a1 3a 20 00 0a 66 69 6c 65 33 00 00 00 00 ^ make[2]: *** [../Makefile.target:158: run-linux-test] Error 1 make[1]: *** [/builds/philmd/qemu/tests/tcg/Makefile.qemu:102: run-guest-tests] Error 2 make: *** [/builds/philmd/qemu/tests/Makefile.include:63: run-tcg-tests-sh4-linux-user] Error 2 https://gitlab.com/philmd/qemu/-/jobs/1733066358
Re: [PATCH v4 1/2] sev/i386: Introduce sev_add_kernel_loader_hashes for measured linux boot
On 28/10/2021 11:41, Dov Murik wrote: > > > On 27/10/2021 22:43, Brijesh Singh wrote: >> Hi Dov, >> >> Sorry for coming a bit late on it but I am seeing another issue with >> this patch. The hash build logic looks for a SEV_HASH_TABLE_RV_GUID in >> the GUID list. If found, it uses the base address to store the hash'es. >> Looking at the OVMF, it seems that base address for this GUID is zero. > > Yes, I managed to reproduce this. With the OvmfPkgX64 build I see that > the GUID exists but base=0 and size=0. That size should be illegal > anyway for QEMU to fill. > > >> It seems that by default the Base Address is non-zero for the AmdSev >> Package build only. >> >> Can we add a check in the sev_add_kernel_loader_hashes() to verify that >> base address is non-zero and at the same time improve OVMF to update >> *.fdf to reserve this page in the MEMFD ? > > I'll prepare QEMU fixes: > > 1. (reported by Tom) when no SEV_HASH_TABLE_RV_GUID entry is found - > just warn and continue boot. > 2. (reported by Brijesh) verify that base != 0 (supposedly GPA 0 is a > valid address, but I'm willing to take a chance here and not allow it) > and size is big enough for the hashes table structure+padding. If not, > warn and continue boot. I submitted this small series [1]. Tom, Brijesh, I hope this solves the issues you're experiencing and allows you to boot (and displays a QEMU warning during launch). [1] https://lore.kernel.org/qemu-devel/20211101102136.1706421-1-dovmu...@linux.ibm.com/ -Dov > > Separately I'll try to solve the issue in the other OVMF *.fdf's. > > > > Thanks for reporting this. > > -Dov > > >> >> Thanks >> Brijesh >> >> On 10/20/21 10:26 AM, Tom Lendacky wrote: >>> On 10/19/21 1:18 AM, Dov Murik wrote: On 18/10/2021 21:02, Tom Lendacky wrote: > On 9/30/21 12:49 AM, Dov Murik wrote: > > ... > >> +/* >> + * Add the hashes of the linux kernel/initrd/cmdline to an encrypted >> guest page >> + * which is included in SEV's initial memory measurement. >> + */ >> +bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error >> **errp) >> +{ >> + uint8_t *data; >> + SevHashTableDescriptor *area; >> + SevHashTable *ht; >> + uint8_t cmdline_hash[HASH_SIZE]; >> + uint8_t initrd_hash[HASH_SIZE]; >> + uint8_t kernel_hash[HASH_SIZE]; >> + uint8_t *hashp; >> + size_t hash_len = HASH_SIZE; >> + int aligned_len; >> + >> + if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, >> NULL)) { >> + error_setg(errp, "SEV: kernel specified but OVMF has no hash >> table guid"); >> + return false; >> + } > > This breaks backwards compatibility with an older OVMF image. Any older > OVMF image with SEV support that doesn't have the hash table GUID will > now fail to boot using -kernel/-initrd/-append, where it used to be > able > to boot before. > Thanks Tom for noticing this. Just so we're on the same page: this patch is already merged. >>> >>> Right, just not in a release, yet. >>> We're dealing with a scenario of launching a guest with SEV enabled and with -kernel. The behaviours are: A. With current QEMU: A1. New AmdSev OVMF build: OVMF will verify the hashes and boot correctly. A2. New Generic OvmfPkgX64 build: No verification but will boot correctly. A3. Old AmdSev OVMF build: QEMU aborts the launch because there's no hash table GUID. A4. Old Generic OvmfPkgX64 build: QEMU aborts the launch because there's no hash table GUID. B. With older QEMU (before this patch was merged): B1. New AmdSev OVMF build: OVMF will try to verify the hashes but they are not populated; boot aborted. B2. New Generic OvmfPkgX64 build: No verification but will boot correctly. B3. Old AmdSev OVMF build: OVMF aborts the launch because -kernel is not supported at all. B4. Old Generic OvmfPkgX64 build: No verification but will boot correctly. So the problem you are raising is scenario A4 (as opposed to previous behaviour B4). >>> >>> Correct, scenario A4. >>> > Is that anything we need to be concerned about? > Possible solutions: 1. Do nothing. For users that encounter this: tell them to upgrade OVMF. 2. Modify the code: remove the line: error_setg(errp, "SEV: kernel specified but OVMF has no hash table guid") I think that option 2 will not degrade security *if* the Guest Owner verifies the measurement (which is mandatory anyway; otherwise the untrusted host can replace OVMF with a "malicious" version that doesn't verify the hashes). Skipping silently might make debugging a bit harder. Maybe we can print a warning and return, and then the guest launch will >
[PATCH 2/3] sev/i386: Warn if using -kernel with invalid OVMF hashes table area
Commit cff03145ed3c ("sev/i386: Introduce sev_add_kernel_loader_hashes for measured linux boot", 2021-09-30) introduced measured direct boot with -kernel, using an OVMF-designated hashes table which QEMU fills. However, no checks are performed on the validity of the hashes area designated by OVMF. Specifically, if OVMF publishes the SEV_HASH_TABLE_RV_GUID entry but it is filled with zeroes, this will cause QEMU to write the hashes entries over the first page of the guest's memory (GPA 0). Add validity checks to the published area. If the hashes table area's base address is zero, or its size is too small to fit the aligned hashes table, warn and skip the hashes entries addition. In such case, the following warning will be displayed: qemu-system-x86_64: warning: SEV: OVMF's hashes table area is invalid (base=0x0 size=0x0) Signed-off-by: Dov Murik Reported-by: Brijesh Singh --- target/i386/sev.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 682b8ccf6c..a20ddb545e 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -1201,13 +1201,18 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) uint8_t kernel_hash[HASH_SIZE]; uint8_t *hashp; size_t hash_len = HASH_SIZE; -int aligned_len; +int aligned_len = ROUND_UP(sizeof(SevHashTable), 16); if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) { warn_report("SEV: kernel specified but OVMF has no hash table guid"); return false; } area = (SevHashTableDescriptor *)data; +if (!area->base || area->size < aligned_len) { +warn_report("SEV: OVMF's hashes table area is invalid (base=0x%x size=0x%x)", +area->base, area->size); +return false; +} /* * Calculate hash of kernel command-line with the terminating null byte. If @@ -1266,7 +1271,6 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash)); /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */ -aligned_len = ROUND_UP(ht->len, 16); if (aligned_len != ht->len) { /* zero the excess data so the measurement can be reliably calculated */ memset(ht->padding, 0, aligned_len - ht->len); -- 2.25.1
Re: [PATCH 01/13] target/riscv: Sign extend pc for different ol
On 11/1/21 6:01 AM, LIU Zhiwei wrote: +static void gen_set_pc(DisasContext *ctx, target_ulong dest) +{ +TCGv t = tcg_constant_tl(dest); +switch (get_ol(ctx)) { +case MXL_RV32: +tcg_gen_ext32s_tl(cpu_pc, t); Don't compute with tcg to do what you can in C. Dest is constant. And I think that XL is more appropriate than OL (which *should* be the same, but still looks weird). if (get_xl(ctx) == MXL_RV32) { dest = (int32_t)dest; } tcg_gen_movi_tl(cpu_pc, dest); r~
Re: [PATCH v2] .mailmap: Fix more contributor entries
Can this patch go via the Trivial tree? On 10/27/21 06:32, Philippe Mathieu-Daudé wrote: > These authors have some incorrect author email field. > > Acked-by: Pan Nengyuan > Reviewed-by: Alex Chen > Reviewed-by: Hyman Huang > Reviewed-by: Haibin Zhang > Signed-off-by: Philippe Mathieu-Daudé > --- > Patch fully reviewed/acked. > --- > .mailmap | 4 > 1 file changed, 4 insertions(+) > > diff --git a/.mailmap b/.mailmap > index f029d1c21fe..8beb2f95ae2 100644 > --- a/.mailmap > +++ b/.mailmap > @@ -69,6 +69,7 @@ Yongbok Kim > # git author config, or had utf8/latin1 encoding issues. > Aaron Lindsay > Alexey Gerasimenko > +Alex Chen > Alex Ivanov > Andreas Färber > Bandan Das > @@ -99,9 +100,11 @@ Gautham R. Shenoy > Gautham R. Shenoy > Gonglei (Arei) > Guang Wang > +Haibin Zhang > Hailiang Zhang > Hanna Reitz > Hervé Poussineau > +Hyman Huang > Jakub Jermář > Jakub Jermář > Jean-Christophe Dubois > @@ -135,6 +138,7 @@ Nicholas Thomas > Nikunj A Dadhania > Orit Wasserman > Paolo Bonzini > +Pan Nengyuan > Pavel Dovgaluk > Pavel Dovgaluk > Pavel Dovgaluk >
Re: [PULL 28/30] Hexagon HVX (tests/tcg/hexagon) hvx_misc test
On 10/31/21 17:43, Taylor Simpson wrote: > Tests for > packet semantics > vector loads (aligned and unaligned) > vector stores (aligned and unaligned) > vector masked stores > vector new value store > maximum HVX temps in a packet > vector operations > > Acked-by: Richard Henderson > Signed-off-by: Taylor Simpson > --- > tests/tcg/hexagon/hvx_misc.c | 469 > ++ > tests/tcg/hexagon/Makefile.target | 2 + > 2 files changed, 471 insertions(+) > create mode 100644 tests/tcg/hexagon/hvx_misc.c > +static void test_load_tmp(void) > +{ > +void *p0 = buffer0; > +void *p1 = buffer1; > +void *pout = output; > + > +for (int i = 0; i < BUFSIZE; i++) { > +/* > + * Load into v12 as .tmp, then use it in the next packet > + * Should get the new value within the same packet and > + * the old value in the next packet > + */ > +asm("v3 = vmem(%0 + #0)\n\t" > +"r1 = #1\n\t" > +"v12 = vsplat(r1)\n\t" > +"{\n\t" > +"v12.tmp = vmem(%1 + #0)\n\t" > +"v4.w = vadd(v12.w, v3.w)\n\t" > +"}\n\t" > +"v4.w = vadd(v4.w, v12.w)\n\t" > +"vmem(%2 + #0) = v4\n\t" > +: : "r"(p0), "r"(p1), "r"(pout) > +: "r1", "v12", "v3", "v4", "v6", "memory"); > +p0 += sizeof(MMVector); > +p1 += sizeof(MMVector); > +pout += sizeof(MMVector); > + > +for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { > +expect[i].w[j] = buffer0[i].w[j] + buffer1[i].w[j] + 1; > +} > +} > + > +check_output_w(__LINE__, BUFSIZE); > +} This test fails guest-tests: tests/tcg/hexagon/hvx_misc.c:111:21: error: unknown register name 'v12' in asm : "r1", "v12", "v3", "v4", "v6", "memory"); ^ tests/tcg/hexagon/hvx_misc.c:362:9: note: expanded from macro 'TEST_VEC_OP2' VEC_OP2(ASM, EL, p0, p1, pout); \ ^
Re: [PATCH 02/13] target/riscv: Extend pc for runtime pc write
On 11/1/21 6:01 AM, LIU Zhiwei wrote: In some cases, we must restore the guest PC to the address of the start of the TB, such as when the instruction counter hit zero. So extend pc register according to current xlen for these cases. Signed-off-by: LIU Zhiwei --- target/riscv/cpu.c| 20 +--- target/riscv/cpu.h| 2 ++ target/riscv/cpu_helper.c | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7d53125dbc..7eefd4f6a6 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -319,7 +319,12 @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; -env->pc = value; + +if (cpu_get_xl(env) == MXL_RV32) { +env->pc = (int32_t)value; +} else { +env->pc = value; +} } Good. static void riscv_cpu_synchronize_from_tb(CPUState *cs, @@ -327,7 +332,12 @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs, { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; -env->pc = tb->pc; + +if (cpu_get_xl(env) == MXL_RV32) { +env->pc = (int32_t)tb->pc; +} else { +env->pc = tb->pc; +} Bad, since TB->PC should be extended properly. Though this waits on a change to cpu_get_tb_cpu_state. @@ -348,7 +358,11 @@ static bool riscv_cpu_has_work(CPUState *cs) void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb, target_ulong *data) { -env->pc = data[0]; + if (cpu_get_xl(env) == MXL_RV32) { +env->pc = (int32_t)data[0]; +} else { +env->pc = data[0]; +} Likewise. r~
Re: [PATCH v3 03/12] vfio-user: define vfio-user-server object
On Fri, Oct 29, 2021 at 02:42:49PM +, Jag Raman wrote: > > On Oct 27, 2021, at 11:40 AM, Stefan Hajnoczi wrote: > > On Mon, Oct 11, 2021 at 01:31:08AM -0400, Jagannathan Raman wrote: > >> diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c > >> new file mode 100644 > >> index 00..c2a300f0ff > >> --- /dev/null > >> +++ b/hw/remote/vfio-user-obj.c > >> @@ -0,0 +1,173 @@ > >> +/** > >> + * QEMU vfio-user-server server object > >> + * > >> + * Copyright © 2021 Oracle and/or its affiliates. > >> + * > >> + * This work is licensed under the terms of the GNU GPL-v2, version 2 or > >> later. > >> + * > >> + * See the COPYING file in the top-level directory. > >> + * > >> + */ > >> + > >> +/** > >> + * Usage: add options: > >> + * -machine x-remote > >> + * -device ,id= > >> + * -object vfio-user-server,id=,type=unix,path=, > > > > I expected socket.type= and socket.path= based on the QAPI schema. Is > > this command-line example correct? > > When I tried the “socket.path” approach, QEMU was not able to parse the > arguments. So I had to break it down to a series of individual members. > > If “socket.path” is the expected way, I’ll see why the parser is not working > as expected. CCing Markus regarding QAPI. I'm surprised because the QAPI schema for vfio-user-server objects is: { 'struct': 'VfioUserServerProperties', 'data': { 'socket': 'SocketAddress', 'device': 'str' } } It's not clear to me why the command-line parser flattens the 'socket' field into its 'type' and 'path' sub-fields in your example: -object vfio-user-server,id=,type=unix,path=,device= Maybe because SocketAddress is an enum instead of a struct? Imagine a second SocketAddress field is added to vfio-user-server. How can the parser know which field 'type' and 'path' belong to? I tried it: { 'struct': 'VfioUserServerProperties', 'data': { 'socket': 'SocketAddress', 'socket2': 'SocketAddress', 'device': 'str' } } Now the parser refuses any input I've tried. For example: $ build/qemu-system-x86_64 -object vfio-user-server,id=s,device=asdf,type=unix,path=asdf,type=unix qemu-system-x86_64: -object vfio-user-server,id=s,device=asdf,type=unix,path=asdf,type=unix: Parameter 'type' is missing A similar case happens if the parent struct has 'type' or 'path' fields. They collide with the SocketAddress union fields. I didn't test this though. Questions for Markus: 1. Do you know why the parser behaves like this? 2. Is it good practice to embed SocketAddress into parent structs or should we force it into a struct? Stefan signature.asc Description: PGP signature
Re: [PATCH v3 04/12] vfio-user: instantiate vfio-user context
On Fri, Oct 29, 2021 at 02:59:02PM +, Jag Raman wrote: > > > > On Oct 27, 2021, at 11:59 AM, Stefan Hajnoczi wrote: > > > > On Mon, Oct 11, 2021 at 01:31:09AM -0400, Jagannathan Raman wrote: > >> @@ -94,9 +101,31 @@ static void vfu_object_set_device(Object *obj, const > >> char *str, Error **errp) > >> trace_vfu_prop("device", str); > >> } > >> > >> +/* > >> + * vfio-user-server depends on the availability of the 'socket' and > >> 'device' > >> + * properties. It also depends on devices instantiated in QEMU. These > >> + * dependencies are not available during the instance_init phase of this > >> + * object's life-cycle. As such, the server is initialized after the > >> + * machine is setup. machine_init_done_notifier notifies vfio-user-server > >> + * when the machine is setup, and the dependencies are available. > >> + */ > >> +static void vfu_object_machine_done(Notifier *notifier, void *data) > >> +{ > >> +VfuObject *o = container_of(notifier, VfuObject, machine_done); > > > > Was there a check for non-NULL o->socket before this? Maybe it's not > > needed because QAPI treats 'socket' as a required field and refuses to > > create the SocketAddress if it's missing? > > Yes, “socket” is a required option. The server will not launch without that > option. Thanks for confirming! > I believe optional parameters are defined within ‘[‘ and ‘]’ braces in > "./qapi/qom.json" Optional parameters have the asterisk ('*'). Block quotes are for lists. Stefan signature.asc Description: PGP signature
Re: [PATCH v3 05/12] vfio-user: find and init PCI device
On Fri, Oct 29, 2021 at 03:58:28PM +, Jag Raman wrote: > > > > On Oct 27, 2021, at 12:05 PM, Stefan Hajnoczi wrote: > > > > On Mon, Oct 11, 2021 at 01:31:10AM -0400, Jagannathan Raman wrote: > >> Find the PCI device with specified id. Initialize the device context > >> with the QEMU PCI device > >> > >> Signed-off-by: Elena Ufimtseva > >> Signed-off-by: John G Johnson > >> Signed-off-by: Jagannathan Raman > >> --- > >> hw/remote/vfio-user-obj.c | 32 > >> 1 file changed, 32 insertions(+) > >> > >> diff --git a/hw/remote/vfio-user-obj.c b/hw/remote/vfio-user-obj.c > >> index d26e5ec9e9..7ce4e5b256 100644 > >> --- a/hw/remote/vfio-user-obj.c > >> +++ b/hw/remote/vfio-user-obj.c > >> @@ -44,6 +44,8 @@ > >> #include "qemu/notify.h" > >> #include "sysemu/sysemu.h" > >> #include "libvfio-user.h" > >> +#include "hw/qdev-core.h" > >> +#include "hw/pci/pci.h" > >> > >> #define TYPE_VFU_OBJECT "vfio-user-server" > >> OBJECT_DECLARE_TYPE(VfuObject, VfuObjectClass, VFU_OBJECT) > >> @@ -68,6 +70,8 @@ struct VfuObject { > >> Notifier machine_done; > >> > >> vfu_ctx_t *vfu_ctx; > >> + > >> +PCIDevice *pci_dev; > >> }; > >> > >> static void vfu_object_set_socket(Object *obj, Visitor *v, const char > >> *name, > >> @@ -112,6 +116,9 @@ static void vfu_object_set_device(Object *obj, const > >> char *str, Error **errp) > >> static void vfu_object_machine_done(Notifier *notifier, void *data) > >> { > >> VfuObject *o = container_of(notifier, VfuObject, machine_done); > >> +DeviceState *dev = NULL; > >> +vfu_pci_type_t pci_type = VFU_PCI_TYPE_CONVENTIONAL; > >> +int ret; > >> > >> o->vfu_ctx = vfu_create_ctx(VFU_TRANS_SOCK, o->socket->u.q_unix.path, > >> 0, > >> o, VFU_DEV_TYPE_PCI); > >> @@ -120,6 +127,31 @@ static void vfu_object_machine_done(Notifier > >> *notifier, void *data) > >>strerror(errno)); > >> return; > >> } > >> + > >> +dev = qdev_find_recursive(sysbus_get_default(), o->device); > >> +if (dev == NULL) { > >> +error_setg(&error_abort, "vfu: Device %s not found", o->device); > >> +return; > >> +} > >> + > >> +if (!object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { > >> +error_setg(&error_abort, "vfu: %s not a PCI device", o->device); > >> +return; > >> +} > >> + > >> +o->pci_dev = PCI_DEVICE(dev); > >> + > >> +if (pci_is_express(o->pci_dev)) { > >> +pci_type = VFU_PCI_TYPE_EXPRESS; > >> +} > >> + > >> +ret = vfu_pci_init(o->vfu_ctx, pci_type, PCI_HEADER_TYPE_NORMAL, 0); > >> +if (ret < 0) { > >> +error_setg(&error_abort, > >> + "vfu: Failed to attach PCI device %s to context - %s", > >> + o->device, strerror(errno)); > >> +return; > >> +} > > > > It's unclear what happens when one of these error code paths is taken. > > o->vfu_ctx and o->pci_dev might both be initialized, so how does the > > code know not to service the vfio-user connection? It would be easy to > > tell that this is correct if o->pci_dev and o->vfu_ctx were destroyed > > when an error occurs. > > Hey Stefan, if I understand your question correctly, you’re wondering > if the server would still service the connection if it takes the above > error path. > > I don’t believe that would happen. When the above error path is taken, > “error_abort” is set. Setting error_abort immediately terminates the > QEMU process. Additionally, vfu_object_ctx_run() won’t be > attached to the unix socket as the function exits early - so the > connection wouldn’t be serviced. Thanks. I'll revisit this next revision because error_abort cannot be used for hotplug. It's okay to terminate the process on startup, but for hotplug the expected behavior is to report an error and continue running. Stefan signature.asc Description: PGP signature
Re: [PATCH 03/13] target/riscv: Ignore the pc bits above XLEN
On 11/1/21 6:01 AM, LIU Zhiwei wrote: The read from PC for translation is in cpu_get_tb_cpu_state, before translation. Signed-off-by: LIU Zhiwei --- target/riscv/cpu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Reviewed-by: Richard Henderson Could perhaps be sorted to patch 2, then riscv_cpu_synchronize_from_tb and restore_state_to_opc could assert that the pc is properly extended. r~
Re: [PATCH 04/13] target/riscv: Use gdb xml according to max mxlen
On 11/1/21 6:01 AM, LIU Zhiwei wrote: +switch (env->misa_mxl_max) { +case MXL_RV32: +tmp = (uint32_t)ldl_p(mem_buf); Signed int32_t. Otherwise, Reviewed-by: Richard Henderson r~
Re: [PATCH v4 2/2] tests/unit: Add an unit test for smp parsing
On 10/31/21 13:02, wangyanan (Y) wrote: > Hi Philippe, > > I saw that there are some cross-build failures and a clang complain > about this patch in your triggered CI pipeline. I believe the minor > diff below will resolve them. If you are going to resend v2 of the > "qdev-hotplug" patches, I would very much appreciate it if you > can also help to respin v5 of this series with the diff applied. > Sorry for the extra work included. :) Sure, thanks for running the CI pipeline, you saved me time (I'll still run it again, but with your diff applied). > > Thanks, > Yanan > > diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c > index e96abe9ba4..61985094f5 100644 > --- a/tests/unit/test-smp-parse.c > +++ b/tests/unit/test-smp-parse.c > @@ -347,12 +347,12 @@ static char *smp_config_to_string(SMPConfiguration > *config) > { > return g_strdup_printf( > "(SMPConfiguration) {\n" > - " .has_cpus = %5s, cpus = %ld,\n" > - " .has_sockets = %5s, sockets = %ld,\n" > - " .has_dies = %5s, dies = %ld,\n" > - " .has_cores = %5s, cores = %ld,\n" > - " .has_threads = %5s, threads = %ld,\n" > - " .has_maxcpus = %5s, maxcpus = %ld,\n" > + " .has_cpus = %5s, cpus = %" PRId64 ",\n" > + " .has_sockets = %5s, sockets = %" PRId64 ",\n" > + " .has_dies = %5s, dies = %" PRId64 ",\n" > + " .has_cores = %5s, cores = %" PRId64 ",\n" > + " .has_threads = %5s, threads = %" PRId64 ",\n" > + " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" > "}", > config->has_cpus ? "true" : "false", config->cpus, > config->has_sockets ? "true" : "false", config->sockets, > @@ -495,7 +495,7 @@ static void test_generic(void) > Object *obj = object_new(TYPE_MACHINE); > MachineState *ms = MACHINE(obj); > MachineClass *mc = MACHINE_GET_CLASS(obj); > - SMPTestData *data = &(SMPTestData){0}; > + SMPTestData *data = &(SMPTestData){{0}}; > int i; > > smp_machine_class_init(mc); > @@ -531,7 +531,7 @@ static void test_with_dies(void) > Object *obj = object_new(TYPE_MACHINE); > MachineState *ms = MACHINE(obj); > MachineClass *mc = MACHINE_GET_CLASS(obj); > - SMPTestData *data = &(SMPTestData){0}; > + SMPTestData *data = &(SMPTestData){{0}}; > unsigned int num_dies = 2; > int i; > > On 2021/10/28 23:09, Philippe Mathieu-Daudé wrote: >> From: Yanan Wang >> >> Now that we have a generic parser smp_parse(), let's add an unit >> test for the code. All possible valid/invalid SMP configurations >> that the user can specify are covered. >> >> Signed-off-by: Yanan Wang >> Reviewed-by: Andrew Jones >> Tested-by: Philippe Mathieu-Daudé >> Message-Id: <20211026034659.22040-3-wangyana...@huawei.com> >> Signed-off-by: Philippe Mathieu-Daudé >> --- >> tests/unit/test-smp-parse.c | 594 >> MAINTAINERS | 1 + >> tests/unit/meson.build | 1 + >> 3 files changed, 596 insertions(+) >> create mode 100644 tests/unit/test-smp-parse.c
Re: [PATCH v8 28/29] accel/tcg/user-exec: Implement CPU-specific signal handler for loongarch64 hosts
Hi, On 2021/11/1 17:51, Song Gao wrote: > Base-on: <20210925173032.2434906-30-...@xen0n.name> > Signed-off-by: Song Gao > Signed-off-by: Xiaojuan Yang > --- > accel/tcg/user-exec.c | 64 > --- > 1 file changed, 61 insertions(+), 3 deletions(-) While I can see this patch and the next one are clearly from me, my author info is lost as I didn't spot any "From:" line in the mail body? Also I don't remember seeing "Base-on" tags in QEMU either. I think you're meaning to include the "Based-on" tags in your cover letter instead?