target-arm queue:

* raspi: add model of cprman clock manager
  * sbsa-ref: add an SBSA generic watchdog device
  * arm/trace: Fix hex printing
  * raspi: Add models of Pi 3 model A+, Pi Zero and Pi A+
  * hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 explicitly
  * Nuvoton NPCM7xx: Add USB, RNG, GPIO and watchdog support
  * hw/arm: fix min_cpus for xlnx-versal-virt platform
  * hw/arm/highbank: Silence warnings about missing fallthrough statements
  * linux-user: Support Aarch64 BTI
  * Armv7M systick: fix corner case bugs by rewriting to use ptimer
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl+YBA4ZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3rWRD/9hqjzL4d7xKcFQdQdRXsxv
 7zX82arHdxg9pNvusie/tuhX0PLswQ8TPEHEBVQvngxF7y/HqLBFuZAQvFf4ou6R
 9+myTXE2RuWHOYKlrr/M6p4csABXNMm7PiA3VMeKcTEh4DoamLyBz6j1X4obPiA+
 tLaRw4azzYAZnHoCaF6BX+4uf4bQZoqAtAS4IodJAAbDXJStl0VUFoS34MPhgW6/
 dwGF8DbQJVYRqa7xEXck4Yx7dkx13I66+iYUf9kCyoCkdyz1sIq58fbKhXQP4lqN
 I3e5XGBVJfeku7w/TGOpsw8OCyTng0z636iglfLVOrsj5N03fT8j72ehY7jJsN9f
 CgHvQ1JAX1DvA/v23oxs3WccwAOfJJsOERtf9QxyMbTR1czCeIY1LYMnkOFtyL87
 6IQpwM0WF1z4lja0dmrvhKJWjqn+kVI2cDtxrprsulCHi+pcIdJMq8vJDfxjpqqe
 SnDXVSAn8KjBrClaJRqHfbi+5ggsTwsLpBtEToQ4AOR342XVRfEY8IfTLb1D2+6q
 z99BFiyJtZ6iiJq5jgGMhppN6tEuHFK7Vr6IwhGDgFTchWb6by+K3i8/VzrbWVk9
 O+KEeO92dg6jVd+6FyXOPnJ3DcUXEp6EVUVrKBBUC+LTU8Lf1MCgeprjSi87UHIX
 xQg635uOQU3gxkqxCaE0XA==
 =OFlu
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20201027-1' into staging

target-arm queue:
 * raspi: add model of cprman clock manager
 * sbsa-ref: add an SBSA generic watchdog device
 * arm/trace: Fix hex printing
 * raspi: Add models of Pi 3 model A+, Pi Zero and Pi A+
 * hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 explicitly
 * Nuvoton NPCM7xx: Add USB, RNG, GPIO and watchdog support
 * hw/arm: fix min_cpus for xlnx-versal-virt platform
 * hw/arm/highbank: Silence warnings about missing fallthrough statements
 * linux-user: Support Aarch64 BTI
 * Armv7M systick: fix corner case bugs by rewriting to use ptimer

# gpg: Signature made Tue 27 Oct 2020 11:27:10 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20201027-1: (48 commits)
  hw/timer/armv7m_systick: Rewrite to use ptimers
  hw/core/ptimer: Support ptimer being disabled by timer callback
  hw/arm/sbsa-ref: add SBSA watchdog device
  hw/watchdog: Implement SBSA watchdog device
  hw/arm/bcm2835_peripherals: connect the UART clock
  hw/char/pl011: add a clock input
  hw/misc/bcm2835_cprman: add sane reset values to the registers
  hw/misc/bcm2835_cprman: add the DSI0HSCK multiplexer
  hw/misc/bcm2835_cprman: implement clock mux behaviour
  hw/misc/bcm2835_cprman: add a clock mux skeleton implementation
  hw/misc/bcm2835_cprman: implement PLL channels behaviour
  hw/misc/bcm2835_cprman: add a PLL channel skeleton implementation
  hw/misc/bcm2835_cprman: implement PLLs behaviour
  hw/misc/bcm2835_cprman: add a PLL skeleton implementation
  hw/arm/raspi: add a skeleton implementation of the CPRMAN
  hw/arm/raspi: fix CPRMAN base address
  hw/core/clock: trace clock values in Hz instead of ns
  hw/core/clock: provide the VMSTATE_ARRAY_CLOCK macro
  arm/trace: Fix hex printing
  hw/arm/raspi: Add the Raspberry Pi 3 model A+
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-10-29 11:40:04 +00:00
commit 802427bcda
64 changed files with 5461 additions and 279 deletions

View file

@ -506,10 +506,16 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
+ offsetof(struct target_rt_frame_record, tramp);
}
env->xregs[0] = usig;
env->xregs[31] = frame_addr;
env->xregs[29] = frame_addr + fr_ofs;
env->pc = ka->_sa_handler;
env->xregs[30] = return_addr;
env->xregs[31] = frame_addr;
env->pc = ka->_sa_handler;
/* Invoke the signal handler as if by indirect call. */
if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
env->btype = 2;
}
if (info) {
tswap_siginfo(&frame->info, info);
env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);

View file

@ -12,6 +12,7 @@
#include "qemu/guest-random.h"
#include "qemu/units.h"
#include "qemu/selfmap.h"
#include "qapi/error.h"
#ifdef _ARCH_PPC64
#undef ARCH_DLINFO
@ -1521,6 +1522,39 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
#include "elf.h"
/* We must delay the following stanzas until after "elf.h". */
#if defined(TARGET_AARCH64)
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
const uint32_t *data,
struct image_info *info,
Error **errp)
{
if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
if (pr_datasz != sizeof(uint32_t)) {
error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
return false;
}
/* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
info->note_flags = *data;
}
return true;
}
#define ARCH_USE_GNU_PROPERTY 1
#else
static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
const uint32_t *data,
struct image_info *info,
Error **errp)
{
g_assert_not_reached();
}
#define ARCH_USE_GNU_PROPERTY 0
#endif
struct exec
{
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
@ -2372,6 +2406,150 @@ void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
"@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
}
enum {
/* The string "GNU\0" as a magic number. */
GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
NOTE_DATA_SZ = 1 * KiB,
NOTE_NAME_SZ = 4,
ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
};
/*
* Process a single gnu_property entry.
* Return false for error.
*/
static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
struct image_info *info, bool have_prev_type,
uint32_t *prev_type, Error **errp)
{
uint32_t pr_type, pr_datasz, step;
if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
goto error_data;
}
datasz -= *off;
data += *off / sizeof(uint32_t);
if (datasz < 2 * sizeof(uint32_t)) {
goto error_data;
}
pr_type = data[0];
pr_datasz = data[1];
data += 2;
datasz -= 2 * sizeof(uint32_t);
step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
if (step > datasz) {
goto error_data;
}
/* Properties are supposed to be unique and sorted on pr_type. */
if (have_prev_type && pr_type <= *prev_type) {
if (pr_type == *prev_type) {
error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
} else {
error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
}
return false;
}
*prev_type = pr_type;
if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
return false;
}
*off += 2 * sizeof(uint32_t) + step;
return true;
error_data:
error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
return false;
}
/* Process NT_GNU_PROPERTY_TYPE_0. */
static bool parse_elf_properties(int image_fd,
struct image_info *info,
const struct elf_phdr *phdr,
char bprm_buf[BPRM_BUF_SIZE],
Error **errp)
{
union {
struct elf_note nhdr;
uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
} note;
int n, off, datasz;
bool have_prev_type;
uint32_t prev_type;
/* Unless the arch requires properties, ignore them. */
if (!ARCH_USE_GNU_PROPERTY) {
return true;
}
/* If the properties are crazy large, that's too bad. */
n = phdr->p_filesz;
if (n > sizeof(note)) {
error_setg(errp, "PT_GNU_PROPERTY too large");
return false;
}
if (n < sizeof(note.nhdr)) {
error_setg(errp, "PT_GNU_PROPERTY too small");
return false;
}
if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
memcpy(&note, bprm_buf + phdr->p_offset, n);
} else {
ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
if (len != n) {
error_setg_errno(errp, errno, "Error reading file header");
return false;
}
}
/*
* The contents of a valid PT_GNU_PROPERTY is a sequence
* of uint32_t -- swap them all now.
*/
#ifdef BSWAP_NEEDED
for (int i = 0; i < n / 4; i++) {
bswap32s(note.data + i);
}
#endif
/*
* Note that nhdr is 3 words, and that the "name" described by namesz
* immediately follows nhdr and is thus at the 4th word. Further, all
* of the inputs to the kernel's round_up are multiples of 4.
*/
if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
note.nhdr.n_namesz != NOTE_NAME_SZ ||
note.data[3] != GNU0_MAGIC) {
error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
return false;
}
off = sizeof(note.nhdr) + NOTE_NAME_SZ;
datasz = note.nhdr.n_descsz + off;
if (datasz > n) {
error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
return false;
}
have_prev_type = false;
prev_type = 0;
while (1) {
if (off == datasz) {
return true; /* end, exit ok */
}
if (!parse_elf_property(note.data, &off, datasz, info,
have_prev_type, &prev_type, errp)) {
return false;
}
have_prev_type = true;
}
}
/* Load an ELF image into the address space.
IMAGE_NAME is the filename of the image, to use in error messages.
@ -2391,16 +2569,17 @@ static void load_elf_image(const char *image_name, int image_fd,
struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
struct elf_phdr *phdr;
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
int i, retval;
const char *errmsg;
int i, retval, prot_exec;
Error *err = NULL;
/* First of all, some simple consistency checks */
errmsg = "Invalid ELF image for this architecture";
if (!elf_check_ident(ehdr)) {
error_setg(&err, "Invalid ELF image for this architecture");
goto exit_errmsg;
}
bswap_ehdr(ehdr);
if (!elf_check_ehdr(ehdr)) {
error_setg(&err, "Invalid ELF image for this architecture");
goto exit_errmsg;
}
@ -2421,22 +2600,54 @@ static void load_elf_image(const char *image_name, int image_fd,
mmap_lock();
/* Find the maximum size of the image and allocate an appropriate
amount of memory to handle that. */
/*
* Find the maximum size of the image and allocate an appropriate
* amount of memory to handle that. Locate the interpreter, if any.
*/
loaddr = -1, hiaddr = 0;
info->alignment = 0;
for (i = 0; i < ehdr->e_phnum; ++i) {
if (phdr[i].p_type == PT_LOAD) {
abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
struct elf_phdr *eppnt = phdr + i;
if (eppnt->p_type == PT_LOAD) {
abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
if (a < loaddr) {
loaddr = a;
}
a = phdr[i].p_vaddr + phdr[i].p_memsz;
a = eppnt->p_vaddr + eppnt->p_memsz;
if (a > hiaddr) {
hiaddr = a;
}
++info->nsegs;
info->alignment |= phdr[i].p_align;
info->alignment |= eppnt->p_align;
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
g_autofree char *interp_name = NULL;
if (*pinterp_name) {
error_setg(&err, "Multiple PT_INTERP entries");
goto exit_errmsg;
}
interp_name = g_malloc(eppnt->p_filesz);
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
memcpy(interp_name, bprm_buf + eppnt->p_offset,
eppnt->p_filesz);
} else {
retval = pread(image_fd, interp_name, eppnt->p_filesz,
eppnt->p_offset);
if (retval != eppnt->p_filesz) {
goto exit_read;
}
}
if (interp_name[eppnt->p_filesz - 1] != 0) {
error_setg(&err, "Invalid PT_INTERP entry");
goto exit_errmsg;
}
*pinterp_name = g_steal_pointer(&interp_name);
} else if (eppnt->p_type == PT_GNU_PROPERTY) {
if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
goto exit_errmsg;
}
}
}
@ -2490,7 +2701,7 @@ static void load_elf_image(const char *image_name, int image_fd,
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
-1, 0);
if (load_addr == -1) {
goto exit_perror;
goto exit_mmap;
}
load_bias = load_addr - loaddr;
@ -2525,15 +2736,41 @@ static void load_elf_image(const char *image_name, int image_fd,
info->brk = 0;
info->elf_flags = ehdr->e_flags;
prot_exec = PROT_EXEC;
#ifdef TARGET_AARCH64
/*
* If the BTI feature is present, this indicates that the executable
* pages of the startup binary should be mapped with PROT_BTI, so that
* branch targets are enforced.
*
* The startup binary is either the interpreter or the static executable.
* The interpreter is responsible for all pages of a dynamic executable.
*
* Elf notes are backward compatible to older cpus.
* Do not enable BTI unless it is supported.
*/
if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
&& (pinterp_name == NULL || *pinterp_name == 0)
&& cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
prot_exec |= TARGET_PROT_BTI;
}
#endif
for (i = 0; i < ehdr->e_phnum; i++) {
struct elf_phdr *eppnt = phdr + i;
if (eppnt->p_type == PT_LOAD) {
abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
int elf_prot = 0;
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
if (eppnt->p_flags & PF_R) {
elf_prot |= PROT_READ;
}
if (eppnt->p_flags & PF_W) {
elf_prot |= PROT_WRITE;
}
if (eppnt->p_flags & PF_X) {
elf_prot |= prot_exec;
}
vaddr = load_bias + eppnt->p_vaddr;
vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
@ -2551,7 +2788,7 @@ static void load_elf_image(const char *image_name, int image_fd,
image_fd, eppnt->p_offset - vaddr_po);
if (error == -1) {
goto exit_perror;
goto exit_mmap;
}
}
@ -2583,38 +2820,11 @@ static void load_elf_image(const char *image_name, int image_fd,
if (vaddr_em > info->brk) {
info->brk = vaddr_em;
}
} else if (eppnt->p_type == PT_INTERP && pinterp_name) {
char *interp_name;
if (*pinterp_name) {
errmsg = "Multiple PT_INTERP entries";
goto exit_errmsg;
}
interp_name = malloc(eppnt->p_filesz);
if (!interp_name) {
goto exit_perror;
}
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
memcpy(interp_name, bprm_buf + eppnt->p_offset,
eppnt->p_filesz);
} else {
retval = pread(image_fd, interp_name, eppnt->p_filesz,
eppnt->p_offset);
if (retval != eppnt->p_filesz) {
goto exit_perror;
}
}
if (interp_name[eppnt->p_filesz - 1] != 0) {
errmsg = "Invalid PT_INTERP entry";
goto exit_errmsg;
}
*pinterp_name = interp_name;
#ifdef TARGET_MIPS
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
Mips_elf_abiflags_v0 abiflags;
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
goto exit_errmsg;
}
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
@ -2624,7 +2834,7 @@ static void load_elf_image(const char *image_name, int image_fd,
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
eppnt->p_offset);
if (retval != sizeof(Mips_elf_abiflags_v0)) {
goto exit_perror;
goto exit_read;
}
}
bswap_mips_abiflags(&abiflags);
@ -2649,13 +2859,16 @@ static void load_elf_image(const char *image_name, int image_fd,
exit_read:
if (retval >= 0) {
errmsg = "Incomplete read of file header";
goto exit_errmsg;
error_setg(&err, "Incomplete read of file header");
} else {
error_setg_errno(&err, errno, "Error reading file header");
}
exit_perror:
errmsg = strerror(errno);
goto exit_errmsg;
exit_mmap:
error_setg_errno(&err, errno, "Error mapping file");
goto exit_errmsg;
exit_errmsg:
fprintf(stderr, "%s: %s\n", image_name, errmsg);
error_reportf_err(err, "%s: ", image_name);
exit(-1);
}
@ -2663,26 +2876,27 @@ static void load_elf_interp(const char *filename, struct image_info *info,
char bprm_buf[BPRM_BUF_SIZE])
{
int fd, retval;
Error *err = NULL;
fd = open(path(filename), O_RDONLY);
if (fd < 0) {
goto exit_perror;
error_setg_file_open(&err, errno, filename);
error_report_err(err);
exit(-1);
}
retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
if (retval < 0) {
goto exit_perror;
error_setg_errno(&err, errno, "Error reading file header");
error_reportf_err(err, "%s: ", filename);
exit(-1);
}
if (retval < BPRM_BUF_SIZE) {
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
}
load_elf_image(filename, fd, info, NULL, bprm_buf);
return;
exit_perror:
fprintf(stderr, "%s: %s\n", filename, strerror(errno));
exit(-1);
}
static int symfind(const void *s0, const void *s1)
@ -2961,7 +3175,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
if (elf_interpreter) {
info->load_bias = interp_info.load_bias;
info->entry = interp_info.entry;
free(elf_interpreter);
g_free(elf_interpreter);
}
#ifdef USE_ELF_CORE_DUMP

View file

@ -83,6 +83,22 @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
*host_prot = (prot & (PROT_READ | PROT_WRITE))
| (prot & PROT_EXEC ? PROT_READ : 0);
#ifdef TARGET_AARCH64
/*
* The PROT_BTI bit is only accepted if the cpu supports the feature.
* Since this is the unusual case, don't bother checking unless
* the bit has been requested. If set and valid, record the bit
* within QEMU's page_flags.
*/
if (prot & TARGET_PROT_BTI) {
ARMCPU *cpu = ARM_CPU(thread_cpu);
if (cpu_isar_feature(aa64_bti, cpu)) {
valid |= TARGET_PROT_BTI;
page_flags |= PAGE_BTI;
}
}
#endif
return prot & ~valid ? 0 : page_flags;
}

View file

@ -61,6 +61,10 @@ struct image_info {
abi_ulong interpreter_loadmap_addr;
abi_ulong interpreter_pt_dynamic_addr;
struct image_info *other_info;
/* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
uint32_t note_flags;
#ifdef TARGET_MIPS
int fp_abi;
int interp_fp_abi;

View file

@ -1277,6 +1277,10 @@ struct target_winsize {
#define TARGET_PROT_SEM 0x08
#endif
#ifdef TARGET_AARCH64
#define TARGET_PROT_BTI 0x10
#endif
/* Common */
#define TARGET_MAP_SHARED 0x01 /* Share changes */
#define TARGET_MAP_PRIVATE 0x02 /* Changes are private */