Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2995afed2 | ||
|
|
0befc056f3 | ||
|
|
148eb79f57 | ||
|
|
b1ff64ba4e | ||
|
|
53a4bf6830 | ||
|
|
5a1414313b | ||
|
|
361bd5efe4 | ||
|
|
5d139247e9 | ||
|
|
289dcab554 | ||
|
|
e2d4d3c2ac | ||
|
|
6b10b25ddd | ||
|
|
800495a394 | ||
|
|
ac053657f0 | ||
|
|
41c984df66 | ||
|
|
84dd432553 | ||
|
|
dec1f0b924 | ||
|
|
32f8a2b429 | ||
|
|
d5166dad55 | ||
|
|
80eebc00f9 | ||
|
|
fd0fc3eb48 | ||
|
|
28ee50bbe9 | ||
|
|
6c4ddafa0d | ||
|
|
10bfc8d45e | ||
|
|
fb1f88ee29 | ||
|
|
82c0f4946a | ||
|
|
d6258d62cf | ||
|
|
0b8c7cdeff | ||
|
|
0883bdd92e | ||
|
|
3d2e7e1428 | ||
|
|
649ef0c6f1 | ||
|
|
93e5ecd780 | ||
|
|
dc5208769a | ||
|
|
5dd4660f5f | ||
|
|
4ba45dffde | ||
|
|
9e13cd7232 | ||
|
|
7407d2319d | ||
|
|
83c926daf8 | ||
|
|
8696da0495 | ||
|
|
dc13fed5f0 | ||
|
|
639cee5ed7 | ||
|
|
c7e0189982 | ||
|
|
e6e49667ae | ||
|
|
9f8bb7edac | ||
|
|
1cc062970e | ||
|
|
af01cf195b | ||
|
|
7f637d2922 | ||
|
|
138d48eca8 | ||
|
|
d1960fafec | ||
|
|
6a3304c84a | ||
|
|
697209ff41 | ||
|
|
849a6aea33 | ||
|
|
5313973fd4 | ||
|
|
83d36ab099 | ||
|
|
ff765e490e | ||
|
|
6e827147d6 | ||
|
|
08c3572736 | ||
|
|
4580c38134 | ||
|
|
8a669b8aae | ||
|
|
fa7638d8c1 | ||
|
|
358f7c6892 | ||
|
|
d87ee29327 | ||
|
|
ec877d2ab0 |
@@ -21,7 +21,7 @@ repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
||||
|
||||
print(f"adding upstream git repo @ {repourl}")
|
||||
subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
|
||||
subprocess.check_call(["git", "fetch", "check-dco", "master"])
|
||||
subprocess.check_call(["git", "fetch", "--refetch", "check-dco", "master"])
|
||||
|
||||
ancestor = subprocess.check_output(["git", "merge-base",
|
||||
"check-dco/master", "HEAD"],
|
||||
|
||||
@@ -24,7 +24,7 @@ print(f"adding upstream git repo @ {repourl}")
|
||||
# base for the user's branch. We thus need to figure out a common
|
||||
# ancestor between the user's branch and current git master.
|
||||
subprocess.check_call(["git", "remote", "add", "check-patch", repourl])
|
||||
subprocess.check_call(["git", "fetch", "check-patch", "master"])
|
||||
subprocess.check_call(["git", "fetch", "--refetch", "check-patch", "master"])
|
||||
|
||||
ancestor = subprocess.check_output(["git", "merge-base",
|
||||
"check-patch/master", "HEAD"],
|
||||
|
||||
@@ -105,7 +105,7 @@ static int64_t decode_sleb128(const uint8_t **pp)
|
||||
val |= (int64_t)(byte & 0x7f) << shift;
|
||||
shift += 7;
|
||||
} while (byte & 0x80);
|
||||
if (shift < TARGET_LONG_BITS && (byte & 0x40)) {
|
||||
if (shift < 64 && (byte & 0x40)) {
|
||||
val |= -(int64_t)1 << shift;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,11 +69,11 @@ safe_syscall_end:
|
||||
|
||||
/* code path setting errno */
|
||||
0: neg a0, a0
|
||||
j safe_syscall_set_errno_tail
|
||||
tail safe_syscall_set_errno_tail
|
||||
|
||||
/* code path when we didn't execute the syscall */
|
||||
2: li a0, QEMU_ERESTARTSYS
|
||||
j safe_syscall_set_errno_tail
|
||||
tail safe_syscall_set_errno_tail
|
||||
|
||||
.cfi_endproc
|
||||
.size safe_syscall_base, .-safe_syscall_base
|
||||
|
||||
@@ -4,7 +4,7 @@ RISC-V IOMMU support for RISC-V machines
|
||||
========================================
|
||||
|
||||
QEMU implements a RISC-V IOMMU emulation based on the RISC-V IOMMU spec
|
||||
version 1.0 `iommu1.0`_.
|
||||
version 1.0 `iommu1.0.0`_.
|
||||
|
||||
The emulation includes a PCI reference device, riscv-iommu-pci, that QEMU
|
||||
RISC-V boards can use. The 'virt' RISC-V machine is compatible with this
|
||||
@@ -14,7 +14,7 @@ riscv-iommu-pci reference device
|
||||
--------------------------------
|
||||
|
||||
This device implements the RISC-V IOMMU emulation as recommended by the section
|
||||
"Integrating an IOMMU as a PCIe device" of `iommu1.0`_: a PCI device with base
|
||||
"Integrating an IOMMU as a PCIe device" of `iommu1.0.0`_: a PCI device with base
|
||||
class 08h, sub-class 06h and programming interface 00h.
|
||||
|
||||
As a reference device it doesn't implement anything outside of the specification,
|
||||
@@ -83,7 +83,7 @@ Several options are available to control the capabilities of the device, namely:
|
||||
- "s-stage": enable s-stage support
|
||||
- "g-stage": enable g-stage support
|
||||
|
||||
.. _iommu1.0: https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf
|
||||
.. _iommu1.0.0: https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0.0/riscv-iommu.pdf
|
||||
|
||||
.. _linux-v8: https://lore.kernel.org/linux-riscv/cover.1718388908.git.tjeznach@rivosinc.com/
|
||||
|
||||
|
||||
+30
-9
@@ -434,16 +434,24 @@ void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu)
|
||||
V9fsFidState *f;
|
||||
GHashTableIter iter;
|
||||
gpointer fid;
|
||||
int err;
|
||||
int nclosed = 0;
|
||||
|
||||
/* prevent multiple coroutines running this function simultaniously */
|
||||
if (s->reclaiming) {
|
||||
return;
|
||||
}
|
||||
s->reclaiming = true;
|
||||
|
||||
g_hash_table_iter_init(&iter, s->fids);
|
||||
|
||||
QSLIST_HEAD(, V9fsFidState) reclaim_list =
|
||||
QSLIST_HEAD_INITIALIZER(reclaim_list);
|
||||
|
||||
/* Pick FIDs to be closed, collect them on reclaim_list. */
|
||||
while (g_hash_table_iter_next(&iter, &fid, (gpointer *) &f)) {
|
||||
/*
|
||||
* Unlink fids cannot be reclaimed. Check
|
||||
* for them and skip them. Also skip fids
|
||||
* Unlinked fids cannot be reclaimed, skip those, and also skip fids
|
||||
* currently being operated on.
|
||||
*/
|
||||
if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
|
||||
@@ -493,23 +501,34 @@ void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now close the fid in reclaim list. Free them if they
|
||||
* are already clunked.
|
||||
* Close the picked FIDs altogether on a background I/O driver thread. Do
|
||||
* this all at once to keep latency (i.e. amount of thread hops between main
|
||||
* thread <-> fs driver background thread) as low as possible.
|
||||
*/
|
||||
v9fs_co_run_in_worker({
|
||||
QSLIST_FOREACH(f, &reclaim_list, reclaim_next) {
|
||||
err = (f->fid_type == P9_FID_DIR) ?
|
||||
s->ops->closedir(&s->ctx, &f->fs_reclaim) :
|
||||
s->ops->close(&s->ctx, &f->fs_reclaim);
|
||||
if (!err) {
|
||||
/* total_open_fd must only be mutated on main thread */
|
||||
nclosed++;
|
||||
}
|
||||
}
|
||||
});
|
||||
total_open_fd -= nclosed;
|
||||
/* Free the closed FIDs. */
|
||||
while (!QSLIST_EMPTY(&reclaim_list)) {
|
||||
f = QSLIST_FIRST(&reclaim_list);
|
||||
QSLIST_REMOVE(&reclaim_list, f, V9fsFidState, reclaim_next);
|
||||
if (f->fid_type == P9_FID_FILE) {
|
||||
v9fs_co_close(pdu, &f->fs_reclaim);
|
||||
} else if (f->fid_type == P9_FID_DIR) {
|
||||
v9fs_co_closedir(pdu, &f->fs_reclaim);
|
||||
}
|
||||
/*
|
||||
* Now drop the fid reference, free it
|
||||
* if clunked.
|
||||
*/
|
||||
put_fid(pdu, f);
|
||||
}
|
||||
|
||||
s->reclaiming = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4291,6 +4310,8 @@ int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
|
||||
s->ctx.fst = &fse->fst;
|
||||
fsdev_throttle_init(s->ctx.fst);
|
||||
|
||||
s->reclaiming = false;
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
if (rc) {
|
||||
|
||||
@@ -362,6 +362,7 @@ struct V9fsState {
|
||||
uint64_t qp_ndevices; /* Amount of entries in qpd_table. */
|
||||
uint16_t qp_affix_next;
|
||||
uint64_t qp_fullpath_next;
|
||||
bool reclaiming;
|
||||
};
|
||||
|
||||
/* 9p2000.L open flags */
|
||||
|
||||
@@ -72,6 +72,7 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
|
||||
|
||||
for (el = machines; el; el = el->next) {
|
||||
MachineClass *mc = el->data;
|
||||
const char *default_cpu_type = machine_class_default_cpu_type(mc);
|
||||
MachineInfo *info;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
@@ -90,8 +91,8 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
|
||||
info->numa_mem_supported = mc->numa_mem_supported;
|
||||
info->deprecated = !!mc->deprecation_reason;
|
||||
info->acpi = !!object_class_property_find(OBJECT_CLASS(mc), "acpi");
|
||||
if (mc->default_cpu_type) {
|
||||
info->default_cpu_type = g_strdup(mc->default_cpu_type);
|
||||
if (default_cpu_type) {
|
||||
info->default_cpu_type = g_strdup(default_cpu_type);
|
||||
}
|
||||
if (mc->default_ram_id) {
|
||||
info->default_ram_id = g_strdup(mc->default_ram_id);
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ static void imx_gpio_update_int(IMXGPIOState *s)
|
||||
static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
|
||||
{
|
||||
/* if this signal isn't configured as an input signal, nothing to do */
|
||||
if (!extract32(s->gdir, line, 1)) {
|
||||
if (extract32(s->gdir, line, 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+5
-6
@@ -90,13 +90,12 @@ static void imx_i2c_reset(DeviceState *dev)
|
||||
|
||||
static inline void imx_i2c_raise_interrupt(IMXI2CState *s)
|
||||
{
|
||||
/*
|
||||
* raise an interrupt if the device is enabled and it is configured
|
||||
* to generate some interrupts.
|
||||
*/
|
||||
if (imx_i2c_is_enabled(s) && imx_i2c_interrupt_is_enabled(s)) {
|
||||
if (imx_i2c_is_enabled(s)) {
|
||||
s->i2sr |= I2SR_IIF;
|
||||
qemu_irq_raise(s->irq);
|
||||
|
||||
if (imx_i2c_interrupt_is_enabled(s)) {
|
||||
qemu_irq_raise(s->irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1716,6 +1716,7 @@ static void amdvi_pci_class_init(ObjectClass *klass, void *data)
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->vendor_id = PCI_VENDOR_ID_AMD;
|
||||
k->device_id = 0x1419;
|
||||
k->class_id = 0x0806;
|
||||
k->realize = amdvi_pci_realize;
|
||||
|
||||
|
||||
@@ -333,7 +333,6 @@ static void mips_fuloong2e_machine_init(MachineClass *mc)
|
||||
mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-2E");
|
||||
mc->default_ram_size = 256 * MiB;
|
||||
mc->default_ram_id = "fuloong2e.ram";
|
||||
mc->minimum_page_bits = 14;
|
||||
machine_add_audiodev_property(mc);
|
||||
}
|
||||
|
||||
|
||||
@@ -670,7 +670,6 @@ static void loongson3v_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->max_cpus = LOONGSON_MAX_VCPUS;
|
||||
mc->default_ram_id = "loongson3.highram";
|
||||
mc->default_ram_size = 1600 * MiB;
|
||||
mc->minimum_page_bits = 14;
|
||||
mc->default_nic = "virtio-net-pci";
|
||||
}
|
||||
|
||||
|
||||
+41
-46
@@ -1702,44 +1702,41 @@ static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr)
|
||||
* cache.
|
||||
*/
|
||||
static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
|
||||
size_t *hdr_len, const uint8_t *buf,
|
||||
size_t buf_size, size_t *buf_offset)
|
||||
uint8_t *buf, size_t size)
|
||||
{
|
||||
size_t csum_size = ETH_HLEN + sizeof(struct ip_header) +
|
||||
sizeof(struct udp_header);
|
||||
|
||||
buf += *buf_offset;
|
||||
buf_size -= *buf_offset;
|
||||
|
||||
if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
|
||||
(buf_size >= csum_size && buf_size < 1500) && /* normal sized MTU */
|
||||
(size >= csum_size && size < 1500) && /* normal sized MTU */
|
||||
(buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
|
||||
(buf[23] == 17) && /* ip.protocol == UDP */
|
||||
(buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
|
||||
memcpy((uint8_t *)hdr + *hdr_len, buf, csum_size);
|
||||
net_checksum_calculate((uint8_t *)hdr + *hdr_len, csum_size, CSUM_UDP);
|
||||
net_checksum_calculate(buf, size, CSUM_UDP);
|
||||
hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
|
||||
*hdr_len += csum_size;
|
||||
*buf_offset += csum_size;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t receive_header(VirtIONet *n, struct virtio_net_hdr *hdr,
|
||||
const void *buf, size_t buf_size,
|
||||
size_t *buf_offset)
|
||||
static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
|
||||
const void *buf, size_t size)
|
||||
{
|
||||
size_t hdr_len = n->guest_hdr_len;
|
||||
if (n->has_vnet_hdr) {
|
||||
/* FIXME this cast is evil */
|
||||
void *wbuf = (void *)buf;
|
||||
work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
|
||||
size - n->host_hdr_len);
|
||||
|
||||
memcpy(hdr, buf, sizeof(struct virtio_net_hdr));
|
||||
|
||||
*buf_offset = n->host_hdr_len;
|
||||
work_around_broken_dhclient(hdr, &hdr_len, buf, buf_size, buf_offset);
|
||||
|
||||
if (n->needs_vnet_hdr_swap) {
|
||||
virtio_net_hdr_swap(VIRTIO_DEVICE(n), hdr);
|
||||
if (n->needs_vnet_hdr_swap) {
|
||||
virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf);
|
||||
}
|
||||
iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
|
||||
} else {
|
||||
struct virtio_net_hdr hdr = {
|
||||
.flags = 0,
|
||||
.gso_type = VIRTIO_NET_HDR_GSO_NONE
|
||||
};
|
||||
iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr);
|
||||
}
|
||||
|
||||
return hdr_len;
|
||||
}
|
||||
|
||||
static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
|
||||
@@ -1907,13 +1904,6 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
|
||||
return (index == new_index) ? -1 : new_index;
|
||||
}
|
||||
|
||||
typedef struct Header {
|
||||
struct virtio_net_hdr_v1_hash virtio_net;
|
||||
struct eth_header eth;
|
||||
struct ip_header ip;
|
||||
struct udp_header udp;
|
||||
} Header;
|
||||
|
||||
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
size_t size)
|
||||
{
|
||||
@@ -1923,15 +1913,15 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
|
||||
size_t lens[VIRTQUEUE_MAX_SIZE];
|
||||
struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
|
||||
Header hdr;
|
||||
struct virtio_net_hdr_v1_hash extra_hdr;
|
||||
unsigned mhdr_cnt = 0;
|
||||
size_t offset, i, guest_offset, j;
|
||||
ssize_t err;
|
||||
|
||||
memset(&hdr.virtio_net, 0, sizeof(hdr.virtio_net));
|
||||
memset(&extra_hdr, 0, sizeof(extra_hdr));
|
||||
|
||||
if (n->rss_data.enabled && n->rss_data.enabled_software_rss) {
|
||||
int index = virtio_net_process_rss(nc, buf, size, &hdr.virtio_net);
|
||||
int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
|
||||
if (index >= 0) {
|
||||
nc = qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
|
||||
}
|
||||
@@ -1996,18 +1986,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
if (n->mergeable_rx_bufs) {
|
||||
mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg),
|
||||
sg, elem->in_num,
|
||||
offsetof(typeof(hdr),
|
||||
virtio_net.hdr.num_buffers),
|
||||
sizeof(hdr.virtio_net.hdr.num_buffers));
|
||||
offsetof(typeof(extra_hdr), hdr.num_buffers),
|
||||
sizeof(extra_hdr.hdr.num_buffers));
|
||||
} else {
|
||||
extra_hdr.hdr.num_buffers = cpu_to_le16(1);
|
||||
}
|
||||
|
||||
guest_offset = n->has_vnet_hdr ?
|
||||
receive_header(n, (struct virtio_net_hdr *)&hdr,
|
||||
buf, size, &offset) :
|
||||
n->guest_hdr_len;
|
||||
|
||||
iov_from_buf(sg, elem->in_num, 0, &hdr, guest_offset);
|
||||
total += guest_offset;
|
||||
receive_header(n, sg, elem->in_num, buf, size);
|
||||
if (n->rss_data.populate_hash) {
|
||||
offset = offsetof(typeof(extra_hdr), hash_value);
|
||||
iov_from_buf(sg, elem->in_num, offset,
|
||||
(char *)&extra_hdr + offset,
|
||||
sizeof(extra_hdr.hash_value) +
|
||||
sizeof(extra_hdr.hash_report));
|
||||
}
|
||||
offset = n->host_hdr_len;
|
||||
total += n->guest_hdr_len;
|
||||
guest_offset = n->guest_hdr_len;
|
||||
} else {
|
||||
guest_offset = 0;
|
||||
}
|
||||
@@ -2033,11 +2028,11 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
}
|
||||
|
||||
if (mhdr_cnt) {
|
||||
virtio_stw_p(vdev, &hdr.virtio_net.hdr.num_buffers, i);
|
||||
virtio_stw_p(vdev, &extra_hdr.hdr.num_buffers, i);
|
||||
iov_from_buf(mhdr_sg, mhdr_cnt,
|
||||
0,
|
||||
&hdr.virtio_net.hdr.num_buffers,
|
||||
sizeof hdr.virtio_net.hdr.num_buffers);
|
||||
&extra_hdr.hdr.num_buffers,
|
||||
sizeof extra_hdr.hdr.num_buffers);
|
||||
}
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
|
||||
@@ -362,7 +362,7 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
|
||||
|
||||
case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
|
||||
viewport->target &= 0x00000000FFFFFFFFULL;
|
||||
viewport->target |= val;
|
||||
viewport->target |= (uint64_t)val << 32;
|
||||
break;
|
||||
|
||||
case DESIGNWARE_PCIE_ATU_LIMIT:
|
||||
|
||||
+48
-34
@@ -320,38 +320,6 @@ static void gt64120_isd_mapping(GT64120State *s)
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
static void gt64120_update_pci_cfgdata_mapping(GT64120State *s)
|
||||
{
|
||||
/* Indexed on MByteSwap bit, see Table 158: PCI_0 Command, Offset: 0xc00 */
|
||||
static const MemoryRegionOps *pci_host_data_ops[] = {
|
||||
&pci_host_data_be_ops, &pci_host_data_le_ops
|
||||
};
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
|
||||
memory_region_transaction_begin();
|
||||
|
||||
/*
|
||||
* The setting of the MByteSwap bit and MWordSwap bit in the PCI Internal
|
||||
* Command Register determines how data transactions from the CPU to/from
|
||||
* PCI are handled along with the setting of the Endianness bit in the CPU
|
||||
* Configuration Register. See:
|
||||
* - Table 16: 32-bit PCI Transaction Endianness
|
||||
* - Table 158: PCI_0 Command, Offset: 0xc00
|
||||
*/
|
||||
|
||||
if (memory_region_is_mapped(&phb->data_mem)) {
|
||||
memory_region_del_subregion(&s->ISD_mem, &phb->data_mem);
|
||||
object_unparent(OBJECT(&phb->data_mem));
|
||||
}
|
||||
memory_region_init_io(&phb->data_mem, OBJECT(phb),
|
||||
pci_host_data_ops[s->regs[GT_PCI0_CMD] & 1],
|
||||
s, "pci-conf-data", 4);
|
||||
memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGDATA << 2,
|
||||
&phb->data_mem, 1);
|
||||
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
static void gt64120_pci_mapping(GT64120State *s)
|
||||
{
|
||||
memory_region_transaction_begin();
|
||||
@@ -645,7 +613,6 @@ static void gt64120_writel(void *opaque, hwaddr addr,
|
||||
case GT_PCI0_CMD:
|
||||
case GT_PCI1_CMD:
|
||||
s->regs[saddr] = val & 0x0401fc0f;
|
||||
gt64120_update_pci_cfgdata_mapping(s);
|
||||
break;
|
||||
case GT_PCI0_TOR:
|
||||
case GT_PCI0_BS_SCS10:
|
||||
@@ -1024,6 +991,48 @@ static const MemoryRegionOps isd_mem_ops = {
|
||||
},
|
||||
};
|
||||
|
||||
static bool bswap(const GT64120State *s)
|
||||
{
|
||||
PCIHostState *phb = PCI_HOST_BRIDGE(s);
|
||||
/*check for bus == 0 && device == 0, Bits 11:15 = Device , Bits 16:23 = Bus*/
|
||||
bool is_phb_dev0 = extract32(phb->config_reg, 11, 13) == 0;
|
||||
bool le_mode = FIELD_EX32(s->regs[GT_PCI0_CMD], GT_PCI0_CMD, MByteSwap);
|
||||
/* Only swap for non-bridge devices in big-endian mode */
|
||||
return !le_mode && !is_phb_dev0;
|
||||
}
|
||||
|
||||
static uint64_t gt64120_pci_data_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
GT64120State *s = opaque;
|
||||
uint32_t val = pci_host_data_le_ops.read(opaque, addr, size);
|
||||
|
||||
if (bswap(s)) {
|
||||
val = bswap32(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void gt64120_pci_data_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
GT64120State *s = opaque;
|
||||
|
||||
if (bswap(s)) {
|
||||
val = bswap32(val);
|
||||
}
|
||||
pci_host_data_le_ops.write(opaque, addr, val, size);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gt64120_pci_data_ops = {
|
||||
.read = gt64120_pci_data_read,
|
||||
.write = gt64120_pci_data_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
};
|
||||
|
||||
static void gt64120_reset(DeviceState *dev)
|
||||
{
|
||||
GT64120State *s = GT64120_PCI_HOST_BRIDGE(dev);
|
||||
@@ -1178,7 +1187,6 @@ static void gt64120_reset(DeviceState *dev)
|
||||
|
||||
gt64120_isd_mapping(s);
|
||||
gt64120_pci_mapping(s);
|
||||
gt64120_update_pci_cfgdata_mapping(s);
|
||||
}
|
||||
|
||||
static void gt64120_realize(DeviceState *dev, Error **errp)
|
||||
@@ -1202,6 +1210,12 @@ static void gt64120_realize(DeviceState *dev, Error **errp)
|
||||
memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGADDR << 2,
|
||||
&phb->conf_mem, 1);
|
||||
|
||||
memory_region_init_io(&phb->data_mem, OBJECT(phb),
|
||||
>64120_pci_data_ops,
|
||||
s, "pci-conf-data", 4);
|
||||
memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGDATA << 2,
|
||||
&phb->data_mem, 1);
|
||||
|
||||
|
||||
/*
|
||||
* The whole address space decoded by the GT-64120A doesn't generate
|
||||
|
||||
@@ -217,12 +217,6 @@ const MemoryRegionOps pci_host_data_le_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
const MemoryRegionOps pci_host_data_be_ops = {
|
||||
.read = pci_host_data_read,
|
||||
.write = pci_host_data_write,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
static bool pci_host_needed(void *opaque)
|
||||
{
|
||||
PCIHostState *s = opaque;
|
||||
|
||||
@@ -239,15 +239,8 @@ static const VMStateDescription goldfish_rtc_vmstate = {
|
||||
static void goldfish_rtc_reset(DeviceState *dev)
|
||||
{
|
||||
GoldfishRTCState *s = GOLDFISH_RTC(dev);
|
||||
struct tm tm;
|
||||
|
||||
timer_del(s->timer);
|
||||
|
||||
qemu_get_timedate(&tm, 0);
|
||||
s->tick_offset = mktimegm(&tm);
|
||||
s->tick_offset *= NANOSECONDS_PER_SECOND;
|
||||
s->tick_offset -= qemu_clock_get_ns(rtc_clock);
|
||||
s->tick_offset_vmstate = 0;
|
||||
s->alarm_next = 0;
|
||||
s->alarm_running = 0;
|
||||
s->irq_pending = 0;
|
||||
@@ -258,6 +251,7 @@ static void goldfish_rtc_realize(DeviceState *d, Error **errp)
|
||||
{
|
||||
SysBusDevice *dev = SYS_BUS_DEVICE(d);
|
||||
GoldfishRTCState *s = GOLDFISH_RTC(d);
|
||||
struct tm tm;
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s),
|
||||
&goldfish_rtc_ops[s->big_endian], s,
|
||||
@@ -267,6 +261,11 @@ static void goldfish_rtc_realize(DeviceState *d, Error **errp)
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
|
||||
s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
|
||||
|
||||
qemu_get_timedate(&tm, 0);
|
||||
s->tick_offset = mktimegm(&tm);
|
||||
s->tick_offset *= NANOSECONDS_PER_SECOND;
|
||||
s->tick_offset -= qemu_clock_get_ns(rtc_clock);
|
||||
}
|
||||
|
||||
static Property goldfish_rtc_properties[] = {
|
||||
|
||||
@@ -739,6 +739,7 @@ static void machine_set_loadparm(Object *obj, Visitor *v,
|
||||
}
|
||||
|
||||
s390_ipl_fmt_loadparm(ms->loadparm, val, errp);
|
||||
g_free(val);
|
||||
}
|
||||
|
||||
static void ccw_machine_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
+25
-14
@@ -68,10 +68,9 @@ struct SCSIDiskClass {
|
||||
SCSIDeviceClass parent_class;
|
||||
/*
|
||||
* Callbacks receive ret == 0 for success. Errors are represented either as
|
||||
* negative errno values, or as positive SAM status codes.
|
||||
*
|
||||
* Beware: For errors returned in host_status, the function may directly
|
||||
* complete the request and never call the callback.
|
||||
* negative errno values, or as positive SAM status codes. For host_status
|
||||
* errors, the function passes ret == -ENODEV and sets the host_status field
|
||||
* of the SCSIRequest.
|
||||
*/
|
||||
DMAIOFunc *dma_readv;
|
||||
DMAIOFunc *dma_writev;
|
||||
@@ -226,11 +225,26 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
|
||||
SCSISense sense = SENSE_CODE(NO_SENSE);
|
||||
int16_t host_status;
|
||||
int error;
|
||||
bool req_has_sense = false;
|
||||
BlockErrorAction action;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* host_status should only be set for SG_IO requests that came back with a
|
||||
* host_status error in scsi_block_sgio_complete(). This error path passes
|
||||
* -ENODEV as the return value.
|
||||
*
|
||||
* Reset host_status in the request because we may still want to complete
|
||||
* the request successfully with the 'stop' or 'ignore' error policy.
|
||||
*/
|
||||
host_status = r->req.host_status;
|
||||
if (host_status != -1) {
|
||||
assert(ret == -ENODEV);
|
||||
r->req.host_status = -1;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
status = scsi_sense_from_errno(-ret, &sense);
|
||||
error = -ret;
|
||||
@@ -290,6 +304,10 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
|
||||
if (acct_failed) {
|
||||
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
||||
}
|
||||
if (host_status != -1) {
|
||||
scsi_req_complete_failed(&r->req, host_status);
|
||||
return true;
|
||||
}
|
||||
if (req_has_sense) {
|
||||
sdc->update_sense(&r->req);
|
||||
} else if (status == CHECK_CONDITION) {
|
||||
@@ -411,7 +429,6 @@ done:
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
/* May not be called in all error cases, don't rely on cleanup here */
|
||||
static void scsi_dma_complete(void *opaque, int ret)
|
||||
{
|
||||
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
|
||||
@@ -452,7 +469,6 @@ done:
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
/* May not be called in all error cases, don't rely on cleanup here */
|
||||
static void scsi_read_complete(void *opaque, int ret)
|
||||
{
|
||||
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
|
||||
@@ -592,7 +608,6 @@ done:
|
||||
scsi_req_unref(&r->req);
|
||||
}
|
||||
|
||||
/* May not be called in all error cases, don't rely on cleanup here */
|
||||
static void scsi_write_complete(void * opaque, int ret)
|
||||
{
|
||||
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
|
||||
@@ -2854,14 +2869,10 @@ static void scsi_block_sgio_complete(void *opaque, int ret)
|
||||
sg_io_hdr_t *io_hdr = &req->io_header;
|
||||
|
||||
if (ret == 0) {
|
||||
/* FIXME This skips calling req->cb() and any cleanup in it */
|
||||
if (io_hdr->host_status != SCSI_HOST_OK) {
|
||||
scsi_req_complete_failed(&r->req, io_hdr->host_status);
|
||||
scsi_req_unref(&r->req);
|
||||
return;
|
||||
}
|
||||
|
||||
if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
|
||||
r->req.host_status = io_hdr->host_status;
|
||||
ret = -ENODEV;
|
||||
} else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
|
||||
ret = BUSY;
|
||||
} else {
|
||||
ret = io_hdr->status;
|
||||
|
||||
@@ -1285,6 +1285,9 @@ static int save_opt_one(void *opaque,
|
||||
g_byte_array_append(data, (guint8 *)buf, ret);
|
||||
}
|
||||
|
||||
buf[0] = '\0';
|
||||
g_byte_array_append(data, (guint8 *)buf, 1);
|
||||
|
||||
qemu_close(fd);
|
||||
|
||||
*opt->dest = g_renew(char *, *opt->dest, (*opt->ndest) + 1);
|
||||
|
||||
+3
-1
@@ -2316,6 +2316,8 @@ void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
|
||||
}
|
||||
}
|
||||
|
||||
static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val);
|
||||
|
||||
void virtio_reset(void *opaque)
|
||||
{
|
||||
VirtIODevice *vdev = opaque;
|
||||
@@ -2346,7 +2348,7 @@ void virtio_reset(void *opaque)
|
||||
vdev->start_on_kick = false;
|
||||
vdev->started = false;
|
||||
vdev->broken = false;
|
||||
vdev->guest_features = 0;
|
||||
virtio_set_features_nocheck(vdev, 0);
|
||||
vdev->queue_sel = 0;
|
||||
vdev->status = 0;
|
||||
vdev->disabled = false;
|
||||
|
||||
@@ -134,7 +134,8 @@ struct SysemuCPUOps;
|
||||
* @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
|
||||
* before the insn which triggers a watchpoint rather than after it.
|
||||
* @gdb_arch_name: Optional callback that returns the architecture name known
|
||||
* to GDB. The caller must free the returned string with g_free.
|
||||
* to GDB. The returned value is expected to be a simple constant string:
|
||||
* the caller will not g_free() it.
|
||||
* @disas_set_info: Setup architecture specific components of disassembly info
|
||||
* @adjust_watchpoint_address: Perform a target-specific adjustment to an
|
||||
* address before attempting to match it against watchpoints.
|
||||
|
||||
@@ -109,10 +109,6 @@ static const uint32_t reg800_keep_bits[DINO800_REGS] = {
|
||||
struct DinoState {
|
||||
PCIHostState parent_obj;
|
||||
|
||||
/*
|
||||
* PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops,
|
||||
* so that we can map PCI_CONFIG_DATA to pci_host_data_be_ops.
|
||||
*/
|
||||
uint32_t config_reg_dino; /* keep original copy, including 2 lowest bits */
|
||||
|
||||
uint32_t iar0;
|
||||
|
||||
@@ -68,6 +68,5 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, unsigned len);
|
||||
extern const MemoryRegionOps pci_host_conf_le_ops;
|
||||
extern const MemoryRegionOps pci_host_conf_be_ops;
|
||||
extern const MemoryRegionOps pci_host_data_le_ops;
|
||||
extern const MemoryRegionOps pci_host_data_be_ops;
|
||||
|
||||
#endif /* PCI_HOST_H */
|
||||
|
||||
@@ -112,7 +112,7 @@ static abi_ulong hppa_lws(CPUHPPAState *env)
|
||||
void cpu_loop(CPUHPPAState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
abi_ulong ret;
|
||||
abi_ulong ret, si_code = 0;
|
||||
int trapnr;
|
||||
|
||||
while (1) {
|
||||
@@ -169,7 +169,15 @@ void cpu_loop(CPUHPPAState *env)
|
||||
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f);
|
||||
break;
|
||||
case EXCP_ASSIST:
|
||||
force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
|
||||
#define set_si_code(mask, val) \
|
||||
if (env->fr[0] & mask) { si_code = val; }
|
||||
set_si_code(R_FPSR_FLG_I_MASK, TARGET_FPE_FLTRES);
|
||||
set_si_code(R_FPSR_FLG_U_MASK, TARGET_FPE_FLTUND);
|
||||
set_si_code(R_FPSR_FLG_O_MASK, TARGET_FPE_FLTOVF);
|
||||
set_si_code(R_FPSR_FLG_Z_MASK, TARGET_FPE_FLTDIV);
|
||||
set_si_code(R_FPSR_FLG_V_MASK, TARGET_FPE_FLTINV);
|
||||
#undef set_si_code
|
||||
force_sig_fault(TARGET_SIGFPE, si_code, env->iaoq_f);
|
||||
break;
|
||||
case EXCP_BREAK:
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
|
||||
|
||||
+2
-11
@@ -2159,14 +2159,6 @@ gnu_source_prefix = '''
|
||||
#endif
|
||||
'''
|
||||
|
||||
# Check whether the glibc provides STATX_BASIC_STATS
|
||||
|
||||
has_statx = cc.has_header_symbol('sys/stat.h', 'STATX_BASIC_STATS', prefix: gnu_source_prefix)
|
||||
|
||||
# Check whether statx() provides mount ID information
|
||||
|
||||
has_statx_mnt_id = cc.has_header_symbol('sys/stat.h', 'STATX_MNT_ID', prefix: gnu_source_prefix)
|
||||
|
||||
have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
|
||||
.require(host_os == 'linux',
|
||||
error_message: 'vhost_user_blk_server requires linux') \
|
||||
@@ -2528,8 +2520,6 @@ config_host_data.set('CONFIG_CRYPTO_SM3', crypto_sm3.found())
|
||||
config_host_data.set('CONFIG_HOGWEED', hogweed.found())
|
||||
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
|
||||
config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
|
||||
config_host_data.set('CONFIG_STATX', has_statx)
|
||||
config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
|
||||
config_host_data.set('CONFIG_ZSTD', zstd.found())
|
||||
config_host_data.set('CONFIG_QPL', qpl.found())
|
||||
config_host_data.set('CONFIG_UADK', uadk.found())
|
||||
@@ -2603,7 +2593,6 @@ config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
|
||||
config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
|
||||
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
|
||||
config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
|
||||
config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
|
||||
config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
|
||||
# Note that we need to specify prefix: here to avoid incorrectly
|
||||
# thinking that Windows has posix_memalign()
|
||||
@@ -2680,6 +2669,8 @@ config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
|
||||
config_host_data.set('CONFIG_FIEMAP',
|
||||
cc.has_header('linux/fiemap.h') and
|
||||
cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
|
||||
config_host_data.set('CONFIG_GETCPU',
|
||||
cc.has_header_symbol('sched.h', 'getcpu', prefix: gnu_source_prefix))
|
||||
config_host_data.set('CONFIG_GETRANDOM',
|
||||
cc.has_function('getrandom') and
|
||||
cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
|
||||
|
||||
@@ -123,7 +123,7 @@ qio_channel_block_seek(QIOChannel *ioc,
|
||||
bioc->offset = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
bioc->offset += whence;
|
||||
bioc->offset += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
error_setg(errp, "Size of VMstate region is unknown");
|
||||
|
||||
+2
-2
@@ -543,7 +543,7 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (migrate_incoming_started()) {
|
||||
if (!migrate_postcopy_preempt() && migrate_incoming_started()) {
|
||||
error_setg(errp,
|
||||
"Postcopy preempt must be set before incoming starts");
|
||||
return false;
|
||||
@@ -551,7 +551,7 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
|
||||
}
|
||||
|
||||
if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
|
||||
if (migrate_incoming_started()) {
|
||||
if (!migrate_multifd() && migrate_incoming_started()) {
|
||||
error_setg(errp, "Multifd must be set before incoming starts");
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -379,7 +379,7 @@ static void plugin_reset_destroy(struct qemu_plugin_reset_data *data)
|
||||
{
|
||||
qemu_rec_mutex_lock(&plugin.lock);
|
||||
plugin_reset_destroy__locked(data);
|
||||
qemu_rec_mutex_lock(&plugin.lock);
|
||||
qemu_rec_mutex_unlock(&plugin.lock);
|
||||
}
|
||||
|
||||
static void plugin_flush_destroy(CPUState *cpu, run_on_cpu_data arg)
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
##
|
||||
# @query-sgx:
|
||||
#
|
||||
# Returns information about SGX
|
||||
# Returns information about configured SGX capabilities of guest
|
||||
#
|
||||
# Returns: @SGXInfo
|
||||
#
|
||||
@@ -399,7 +399,7 @@
|
||||
##
|
||||
# @query-sgx-capabilities:
|
||||
#
|
||||
# Returns information from host SGX capabilities
|
||||
# Returns information about SGX capabilities of host
|
||||
#
|
||||
# Returns: @SGXInfo
|
||||
#
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ def find_deps(exe_or_dll, search_path, analyzed_deps):
|
||||
output = subprocess.check_output(["objdump", "-p", exe_or_dll], text=True)
|
||||
output = output.split("\n")
|
||||
for line in output:
|
||||
if not line.startswith("\tDLL Name: "):
|
||||
if not line.lstrip().startswith("DLL Name: "):
|
||||
continue
|
||||
|
||||
dep = line.split("DLL Name: ")[1].strip()
|
||||
|
||||
@@ -7770,7 +7770,8 @@ static bool arm_check_ss_active(DisasContext *dc)
|
||||
|
||||
static void arm_post_translate_insn(DisasContext *dc)
|
||||
{
|
||||
if (dc->condjmp && dc->base.is_jmp == DISAS_NEXT) {
|
||||
if (dc->condjmp &&
|
||||
(dc->base.is_jmp == DISAS_NEXT || dc->base.is_jmp == DISAS_TOO_MANY)) {
|
||||
if (dc->pc_save != dc->condlabel.pc_save) {
|
||||
gen_update_pc(dc, dc->condlabel.pc_save - dc->pc_save);
|
||||
}
|
||||
|
||||
+14
-7
@@ -68,28 +68,35 @@ static bool decode_insn(DisasContext *ctx, uint16_t insn);
|
||||
|
||||
int avr_print_insn(bfd_vma addr, disassemble_info *info)
|
||||
{
|
||||
DisasContext ctx;
|
||||
DisasContext ctx = { info };
|
||||
DisasContext *pctx = &ctx;
|
||||
bfd_byte buffer[4];
|
||||
uint16_t insn;
|
||||
int status;
|
||||
|
||||
ctx.info = info;
|
||||
|
||||
status = info->read_memory_func(addr, buffer, 4, info);
|
||||
status = info->read_memory_func(addr, buffer, 2, info);
|
||||
if (status != 0) {
|
||||
info->memory_error_func(status, addr, info);
|
||||
return -1;
|
||||
}
|
||||
insn = bfd_getl16(buffer);
|
||||
ctx.next_word = bfd_getl16(buffer + 2);
|
||||
ctx.next_word_used = false;
|
||||
|
||||
status = info->read_memory_func(addr + 2, buffer + 2, 2, info);
|
||||
if (status == 0) {
|
||||
ctx.next_word = bfd_getl16(buffer + 2);
|
||||
}
|
||||
|
||||
if (!decode_insn(&ctx, insn)) {
|
||||
output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
|
||||
}
|
||||
|
||||
return ctx.next_word_used ? 4 : 2;
|
||||
if (!ctx.next_word_used) {
|
||||
return 2;
|
||||
} else if (status == 0) {
|
||||
return 4;
|
||||
}
|
||||
info->memory_error_func(status, addr + 2, info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -118,11 +118,8 @@ BRBC 1111 01 ....... ... @op_bit_imm
|
||||
@io_rd_imm .... . .. ..... .... &rd_imm rd=%rd imm=%io_imm
|
||||
@ldst_d .. . . .. . rd:5 . ... &rd_imm imm=%ldst_d_imm
|
||||
|
||||
# The 16-bit immediate is completely in the next word.
|
||||
# Fields cannot be defined with no bits, so we cannot play
|
||||
# the same trick and append to a zero-bit value.
|
||||
# Defer reading the immediate until trans_{LDS,STS}.
|
||||
@ldst_s .... ... rd:5 .... imm=0
|
||||
%ldst_imm !function=next_word
|
||||
@ldst_s .... ... rd:5 .... imm=%ldst_imm
|
||||
|
||||
MOV 0010 11 . ..... .... @op_rd_rr
|
||||
MOVW 0000 0001 .... .... &rd_rr rd=%rd_d rr=%rr_d
|
||||
|
||||
@@ -1577,7 +1577,6 @@ static bool trans_LDS(DisasContext *ctx, arg_LDS *a)
|
||||
TCGv Rd = cpu_r[a->rd];
|
||||
TCGv addr = tcg_temp_new_i32();
|
||||
TCGv H = cpu_rampD;
|
||||
a->imm = next_word(ctx);
|
||||
|
||||
tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
|
||||
tcg_gen_shli_tl(addr, addr, 16);
|
||||
@@ -1782,7 +1781,6 @@ static bool trans_STS(DisasContext *ctx, arg_STS *a)
|
||||
TCGv Rd = cpu_r[a->rd];
|
||||
TCGv addr = tcg_temp_new_i32();
|
||||
TCGv H = cpu_rampD;
|
||||
a->imm = next_word(ctx);
|
||||
|
||||
tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
|
||||
tcg_gen_shli_tl(addr, addr, 16);
|
||||
|
||||
@@ -71,7 +71,8 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
|
||||
{
|
||||
uint32_t soft_exp = get_float_exception_flags(&env->fp_status);
|
||||
uint32_t hard_exp = 0;
|
||||
uint32_t shadow = env->fr0_shadow;
|
||||
uint32_t shadow = env->fr0_shadow & 0x3ffffff;
|
||||
uint32_t fr1 = 0;
|
||||
|
||||
if (likely(soft_exp == 0)) {
|
||||
env->fr[0] = (uint64_t)shadow << 32;
|
||||
@@ -84,9 +85,22 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, R_FPSR_ENA_O_MASK);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, R_FPSR_ENA_Z_MASK);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, R_FPSR_ENA_V_MASK);
|
||||
shadow |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
|
||||
if (hard_exp & shadow) {
|
||||
shadow = FIELD_DP32(shadow, FPSR, T, 1);
|
||||
/* fill exception register #1, which is lower 32-bits of fr[0] */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (hard_exp & (R_FPSR_ENA_O_MASK | R_FPSR_ENA_U_MASK)) {
|
||||
/* over- and underflow both set overflow flag only */
|
||||
fr1 = FIELD_DP32(fr1, FPSR, C, 1);
|
||||
fr1 = FIELD_DP32(fr1, FPSR, FLG_O, 1);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
fr1 |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
|
||||
}
|
||||
}
|
||||
env->fr0_shadow = shadow;
|
||||
env->fr[0] = (uint64_t)shadow << 32;
|
||||
env->fr[0] = (uint64_t)shadow << 32 | fr1;
|
||||
|
||||
if (hard_exp & shadow) {
|
||||
hppa_dynamic_excp(env, EXCP_ASSIST, ra);
|
||||
|
||||
@@ -175,6 +175,10 @@ void hppa_cpu_do_interrupt(CPUState *cs)
|
||||
}
|
||||
}
|
||||
env->cr[CR_IIR] = ldl_phys(cs->as, paddr);
|
||||
if (i == EXCP_ASSIST) {
|
||||
/* stuff insn code into bits of FP exception register #1 */
|
||||
env->fr[0] |= (env->cr[CR_IIR] & 0x03ffffff);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -293,6 +293,7 @@ void set_SF(CPUX86State *env, bool val)
|
||||
|
||||
void lflags_to_rflags(CPUX86State *env)
|
||||
{
|
||||
env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O);
|
||||
env->eflags |= get_CF(env) ? CC_C : 0;
|
||||
env->eflags |= get_PF(env) ? CC_P : 0;
|
||||
env->eflags |= get_AF(env) ? CC_A : 0;
|
||||
|
||||
@@ -355,7 +355,7 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv
|
||||
break;
|
||||
case X86_OP_SEG:
|
||||
/* Note that gen_movl_seg takes care of interrupt shadow and TF. */
|
||||
gen_movl_seg(s, op->n, s->T0);
|
||||
gen_movl_seg(s, op->n, v, op->n == R_SS);
|
||||
break;
|
||||
case X86_OP_INT:
|
||||
if (op->has_ea) {
|
||||
@@ -2360,7 +2360,7 @@ static void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg)
|
||||
gen_op_ld_v(s, MO_16, s->T1, s->A0);
|
||||
|
||||
/* load the segment here to handle exceptions properly */
|
||||
gen_movl_seg(s, seg, s->T1);
|
||||
gen_movl_seg(s, seg, s->T1, false);
|
||||
}
|
||||
|
||||
static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)
|
||||
|
||||
+25
-14
@@ -1876,25 +1876,36 @@ static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg)
|
||||
|
||||
/* move SRC to seg_reg and compute if the CPU state may change. Never
|
||||
call this function with seg_reg == R_CS */
|
||||
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src)
|
||||
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit_irq)
|
||||
{
|
||||
if (PE(s) && !VM86(s)) {
|
||||
tcg_gen_trunc_tl_i32(s->tmp2_i32, src);
|
||||
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), s->tmp2_i32);
|
||||
/* abort translation because the addseg value may change or
|
||||
because ss32 may change. For R_SS, translation must always
|
||||
stop as a special handling must be done to disable hardware
|
||||
interrupts for the next instruction */
|
||||
if (seg_reg == R_SS) {
|
||||
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
|
||||
} else if (CODE32(s) && seg_reg < R_FS) {
|
||||
TCGv_i32 sel = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_trunc_tl_i32(sel, src);
|
||||
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel);
|
||||
|
||||
/* For move to DS/ES/SS, the addseg or ss32 flags may change. */
|
||||
if (CODE32(s) && seg_reg < R_FS) {
|
||||
s->base.is_jmp = DISAS_EOB_NEXT;
|
||||
}
|
||||
} else {
|
||||
gen_op_movl_seg_real(s, seg_reg, src);
|
||||
if (seg_reg == R_SS) {
|
||||
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For MOV or POP to SS (but not LSS) translation must always
|
||||
* stop as a special handling must be done to disable hardware
|
||||
* interrupts for the next instruction.
|
||||
*
|
||||
* This is the last instruction, so it's okay to overwrite
|
||||
* HF_TF_MASK; the next TB will start with the flag set.
|
||||
*
|
||||
* DISAS_EOB_INHIBIT_IRQ is a superset of DISAS_EOB_NEXT which
|
||||
* might have been set above.
|
||||
*/
|
||||
if (inhibit_irq) {
|
||||
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
|
||||
s->flags &= ~HF_TF_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2182,7 +2193,7 @@ gen_eob(DisasContext *s, int mode)
|
||||
if (mode == DISAS_EOB_RECHECK_TF) {
|
||||
gen_helper_rechecking_single_step(tcg_env);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
} else if ((s->flags & HF_TF_MASK) && mode != DISAS_EOB_INHIBIT_IRQ) {
|
||||
} else if (s->flags & HF_TF_MASK) {
|
||||
gen_helper_single_step(tcg_env);
|
||||
} else if (mode == DISAS_JUMP &&
|
||||
/* give irqs a chance to happen */
|
||||
|
||||
@@ -23,12 +23,7 @@
|
||||
# define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#define TARGET_PAGE_BITS 12
|
||||
#else
|
||||
#define TARGET_PAGE_BITS_VARY
|
||||
#define TARGET_PAGE_BITS_MIN 12
|
||||
#endif
|
||||
|
||||
#define TCG_GUEST_DEFAULT_MO (0)
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ static void gen_mips16_restore(DisasContext *ctx,
|
||||
int astatic;
|
||||
TCGv t0 = tcg_temp_new();
|
||||
|
||||
gen_op_addr_addi(ctx, t0, cpu_gpr[29], -framesize);
|
||||
gen_op_addr_addi(ctx, t0, cpu_gpr[29], framesize);
|
||||
|
||||
if (do_ra) {
|
||||
decr_and_load(ctx, 31, t0);
|
||||
@@ -386,7 +386,7 @@ static void gen_mips16_restore(DisasContext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], -framesize);
|
||||
gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], framesize);
|
||||
}
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
|
||||
@@ -864,36 +864,24 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
|
||||
}
|
||||
}
|
||||
|
||||
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
|
||||
uint32_t compute_pagemask(uint32_t val)
|
||||
{
|
||||
uint32_t mask;
|
||||
int maskbits;
|
||||
|
||||
/* Don't care MASKX as we don't support 1KB page */
|
||||
mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
|
||||
maskbits = cto32(mask);
|
||||
uint32_t mask = extract32(val, CP0PM_MASK, 16);
|
||||
int maskbits = cto32(mask);
|
||||
|
||||
/* Ensure no more set bit after first zero */
|
||||
if ((mask >> maskbits) != 0) {
|
||||
goto invalid;
|
||||
/* Ensure no more set bit after first zero, and maskbits even. */
|
||||
if ((mask >> maskbits) == 0 && maskbits % 2 == 0) {
|
||||
return mask << CP0PM_MASK;
|
||||
} else {
|
||||
/* When invalid, set to default target page size. */
|
||||
return 0;
|
||||
}
|
||||
/* We don't support VTLB entry smaller than target page */
|
||||
if ((maskbits + TARGET_PAGE_BITS_MIN) < TARGET_PAGE_BITS) {
|
||||
goto invalid;
|
||||
}
|
||||
env->CP0_PageMask = mask << CP0PM_MASK;
|
||||
|
||||
return;
|
||||
|
||||
invalid:
|
||||
/* When invalid, set to default target page size. */
|
||||
mask = (~TARGET_PAGE_MASK >> TARGET_PAGE_BITS_MIN);
|
||||
env->CP0_PageMask = mask << CP0PM_MASK;
|
||||
}
|
||||
|
||||
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
update_pagemask(env, arg1, &env->CP0_PageMask);
|
||||
env->CP0_PageMask = compute_pagemask(arg1);
|
||||
}
|
||||
|
||||
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
|
||||
|
||||
@@ -874,8 +874,8 @@ refill:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pw_pagemask = m >> TARGET_PAGE_BITS_MIN;
|
||||
update_pagemask(env, pw_pagemask << CP0PM_MASK, &pw_pagemask);
|
||||
pw_pagemask = m >> TARGET_PAGE_BITS;
|
||||
pw_pagemask = compute_pagemask(pw_pagemask << CP0PM_MASK);
|
||||
pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF);
|
||||
{
|
||||
target_ulong tmp_entryhi = env->CP0_EntryHi;
|
||||
|
||||
@@ -45,7 +45,7 @@ bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
|
||||
void mmu_init(CPUMIPSState *env, const mips_def_t *def);
|
||||
|
||||
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
|
||||
uint32_t compute_pagemask(uint32_t val);
|
||||
|
||||
void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
|
||||
uint32_t cpu_mips_get_random(CPUMIPSState *env);
|
||||
|
||||
+13
-12
@@ -5765,6 +5765,18 @@ static void register_power9_book4_sprs(CPUPPCState *env)
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
KVM_REG_PPC_WORT, 0);
|
||||
|
||||
/* SPRC/SPRD exist in earlier CPUs but only tested on POWER9/10 */
|
||||
spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_sprc,
|
||||
0x00000000);
|
||||
spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_sprd, &spr_write_sprd,
|
||||
0x00000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5786,17 +5798,6 @@ static void register_power8_book4_sprs(CPUPPCState *env)
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_generic,
|
||||
KVM_REG_PPC_WORT, 0);
|
||||
/* SPRC/SPRD exist in earlier CPUs but only tested on POWER9/10 */
|
||||
spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_generic, &spr_write_sprc,
|
||||
0x00000000);
|
||||
spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
SPR_NOACCESS, SPR_NOACCESS,
|
||||
&spr_read_sprd, &spr_write_sprd,
|
||||
0x00000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -7033,7 +7034,7 @@ ObjectClass *ppc_cpu_class_by_name(const char *name)
|
||||
if (strcmp(name, "max") == 0) {
|
||||
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
|
||||
if (mc) {
|
||||
return object_class_by_name(mc->default_cpu_type);
|
||||
return object_class_by_name(machine_class_default_cpu_type(mc));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -321,6 +321,10 @@ target_ulong helper_load_sprd(CPUPPCState *env)
|
||||
PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
|
||||
target_ulong sprc = env->spr[SPR_POWER_SPRC];
|
||||
|
||||
if (pc->big_core) {
|
||||
pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
|
||||
}
|
||||
|
||||
switch (sprc & 0x3e0) {
|
||||
case 0: /* SCRATCH0-3 */
|
||||
case 1: /* SCRATCH4-7 */
|
||||
@@ -357,6 +361,10 @@ void helper_store_sprd(CPUPPCState *env, target_ulong val)
|
||||
PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
|
||||
int nr;
|
||||
|
||||
if (pc->big_core) {
|
||||
pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
|
||||
}
|
||||
|
||||
switch (sprc & 0x3e0) {
|
||||
case 0: /* SCRATCH0-3 */
|
||||
case 1: /* SCRATCH4-7 */
|
||||
@@ -367,7 +375,6 @@ void helper_store_sprd(CPUPPCState *env, target_ulong val)
|
||||
* information. Could also dump these upon checkstop.
|
||||
*/
|
||||
nr = (sprc >> 3) & 0x7;
|
||||
qemu_log("SPRD write 0x" TARGET_FMT_lx " to SCRATCH%d\n", val, nr);
|
||||
pc->scratch[nr] = val;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -80,6 +80,7 @@ const char *riscv_get_misa_ext_name(uint32_t bit);
|
||||
const char *riscv_get_misa_ext_description(uint32_t bit);
|
||||
|
||||
#define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop)
|
||||
#define ENV_CSR_OFFSET(_csr) offsetof(CPURISCVState, _csr)
|
||||
|
||||
typedef struct riscv_cpu_profile {
|
||||
struct riscv_cpu_profile *parent;
|
||||
|
||||
@@ -1240,9 +1240,11 @@ restart:
|
||||
#else
|
||||
target_ulong old_pte;
|
||||
if (riscv_cpu_sxl(env) == MXL_RV32) {
|
||||
old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, updated_pte);
|
||||
old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_le32(pte), cpu_to_le32(updated_pte));
|
||||
old_pte = le32_to_cpu(old_pte);
|
||||
} else {
|
||||
old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
|
||||
old_pte = qatomic_cmpxchg(pte_pa, cpu_to_le64(pte), cpu_to_le64(updated_pte));
|
||||
old_pte = le64_to_cpu(old_pte);
|
||||
}
|
||||
if (old_pte != pte) {
|
||||
goto restart;
|
||||
|
||||
@@ -700,14 +700,14 @@ vfredmax_vs 000111 . ..... ..... 001 ..... 1010111 @r_vm
|
||||
# Vector widening ordered and unordered float reduction sum
|
||||
vfwredusum_vs 110001 . ..... ..... 001 ..... 1010111 @r_vm
|
||||
vfwredosum_vs 110011 . ..... ..... 001 ..... 1010111 @r_vm
|
||||
vmand_mm 011001 - ..... ..... 010 ..... 1010111 @r
|
||||
vmnand_mm 011101 - ..... ..... 010 ..... 1010111 @r
|
||||
vmandn_mm 011000 - ..... ..... 010 ..... 1010111 @r
|
||||
vmxor_mm 011011 - ..... ..... 010 ..... 1010111 @r
|
||||
vmor_mm 011010 - ..... ..... 010 ..... 1010111 @r
|
||||
vmnor_mm 011110 - ..... ..... 010 ..... 1010111 @r
|
||||
vmorn_mm 011100 - ..... ..... 010 ..... 1010111 @r
|
||||
vmxnor_mm 011111 - ..... ..... 010 ..... 1010111 @r
|
||||
vmand_mm 011001 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmnand_mm 011101 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmandn_mm 011000 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmxor_mm 011011 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmor_mm 011010 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmnor_mm 011110 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmorn_mm 011100 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmxnor_mm 011111 1 ..... ..... 010 ..... 1010111 @r
|
||||
vcpop_m 010000 . ..... 10000 010 ..... 1010111 @r2_vm
|
||||
vfirst_m 010000 . ..... 10001 010 ..... 1010111 @r2_vm
|
||||
vmsbf_m 010100 . ..... 00001 010 ..... 1010111 @r2_vm
|
||||
@@ -729,7 +729,7 @@ vrgather_vv 001100 . ..... ..... 000 ..... 1010111 @r_vm
|
||||
vrgatherei16_vv 001110 . ..... ..... 000 ..... 1010111 @r_vm
|
||||
vrgather_vx 001100 . ..... ..... 100 ..... 1010111 @r_vm
|
||||
vrgather_vi 001100 . ..... ..... 011 ..... 1010111 @r_vm
|
||||
vcompress_vm 010111 - ..... ..... 010 ..... 1010111 @r
|
||||
vcompress_vm 010111 1 ..... ..... 010 ..... 1010111 @r
|
||||
vmv1r_v 100111 1 ..... 00000 011 ..... 1010111 @r2rd
|
||||
vmv2r_v 100111 1 ..... 00001 011 ..... 1010111 @r2rd
|
||||
vmv4r_v 100111 1 ..... 00011 011 ..... 1010111 @r2rd
|
||||
|
||||
@@ -119,8 +119,11 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a)
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZVFBFWMA(ctx);
|
||||
|
||||
uint8_t sew = ctx->sew;
|
||||
if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) &&
|
||||
vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm)) {
|
||||
vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm) &&
|
||||
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs1, sew, a->vm) &&
|
||||
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
|
||||
uint32_t data = 0;
|
||||
|
||||
gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
|
||||
@@ -146,8 +149,10 @@ static bool trans_vfwmaccbf16_vf(DisasContext *ctx, arg_vfwmaccbf16_vf *a)
|
||||
REQUIRE_FPU;
|
||||
REQUIRE_ZVFBFWMA(ctx);
|
||||
|
||||
uint8_t sew = ctx->sew;
|
||||
if (require_rvv(ctx) && (ctx->sew == MO_16) && vext_check_isa_ill(ctx) &&
|
||||
vext_check_ds(ctx, a->rd, a->rs2, a->vm)) {
|
||||
vext_check_ds(ctx, a->rd, a->rs2, a->vm) &&
|
||||
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
|
||||
uint32_t data = 0;
|
||||
|
||||
gen_set_rm(ctx, RISCV_FRM_DYN);
|
||||
|
||||
@@ -100,10 +100,33 @@ static bool require_scale_rvfmin(DisasContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
/* Destination vector register group cannot overlap source mask register. */
|
||||
static bool require_vm(int vm, int vd)
|
||||
/*
|
||||
* Source and destination vector register groups cannot overlap source mask
|
||||
* register:
|
||||
*
|
||||
* A vector register cannot be used to provide source operands with more than
|
||||
* one EEW for a single instruction. A mask register source is considered to
|
||||
* have EEW=1 for this constraint. An encoding that would result in the same
|
||||
* vector register being read with two or more different EEWs, including when
|
||||
* the vector register appears at different positions within two or more vector
|
||||
* register groups, is reserved.
|
||||
* (Section 5.2)
|
||||
*
|
||||
* A destination vector register group can overlap a source vector
|
||||
* register group only if one of the following holds:
|
||||
* 1. The destination EEW equals the source EEW.
|
||||
* 2. The destination EEW is smaller than the source EEW and the overlap
|
||||
* is in the lowest-numbered part of the source register group.
|
||||
* 3. The destination EEW is greater than the source EEW, the source EMUL
|
||||
* is at least 1, and the overlap is in the highest-numbered part of
|
||||
* the destination register group.
|
||||
* For the purpose of determining register group overlap constraints, mask
|
||||
* elements have EEW=1.
|
||||
* (Section 5.2)
|
||||
*/
|
||||
static bool require_vm(int vm, int v)
|
||||
{
|
||||
return (vm != 0 || vd != 0);
|
||||
return (vm != 0 || v != 0);
|
||||
}
|
||||
|
||||
static bool require_nf(int vd, int nf, int lmul)
|
||||
@@ -356,11 +379,41 @@ static bool vext_check_ld_index(DisasContext *s, int vd, int vs2,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a vector register is used to provide source operands with
|
||||
* more than one EEW for the vector instruction.
|
||||
* Returns true if the instruction has valid encoding
|
||||
* Returns false if encoding violates the mismatched input EEWs constraint
|
||||
*/
|
||||
static bool vext_check_input_eew(DisasContext *s, int vs1, uint8_t eew_vs1,
|
||||
int vs2, uint8_t eew_vs2, int vm)
|
||||
{
|
||||
bool is_valid = true;
|
||||
int8_t emul_vs1 = eew_vs1 - s->sew + s->lmul;
|
||||
int8_t emul_vs2 = eew_vs2 - s->sew + s->lmul;
|
||||
|
||||
/* When vm is 0, vs1 & vs2(EEW!=1) group can't overlap v0 (EEW=1) */
|
||||
if ((vs1 != -1 && !require_vm(vm, vs1)) ||
|
||||
(vs2 != -1 && !require_vm(vm, vs2))) {
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
/* When eew_vs1 != eew_vs2, check whether vs1 and vs2 are overlapped */
|
||||
if ((vs1 != -1 && vs2 != -1) && (eew_vs1 != eew_vs2) &&
|
||||
is_overlapped(vs1, 1 << MAX(emul_vs1, 0),
|
||||
vs2, 1 << MAX(emul_vs2, 0))) {
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
static bool vext_check_ss(DisasContext *s, int vd, int vs, int vm)
|
||||
{
|
||||
return require_vm(vm, vd) &&
|
||||
require_align(vd, s->lmul) &&
|
||||
require_align(vs, s->lmul);
|
||||
require_align(vs, s->lmul) &&
|
||||
vext_check_input_eew(s, vs, s->sew, -1, s->sew, vm);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -379,6 +432,7 @@ static bool vext_check_ss(DisasContext *s, int vd, int vs, int vm)
|
||||
static bool vext_check_sss(DisasContext *s, int vd, int vs1, int vs2, int vm)
|
||||
{
|
||||
return vext_check_ss(s, vd, vs2, vm) &&
|
||||
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew, vm) &&
|
||||
require_align(vs1, s->lmul);
|
||||
}
|
||||
|
||||
@@ -474,6 +528,7 @@ static bool vext_narrow_check_common(DisasContext *s, int vd, int vs2,
|
||||
static bool vext_check_ds(DisasContext *s, int vd, int vs, int vm)
|
||||
{
|
||||
return vext_wide_check_common(s, vd, vm) &&
|
||||
vext_check_input_eew(s, vs, s->sew, -1, 0, vm) &&
|
||||
require_align(vs, s->lmul) &&
|
||||
require_noover(vd, s->lmul + 1, vs, s->lmul);
|
||||
}
|
||||
@@ -481,6 +536,7 @@ static bool vext_check_ds(DisasContext *s, int vd, int vs, int vm)
|
||||
static bool vext_check_dd(DisasContext *s, int vd, int vs, int vm)
|
||||
{
|
||||
return vext_wide_check_common(s, vd, vm) &&
|
||||
vext_check_input_eew(s, vs, s->sew + 1, -1, 0, vm) &&
|
||||
require_align(vs, s->lmul + 1);
|
||||
}
|
||||
|
||||
@@ -499,6 +555,7 @@ static bool vext_check_dd(DisasContext *s, int vd, int vs, int vm)
|
||||
static bool vext_check_dss(DisasContext *s, int vd, int vs1, int vs2, int vm)
|
||||
{
|
||||
return vext_check_ds(s, vd, vs2, vm) &&
|
||||
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew, vm) &&
|
||||
require_align(vs1, s->lmul) &&
|
||||
require_noover(vd, s->lmul + 1, vs1, s->lmul);
|
||||
}
|
||||
@@ -521,12 +578,14 @@ static bool vext_check_dss(DisasContext *s, int vd, int vs1, int vs2, int vm)
|
||||
static bool vext_check_dds(DisasContext *s, int vd, int vs1, int vs2, int vm)
|
||||
{
|
||||
return vext_check_ds(s, vd, vs1, vm) &&
|
||||
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew + 1, vm) &&
|
||||
require_align(vs2, s->lmul + 1);
|
||||
}
|
||||
|
||||
static bool vext_check_sd(DisasContext *s, int vd, int vs, int vm)
|
||||
{
|
||||
bool ret = vext_narrow_check_common(s, vd, vs, vm);
|
||||
bool ret = vext_narrow_check_common(s, vd, vs, vm) &&
|
||||
vext_check_input_eew(s, vs, s->sew + 1, -1, 0, vm);
|
||||
if (vd != vs) {
|
||||
ret &= require_noover(vd, s->lmul, vs, s->lmul + 1);
|
||||
}
|
||||
@@ -549,6 +608,7 @@ static bool vext_check_sd(DisasContext *s, int vd, int vs, int vm)
|
||||
static bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
|
||||
{
|
||||
return vext_check_sd(s, vd, vs2, vm) &&
|
||||
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew + 1, vm) &&
|
||||
require_align(vs1, s->lmul);
|
||||
}
|
||||
|
||||
@@ -584,7 +644,9 @@ static bool vext_check_slide(DisasContext *s, int vd, int vs2,
|
||||
{
|
||||
bool ret = require_align(vs2, s->lmul) &&
|
||||
require_align(vd, s->lmul) &&
|
||||
require_vm(vm, vd);
|
||||
require_vm(vm, vd) &&
|
||||
vext_check_input_eew(s, -1, 0, vs2, s->sew, vm);
|
||||
|
||||
if (is_over) {
|
||||
ret &= (vd != vs2);
|
||||
}
|
||||
@@ -981,7 +1043,8 @@ static bool ld_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_ld_index(s, a->rd, a->rs2, a->nf, a->vm, eew);
|
||||
vext_check_ld_index(s, a->rd, a->rs2, a->nf, a->vm, eew) &&
|
||||
vext_check_input_eew(s, -1, 0, a->rs2, eew, a->vm);
|
||||
}
|
||||
|
||||
GEN_VEXT_TRANS(vlxei8_v, MO_8, rnfvm, ld_index_op, ld_index_check)
|
||||
@@ -1033,7 +1096,8 @@ static bool st_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_st_index(s, a->rd, a->rs2, a->nf, eew);
|
||||
vext_check_st_index(s, a->rd, a->rs2, a->nf, eew) &&
|
||||
vext_check_input_eew(s, a->rd, s->sew, a->rs2, eew, a->vm);
|
||||
}
|
||||
|
||||
GEN_VEXT_TRANS(vsxei8_v, MO_8, rnfvm, st_index_op, st_index_check)
|
||||
@@ -1475,6 +1539,16 @@ static bool opivv_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
/* OPIVV with overwrite and WIDEN */
|
||||
static bool opivv_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) &&
|
||||
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs1, s->sew, a->vm) &&
|
||||
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
|
||||
}
|
||||
|
||||
static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
|
||||
gen_helper_gvec_4_ptr *fn,
|
||||
bool (*checkfn)(DisasContext *, arg_rmrr *))
|
||||
@@ -1522,6 +1596,14 @@ static bool opivx_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
static bool opivx_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm) &&
|
||||
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
|
||||
}
|
||||
|
||||
#define GEN_OPIVX_WIDEN_TRANS(NAME, CHECK) \
|
||||
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
||||
{ \
|
||||
@@ -1993,13 +2075,13 @@ GEN_OPIVX_TRANS(vmadd_vx, opivx_check)
|
||||
GEN_OPIVX_TRANS(vnmsub_vx, opivx_check)
|
||||
|
||||
/* Vector Widening Integer Multiply-Add Instructions */
|
||||
GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_widen_check)
|
||||
GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_widen_check)
|
||||
GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx, opivx_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmacc_vx, opivx_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx, opivx_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx, opivx_widen_check)
|
||||
GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_overwrite_widen_check)
|
||||
GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_overwrite_widen_check)
|
||||
GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_overwrite_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx, opivx_overwrite_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmacc_vx, opivx_overwrite_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx, opivx_overwrite_widen_check)
|
||||
GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx, opivx_overwrite_widen_check)
|
||||
|
||||
/* Vector Integer Merge and Move Instructions */
|
||||
static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
|
||||
@@ -2340,6 +2422,17 @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
static bool opfvv_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
require_scale_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) &&
|
||||
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs1, s->sew, a->vm) &&
|
||||
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
|
||||
}
|
||||
|
||||
/* OPFVV with WIDEN */
|
||||
#define GEN_OPFVV_WIDEN_TRANS(NAME, CHECK) \
|
||||
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
||||
@@ -2379,11 +2472,21 @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm);
|
||||
}
|
||||
|
||||
static bool opfvf_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
require_rvf(s) &&
|
||||
require_scale_rvf(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_ds(s, a->rd, a->rs2, a->vm) &&
|
||||
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
|
||||
}
|
||||
|
||||
/* OPFVF with WIDEN */
|
||||
#define GEN_OPFVF_WIDEN_TRANS(NAME) \
|
||||
#define GEN_OPFVF_WIDEN_TRANS(NAME, CHECK) \
|
||||
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
||||
{ \
|
||||
if (opfvf_widen_check(s, a)) { \
|
||||
if (CHECK(s, a)) { \
|
||||
uint32_t data = 0; \
|
||||
static gen_helper_opfvf *const fns[2] = { \
|
||||
gen_helper_##NAME##_h, gen_helper_##NAME##_w, \
|
||||
@@ -2399,8 +2502,8 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
|
||||
return false; \
|
||||
}
|
||||
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwadd_vf)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwadd_vf, opfvf_widen_check)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwsub_vf, opfvf_widen_check)
|
||||
|
||||
static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
@@ -2482,7 +2585,7 @@ GEN_OPFVF_TRANS(vfrdiv_vf, opfvf_check)
|
||||
|
||||
/* Vector Widening Floating-Point Multiply */
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwmul_vv, opfvv_widen_check)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwmul_vf)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwmul_vf, opfvf_widen_check)
|
||||
|
||||
/* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */
|
||||
GEN_OPFVV_TRANS(vfmacc_vv, opfvv_check)
|
||||
@@ -2503,14 +2606,14 @@ GEN_OPFVF_TRANS(vfmsub_vf, opfvf_check)
|
||||
GEN_OPFVF_TRANS(vfnmsub_vf, opfvf_check)
|
||||
|
||||
/* Vector Widening Floating-Point Fused Multiply-Add Instructions */
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_widen_check)
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_widen_check)
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_widen_check)
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_widen_check)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwmacc_vf)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwmsac_vf)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf)
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_overwrite_widen_check)
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_overwrite_widen_check)
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_overwrite_widen_check)
|
||||
GEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_overwrite_widen_check)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwmacc_vf, opfvf_overwrite_widen_check)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf, opfvf_overwrite_widen_check)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwmsac_vf, opfvf_overwrite_widen_check)
|
||||
GEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf, opfvf_overwrite_widen_check)
|
||||
|
||||
/* Vector Floating-Point Square-Root Instruction */
|
||||
|
||||
@@ -3426,6 +3529,7 @@ static bool vrgather_vv_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_input_eew(s, a->rs1, s->sew, a->rs2, s->sew, a->vm) &&
|
||||
require_align(a->rd, s->lmul) &&
|
||||
require_align(a->rs1, s->lmul) &&
|
||||
require_align(a->rs2, s->lmul) &&
|
||||
@@ -3438,6 +3542,7 @@ static bool vrgatherei16_vv_check(DisasContext *s, arg_rmrr *a)
|
||||
int8_t emul = MO_16 - s->sew + s->lmul;
|
||||
return require_rvv(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_input_eew(s, a->rs1, MO_16, a->rs2, s->sew, a->vm) &&
|
||||
(emul >= -3 && emul <= 3) &&
|
||||
require_align(a->rd, s->lmul) &&
|
||||
require_align(a->rs1, emul) &&
|
||||
@@ -3457,6 +3562,7 @@ static bool vrgather_vx_check(DisasContext *s, arg_rmrr *a)
|
||||
{
|
||||
return require_rvv(s) &&
|
||||
vext_check_isa_ill(s) &&
|
||||
vext_check_input_eew(s, -1, MO_64, a->rs2, s->sew, a->vm) &&
|
||||
require_align(a->rd, s->lmul) &&
|
||||
require_align(a->rs2, s->lmul) &&
|
||||
(a->rd != a->rs2) &&
|
||||
@@ -3600,7 +3706,9 @@ static bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div)
|
||||
require_align(a->rd, s->lmul) &&
|
||||
require_align(a->rs2, s->lmul - div) &&
|
||||
require_vm(a->vm, a->rd) &&
|
||||
require_noover(a->rd, s->lmul, a->rs2, s->lmul - div);
|
||||
require_noover(a->rd, s->lmul, a->rs2, s->lmul - div) &&
|
||||
vext_check_input_eew(s, -1, 0, a->rs2, s->sew, a->vm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+132
-104
@@ -58,33 +58,17 @@ void riscv_kvm_aplic_request(void *opaque, int irq, int level)
|
||||
|
||||
static bool cap_has_mp_state;
|
||||
|
||||
static uint64_t kvm_riscv_reg_id_ulong(CPURISCVState *env, uint64_t type,
|
||||
uint64_t idx)
|
||||
{
|
||||
uint64_t id = KVM_REG_RISCV | type | idx;
|
||||
#define KVM_RISCV_REG_ID_U32(type, idx) (KVM_REG_RISCV | KVM_REG_SIZE_U32 | \
|
||||
type | idx)
|
||||
|
||||
switch (riscv_cpu_mxl(env)) {
|
||||
case MXL_RV32:
|
||||
id |= KVM_REG_SIZE_U32;
|
||||
break;
|
||||
case MXL_RV64:
|
||||
id |= KVM_REG_SIZE_U64;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
#define KVM_RISCV_REG_ID_U64(type, idx) (KVM_REG_RISCV | KVM_REG_SIZE_U64 | \
|
||||
type | idx)
|
||||
|
||||
static uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx)
|
||||
{
|
||||
return KVM_REG_RISCV | KVM_REG_SIZE_U32 | type | idx;
|
||||
}
|
||||
|
||||
static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx)
|
||||
{
|
||||
return KVM_REG_RISCV | KVM_REG_SIZE_U64 | type | idx;
|
||||
}
|
||||
#if defined(TARGET_RISCV64)
|
||||
#define KVM_RISCV_REG_ID_ULONG(type, idx) KVM_RISCV_REG_ID_U64(type, idx)
|
||||
#else
|
||||
#define KVM_RISCV_REG_ID_ULONG(type, idx) KVM_RISCV_REG_ID_U32(type, idx)
|
||||
#endif
|
||||
|
||||
static uint64_t kvm_encode_reg_size_id(uint64_t id, size_t size_b)
|
||||
{
|
||||
@@ -107,45 +91,29 @@ static uint64_t kvm_riscv_vector_reg_id(RISCVCPU *cpu,
|
||||
return kvm_encode_reg_size_id(id, size_b);
|
||||
}
|
||||
|
||||
#define RISCV_CORE_REG(env, name) \
|
||||
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, \
|
||||
#define RISCV_CORE_REG(name) \
|
||||
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CORE, \
|
||||
KVM_REG_RISCV_CORE_REG(name))
|
||||
|
||||
#define RISCV_CSR_REG(env, name) \
|
||||
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CSR, \
|
||||
#define RISCV_CSR_REG(name) \
|
||||
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CSR, \
|
||||
KVM_REG_RISCV_CSR_REG(name))
|
||||
|
||||
#define RISCV_CONFIG_REG(env, name) \
|
||||
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG, \
|
||||
#define RISCV_CONFIG_REG(name) \
|
||||
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG, \
|
||||
KVM_REG_RISCV_CONFIG_REG(name))
|
||||
|
||||
#define RISCV_TIMER_REG(name) kvm_riscv_reg_id_u64(KVM_REG_RISCV_TIMER, \
|
||||
#define RISCV_TIMER_REG(name) KVM_RISCV_REG_ID_U64(KVM_REG_RISCV_TIMER, \
|
||||
KVM_REG_RISCV_TIMER_REG(name))
|
||||
|
||||
#define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx)
|
||||
#define RISCV_FP_F_REG(idx) KVM_RISCV_REG_ID_U32(KVM_REG_RISCV_FP_F, idx)
|
||||
|
||||
#define RISCV_FP_D_REG(idx) kvm_riscv_reg_id_u64(KVM_REG_RISCV_FP_D, idx)
|
||||
#define RISCV_FP_D_REG(idx) KVM_RISCV_REG_ID_U64(KVM_REG_RISCV_FP_D, idx)
|
||||
|
||||
#define RISCV_VECTOR_CSR_REG(env, name) \
|
||||
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_VECTOR, \
|
||||
#define RISCV_VECTOR_CSR_REG(name) \
|
||||
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_VECTOR, \
|
||||
KVM_REG_RISCV_VECTOR_CSR_REG(name))
|
||||
|
||||
#define KVM_RISCV_GET_CSR(cs, env, csr, reg) \
|
||||
do { \
|
||||
int _ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \
|
||||
if (_ret) { \
|
||||
return _ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define KVM_RISCV_SET_CSR(cs, env, csr, reg) \
|
||||
do { \
|
||||
int _ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \
|
||||
if (_ret) { \
|
||||
return _ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define KVM_RISCV_GET_TIMER(cs, name, reg) \
|
||||
do { \
|
||||
int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(name), ®); \
|
||||
@@ -248,7 +216,7 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs)
|
||||
|
||||
/* If we're here we're going to disable the MISA bit */
|
||||
reg = 0;
|
||||
id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT,
|
||||
id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
|
||||
misa_cfg->kvm_reg_id);
|
||||
ret = kvm_set_one_reg(cs, id, ®);
|
||||
if (ret != 0) {
|
||||
@@ -267,6 +235,53 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs)
|
||||
}
|
||||
}
|
||||
|
||||
#define KVM_CSR_CFG(_name, _env_prop, reg_id) \
|
||||
{.name = _name, .offset = ENV_CSR_OFFSET(_env_prop), \
|
||||
.kvm_reg_id = reg_id}
|
||||
|
||||
static KVMCPUConfig kvm_csr_cfgs[] = {
|
||||
KVM_CSR_CFG("sstatus", mstatus, RISCV_CSR_REG(sstatus)),
|
||||
KVM_CSR_CFG("sie", mie, RISCV_CSR_REG(sie)),
|
||||
KVM_CSR_CFG("stvec", stvec, RISCV_CSR_REG(stvec)),
|
||||
KVM_CSR_CFG("sscratch", sscratch, RISCV_CSR_REG(sscratch)),
|
||||
KVM_CSR_CFG("sepc", sepc, RISCV_CSR_REG(sepc)),
|
||||
KVM_CSR_CFG("scause", scause, RISCV_CSR_REG(scause)),
|
||||
KVM_CSR_CFG("stval", stval, RISCV_CSR_REG(stval)),
|
||||
KVM_CSR_CFG("sip", mip, RISCV_CSR_REG(sip)),
|
||||
KVM_CSR_CFG("satp", satp, RISCV_CSR_REG(satp)),
|
||||
};
|
||||
|
||||
static void *kvmconfig_get_env_addr(RISCVCPU *cpu, KVMCPUConfig *csr_cfg)
|
||||
{
|
||||
return (void *)&cpu->env + csr_cfg->offset;
|
||||
}
|
||||
|
||||
static uint32_t kvm_cpu_csr_get_u32(RISCVCPU *cpu, KVMCPUConfig *csr_cfg)
|
||||
{
|
||||
uint32_t *val32 = kvmconfig_get_env_addr(cpu, csr_cfg);
|
||||
return *val32;
|
||||
}
|
||||
|
||||
static uint64_t kvm_cpu_csr_get_u64(RISCVCPU *cpu, KVMCPUConfig *csr_cfg)
|
||||
{
|
||||
uint64_t *val64 = kvmconfig_get_env_addr(cpu, csr_cfg);
|
||||
return *val64;
|
||||
}
|
||||
|
||||
static void kvm_cpu_csr_set_u32(RISCVCPU *cpu, KVMCPUConfig *csr_cfg,
|
||||
uint32_t val)
|
||||
{
|
||||
uint32_t *val32 = kvmconfig_get_env_addr(cpu, csr_cfg);
|
||||
*val32 = val;
|
||||
}
|
||||
|
||||
static void kvm_cpu_csr_set_u64(RISCVCPU *cpu, KVMCPUConfig *csr_cfg,
|
||||
uint64_t val)
|
||||
{
|
||||
uint64_t *val64 = kvmconfig_get_env_addr(cpu, csr_cfg);
|
||||
*val64 = val;
|
||||
}
|
||||
|
||||
#define KVM_EXT_CFG(_name, _prop, _reg_id) \
|
||||
{.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
|
||||
.kvm_reg_id = _reg_id}
|
||||
@@ -426,7 +441,6 @@ static KVMCPUConfig kvm_sbi_dbcn = {
|
||||
|
||||
static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
|
||||
{
|
||||
CPURISCVState *env = &cpu->env;
|
||||
uint64_t id, reg;
|
||||
int i, ret;
|
||||
|
||||
@@ -437,7 +451,7 @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
|
||||
continue;
|
||||
}
|
||||
|
||||
id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT,
|
||||
id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
|
||||
multi_ext_cfg->kvm_reg_id);
|
||||
reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
|
||||
ret = kvm_set_one_reg(cs, id, ®);
|
||||
@@ -562,14 +576,14 @@ static int kvm_riscv_get_regs_core(CPUState *cs)
|
||||
target_ulong reg;
|
||||
CPURISCVState *env = &RISCV_CPU(cs)->env;
|
||||
|
||||
ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®);
|
||||
ret = kvm_get_one_reg(cs, RISCV_CORE_REG(regs.pc), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
env->pc = reg;
|
||||
|
||||
for (i = 1; i < 32; i++) {
|
||||
uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i);
|
||||
uint64_t id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CORE, i);
|
||||
ret = kvm_get_one_reg(cs, id, ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
@@ -588,13 +602,13 @@ static int kvm_riscv_put_regs_core(CPUState *cs)
|
||||
CPURISCVState *env = &RISCV_CPU(cs)->env;
|
||||
|
||||
reg = env->pc;
|
||||
ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®);
|
||||
ret = kvm_set_one_reg(cs, RISCV_CORE_REG(regs.pc), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 1; i < 32; i++) {
|
||||
uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i);
|
||||
uint64_t id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CORE, i);
|
||||
reg = env->gpr[i];
|
||||
ret = kvm_set_one_reg(cs, id, ®);
|
||||
if (ret) {
|
||||
@@ -607,34 +621,52 @@ static int kvm_riscv_put_regs_core(CPUState *cs)
|
||||
|
||||
static int kvm_riscv_get_regs_csr(CPUState *cs)
|
||||
{
|
||||
CPURISCVState *env = &RISCV_CPU(cs)->env;
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
uint64_t reg;
|
||||
int i, ret;
|
||||
|
||||
KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus);
|
||||
KVM_RISCV_GET_CSR(cs, env, sie, env->mie);
|
||||
KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec);
|
||||
KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch);
|
||||
KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc);
|
||||
KVM_RISCV_GET_CSR(cs, env, scause, env->scause);
|
||||
KVM_RISCV_GET_CSR(cs, env, stval, env->stval);
|
||||
KVM_RISCV_GET_CSR(cs, env, sip, env->mip);
|
||||
KVM_RISCV_GET_CSR(cs, env, satp, env->satp);
|
||||
for (i = 0; i < ARRAY_SIZE(kvm_csr_cfgs); i++) {
|
||||
KVMCPUConfig *csr_cfg = &kvm_csr_cfgs[i];
|
||||
|
||||
ret = kvm_get_one_reg(cs, csr_cfg->kvm_reg_id, ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint32_t)) {
|
||||
kvm_cpu_csr_set_u32(cpu, csr_cfg, reg);
|
||||
} else if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint64_t)) {
|
||||
kvm_cpu_csr_set_u64(cpu, csr_cfg, reg);
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_riscv_put_regs_csr(CPUState *cs)
|
||||
{
|
||||
CPURISCVState *env = &RISCV_CPU(cs)->env;
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
uint64_t reg;
|
||||
int i, ret;
|
||||
|
||||
KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus);
|
||||
KVM_RISCV_SET_CSR(cs, env, sie, env->mie);
|
||||
KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec);
|
||||
KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch);
|
||||
KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc);
|
||||
KVM_RISCV_SET_CSR(cs, env, scause, env->scause);
|
||||
KVM_RISCV_SET_CSR(cs, env, stval, env->stval);
|
||||
KVM_RISCV_SET_CSR(cs, env, sip, env->mip);
|
||||
KVM_RISCV_SET_CSR(cs, env, satp, env->satp);
|
||||
for (i = 0; i < ARRAY_SIZE(kvm_csr_cfgs); i++) {
|
||||
KVMCPUConfig *csr_cfg = &kvm_csr_cfgs[i];
|
||||
|
||||
if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint32_t)) {
|
||||
reg = kvm_cpu_csr_get_u32(cpu, csr_cfg);
|
||||
} else if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint64_t)) {
|
||||
reg = kvm_cpu_csr_get_u64(cpu, csr_cfg);
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
ret = kvm_set_one_reg(cs, csr_cfg->kvm_reg_id, ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -779,26 +811,26 @@ static int kvm_riscv_get_regs_vector(CPUState *cs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vstart), ®);
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vstart), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
env->vstart = reg;
|
||||
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vl), ®);
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vl), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
env->vl = reg;
|
||||
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), ®);
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vtype), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
env->vtype = reg;
|
||||
|
||||
if (kvm_v_vlenb.supported) {
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®);
|
||||
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vlenb), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
@@ -836,26 +868,26 @@ static int kvm_riscv_put_regs_vector(CPUState *cs)
|
||||
}
|
||||
|
||||
reg = env->vstart;
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vstart), ®);
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vstart), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
reg = env->vl;
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vl), ®);
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vl), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
reg = env->vtype;
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), ®);
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vtype), ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (kvm_v_vlenb.supported) {
|
||||
reg = cpu->cfg.vlenb;
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), ®);
|
||||
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vlenb), ®);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
/*
|
||||
@@ -934,25 +966,24 @@ static void kvm_riscv_destroy_scratch_vcpu(KVMScratchCPU *scratch)
|
||||
|
||||
static void kvm_riscv_init_machine_ids(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
|
||||
{
|
||||
CPURISCVState *env = &cpu->env;
|
||||
struct kvm_one_reg reg;
|
||||
int ret;
|
||||
|
||||
reg.id = RISCV_CONFIG_REG(env, mvendorid);
|
||||
reg.id = RISCV_CONFIG_REG(mvendorid);
|
||||
reg.addr = (uint64_t)&cpu->cfg.mvendorid;
|
||||
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
|
||||
if (ret != 0) {
|
||||
error_report("Unable to retrieve mvendorid from host, error %d", ret);
|
||||
}
|
||||
|
||||
reg.id = RISCV_CONFIG_REG(env, marchid);
|
||||
reg.id = RISCV_CONFIG_REG(marchid);
|
||||
reg.addr = (uint64_t)&cpu->cfg.marchid;
|
||||
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
|
||||
if (ret != 0) {
|
||||
error_report("Unable to retrieve marchid from host, error %d", ret);
|
||||
}
|
||||
|
||||
reg.id = RISCV_CONFIG_REG(env, mimpid);
|
||||
reg.id = RISCV_CONFIG_REG(mimpid);
|
||||
reg.addr = (uint64_t)&cpu->cfg.mimpid;
|
||||
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
|
||||
if (ret != 0) {
|
||||
@@ -967,7 +998,7 @@ static void kvm_riscv_init_misa_ext_mask(RISCVCPU *cpu,
|
||||
struct kvm_one_reg reg;
|
||||
int ret;
|
||||
|
||||
reg.id = RISCV_CONFIG_REG(env, isa);
|
||||
reg.id = RISCV_CONFIG_REG(isa);
|
||||
reg.addr = (uint64_t)&env->misa_ext_mask;
|
||||
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
|
||||
|
||||
@@ -984,11 +1015,10 @@ static void kvm_riscv_init_misa_ext_mask(RISCVCPU *cpu,
|
||||
static void kvm_riscv_read_cbomz_blksize(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
|
||||
KVMCPUConfig *cbomz_cfg)
|
||||
{
|
||||
CPURISCVState *env = &cpu->env;
|
||||
struct kvm_one_reg reg;
|
||||
int ret;
|
||||
|
||||
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
|
||||
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG,
|
||||
cbomz_cfg->kvm_reg_id);
|
||||
reg.addr = (uint64_t)kvmconfig_get_cfg_addr(cpu, cbomz_cfg);
|
||||
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
|
||||
@@ -1002,7 +1032,6 @@ static void kvm_riscv_read_cbomz_blksize(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
|
||||
static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu,
|
||||
KVMScratchCPU *kvmcpu)
|
||||
{
|
||||
CPURISCVState *env = &cpu->env;
|
||||
uint64_t val;
|
||||
int i, ret;
|
||||
|
||||
@@ -1010,7 +1039,7 @@ static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu,
|
||||
KVMCPUConfig *multi_ext_cfg = &kvm_multi_ext_cfgs[i];
|
||||
struct kvm_one_reg reg;
|
||||
|
||||
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT,
|
||||
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
|
||||
multi_ext_cfg->kvm_reg_id);
|
||||
reg.addr = (uint64_t)&val;
|
||||
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®);
|
||||
@@ -1099,10 +1128,10 @@ static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
|
||||
|
||||
static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
|
||||
{
|
||||
g_autofree struct kvm_reg_list *reglist = NULL;
|
||||
KVMCPUConfig *multi_ext_cfg;
|
||||
struct kvm_one_reg reg;
|
||||
struct kvm_reg_list rl_struct;
|
||||
struct kvm_reg_list *reglist;
|
||||
uint64_t val, reg_id, *reg_search;
|
||||
int i, ret;
|
||||
|
||||
@@ -1143,7 +1172,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(kvm_multi_ext_cfgs); i++) {
|
||||
multi_ext_cfg = &kvm_multi_ext_cfgs[i];
|
||||
reg_id = kvm_riscv_reg_id_ulong(&cpu->env, KVM_REG_RISCV_ISA_EXT,
|
||||
reg_id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
|
||||
multi_ext_cfg->kvm_reg_id);
|
||||
reg_search = bsearch(®_id, reglist->reg, reglist->n,
|
||||
sizeof(uint64_t), uint64_cmp);
|
||||
@@ -1322,12 +1351,11 @@ void kvm_arch_init_irq_routing(KVMState *s)
|
||||
|
||||
static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
|
||||
{
|
||||
CPURISCVState *env = &cpu->env;
|
||||
target_ulong reg;
|
||||
uint64_t id;
|
||||
int ret;
|
||||
|
||||
id = RISCV_CONFIG_REG(env, mvendorid);
|
||||
id = RISCV_CONFIG_REG(mvendorid);
|
||||
/*
|
||||
* cfg.mvendorid is an uint32 but a target_ulong will
|
||||
* be written. Assign it to a target_ulong var to avoid
|
||||
@@ -1339,13 +1367,13 @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
id = RISCV_CONFIG_REG(env, marchid);
|
||||
id = RISCV_CONFIG_REG(marchid);
|
||||
ret = kvm_set_one_reg(cs, id, &cpu->cfg.marchid);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
id = RISCV_CONFIG_REG(env, mimpid);
|
||||
id = RISCV_CONFIG_REG(mimpid);
|
||||
ret = kvm_set_one_reg(cs, id, &cpu->cfg.mimpid);
|
||||
|
||||
return ret;
|
||||
@@ -1901,7 +1929,7 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
|
||||
if (cpu->cfg.ext_zicbom &&
|
||||
riscv_cpu_option_set(kvm_cbom_blocksize.name)) {
|
||||
|
||||
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
|
||||
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG,
|
||||
kvm_cbom_blocksize.kvm_reg_id);
|
||||
reg.addr = (uint64_t)&val;
|
||||
ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®);
|
||||
@@ -1920,7 +1948,7 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
|
||||
if (cpu->cfg.ext_zicboz &&
|
||||
riscv_cpu_option_set(kvm_cboz_blocksize.name)) {
|
||||
|
||||
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
|
||||
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG,
|
||||
kvm_cboz_blocksize.kvm_reg_id);
|
||||
reg.addr = (uint64_t)&val;
|
||||
ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®);
|
||||
|
||||
+12
-10
@@ -31,6 +31,15 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
|
||||
uint8_t val);
|
||||
static uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t addr_index);
|
||||
|
||||
/*
|
||||
* Convert the PMP permissions to match the truth table in the Smepmp spec.
|
||||
*/
|
||||
static inline uint8_t pmp_get_smepmp_operation(uint8_t cfg)
|
||||
{
|
||||
return ((cfg & PMP_LOCK) >> 4) | ((cfg & PMP_READ) << 2) |
|
||||
(cfg & PMP_WRITE) | ((cfg & PMP_EXEC) >> 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accessor method to extract address matching type 'a field' from cfg reg
|
||||
*/
|
||||
@@ -352,16 +361,6 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
|
||||
const uint8_t a_field =
|
||||
pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg);
|
||||
|
||||
/*
|
||||
* Convert the PMP permissions to match the truth table in the
|
||||
* Smepmp spec.
|
||||
*/
|
||||
const uint8_t smepmp_operation =
|
||||
((env->pmp_state.pmp[i].cfg_reg & PMP_LOCK) >> 4) |
|
||||
((env->pmp_state.pmp[i].cfg_reg & PMP_READ) << 2) |
|
||||
(env->pmp_state.pmp[i].cfg_reg & PMP_WRITE) |
|
||||
((env->pmp_state.pmp[i].cfg_reg & PMP_EXEC) >> 2);
|
||||
|
||||
if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) {
|
||||
/*
|
||||
* If the PMP entry is not off and the address is in range,
|
||||
@@ -380,6 +379,9 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
|
||||
/*
|
||||
* If mseccfg.MML Bit set, do the enhanced pmp priv check
|
||||
*/
|
||||
const uint8_t smepmp_operation =
|
||||
pmp_get_smepmp_operation(env->pmp_state.pmp[i].cfg_reg);
|
||||
|
||||
if (mode == PRV_M) {
|
||||
switch (smepmp_operation) {
|
||||
case 0:
|
||||
|
||||
@@ -5089,9 +5089,11 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
|
||||
} \
|
||||
\
|
||||
for (i = i_max; i < vl; ++i) { \
|
||||
if (vm || vext_elem_mask(v0, i)) { \
|
||||
*((ETYPE *)vd + H(i)) = 0; \
|
||||
if (!vm && !vext_elem_mask(v0, i)) { \
|
||||
vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
|
||||
continue; \
|
||||
} \
|
||||
*((ETYPE *)vd + H(i)) = 0; \
|
||||
} \
|
||||
\
|
||||
env->vstart = 0; \
|
||||
|
||||
@@ -4461,6 +4461,9 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
|
||||
ts->mem_coherent = 0;
|
||||
break;
|
||||
case TEMP_VAL_MEM:
|
||||
if (!ts->mem_allocated) {
|
||||
temp_allocate_frame(s, ts);
|
||||
}
|
||||
reg = tcg_reg_alloc(s, desired_regs, allocated_regs,
|
||||
preferred_regs, ts->indirect_base);
|
||||
tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
|
||||
|
||||
Reference in New Issue
Block a user