aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rw-r--r--accel/tcg/cputlb.c23
-rw-r--r--accel/tcg/user-exec.c114
-rw-r--r--bsd-user/bsd-mem.h7
-rw-r--r--bsd-user/mmap.c6
-rw-r--r--hw/intc/loongarch_pic_kvm.c1
-rw-r--r--hw/loongarch/virt-acpi-build.c1
-rw-r--r--hw/loongarch/virt-fdt-build.c1
-rw-r--r--hw/loongarch/virt.c3
-rw-r--r--include/exec/page-protection.h19
-rw-r--r--include/hw/intc/loongarch_pic_common.h2
-rw-r--r--include/hw/loongarch/virt.h75
-rw-r--r--include/hw/pci-host/ls7a.h39
-rw-r--r--include/user/page-protection.h9
-rw-r--r--linux-user/arm/elfload.c2
-rw-r--r--linux-user/elfload.c4
-rw-r--r--linux-user/hppa/elfload.c2
-rw-r--r--linux-user/mmap.c38
-rw-r--r--linux-user/x86_64/elfload.c2
-rw-r--r--target/arm/cpu.h1
-rw-r--r--target/loongarch/tcg/tlb_helper.c22
21 files changed, 167 insertions, 205 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 84cfd85..0c76696 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1308,7 +1308,6 @@ F: include/hw/intc/loongarch_*.h
F: include/hw/intc/loongson_ipi_common.h
F: hw/intc/loongarch_*.c
F: hw/intc/loongson_ipi_common.c
-F: include/hw/pci-host/ls7a.h
F: hw/rtc/ls7a_rtc.c
F: gdb-xml/loongarch*.xml
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 3010dd4..631f1fe 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1742,6 +1742,7 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
uintptr_t ra, MMUAccessType type, MMULookupLocals *l)
{
bool crosspage;
+ vaddr last;
int flags;
l->memop = get_memop(oi);
@@ -1751,13 +1752,15 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
l->page[0].addr = addr;
l->page[0].size = memop_size(l->memop);
- l->page[1].addr = (addr + l->page[0].size - 1) & TARGET_PAGE_MASK;
+ l->page[1].addr = 0;
l->page[1].size = 0;
- crosspage = (addr ^ l->page[1].addr) & TARGET_PAGE_MASK;
- if (likely(!crosspage)) {
- mmu_lookup1(cpu, &l->page[0], l->memop, l->mmu_idx, type, ra);
+ /* Lookup and recognize exceptions from the first page. */
+ mmu_lookup1(cpu, &l->page[0], l->memop, l->mmu_idx, type, ra);
+ last = addr + l->page[0].size - 1;
+ crosspage = (addr ^ last) & TARGET_PAGE_MASK;
+ if (likely(!crosspage)) {
flags = l->page[0].flags;
if (unlikely(flags & (TLB_WATCHPOINT | TLB_NOTDIRTY))) {
mmu_watch_or_dirty(cpu, &l->page[0], type, ra);
@@ -1767,18 +1770,18 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
}
} else {
/* Finish compute of page crossing. */
- int size0 = l->page[1].addr - addr;
+ vaddr addr1 = last & TARGET_PAGE_MASK;
+ int size0 = addr1 - addr;
l->page[1].size = l->page[0].size - size0;
l->page[0].size = size0;
-
l->page[1].addr = cpu->cc->tcg_ops->pointer_wrap(cpu, l->mmu_idx,
- l->page[1].addr, addr);
+ addr1, addr);
/*
- * Lookup both pages, recognizing exceptions from either. If the
- * second lookup potentially resized, refresh first CPUTLBEntryFull.
+ * Lookup and recognize exceptions from the second page.
+ * If the lookup potentially resized the table, refresh the
+ * first CPUTLBEntryFull pointer.
*/
- mmu_lookup1(cpu, &l->page[0], l->memop, l->mmu_idx, type, ra);
if (mmu_lookup1(cpu, &l->page[1], 0, l->mmu_idx, type, ra)) {
uintptr_t index = tlb_index(cpu, l->mmu_idx, addr);
l->page[0].full = &cpu->neg.tlb.d[l->mmu_idx].fulltlb[index];
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 916f187..1800dff 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -269,48 +269,6 @@ static void pageflags_create(vaddr start, vaddr last, int flags)
interval_tree_insert(&p->itree, &pageflags_root);
}
-/* A subroutine of page_set_flags: remove everything in [start,last]. */
-static bool pageflags_unset(vaddr start, vaddr last)
-{
- bool inval_tb = false;
-
- while (true) {
- PageFlagsNode *p = pageflags_find(start, last);
- vaddr p_last;
-
- if (!p) {
- break;
- }
-
- if (p->flags & PAGE_EXEC) {
- inval_tb = true;
- }
-
- interval_tree_remove(&p->itree, &pageflags_root);
- p_last = p->itree.last;
-
- if (p->itree.start < start) {
- /* Truncate the node from the end, or split out the middle. */
- p->itree.last = start - 1;
- interval_tree_insert(&p->itree, &pageflags_root);
- if (last < p_last) {
- pageflags_create(last + 1, p_last, p->flags);
- break;
- }
- } else if (p_last <= last) {
- /* Range completely covers node -- remove it. */
- g_free_rcu(p, rcu);
- } else {
- /* Truncate the node from the start. */
- p->itree.start = last + 1;
- interval_tree_insert(&p->itree, &pageflags_root);
- break;
- }
- }
-
- return inval_tb;
-}
-
/*
* A subroutine of page_set_flags: nothing overlaps [start,last],
* but check adjacent mappings and maybe merge into a single range.
@@ -356,15 +314,6 @@ static void pageflags_create_merge(vaddr start, vaddr last, int flags)
}
}
-/*
- * Allow the target to decide if PAGE_TARGET_[12] may be reset.
- * By default, they are not kept.
- */
-#ifndef PAGE_TARGET_STICKY
-#define PAGE_TARGET_STICKY 0
-#endif
-#define PAGE_STICKY (PAGE_ANON | PAGE_PASSTHROUGH | PAGE_TARGET_STICKY)
-
/* A subroutine of page_set_flags: add flags to [start,last]. */
static bool pageflags_set_clear(vaddr start, vaddr last,
int set_flags, int clear_flags)
@@ -377,7 +326,7 @@ static bool pageflags_set_clear(vaddr start, vaddr last,
restart:
p = pageflags_find(start, last);
if (!p) {
- if (set_flags) {
+ if (set_flags & PAGE_VALID) {
pageflags_create_merge(start, last, set_flags);
}
goto done;
@@ -391,11 +340,12 @@ static bool pageflags_set_clear(vaddr start, vaddr last,
/*
* Need to flush if an overlapping executable region
- * removes exec, or adds write.
+ * removes exec, adds write, or is a new mapping.
*/
if ((p_flags & PAGE_EXEC)
&& (!(merge_flags & PAGE_EXEC)
- || (merge_flags & ~p_flags & PAGE_WRITE))) {
+ || (merge_flags & ~p_flags & PAGE_WRITE)
+ || (clear_flags & PAGE_VALID))) {
inval_tb = true;
}
@@ -404,7 +354,7 @@ static bool pageflags_set_clear(vaddr start, vaddr last,
* attempting to merge with adjacent regions.
*/
if (start == p_start && last == p_last) {
- if (merge_flags) {
+ if (merge_flags & PAGE_VALID) {
p->flags = merge_flags;
} else {
interval_tree_remove(&p->itree, &pageflags_root);
@@ -424,12 +374,12 @@ static bool pageflags_set_clear(vaddr start, vaddr last,
interval_tree_insert(&p->itree, &pageflags_root);
if (last < p_last) {
- if (merge_flags) {
+ if (merge_flags & PAGE_VALID) {
pageflags_create(start, last, merge_flags);
}
pageflags_create(last + 1, p_last, p_flags);
} else {
- if (merge_flags) {
+ if (merge_flags & PAGE_VALID) {
pageflags_create(start, p_last, merge_flags);
}
if (p_last < last) {
@@ -438,18 +388,18 @@ static bool pageflags_set_clear(vaddr start, vaddr last,
}
}
} else {
- if (start < p_start && set_flags) {
+ if (start < p_start && (set_flags & PAGE_VALID)) {
pageflags_create(start, p_start - 1, set_flags);
}
if (last < p_last) {
interval_tree_remove(&p->itree, &pageflags_root);
p->itree.start = last + 1;
interval_tree_insert(&p->itree, &pageflags_root);
- if (merge_flags) {
+ if (merge_flags & PAGE_VALID) {
pageflags_create(start, last, merge_flags);
}
} else {
- if (merge_flags) {
+ if (merge_flags & PAGE_VALID) {
p->flags = merge_flags;
} else {
interval_tree_remove(&p->itree, &pageflags_root);
@@ -497,7 +447,7 @@ static bool pageflags_set_clear(vaddr start, vaddr last,
g_free_rcu(p, rcu);
goto restart;
}
- if (set_flags) {
+ if (set_flags & PAGE_VALID) {
pageflags_create(start, last, set_flags);
}
@@ -505,42 +455,36 @@ static bool pageflags_set_clear(vaddr start, vaddr last,
return inval_tb;
}
-void page_set_flags(vaddr start, vaddr last, int flags)
+void page_set_flags(vaddr start, vaddr last, int set_flags, int clear_flags)
{
- bool reset = false;
- bool inval_tb = false;
-
- /* This function should never be called with addresses outside the
- guest address space. If this assert fires, it probably indicates
- a missing call to h2g_valid. */
+ /*
+ * This function should never be called with addresses outside the
+ * guest address space. If this assert fires, it probably indicates
+ * a missing call to h2g_valid.
+ */
assert(start <= last);
assert(last <= guest_addr_max);
- /* Only set PAGE_ANON with new mappings. */
- assert(!(flags & PAGE_ANON) || (flags & PAGE_RESET));
assert_memory_lock();
start &= TARGET_PAGE_MASK;
last |= ~TARGET_PAGE_MASK;
- if (!(flags & PAGE_VALID)) {
- flags = 0;
- } else {
- reset = flags & PAGE_RESET;
- flags &= ~PAGE_RESET;
- if (flags & PAGE_WRITE) {
- flags |= PAGE_WRITE_ORG;
- }
+ if (set_flags & PAGE_WRITE) {
+ set_flags |= PAGE_WRITE_ORG;
+ }
+ if (clear_flags & PAGE_WRITE) {
+ clear_flags |= PAGE_WRITE_ORG;
}
- if (!flags || reset) {
+ if (clear_flags & PAGE_VALID) {
page_reset_target_data(start, last);
- inval_tb |= pageflags_unset(start, last);
- }
- if (flags) {
- inval_tb |= pageflags_set_clear(start, last, flags,
- ~(reset ? 0 : PAGE_STICKY));
+ clear_flags = -1;
+ } else {
+ /* Only set PAGE_ANON with new mappings. */
+ assert(!(set_flags & PAGE_ANON));
}
- if (inval_tb) {
+
+ if (pageflags_set_clear(start, last, set_flags, clear_flags)) {
tb_invalidate_phys_range(NULL, start, last);
}
}
diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h
index 1be906c..416d0f8 100644
--- a/bsd-user/bsd-mem.h
+++ b/bsd-user/bsd-mem.h
@@ -390,8 +390,9 @@ static inline abi_long do_bsd_shmat(int shmid, abi_ulong shmaddr, int shmflg)
raddr = h2g(host_raddr);
page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
- PAGE_VALID | PAGE_RESET | PAGE_READ |
- (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
+ PAGE_VALID | PAGE_READ |
+ (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE),
+ PAGE_VALID);
for (int i = 0; i < N_BSD_SHM_REGIONS; i++) {
if (bsd_shm_regions[i].start == 0) {
@@ -428,7 +429,7 @@ static inline abi_long do_bsd_shmdt(abi_ulong shmaddr)
abi_ulong size = bsd_shm_regions[i].size;
bsd_shm_regions[i].start = 0;
- page_set_flags(shmaddr, shmaddr + size - 1, 0);
+ page_set_flags(shmaddr, shmaddr + size - 1, 0, PAGE_VALID);
mmap_reserve(shmaddr, size);
}
}
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index 47e3175..24ba172 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -122,7 +122,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
if (ret != 0)
goto error;
}
- page_set_flags(start, start + len - 1, prot | PAGE_VALID);
+ page_set_flags(start, start + len - 1, prot, PAGE_RWX);
mmap_unlock();
return 0;
error:
@@ -652,7 +652,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
}
}
the_end1:
- page_set_flags(start, start + len - 1, prot | PAGE_VALID);
+ page_set_flags(start, start + len - 1, prot | PAGE_VALID, PAGE_VALID);
the_end:
#ifdef DEBUG_MMAP
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
@@ -763,7 +763,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
}
if (ret == 0) {
- page_set_flags(start, start + len - 1, 0);
+ page_set_flags(start, start + len - 1, 0, PAGE_VALID);
}
mmap_unlock();
return ret;
diff --git a/hw/intc/loongarch_pic_kvm.c b/hw/intc/loongarch_pic_kvm.c
index dd504ec..6cfddf4 100644
--- a/hw/intc/loongarch_pic_kvm.c
+++ b/hw/intc/loongarch_pic_kvm.c
@@ -10,7 +10,6 @@
#include "hw/boards.h"
#include "hw/intc/loongarch_pch_pic.h"
#include "hw/loongarch/virt.h"
-#include "hw/pci-host/ls7a.h"
#include "system/kvm.h"
static void kvm_pch_pic_access_reg(int fd, uint64_t addr, void *val, bool write)
diff --git a/hw/loongarch/virt-acpi-build.c b/hw/loongarch/virt-acpi-build.c
index 8c2228a..3694c98 100644
--- a/hw/loongarch/virt-acpi-build.c
+++ b/hw/loongarch/virt-acpi-build.c
@@ -21,7 +21,6 @@
#include "system/reset.h"
/* Supported chipsets: */
-#include "hw/pci-host/ls7a.h"
#include "hw/loongarch/virt.h"
#include "hw/acpi/utils.h"
diff --git a/hw/loongarch/virt-fdt-build.c b/hw/loongarch/virt-fdt-build.c
index 728ce46..1f0ba01 100644
--- a/hw/loongarch/virt-fdt-build.c
+++ b/hw/loongarch/virt-fdt-build.c
@@ -12,7 +12,6 @@
#include "hw/loader.h"
#include "hw/loongarch/virt.h"
#include "hw/pci-host/gpex.h"
-#include "hw/pci-host/ls7a.h"
#include "system/device_tree.h"
#include "system/reset.h"
#include "target/loongarch/cpu.h"
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index c176042..49434ad 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -29,7 +29,6 @@
#include "hw/intc/loongarch_pch_pic.h"
#include "hw/intc/loongarch_pch_msi.h"
#include "hw/intc/loongarch_dintc.h"
-#include "hw/pci-host/ls7a.h"
#include "hw/pci-host/gpex.h"
#include "hw/misc/unimp.h"
#include "hw/loongarch/fw_cfg.h"
@@ -521,7 +520,7 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
}
/* PCH_PIC memory region */
- memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE,
+ memory_region_add_subregion(get_system_memory(), VIRT_PCH_REG_BASE,
sysbus_mmio_get_region(SYS_BUS_DEVICE(pch_pic), 0));
/* Connect pch_pic irqs to extioi */
diff --git a/include/exec/page-protection.h b/include/exec/page-protection.h
index c43231a..c50ce57 100644
--- a/include/exec/page-protection.h
+++ b/include/exec/page-protection.h
@@ -23,19 +23,20 @@
* Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs()
*/
#define PAGE_WRITE_INV 0x0020
-/* For use with page_set_flags: page is being replaced; target_data cleared. */
-#define PAGE_RESET 0x0040
+/*
+ * For linux-user, indicates that the page is mapped with the same semantics
+ * in both guest and host.
+ */
+#define PAGE_PASSTHROUGH 0x40
/* For linux-user, indicates that the page is MAP_ANON. */
#define PAGE_ANON 0x0080
-
+/*
+ * For linux-user, indicates that the page should not be
+ * included in a core dump.
+ */
+#define PAGE_DONTDUMP 0x0100
/* Target-specific bits that will be used via page_get_flags(). */
#define PAGE_TARGET_1 0x0200
#define PAGE_TARGET_2 0x0400
-/*
- * For linux-user, indicates that the page is mapped with the same semantics
- * in both guest and host.
- */
-#define PAGE_PASSTHROUGH 0x0800
-
#endif
diff --git a/include/hw/intc/loongarch_pic_common.h b/include/hw/intc/loongarch_pic_common.h
index f774c97..675ba96 100644
--- a/include/hw/intc/loongarch_pic_common.h
+++ b/include/hw/intc/loongarch_pic_common.h
@@ -7,7 +7,7 @@
#ifndef HW_LOONGARCH_PIC_COMMON_H
#define HW_LOONGARCH_PIC_COMMON_H
-#include "hw/pci-host/ls7a.h"
+#include "hw/loongarch/virt.h"
#include "hw/sysbus.h"
#define PCH_PIC_INT_ID 0x00
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 76fa57c..27b1755 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -13,49 +13,84 @@
#include "hw/block/flash.h"
#include "hw/loongarch/boot.h"
-#define IOCSRF_TEMP 0
-#define IOCSRF_NODECNT 1
-#define IOCSRF_MSI 2
-#define IOCSRF_EXTIOI 3
-#define IOCSRF_CSRIPI 4
-#define IOCSRF_FREQCSR 5
-#define IOCSRF_FREQSCALE 6
-#define IOCSRF_DVFSV1 7
-#define IOCSRF_GMOD 9
-#define IOCSRF_VM 11
-#define IOCSRF_DMSI 15
-
+/* IOCSR region */
#define VERSION_REG 0x0
#define FEATURE_REG 0x8
+#define IOCSRF_TEMP 0
+#define IOCSRF_NODECNT 1
+#define IOCSRF_MSI 2
+#define IOCSRF_EXTIOI 3
+#define IOCSRF_CSRIPI 4
+#define IOCSRF_FREQCSR 5
+#define IOCSRF_FREQSCALE 6
+#define IOCSRF_DVFSV1 7
+#define IOCSRF_GMOD 9
+#define IOCSRF_VM 11
+#define IOCSRF_DMSI 15
#define VENDOR_REG 0x10
#define CPUNAME_REG 0x20
#define MISC_FUNC_REG 0x420
-#define IOCSRM_EXTIOI_EN 48
-#define IOCSRM_EXTIOI_INT_ENCODE 49
-#define IOCSRM_DMSI_EN 51
+#define IOCSRM_EXTIOI_EN 48
+#define IOCSRM_EXTIOI_INT_ENCODE 49
+#define IOCSRM_DMSI_EN 51
#define LOONGARCH_MAX_CPUS 256
-#define VIRT_FWCFG_BASE 0x1e020000UL
+/* MMIO memory region */
+#define VIRT_PCH_REG_BASE 0x10000000UL
+#define VIRT_PCH_REG_SIZE 0x400
+#define VIRT_RTC_REG_BASE 0x100d0100UL
+#define VIRT_RTC_LEN 0x100
+#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000UL
+#define VIRT_PLATFORM_BUS_SIZE 0x02000000
+#define VIRT_PCI_IO_BASE 0x18004000UL
+#define VIRT_PCI_IO_OFFSET 0x4000
+#define VIRT_PCI_IO_SIZE 0xC000
#define VIRT_BIOS_BASE 0x1c000000UL
-#define VIRT_BIOS_SIZE (16 * MiB)
+#define VIRT_BIOS_SIZE 0x01000000UL
#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
#define VIRT_FLASH0_BASE VIRT_BIOS_BASE
#define VIRT_FLASH0_SIZE VIRT_BIOS_SIZE
#define VIRT_FLASH1_BASE 0x1d000000UL
-#define VIRT_FLASH1_SIZE (16 * MiB)
+#define VIRT_FLASH1_SIZE 0x01000000UL
+#define VIRT_FWCFG_BASE 0x1e020000UL
+#define VIRT_UART_BASE 0x1fe001e0UL
+#define VIRT_UART_SIZE 0x100
+#define VIRT_PCI_CFG_BASE 0x20000000UL
+#define VIRT_PCI_CFG_SIZE 0x08000000UL
+#define VIRT_DINTC_BASE 0x2FE00000UL
+#define VIRT_DINTC_SIZE 0x00100000UL
+#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL
+#define VIRT_PCH_MSI_SIZE 0x8
+#define VIRT_PCI_MEM_BASE 0x40000000UL
+#define VIRT_PCI_MEM_SIZE 0x40000000UL
#define VIRT_LOWMEM_BASE 0
#define VIRT_LOWMEM_SIZE 0x10000000
+#define FDT_BASE 0x100000
#define VIRT_HIGHMEM_BASE 0x80000000
#define VIRT_GED_EVT_ADDR 0x100e0000
#define VIRT_GED_MEM_ADDR QEMU_ALIGN_UP(VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN, 4)
#define VIRT_GED_REG_ADDR QEMU_ALIGN_UP(VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN, 4)
#define VIRT_GED_CPUHP_ADDR QEMU_ALIGN_UP(VIRT_GED_REG_ADDR + ACPI_GED_REG_COUNT, 4)
-#define COMMAND_LINE_SIZE 512
+/*
+ * GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot
+ * 0 - 15 GSI for ISA devices even if there is no ISA devices
+ * 16 - 63 GSI for CPU devices such as timers/perf monitor etc
+ * 64 - GSI for external devices
+ */
+#define VIRT_PCH_PIC_IRQ_NUM 32
+#define VIRT_GSI_BASE 64
+#define VIRT_DEVICE_IRQS 16
+#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2)
+#define VIRT_UART_COUNT 4
+#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 6)
+#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 7)
+#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 8)
+#define VIRT_PLATFORM_BUS_NUM_IRQS 2
-#define FDT_BASE 0x100000
+#define COMMAND_LINE_SIZE 512
struct LoongArchVirtMachineState {
/*< private >*/
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
index bfdbfe3..33e7942 100644
--- a/include/hw/pci-host/ls7a.h
+++ b/include/hw/pci-host/ls7a.h
@@ -13,43 +13,4 @@
#include "qemu/range.h"
#include "qom/object.h"
-#define VIRT_PCI_MEM_BASE 0x40000000UL
-#define VIRT_PCI_MEM_SIZE 0x40000000UL
-#define VIRT_PCI_IO_OFFSET 0x4000
-#define VIRT_PCI_CFG_BASE 0x20000000
-#define VIRT_PCI_CFG_SIZE 0x08000000
-#define VIRT_PCI_IO_BASE 0x18004000UL
-#define VIRT_PCI_IO_SIZE 0xC000
-
-#define VIRT_PCH_REG_BASE 0x10000000UL
-#define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE)
-#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL
-#define VIRT_DINTC_SIZE 0x100000UL
-#define VIRT_DINTC_BASE 0x2FE00000UL
-#define VIRT_PCH_REG_SIZE 0x400
-#define VIRT_PCH_MSI_SIZE 0x8
-
-/*
- * GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot
- * 0 - 15 GSI for ISA devices even if there is no ISA devices
- * 16 - 63 GSI for CPU devices such as timers/perf monitor etc
- * 64 - GSI for external devices
- */
-#define VIRT_PCH_PIC_IRQ_NUM 32
-#define VIRT_GSI_BASE 64
-#define VIRT_DEVICE_IRQS 16
-#define VIRT_UART_COUNT 4
-#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2)
-#define VIRT_UART_BASE 0x1fe001e0
-#define VIRT_UART_SIZE 0x100
-#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 6)
-#define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000)
-#define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100)
-#define VIRT_RTC_LEN 0x100
-#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 7)
-
-#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000
-#define VIRT_PLATFORM_BUS_SIZE 0x2000000
-#define VIRT_PLATFORM_BUS_NUM_IRQS 2
-#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 8)
#endif
diff --git a/include/user/page-protection.h b/include/user/page-protection.h
index 4bde664..41b23e7 100644
--- a/include/user/page-protection.h
+++ b/include/user/page-protection.h
@@ -23,14 +23,19 @@ int page_get_flags(vaddr address);
* page_set_flags:
* @start: first byte of range
* @last: last byte of range
- * @flags: flags to set
+ * @set_flags: flags to set
+ * @clr_flags: flags to clear
* Context: holding mmap lock
*
* Modify the flags of a page and invalidate the code if necessary.
* The flag PAGE_WRITE_ORG is positioned automatically depending
* on PAGE_WRITE. The mmap_lock should already be held.
+ *
+ * For each page, flags = (flags & ~clr_flags) | set_flags.
+ * If clr_flags includes PAGE_VALID, this indicates a new mapping
+ * and page_reset_target_data will be called as well.
*/
-void page_set_flags(vaddr start, vaddr last, int flags);
+void page_set_flags(vaddr start, vaddr last, int set_flags, int clr_flags);
void page_reset_target_data(vaddr start, vaddr last);
diff --git a/linux-user/arm/elfload.c b/linux-user/arm/elfload.c
index b1a4db4..fef6102 100644
--- a/linux-user/arm/elfload.c
+++ b/linux-user/arm/elfload.c
@@ -243,7 +243,7 @@ bool init_guest_commpage(void)
}
page_set_flags(commpage, commpage | (host_page_size - 1),
- PAGE_READ | PAGE_EXEC | PAGE_VALID);
+ PAGE_READ | PAGE_EXEC | PAGE_VALID, PAGE_VALID);
return true;
}
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 1370ec5..0002d5b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2127,8 +2127,8 @@ static void bswap_note(struct elf_note *en)
*/
static size_t vma_dump_size(vaddr start, vaddr end, int flags)
{
- /* The area must be readable. */
- if (!(flags & PAGE_READ)) {
+ /* The area must be readable and dumpable. */
+ if (!(flags & PAGE_READ) || (flags & PAGE_DONTDUMP)) {
return 0;
}
diff --git a/linux-user/hppa/elfload.c b/linux-user/hppa/elfload.c
index 018034f..4600708 100644
--- a/linux-user/hppa/elfload.c
+++ b/linux-user/hppa/elfload.c
@@ -42,6 +42,6 @@ bool init_guest_commpage(void)
* Special case the entry points during translation (see do_page_zero).
*/
page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
- PAGE_EXEC | PAGE_VALID);
+ PAGE_EXEC | PAGE_VALID, PAGE_VALID);
return true;
}
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 847092a..423c778 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -165,6 +165,13 @@ static int target_to_host_prot(int prot)
(prot & PROT_EXEC ? PROT_READ : 0);
}
+/* Target bits to be cleared by mprotect if not present in target_prot. */
+#ifdef TARGET_AARCH64
+#define TARGET_PAGE_NOTSTICKY PAGE_BTI
+#else
+#define TARGET_PAGE_NOTSTICKY 0
+#endif
+
/* NOTE: all the constants are the HOST ones, but addresses are target. */
int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
{
@@ -262,7 +269,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
}
}
- page_set_flags(start, last, page_flags);
+ page_set_flags(start, last, page_flags, PAGE_RWX | TARGET_PAGE_NOTSTICKY);
ret = 0;
error:
@@ -561,17 +568,17 @@ static abi_long mmap_end(abi_ulong start, abi_ulong last,
if (flags & MAP_ANONYMOUS) {
page_flags |= PAGE_ANON;
}
- page_flags |= PAGE_RESET;
if (passthrough_start > passthrough_last) {
- page_set_flags(start, last, page_flags);
+ page_set_flags(start, last, page_flags, PAGE_VALID);
} else {
if (start < passthrough_start) {
- page_set_flags(start, passthrough_start - 1, page_flags);
+ page_set_flags(start, passthrough_start - 1,
+ page_flags, PAGE_VALID);
}
page_set_flags(passthrough_start, passthrough_last,
- page_flags | PAGE_PASSTHROUGH);
+ page_flags | PAGE_PASSTHROUGH, PAGE_VALID);
if (passthrough_last < last) {
- page_set_flags(passthrough_last + 1, last, page_flags);
+ page_set_flags(passthrough_last + 1, last, page_flags, PAGE_VALID);
}
}
shm_region_rm_complete(start, last);
@@ -1088,7 +1095,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
mmap_lock();
ret = mmap_reserve_or_unmap(start, len);
if (likely(ret == 0)) {
- page_set_flags(start, start + len - 1, 0);
+ page_set_flags(start, start + len - 1, 0, PAGE_VALID);
shm_region_rm_complete(start, start + len - 1);
}
mmap_unlock();
@@ -1179,10 +1186,10 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
} else {
new_addr = h2g(host_addr);
prot = page_get_flags(old_addr);
- page_set_flags(old_addr, old_addr + old_size - 1, 0);
+ page_set_flags(old_addr, old_addr + old_size - 1, 0, PAGE_VALID);
shm_region_rm_complete(old_addr, old_addr + old_size - 1);
page_set_flags(new_addr, new_addr + new_size - 1,
- prot | PAGE_VALID | PAGE_RESET);
+ prot | PAGE_VALID, PAGE_VALID);
shm_region_rm_complete(new_addr, new_addr + new_size - 1);
}
mmap_unlock();
@@ -1241,6 +1248,12 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
*/
mmap_lock();
switch (advice) {
+ case MADV_DONTDUMP:
+ page_set_flags(start, start + len - 1, PAGE_DONTDUMP, 0);
+ break;
+ case MADV_DODUMP:
+ page_set_flags(start, start + len - 1, 0, PAGE_DONTDUMP);
+ break;
case MADV_WIPEONFORK:
case MADV_KEEPONFORK:
ret = -EINVAL;
@@ -1428,9 +1441,10 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
last = shmaddr + m_len - 1;
page_set_flags(shmaddr, last,
- PAGE_VALID | PAGE_RESET | PAGE_READ |
+ PAGE_VALID | PAGE_READ |
(shmflg & SHM_RDONLY ? 0 : PAGE_WRITE) |
- (shmflg & SHM_EXEC ? PAGE_EXEC : 0));
+ (shmflg & SHM_EXEC ? PAGE_EXEC : 0),
+ PAGE_VALID);
shm_region_rm_complete(shmaddr, last);
shm_region_add(shmaddr, last);
@@ -1471,7 +1485,7 @@ abi_long target_shmdt(abi_ulong shmaddr)
if (rv == 0) {
abi_ulong size = last - shmaddr + 1;
- page_set_flags(shmaddr, last, 0);
+ page_set_flags(shmaddr, last, 0, PAGE_VALID);
shm_region_rm_complete(shmaddr, last);
mmap_reserve_or_unmap(shmaddr, size);
}
diff --git a/linux-user/x86_64/elfload.c b/linux-user/x86_64/elfload.c
index 1e7000c..5914f76 100644
--- a/linux-user/x86_64/elfload.c
+++ b/linux-user/x86_64/elfload.c
@@ -37,7 +37,7 @@ bool init_guest_commpage(void)
}
page_set_flags(TARGET_VSYSCALL_PAGE,
TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK,
- PAGE_EXEC | PAGE_VALID);
+ PAGE_EXEC | PAGE_VALID, PAGE_VALID);
return true;
}
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1d4e133..bf221e6 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2642,7 +2642,6 @@ extern const uint64_t pred_esz_masks[5];
*/
#define PAGE_BTI PAGE_TARGET_1
#define PAGE_MTE PAGE_TARGET_2
-#define PAGE_TARGET_STICKY PAGE_MTE
/* We associate one allocation tag per 16 bytes, the minimum. */
#define LOG2_TAG_GRANULE 4
diff --git a/target/loongarch/tcg/tlb_helper.c b/target/loongarch/tcg/tlb_helper.c
index 8cfce48..f1d183c 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -117,13 +117,7 @@ static void invalidate_tlb_entry(CPULoongArchState *env, int index)
uint8_t tlb_v0 = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, V);
uint8_t tlb_v1 = FIELD_EX64(tlb->tlb_entry1, TLBENTRY, V);
uint64_t tlb_vppn = FIELD_EX64(tlb->tlb_misc, TLB_MISC, VPPN);
- uint8_t tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
- if (!tlb_e) {
- return;
- }
-
- tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
tlb_ps = FIELD_EX64(tlb->tlb_misc, TLB_MISC, PS);
pagesize = MAKE_64BIT_MASK(tlb_ps, 1);
mask = MAKE_64BIT_MASK(0, tlb_ps + 1);
@@ -145,11 +139,19 @@ static void invalidate_tlb(CPULoongArchState *env, int index)
{
LoongArchTLB *tlb;
uint16_t csr_asid, tlb_asid, tlb_g;
+ uint8_t tlb_e;
csr_asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
tlb = &env->tlb[index];
+ tlb_e = FIELD_EX64(tlb->tlb_misc, TLB_MISC, E);
+ if (!tlb_e) {
+ return;
+ }
+
+ tlb->tlb_misc = FIELD_DP64(tlb->tlb_misc, TLB_MISC, E, 0);
tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
+ /* QEMU TLB is flushed when asid is changed */
if (tlb_g == 0 && tlb_asid != csr_asid) {
return;
}
@@ -369,7 +371,7 @@ void helper_tlbfill(CPULoongArchState *env)
uint16_t pagesize, stlb_ps;
uint16_t asid, tlb_asid;
LoongArchTLB *tlb;
- uint8_t tlb_e;
+ uint8_t tlb_e, tlb_g;
if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) {
entryhi = env->CSR_TLBREHI;
@@ -398,7 +400,8 @@ void helper_tlbfill(CPULoongArchState *env)
}
tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
- if (asid != tlb_asid) {
+ tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
+ if (tlb_g == 0 && asid != tlb_asid) {
set = i;
}
}
@@ -421,7 +424,8 @@ void helper_tlbfill(CPULoongArchState *env)
}
tlb_asid = FIELD_EX64(tlb->tlb_misc, TLB_MISC, ASID);
- if (asid != tlb_asid) {
+ tlb_g = FIELD_EX64(tlb->tlb_entry0, TLBENTRY, G);
+ if (tlb_g == 0 && asid != tlb_asid) {
index = i;
}
}