1 | Hi, | 1 | From: Aleksandar Markovic <amarkovic@wavecomp.com> |
---|---|---|---|
2 | 2 | ||
3 | This new version removed the translate_fn() from patch 1 because it | 3 | This is a collection of misc patches for Linux user that I recently |
4 | wasn't removing the sign-extension for pentry as we thought it would. | 4 | accumulated from variuous sources. All of them originate from problems |
5 | A more detailed explanation is given in the commit msg of patch 1. | 5 | observed on mips target. However, most of these changes actually |
6 | affect and fix linux-user problems on multiple targets. | ||
6 | 7 | ||
7 | We're now retrieving the 'lowaddr' value from load_elf_ram_sym() and | 8 | There are three checkpatch warninhs and two checkpatch errors that |
8 | using it when we're running a 32-bit CPU. This worked with 32 bit | 9 | sould be ignored in the given circumstances. |
9 | 'virt' machine booting with the -kernel option. | ||
10 | 10 | ||
11 | If this approach doesn't work for the Xvisor use case, IMO we should | 11 | v11->v12: |
12 | just filter kernel_load_addr bits directly as we were doing a handful of | ||
13 | versions ago. | ||
14 | 12 | ||
15 | Patches are based on current riscv-to-apply.next. | 13 | - used the preffered Laurent's email address for linux-user |
14 | - added a note on checkpetch warnings and errors in the commit letter | ||
15 | |||
16 | 16 | ||
17 | Changes from v9: | 17 | v10->v11: |
18 | - patch 1: | ||
19 | - removed the translate_fn() callback | ||
20 | - return 'kernel_low' when running a 32-bit CPU | ||
21 | - v9 link: https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg04509.html | ||
22 | 18 | ||
23 | Daniel Henrique Barboza (3): | 19 | - patch on <ADD|DROP>_MEMEBERSHIP basically reverted to its first |
24 | hw/riscv: handle 32 bit CPUs kernel_addr in riscv_load_kernel() | 20 | version |
25 | hw/riscv/boot.c: consolidate all kernel init in riscv_load_kernel() | 21 | - corrected patch on statx() |
26 | hw/riscv/boot.c: make riscv_load_initrd() static | 22 | - added patch on strace support for statx() |
23 | - added patch on fixing flock structure for MIPS O64 ABI | ||
27 | 24 | ||
28 | hw/riscv/boot.c | 96 +++++++++++++++++++++++--------------- | 25 | v9->v10: |
29 | hw/riscv/microchip_pfsoc.c | 12 +---- | 26 | |
30 | hw/riscv/opentitan.c | 4 +- | 27 | - improved commit messages for patches 2 and 3 |
31 | hw/riscv/sifive_e.c | 4 +- | 28 | |
32 | hw/riscv/sifive_u.c | 12 +---- | 29 | v8->v9: |
33 | hw/riscv/spike.c | 14 ++---- | 30 | |
34 | hw/riscv/virt.c | 12 +---- | 31 | - fixed build error on some systems related to SOL_ALG |
35 | include/hw/riscv/boot.h | 3 +- | 32 | |
36 | 8 files changed, 76 insertions(+), 81 deletions(-) | 33 | v7->v8: |
34 | |||
35 | - added a patch on setsockopt() option SOL_ALG | ||
36 | |||
37 | v6->v7: | ||
38 | |||
39 | - fixed a build error for older kernels related to the patch on | ||
40 | setsockopt() options | ||
41 | - removed four patches that on the meantime got accepted into the | ||
42 | main source tree | ||
43 | |||
44 | v5->v6: | ||
45 | |||
46 | - fixed a mistake in patch #4 | ||
47 | - improved commit messages in patches #4 and #6 | ||
48 | |||
49 | v4->v5: | ||
50 | |||
51 | - added the patch on statx() support | ||
52 | - improved the patch on IPV6_<ADD|DROP>_MEMBERSHIP to take into | ||
53 | account the possibility of different names for a field | ||
54 | - minor corrections in commit messages | ||
55 | |||
56 | v3->v4: | ||
57 | |||
58 | - improved commit messages (fixed some typos, improved relevance) | ||
59 | |||
60 | v2->v3: | ||
61 | |||
62 | - updated and improved commit messages | ||
63 | - added IPV6_DROP_MEMBERSHIP support to the patch on setsockopt()'s | ||
64 | option | ||
65 | |||
66 | v1->v2: | ||
67 | |||
68 | - added the patch on setsockopt()'s option IPV6_ADD_MEMBERSHIP | ||
69 | - improved the commit messages | ||
70 | |||
71 | Aleksandar Markovic (1): | ||
72 | linux-user: Fix flock structure for MIPS O64 ABI | ||
73 | |||
74 | Aleksandar Rikalo (1): | ||
75 | linux-user: Add support for translation of statx() syscall | ||
76 | |||
77 | Jim Wilson (1): | ||
78 | linux-user: Add support for strace for statx() syscall | ||
79 | |||
80 | Neng Chen (1): | ||
81 | linux-user: Add support for setsockopt() options | ||
82 | IPV6_<ADD|DROP>_MEMBERSHIP | ||
83 | |||
84 | Yunqiang Su (1): | ||
85 | linux-user: Add support for setsockopt() option SOL_ALG | ||
86 | |||
87 | linux-user/generic/fcntl.h | 2 +- | ||
88 | linux-user/mips/target_fcntl.h | 4 + | ||
89 | linux-user/strace.c | 86 +++++++++++++++++++ | ||
90 | linux-user/strace.list | 3 + | ||
91 | linux-user/syscall.c | 186 ++++++++++++++++++++++++++++++++++++++++- | ||
92 | linux-user/syscall_defs.h | 37 ++++++++ | ||
93 | 6 files changed, 316 insertions(+), 2 deletions(-) | ||
37 | 94 | ||
38 | -- | 95 | -- |
39 | 2.39.1 | 96 | 2.7.4 |
97 | |||
98 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Neng Chen <nchen@wavecomp.com> | ||
1 | 2 | ||
3 | Add support for the option IPV6_<ADD|DROP>_MEMBERSHIP of the syscall | ||
4 | setsockopt(). This option controls membership in multicast groups. | ||
5 | Argument is a pointer to a struct ipv6_mreq. | ||
6 | |||
7 | The glibc <netinet/in.h> header defines the ipv6_mreq structure, | ||
8 | which includes the following members: | ||
9 | |||
10 | struct in6_addr ipv6mr_multiaddr; | ||
11 | unsigned int ipv6mr_interface; | ||
12 | |||
13 | Whereas the kernel in its <linux/in6.h> header defines following | ||
14 | members of the same structure: | ||
15 | |||
16 | struct in6_addr ipv6mr_multiaddr; | ||
17 | int ipv6mr_ifindex; | ||
18 | |||
19 | POSIX defines ipv6mr_interface [1]. | ||
20 | |||
21 | __UAPI_DEF_IVP6_MREQ appears in kernel headers with v3.12: | ||
22 | |||
23 | cfd280c91253 net: sync some IP headers with glibc | ||
24 | |||
25 | Without __UAPI_DEF_IVP6_MREQ, kernel defines ipv6mr_ifindex, and | ||
26 | this is explained in cfd280c91253: | ||
27 | |||
28 | "If you include the kernel headers first you get those, | ||
29 | and if you include the glibc headers first you get those, | ||
30 | and the following patch arranges a coordination and | ||
31 | synchronization between the two." | ||
32 | |||
33 | So before 3.12, a program can't include both <netinet/in.h> and | ||
34 | <linux/in6.h>. | ||
35 | |||
36 | In linux-user/syscall.c, we only include <netinet/in.h> (glibc) and | ||
37 | not <linux/in6.h> (kernel headers), so ipv6mr_interface is the one | ||
38 | to use. | ||
39 | |||
40 | [1] http://pubs.opengroup.org/onlinepubs/009695399/basedefs/netinet/in.h.html | ||
41 | |||
42 | Signed-off-by: Neng Chen <nchen@wavecomp.com> | ||
43 | Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> | ||
44 | --- | ||
45 | linux-user/syscall.c | 19 +++++++++++++++++++ | ||
46 | 1 file changed, 19 insertions(+) | ||
47 | |||
48 | diff --git a/linux-user/syscall.c b/linux-user/syscall.c | ||
49 | index XXXXXXX..XXXXXXX 100644 | ||
50 | --- a/linux-user/syscall.c | ||
51 | +++ b/linux-user/syscall.c | ||
52 | @@ -XXX,XX +XXX,XX @@ static abi_long do_setsockopt(int sockfd, int level, int optname, | ||
53 | &pki, sizeof(pki))); | ||
54 | break; | ||
55 | } | ||
56 | + case IPV6_ADD_MEMBERSHIP: | ||
57 | + case IPV6_DROP_MEMBERSHIP: | ||
58 | + { | ||
59 | + struct ipv6_mreq ipv6mreq; | ||
60 | + | ||
61 | + if (optlen < sizeof(ipv6mreq)) { | ||
62 | + return -TARGET_EINVAL; | ||
63 | + } | ||
64 | + | ||
65 | + if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) { | ||
66 | + return -TARGET_EFAULT; | ||
67 | + } | ||
68 | + | ||
69 | + ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface); | ||
70 | + | ||
71 | + ret = get_errno(setsockopt(sockfd, level, optname, | ||
72 | + &ipv6mreq, sizeof(ipv6mreq))); | ||
73 | + break; | ||
74 | + } | ||
75 | default: | ||
76 | goto unimplemented; | ||
77 | } | ||
78 | -- | ||
79 | 2.7.4 | ||
80 | |||
81 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Yunqiang Su <ysu@wavecomp.com> | ||
1 | 2 | ||
3 | Add support for options SOL_ALG of the syscall setsockopt(). This | ||
4 | option is used in relation to Linux kernel Crypto API, and allows | ||
5 | a user to set additional information for the cipher operation via | ||
6 | syscall setsockopt(). The field "optname" must be one of the | ||
7 | following: | ||
8 | |||
9 | - ALG_SET_KEY – seting the key | ||
10 | - ALG_SET_AEAD_AUTHSIZE – set the authentication tag size | ||
11 | |||
12 | SOL_ALG is relatively newer setsockopt() option. Therefore, the | ||
13 | code that handles SOL_ALG is enclosed in "ifdef" so that the build | ||
14 | does not fail for older kernels that do not contain support for | ||
15 | SOL_ALG. "ifdef" also contains check if ALG_SET_KEY and | ||
16 | ALG_SET_AEAD_AUTHSIZE are defined. | ||
17 | |||
18 | Signed-off-by: Yunqiang Su <ysu@wavecomp.com> | ||
19 | Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> | ||
20 | Reviewed-by: Laurent Vivier <laurent@vivier.eu> | ||
21 | --- | ||
22 | linux-user/syscall.c | 31 +++++++++++++++++++++++++++++++ | ||
23 | 1 file changed, 31 insertions(+) | ||
24 | |||
25 | diff --git a/linux-user/syscall.c b/linux-user/syscall.c | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/linux-user/syscall.c | ||
28 | +++ b/linux-user/syscall.c | ||
29 | @@ -XXX,XX +XXX,XX @@ | ||
30 | #include <linux/blkpg.h> | ||
31 | #include <netpacket/packet.h> | ||
32 | #include <linux/netlink.h> | ||
33 | +#include <linux/if_alg.h> | ||
34 | #include "linux_loop.h" | ||
35 | #include "uname.h" | ||
36 | |||
37 | @@ -XXX,XX +XXX,XX @@ static abi_long do_setsockopt(int sockfd, int level, int optname, | ||
38 | goto unimplemented; | ||
39 | } | ||
40 | break; | ||
41 | +#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE) | ||
42 | + case SOL_ALG: | ||
43 | + switch (optname) { | ||
44 | + case ALG_SET_KEY: | ||
45 | + { | ||
46 | + char *alg_key = g_malloc(optlen); | ||
47 | + | ||
48 | + if (!alg_key) { | ||
49 | + return -TARGET_ENOMEM; | ||
50 | + } | ||
51 | + if (copy_from_user(alg_key, optval_addr, optlen)) { | ||
52 | + g_free(alg_key); | ||
53 | + return -TARGET_EFAULT; | ||
54 | + } | ||
55 | + ret = get_errno(setsockopt(sockfd, level, optname, | ||
56 | + alg_key, optlen)); | ||
57 | + g_free(alg_key); | ||
58 | + break; | ||
59 | + } | ||
60 | + case ALG_SET_AEAD_AUTHSIZE: | ||
61 | + { | ||
62 | + ret = get_errno(setsockopt(sockfd, level, optname, | ||
63 | + NULL, optlen)); | ||
64 | + break; | ||
65 | + } | ||
66 | + default: | ||
67 | + goto unimplemented; | ||
68 | + } | ||
69 | + break; | ||
70 | +#endif | ||
71 | case TARGET_SOL_SOCKET: | ||
72 | switch (optname) { | ||
73 | case TARGET_SO_RCVTIMEO: | ||
74 | -- | ||
75 | 2.7.4 | ||
76 | |||
77 | diff view generated by jsdifflib |
1 | The microchip_icicle_kit, sifive_u, spike and virt boards are now doing | 1 | From: Aleksandar Rikalo <arikalo@wavecomp.com> |
---|---|---|---|
2 | the same steps when '-kernel' is used: | 2 | |
3 | 3 | Implement support for translation of system call statx(). | |
4 | - execute load_kernel() | 4 | |
5 | - load init_rd() | 5 | The implementation is based on "best effort" approach: if host is |
6 | - write kernel_cmdline | 6 | capable of executing statx(), host statx() is used. If not, the |
7 | 7 | implementation includes invoking other (more mature) system calls | |
8 | Let's fold everything inside riscv_load_kernel() to avoid code | 8 | (from the same 'stat' family) on the host side to achieve as close |
9 | repetition. To not change the behavior of boards that aren't calling | 9 | as possible functionality. |
10 | riscv_load_init(), add an 'load_initrd' flag to riscv_load_kernel() and | 10 | |
11 | allow these boards to opt out from initrd loading. | 11 | Support for statx() in kernel and glibc was, however, introduced |
12 | 12 | at different points of time (the difference is more than a year): | |
13 | Cc: Palmer Dabbelt <palmer@dabbelt.com> | 13 | |
14 | Reviewed-by: Bin Meng <bmeng@tinylab.org> | 14 | - kernel: Linux 4.11 (30 April 2017) |
15 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | 15 | - glibc: glibc 2.28 (1 Aug 2018) |
16 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | 16 | |
17 | In this patch, the availability of statx() support is established | ||
18 | via __NR_statx (if it is defined, statx() is considered available). | ||
19 | This coincedes with statx() introduction in kernel. | ||
20 | |||
21 | However, the structure statx definition may not be available for hosts | ||
22 | with glibc older than 2.28 (it is, by design, to be defined in one of | ||
23 | glibc headers), even though the full statx() functionality may be | ||
24 | supported in kernel, if the kernel is not older than 4.11. Hence, | ||
25 | a structure "target_statx" is defined in this patch, to remove that | ||
26 | dependency on glibc headers, and to use statx() functionality as soon | ||
27 | as the host kernel is capable of supporting it. Such structure statx | ||
28 | definition is used for both target and host structures statx (of | ||
29 | course, this doesn't mean the endian arrangement is the same on | ||
30 | target and host, and endian conversion is done in all necessary | ||
31 | cases). | ||
32 | |||
33 | Signed-off-by: Aleksandar Rikalo <arikalo@wavecomp.com> | ||
34 | Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> | ||
17 | --- | 35 | --- |
18 | hw/riscv/boot.c | 21 ++++++++++++++++++--- | 36 | linux-user/syscall.c | 136 +++++++++++++++++++++++++++++++++++++++++++++- |
19 | hw/riscv/microchip_pfsoc.c | 11 +---------- | 37 | linux-user/syscall_defs.h | 37 +++++++++++++ |
20 | hw/riscv/opentitan.c | 3 ++- | 38 | 2 files changed, 172 insertions(+), 1 deletion(-) |
21 | hw/riscv/sifive_e.c | 3 ++- | 39 | |
22 | hw/riscv/sifive_u.c | 11 +---------- | 40 | diff --git a/linux-user/syscall.c b/linux-user/syscall.c |
23 | hw/riscv/spike.c | 11 +---------- | ||
24 | hw/riscv/virt.c | 11 +---------- | ||
25 | include/hw/riscv/boot.h | 1 + | ||
26 | 8 files changed, 27 insertions(+), 45 deletions(-) | ||
27 | |||
28 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | 41 | index XXXXXXX..XXXXXXX 100644 |
30 | --- a/hw/riscv/boot.c | 42 | --- a/linux-user/syscall.c |
31 | +++ b/hw/riscv/boot.c | 43 | +++ b/linux-user/syscall.c |
32 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | 44 | @@ -XXX,XX +XXX,XX @@ |
33 | target_ulong riscv_load_kernel(MachineState *machine, | 45 | #include <sys/times.h> |
34 | RISCVHartArrayState *harts, | 46 | #include <sys/shm.h> |
35 | target_ulong kernel_start_addr, | 47 | #include <sys/sem.h> |
36 | + bool load_initrd, | 48 | +#include <sys/stat.h> |
37 | symbol_fn_t sym_cb) | 49 | #include <sys/statfs.h> |
38 | { | 50 | #include <utime.h> |
39 | const char *kernel_filename = machine->kernel_filename; | 51 | #include <sys/sysinfo.h> |
40 | uint64_t kernel_load_base, kernel_entry, kernel_low; | 52 | @@ -XXX,XX +XXX,XX @@ _syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type, |
41 | + void *fdt = machine->fdt; | 53 | unsigned long, idx1, unsigned long, idx2) |
42 | 54 | #endif | |
43 | g_assert(kernel_filename != NULL); | 55 | |
44 | 56 | +/* | |
45 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine, | 57 | + * It is assumed that struct statx is architecture independent. |
46 | kernel_entry = kernel_low; | 58 | + */ |
47 | } | 59 | +#if defined(TARGET_NR_statx) && defined(__NR_statx) |
48 | 60 | +_syscall5(int, statx, int, dirfd, const char *, pathname, int, flags, | |
49 | - return kernel_entry; | 61 | + unsigned int, mask, struct target_statx *, statxbuf) |
50 | + goto out; | 62 | +#endif |
51 | } | 63 | + |
52 | 64 | static bitmask_transtbl fcntl_flags_tbl[] = { | |
53 | if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, | 65 | { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, |
54 | NULL, NULL, NULL) > 0) { | 66 | { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, }, |
55 | - return kernel_entry; | 67 | @@ -XXX,XX +XXX,XX @@ static inline abi_long host_to_target_stat64(void *cpu_env, |
56 | + goto out; | 68 | } |
57 | } | 69 | #endif |
58 | 70 | ||
59 | if (load_image_targphys_as(kernel_filename, kernel_start_addr, | 71 | +#if defined(TARGET_NR_statx) && defined(__NR_statx) |
60 | current_machine->ram_size, NULL) > 0) { | 72 | +static inline abi_long host_to_target_statx(struct target_statx *host_stx, |
61 | - return kernel_start_addr; | 73 | + abi_ulong target_addr) |
62 | + kernel_entry = kernel_start_addr; | 74 | +{ |
63 | + goto out; | 75 | + struct target_statx *target_stx; |
64 | } | 76 | + |
65 | 77 | + if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) { | |
66 | error_report("could not load kernel '%s'", kernel_filename); | 78 | + return -TARGET_EFAULT; |
67 | exit(1); | ||
68 | + | ||
69 | +out: | ||
70 | + if (load_initrd && machine->initrd_filename) { | ||
71 | + riscv_load_initrd(machine, kernel_entry); | ||
72 | + } | 79 | + } |
73 | + | 80 | + memset(target_stx, 0, sizeof(*target_stx)); |
74 | + if (fdt && machine->kernel_cmdline && *machine->kernel_cmdline) { | 81 | + |
75 | + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", | 82 | + __put_user(host_stx->stx_mask, &target_stx->stx_mask); |
76 | + machine->kernel_cmdline); | 83 | + __put_user(host_stx->stx_blksize, &target_stx->stx_blksize); |
77 | + } | 84 | + __put_user(host_stx->stx_attributes, &target_stx->stx_attributes); |
78 | + | 85 | + __put_user(host_stx->stx_nlink, &target_stx->stx_nlink); |
79 | + return kernel_entry; | 86 | + __put_user(host_stx->stx_uid, &target_stx->stx_uid); |
80 | } | 87 | + __put_user(host_stx->stx_gid, &target_stx->stx_gid); |
81 | 88 | + __put_user(host_stx->stx_mode, &target_stx->stx_mode); | |
82 | void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) | 89 | + __put_user(host_stx->stx_ino, &target_stx->stx_ino); |
83 | diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c | 90 | + __put_user(host_stx->stx_size, &target_stx->stx_size); |
91 | + __put_user(host_stx->stx_blocks, &target_stx->stx_blocks); | ||
92 | + __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask); | ||
93 | + __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec); | ||
94 | + __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec); | ||
95 | + __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_atime.tv_sec); | ||
96 | + __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_atime.tv_nsec); | ||
97 | + __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_atime.tv_sec); | ||
98 | + __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_atime.tv_nsec); | ||
99 | + __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_atime.tv_sec); | ||
100 | + __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_atime.tv_nsec); | ||
101 | + __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major); | ||
102 | + __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor); | ||
103 | + __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major); | ||
104 | + __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor); | ||
105 | + | ||
106 | + unlock_user_struct(target_stx, target_addr, 1); | ||
107 | + | ||
108 | + return 0; | ||
109 | +} | ||
110 | +#endif | ||
111 | + | ||
112 | + | ||
113 | /* ??? Using host futex calls even when target atomic operations | ||
114 | are not really atomic probably breaks things. However implementing | ||
115 | futexes locally would make futexes shared between multiple processes | ||
116 | @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, | ||
117 | abi_long ret; | ||
118 | #if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \ | ||
119 | || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \ | ||
120 | - || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) | ||
121 | + || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \ | ||
122 | + || defined(TARGET_NR_statx) | ||
123 | struct stat st; | ||
124 | #endif | ||
125 | #if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \ | ||
126 | @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, | ||
127 | ret = host_to_target_stat64(cpu_env, arg3, &st); | ||
128 | return ret; | ||
129 | #endif | ||
130 | +#if defined(TARGET_NR_statx) | ||
131 | + case TARGET_NR_statx: | ||
132 | + { | ||
133 | + struct target_statx *target_stx; | ||
134 | + int dirfd = arg1; | ||
135 | + int flags = arg3; | ||
136 | + | ||
137 | + p = lock_user_string(arg2); | ||
138 | + if (p == NULL) { | ||
139 | + return -TARGET_EFAULT; | ||
140 | + } | ||
141 | +#if defined(__NR_statx) | ||
142 | + { | ||
143 | + /* | ||
144 | + * It is assumed that struct statx is architecture independent. | ||
145 | + */ | ||
146 | + struct target_statx host_stx; | ||
147 | + int mask = arg4; | ||
148 | + | ||
149 | + ret = get_errno(statx(dirfd, p, flags, mask, &host_stx)); | ||
150 | + if (!is_error(ret)) { | ||
151 | + if (host_to_target_statx(&host_stx, arg5) != 0) { | ||
152 | + unlock_user(p, arg2, 0); | ||
153 | + return -TARGET_EFAULT; | ||
154 | + } | ||
155 | + } | ||
156 | + | ||
157 | + if (ret != -TARGET_ENOSYS) { | ||
158 | + unlock_user(p, arg2, 0); | ||
159 | + return ret; | ||
160 | + } | ||
161 | + } | ||
162 | +#endif | ||
163 | + if (*((char *)p) == 0) { | ||
164 | + /* | ||
165 | + * By file descriptor | ||
166 | + */ | ||
167 | + if (flags & AT_EMPTY_PATH) { | ||
168 | + unlock_user(p, arg2, 0); | ||
169 | + return -TARGET_ENOENT; | ||
170 | + } | ||
171 | + ret = get_errno(fstat(dirfd, &st)); | ||
172 | + } else if (*((char *)p) == '/') { | ||
173 | + /* | ||
174 | + * By absolute pathname | ||
175 | + */ | ||
176 | + ret = get_errno(stat(path(p), &st)); | ||
177 | + } else { | ||
178 | + /* | ||
179 | + * By pathname relative to the current working directory | ||
180 | + * (if 'dirfd' is AT_FDCWD) or relative to the directory | ||
181 | + * referred to by the file descriptor 'dirfd'. | ||
182 | + */ | ||
183 | + ret = get_errno(fstatat(dirfd, path(p), &st, flags)); | ||
184 | + } | ||
185 | + unlock_user(p, arg2, 0); | ||
186 | + | ||
187 | + if (!is_error(ret)) { | ||
188 | + if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) { | ||
189 | + return -TARGET_EFAULT; | ||
190 | + } | ||
191 | + memset(target_stx, 0, sizeof(*target_stx)); | ||
192 | + __put_user(major(st.st_dev), &target_stx->stx_dev_major); | ||
193 | + __put_user(minor(st.st_dev), &target_stx->stx_dev_minor); | ||
194 | + __put_user(st.st_ino, &target_stx->stx_ino); | ||
195 | + __put_user(st.st_mode, &target_stx->stx_mode); | ||
196 | + __put_user(st.st_uid, &target_stx->stx_uid); | ||
197 | + __put_user(st.st_gid, &target_stx->stx_gid); | ||
198 | + __put_user(st.st_nlink, &target_stx->stx_nlink); | ||
199 | + __put_user(major(st.st_rdev), &target_stx->stx_rdev_major); | ||
200 | + __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor); | ||
201 | + __put_user(st.st_size, &target_stx->stx_size); | ||
202 | + __put_user(st.st_blksize, &target_stx->stx_blksize); | ||
203 | + __put_user(st.st_blocks, &target_stx->stx_blocks); | ||
204 | + __put_user(st.st_atime, &target_stx->stx_atime.tv_sec); | ||
205 | + __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec); | ||
206 | + __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec); | ||
207 | + unlock_user_struct(target_stx, arg5, 1); | ||
208 | + } | ||
209 | + } | ||
210 | + return ret; | ||
211 | +#endif | ||
212 | #ifdef TARGET_NR_lchown | ||
213 | case TARGET_NR_lchown: | ||
214 | if (!(p = lock_user_string(arg1))) | ||
215 | diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h | ||
84 | index XXXXXXX..XXXXXXX 100644 | 216 | index XXXXXXX..XXXXXXX 100644 |
85 | --- a/hw/riscv/microchip_pfsoc.c | 217 | --- a/linux-user/syscall_defs.h |
86 | +++ b/hw/riscv/microchip_pfsoc.c | 218 | +++ b/linux-user/syscall_defs.h |
87 | @@ -XXX,XX +XXX,XX @@ static void microchip_icicle_kit_machine_init(MachineState *machine) | 219 | @@ -XXX,XX +XXX,XX @@ struct target_user_cap_data { |
88 | firmware_end_addr); | 220 | /* Return size of the log buffer */ |
89 | 221 | #define TARGET_SYSLOG_ACTION_SIZE_BUFFER 10 | |
90 | kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | 222 | |
91 | - kernel_start_addr, NULL); | 223 | +struct target_statx_timestamp { |
92 | - | 224 | + int64_t tv_sec; |
93 | - if (machine->initrd_filename) { | 225 | + uint32_t tv_nsec; |
94 | - riscv_load_initrd(machine, kernel_entry); | 226 | + int32_t __reserved; |
95 | - } | 227 | +}; |
96 | - | 228 | + |
97 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | 229 | +struct target_statx { |
98 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", | 230 | + /* 0x00 */ |
99 | - "bootargs", machine->kernel_cmdline); | 231 | + uint32_t stx_mask; /* What results were written [uncond] */ |
100 | - } | 232 | + uint32_t stx_blksize; /* Preferred general I/O size [uncond] */ |
101 | + kernel_start_addr, true, NULL); | 233 | + uint64_t stx_attributes; /* Flags conveying information about the file */ |
102 | 234 | + /* 0x10 */ | |
103 | /* Compute the fdt load address in dram */ | 235 | + uint32_t stx_nlink; /* Number of hard links */ |
104 | fdt_load_addr = riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base, | 236 | + uint32_t stx_uid; /* User ID of owner */ |
105 | diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c | 237 | + uint32_t stx_gid; /* Group ID of owner */ |
106 | index XXXXXXX..XXXXXXX 100644 | 238 | + uint16_t stx_mode; /* File mode */ |
107 | --- a/hw/riscv/opentitan.c | 239 | + uint16_t __spare0[1]; |
108 | +++ b/hw/riscv/opentitan.c | 240 | + /* 0x20 */ |
109 | @@ -XXX,XX +XXX,XX @@ static void opentitan_board_init(MachineState *machine) | 241 | + uint64_t stx_ino; /* Inode number */ |
110 | 242 | + uint64_t stx_size; /* File size */ | |
111 | if (machine->kernel_filename) { | 243 | + uint64_t stx_blocks; /* Number of 512-byte blocks allocated */ |
112 | riscv_load_kernel(machine, &s->soc.cpus, | 244 | + uint64_t stx_attributes_mask; /* Mask to show what is supported */ |
113 | - memmap[IBEX_DEV_RAM].base, NULL); | 245 | + /* 0x40 */ |
114 | + memmap[IBEX_DEV_RAM].base, | 246 | + struct target_statx_timestamp stx_atime; /* Last access time */ |
115 | + false, NULL); | 247 | + struct target_statx_timestamp stx_btime; /* File creation time */ |
116 | } | 248 | + struct target_statx_timestamp stx_ctime; /* Last attribute change time */ |
117 | } | 249 | + struct target_statx_timestamp stx_mtime; /* Last data modification time */ |
118 | 250 | + /* 0x80 */ | |
119 | diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c | 251 | + uint32_t stx_rdev_major; /* Device ID of special file [if bdev/cdev] */ |
120 | index XXXXXXX..XXXXXXX 100644 | 252 | + uint32_t stx_rdev_minor; |
121 | --- a/hw/riscv/sifive_e.c | 253 | + uint32_t stx_dev_major; /* ID of device containing file [uncond] */ |
122 | +++ b/hw/riscv/sifive_e.c | 254 | + uint32_t stx_dev_minor; |
123 | @@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine) | 255 | + /* 0x90 */ |
124 | 256 | + uint64_t __spare2[14]; /* Spare space for future expansion */ | |
125 | if (machine->kernel_filename) { | 257 | + /* 0x100 */ |
126 | riscv_load_kernel(machine, &s->soc.cpus, | 258 | +}; |
127 | - memmap[SIFIVE_E_DEV_DTIM].base, NULL); | 259 | + |
128 | + memmap[SIFIVE_E_DEV_DTIM].base, | 260 | #endif |
129 | + false, NULL); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c | ||
134 | index XXXXXXX..XXXXXXX 100644 | ||
135 | --- a/hw/riscv/sifive_u.c | ||
136 | +++ b/hw/riscv/sifive_u.c | ||
137 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) | ||
138 | firmware_end_addr); | ||
139 | |||
140 | kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | ||
141 | - kernel_start_addr, NULL); | ||
142 | - | ||
143 | - if (machine->initrd_filename) { | ||
144 | - riscv_load_initrd(machine, kernel_entry); | ||
145 | - } | ||
146 | - | ||
147 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
148 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", | ||
149 | - machine->kernel_cmdline); | ||
150 | - } | ||
151 | + kernel_start_addr, true, NULL); | ||
152 | } else { | ||
153 | /* | ||
154 | * If dynamic firmware is used, it doesn't know where is the next mode | ||
155 | diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c | ||
156 | index XXXXXXX..XXXXXXX 100644 | ||
157 | --- a/hw/riscv/spike.c | ||
158 | +++ b/hw/riscv/spike.c | ||
159 | @@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine) | ||
160 | |||
161 | kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
162 | kernel_start_addr, | ||
163 | - htif_symbol_callback); | ||
164 | - | ||
165 | - if (machine->initrd_filename) { | ||
166 | - riscv_load_initrd(machine, kernel_entry); | ||
167 | - } | ||
168 | - | ||
169 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
170 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", | ||
171 | - machine->kernel_cmdline); | ||
172 | - } | ||
173 | + true, htif_symbol_callback); | ||
174 | } else { | ||
175 | /* | ||
176 | * If dynamic firmware is used, it doesn't know where is the next mode | ||
177 | diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c | ||
178 | index XXXXXXX..XXXXXXX 100644 | ||
179 | --- a/hw/riscv/virt.c | ||
180 | +++ b/hw/riscv/virt.c | ||
181 | @@ -XXX,XX +XXX,XX @@ static void virt_machine_done(Notifier *notifier, void *data) | ||
182 | firmware_end_addr); | ||
183 | |||
184 | kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
185 | - kernel_start_addr, NULL); | ||
186 | - | ||
187 | - if (machine->initrd_filename) { | ||
188 | - riscv_load_initrd(machine, kernel_entry); | ||
189 | - } | ||
190 | - | ||
191 | - if (machine->kernel_cmdline && *machine->kernel_cmdline) { | ||
192 | - qemu_fdt_setprop_string(machine->fdt, "/chosen", "bootargs", | ||
193 | - machine->kernel_cmdline); | ||
194 | - } | ||
195 | + kernel_start_addr, true, NULL); | ||
196 | } else { | ||
197 | /* | ||
198 | * If dynamic firmware is used, it doesn't know where is the next mode | ||
199 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
200 | index XXXXXXX..XXXXXXX 100644 | ||
201 | --- a/include/hw/riscv/boot.h | ||
202 | +++ b/include/hw/riscv/boot.h | ||
203 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
204 | target_ulong riscv_load_kernel(MachineState *machine, | ||
205 | RISCVHartArrayState *harts, | ||
206 | target_ulong firmware_end_addr, | ||
207 | + bool load_initrd, | ||
208 | symbol_fn_t sym_cb); | ||
209 | void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); | ||
210 | uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size, | ||
211 | -- | 261 | -- |
212 | 2.39.1 | 262 | 2.7.4 |
263 | |||
264 | diff view generated by jsdifflib |
1 | The only remaining caller is riscv_load_kernel_and_initrd() which | 1 | From: Jim Wilson <jimw@sifive.com> |
---|---|---|---|
2 | belongs to the same file. | ||
3 | 2 | ||
4 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | 3 | All of the flags need to be conditional as old systems don't have statx |
5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | 4 | support. Otherwise it works the same as other stat family syscalls. |
6 | Reviewed-by: Bin Meng <bmeng@tinylab.org> | 5 | This requires the pending patch to add statx support. |
7 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | 6 | |
7 | Tested on Ubuntu 16.04 (no host statx) and Ubuntu 19.04 (with host statx) | ||
8 | using a riscv32-linux toolchain. | ||
9 | |||
10 | Signed-off-by: Jim Wilson <jimw@sifive.com> | ||
11 | Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> | ||
12 | Reviewed-by: Laurent Vivier <laurent@vivier.eu> | ||
8 | --- | 13 | --- |
9 | hw/riscv/boot.c | 80 ++++++++++++++++++++--------------------- | 14 | linux-user/strace.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ |
10 | include/hw/riscv/boot.h | 1 - | 15 | linux-user/strace.list | 3 ++ |
11 | 2 files changed, 40 insertions(+), 41 deletions(-) | 16 | 2 files changed, 89 insertions(+) |
12 | 17 | ||
13 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | 18 | diff --git a/linux-user/strace.c b/linux-user/strace.c |
14 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/hw/riscv/boot.c | 20 | --- a/linux-user/strace.c |
16 | +++ b/hw/riscv/boot.c | 21 | +++ b/linux-user/strace.c |
17 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | 22 | @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags msg_flags[] = { |
18 | exit(1); | 23 | FLAG_END, |
24 | }; | ||
25 | |||
26 | +UNUSED static struct flags statx_flags[] = { | ||
27 | +#ifdef AT_EMPTY_PATH | ||
28 | + FLAG_GENERIC(AT_EMPTY_PATH), | ||
29 | +#endif | ||
30 | +#ifdef AT_NO_AUTOMOUNT | ||
31 | + FLAG_GENERIC(AT_NO_AUTOMOUNT), | ||
32 | +#endif | ||
33 | +#ifdef AT_SYMLINK_NOFOLLOW | ||
34 | + FLAG_GENERIC(AT_SYMLINK_NOFOLLOW), | ||
35 | +#endif | ||
36 | +#ifdef AT_STATX_SYNC_AS_STAT | ||
37 | + FLAG_GENERIC(AT_STATX_SYNC_AS_STAT), | ||
38 | +#endif | ||
39 | +#ifdef AT_STATX_FORCE_SYNC | ||
40 | + FLAG_GENERIC(AT_STATX_FORCE_SYNC), | ||
41 | +#endif | ||
42 | +#ifdef AT_STATX_DONT_SYNC | ||
43 | + FLAG_GENERIC(AT_STATX_DONT_SYNC), | ||
44 | +#endif | ||
45 | + FLAG_END, | ||
46 | +}; | ||
47 | + | ||
48 | +UNUSED static struct flags statx_mask[] = { | ||
49 | +/* This must come first, because it includes everything. */ | ||
50 | +#ifdef STATX_ALL | ||
51 | + FLAG_GENERIC(STATX_ALL), | ||
52 | +#endif | ||
53 | +/* This must come second; it includes everything except STATX_BTIME. */ | ||
54 | +#ifdef STATX_BASIC_STATS | ||
55 | + FLAG_GENERIC(STATX_BASIC_STATS), | ||
56 | +#endif | ||
57 | +#ifdef STATX_TYPE | ||
58 | + FLAG_GENERIC(STATX_TYPE), | ||
59 | +#endif | ||
60 | +#ifdef STATX_MODE | ||
61 | + FLAG_GENERIC(STATX_MODE), | ||
62 | +#endif | ||
63 | +#ifdef STATX_NLINK | ||
64 | + FLAG_GENERIC(STATX_NLINK), | ||
65 | +#endif | ||
66 | +#ifdef STATX_UID | ||
67 | + FLAG_GENERIC(STATX_UID), | ||
68 | +#endif | ||
69 | +#ifdef STATX_GID | ||
70 | + FLAG_GENERIC(STATX_GID), | ||
71 | +#endif | ||
72 | +#ifdef STATX_ATIME | ||
73 | + FLAG_GENERIC(STATX_ATIME), | ||
74 | +#endif | ||
75 | +#ifdef STATX_MTIME | ||
76 | + FLAG_GENERIC(STATX_MTIME), | ||
77 | +#endif | ||
78 | +#ifdef STATX_CTIME | ||
79 | + FLAG_GENERIC(STATX_CTIME), | ||
80 | +#endif | ||
81 | +#ifdef STATX_INO | ||
82 | + FLAG_GENERIC(STATX_INO), | ||
83 | +#endif | ||
84 | +#ifdef STATX_SIZE | ||
85 | + FLAG_GENERIC(STATX_SIZE), | ||
86 | +#endif | ||
87 | +#ifdef STATX_BLOCKS | ||
88 | + FLAG_GENERIC(STATX_BLOCKS), | ||
89 | +#endif | ||
90 | +#ifdef STATX_BTIME | ||
91 | + FLAG_GENERIC(STATX_BTIME), | ||
92 | +#endif | ||
93 | + FLAG_END, | ||
94 | +}; | ||
95 | + | ||
96 | /* | ||
97 | * print_xxx utility functions. These are used to print syscall | ||
98 | * parameters in certain format. All of these have parameter | ||
99 | @@ -XXX,XX +XXX,XX @@ print_tgkill(const struct syscallname *name, | ||
19 | } | 100 | } |
20 | 101 | #endif | |
21 | +static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) | 102 | |
103 | +#ifdef TARGET_NR_statx | ||
104 | +static void | ||
105 | +print_statx(const struct syscallname *name, | ||
106 | + abi_long arg0, abi_long arg1, abi_long arg2, | ||
107 | + abi_long arg3, abi_long arg4, abi_long arg5) | ||
22 | +{ | 108 | +{ |
23 | + const char *filename = machine->initrd_filename; | 109 | + print_syscall_prologue(name); |
24 | + uint64_t mem_size = machine->ram_size; | 110 | + print_at_dirfd(arg0, 0); |
25 | + void *fdt = machine->fdt; | 111 | + print_string(arg1, 0); |
26 | + hwaddr start, end; | 112 | + print_flags(statx_flags, arg2, 0); |
27 | + ssize_t size; | 113 | + print_flags(statx_mask, arg3, 0); |
114 | + print_pointer(arg4, 1); | ||
115 | + print_syscall_epilogue(name); | ||
116 | +} | ||
117 | +#endif | ||
28 | + | 118 | + |
29 | + g_assert(filename != NULL); | ||
30 | + | ||
31 | + /* | ||
32 | + * We want to put the initrd far enough into RAM that when the | ||
33 | + * kernel is uncompressed it will not clobber the initrd. However | ||
34 | + * on boards without much RAM we must ensure that we still leave | ||
35 | + * enough room for a decent sized initrd, and on boards with large | ||
36 | + * amounts of RAM we must avoid the initrd being so far up in RAM | ||
37 | + * that it is outside lowmem and inaccessible to the kernel. | ||
38 | + * So for boards with less than 256MB of RAM we put the initrd | ||
39 | + * halfway into RAM, and for boards with 256MB of RAM or more we put | ||
40 | + * the initrd at 128MB. | ||
41 | + */ | ||
42 | + start = kernel_entry + MIN(mem_size / 2, 128 * MiB); | ||
43 | + | ||
44 | + size = load_ramdisk(filename, start, mem_size - start); | ||
45 | + if (size == -1) { | ||
46 | + size = load_image_targphys(filename, start, mem_size - start); | ||
47 | + if (size == -1) { | ||
48 | + error_report("could not load ramdisk '%s'", filename); | ||
49 | + exit(1); | ||
50 | + } | ||
51 | + } | ||
52 | + | ||
53 | + /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ | ||
54 | + if (fdt) { | ||
55 | + end = start + size; | ||
56 | + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); | ||
57 | + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end); | ||
58 | + } | ||
59 | +} | ||
60 | + | ||
61 | target_ulong riscv_load_kernel(MachineState *machine, | ||
62 | RISCVHartArrayState *harts, | ||
63 | target_ulong kernel_start_addr, | ||
64 | @@ -XXX,XX +XXX,XX @@ out: | ||
65 | return kernel_entry; | ||
66 | } | ||
67 | |||
68 | -void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry) | ||
69 | -{ | ||
70 | - const char *filename = machine->initrd_filename; | ||
71 | - uint64_t mem_size = machine->ram_size; | ||
72 | - void *fdt = machine->fdt; | ||
73 | - hwaddr start, end; | ||
74 | - ssize_t size; | ||
75 | - | ||
76 | - g_assert(filename != NULL); | ||
77 | - | ||
78 | - /* | ||
79 | - * We want to put the initrd far enough into RAM that when the | ||
80 | - * kernel is uncompressed it will not clobber the initrd. However | ||
81 | - * on boards without much RAM we must ensure that we still leave | ||
82 | - * enough room for a decent sized initrd, and on boards with large | ||
83 | - * amounts of RAM we must avoid the initrd being so far up in RAM | ||
84 | - * that it is outside lowmem and inaccessible to the kernel. | ||
85 | - * So for boards with less than 256MB of RAM we put the initrd | ||
86 | - * halfway into RAM, and for boards with 256MB of RAM or more we put | ||
87 | - * the initrd at 128MB. | ||
88 | - */ | ||
89 | - start = kernel_entry + MIN(mem_size / 2, 128 * MiB); | ||
90 | - | ||
91 | - size = load_ramdisk(filename, start, mem_size - start); | ||
92 | - if (size == -1) { | ||
93 | - size = load_image_targphys(filename, start, mem_size - start); | ||
94 | - if (size == -1) { | ||
95 | - error_report("could not load ramdisk '%s'", filename); | ||
96 | - exit(1); | ||
97 | - } | ||
98 | - } | ||
99 | - | ||
100 | - /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */ | ||
101 | - if (fdt) { | ||
102 | - end = start + size; | ||
103 | - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start); | ||
104 | - qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end); | ||
105 | - } | ||
106 | -} | ||
107 | - | ||
108 | /* | 119 | /* |
109 | * This function makes an assumption that the DRAM interval | 120 | * An array of all of the syscalls we know about |
110 | * 'dram_base' + 'dram_size' is contiguous. | 121 | */ |
111 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | 122 | diff --git a/linux-user/strace.list b/linux-user/strace.list |
112 | index XXXXXXX..XXXXXXX 100644 | 123 | index XXXXXXX..XXXXXXX 100644 |
113 | --- a/include/hw/riscv/boot.h | 124 | --- a/linux-user/strace.list |
114 | +++ b/include/hw/riscv/boot.h | 125 | +++ b/linux-user/strace.list |
115 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine, | 126 | @@ -XXX,XX +XXX,XX @@ |
116 | target_ulong firmware_end_addr, | 127 | #ifdef TARGET_NR_atomic_barrier |
117 | bool load_initrd, | 128 | { TARGET_NR_atomic_barrier, "atomic_barrier", NULL, NULL, NULL }, |
118 | symbol_fn_t sym_cb); | 129 | #endif |
119 | -void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); | 130 | +#ifdef TARGET_NR_statx |
120 | uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size, | 131 | +{ TARGET_NR_statx, "statx", NULL, print_statx, NULL }, |
121 | MachineState *ms); | 132 | +#endif |
122 | void riscv_load_fdt(hwaddr fdt_addr, void *fdt); | ||
123 | -- | 133 | -- |
124 | 2.39.1 | 134 | 2.7.4 |
125 | 135 | ||
126 | 136 | diff view generated by jsdifflib |
1 | load_elf_ram_sym() will sign-extend 32 bit addresses. If a 32 bit QEMU | 1 | From: Aleksandar Markovic <amarkovic@wavecomp.com> |
---|---|---|---|
2 | guest happens to be running in a hypervisor that are using 64 bits to | ||
3 | encode its address, kernel_entry can be padded with '1's and create | ||
4 | problems [1]. | ||
5 | 2 | ||
6 | Using a translate_fn() callback in load_elf_ram_sym() to filter the | 3 | Only MIPS O32 and N32 have special (different than other |
7 | padding from the address doesn't work. A more detailed explanation can | 4 | architectures) definition of structure flock in kernel. |
8 | be found in [2]. The short version is that glue(load_elf, SZ), from | ||
9 | include/hw/elf_ops.h, will calculate 'pentry' (mapped into the | ||
10 | 'kernel_load_base' var in riscv_load_Kernel()) before using | ||
11 | translate_fn(), and will not recalculate it after executing it. This | ||
12 | means that the callback does not prevent the padding from | ||
13 | kernel_load_base to appear. | ||
14 | 5 | ||
15 | Let's instead use a kernel_low var to capture the 'lowaddr' value from | 6 | Bring flock definition for MIPS O64 ABI to the correct state. |
16 | load_elf_ram_sim(), and return it when we're dealing with 32 bit CPUs. | ||
17 | 7 | ||
18 | [1] https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg02281.html | 8 | Reported-by: Dragan Mladjenovic <dmladjenovic@wavecomp.com> |
19 | [2] https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg00099.html | 9 | Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> |
10 | --- | ||
11 | linux-user/generic/fcntl.h | 2 +- | ||
12 | linux-user/mips/target_fcntl.h | 4 ++++ | ||
13 | 2 files changed, 5 insertions(+), 1 deletion(-) | ||
20 | 14 | ||
21 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | 15 | diff --git a/linux-user/generic/fcntl.h b/linux-user/generic/fcntl.h |
22 | --- | 16 | index XXXXXXX..XXXXXXX 100644 |
23 | hw/riscv/boot.c | 15 +++++++++++---- | 17 | --- a/linux-user/generic/fcntl.h |
24 | hw/riscv/microchip_pfsoc.c | 3 ++- | 18 | +++ b/linux-user/generic/fcntl.h |
25 | hw/riscv/opentitan.c | 3 ++- | 19 | @@ -XXX,XX +XXX,XX @@ struct target_flock { |
26 | hw/riscv/sifive_e.c | 3 ++- | 20 | short l_whence; |
27 | hw/riscv/sifive_u.c | 3 ++- | 21 | abi_long l_start; |
28 | hw/riscv/spike.c | 3 ++- | 22 | abi_long l_len; |
29 | hw/riscv/virt.c | 3 ++- | 23 | -#if defined(TARGET_MIPS) |
30 | include/hw/riscv/boot.h | 1 + | 24 | +#if defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) |
31 | 8 files changed, 24 insertions(+), 10 deletions(-) | 25 | abi_long l_sysid; |
26 | #endif | ||
27 | int l_pid; | ||
28 | diff --git a/linux-user/mips/target_fcntl.h b/linux-user/mips/target_fcntl.h | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/linux-user/mips/target_fcntl.h | ||
31 | +++ b/linux-user/mips/target_fcntl.h | ||
32 | @@ -XXX,XX +XXX,XX @@ | ||
33 | #define TARGET_F_SETOWN 24 /* for sockets. */ | ||
34 | #define TARGET_F_GETOWN 23 /* for sockets. */ | ||
35 | |||
36 | +#if (TARGET_ABI_BITS == 32) | ||
37 | #define TARGET_ARCH_FLOCK_PAD abi_long pad[4]; | ||
38 | +#else | ||
39 | +#define TARGET_ARCH_FLOCK_PAD | ||
40 | +#endif | ||
41 | #define TARGET_ARCH_FLOCK64_PAD | ||
42 | |||
43 | #define TARGET_F_GETLK64 33 /* using 'struct flock64' */ | ||
44 | -- | ||
45 | 2.7.4 | ||
32 | 46 | ||
33 | diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c | 47 | |
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/hw/riscv/boot.c | ||
36 | +++ b/hw/riscv/boot.c | ||
37 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
38 | } | ||
39 | |||
40 | target_ulong riscv_load_kernel(MachineState *machine, | ||
41 | + RISCVHartArrayState *harts, | ||
42 | target_ulong kernel_start_addr, | ||
43 | symbol_fn_t sym_cb) | ||
44 | { | ||
45 | const char *kernel_filename = machine->kernel_filename; | ||
46 | - uint64_t kernel_load_base, kernel_entry; | ||
47 | + uint64_t kernel_load_base, kernel_entry, kernel_low; | ||
48 | |||
49 | g_assert(kernel_filename != NULL); | ||
50 | |||
51 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine, | ||
52 | * the (expected) load address load address. This allows kernels to have | ||
53 | * separate SBI and ELF entry points (used by FreeBSD, for example). | ||
54 | */ | ||
55 | - if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, | ||
56 | - NULL, &kernel_load_base, NULL, NULL, 0, | ||
57 | + if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, NULL, | ||
58 | + &kernel_load_base, &kernel_low, NULL, 0, | ||
59 | EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) { | ||
60 | - return kernel_load_base; | ||
61 | + kernel_entry = kernel_load_base; | ||
62 | + | ||
63 | + if (riscv_is_32bit(harts)) { | ||
64 | + kernel_entry = kernel_low; | ||
65 | + } | ||
66 | + | ||
67 | + return kernel_entry; | ||
68 | } | ||
69 | |||
70 | if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL, | ||
71 | diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/hw/riscv/microchip_pfsoc.c | ||
74 | +++ b/hw/riscv/microchip_pfsoc.c | ||
75 | @@ -XXX,XX +XXX,XX @@ static void microchip_icicle_kit_machine_init(MachineState *machine) | ||
76 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, | ||
77 | firmware_end_addr); | ||
78 | |||
79 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); | ||
80 | + kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | ||
81 | + kernel_start_addr, NULL); | ||
82 | |||
83 | if (machine->initrd_filename) { | ||
84 | riscv_load_initrd(machine, kernel_entry); | ||
85 | diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c | ||
86 | index XXXXXXX..XXXXXXX 100644 | ||
87 | --- a/hw/riscv/opentitan.c | ||
88 | +++ b/hw/riscv/opentitan.c | ||
89 | @@ -XXX,XX +XXX,XX @@ static void opentitan_board_init(MachineState *machine) | ||
90 | } | ||
91 | |||
92 | if (machine->kernel_filename) { | ||
93 | - riscv_load_kernel(machine, memmap[IBEX_DEV_RAM].base, NULL); | ||
94 | + riscv_load_kernel(machine, &s->soc.cpus, | ||
95 | + memmap[IBEX_DEV_RAM].base, NULL); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c | ||
100 | index XXXXXXX..XXXXXXX 100644 | ||
101 | --- a/hw/riscv/sifive_e.c | ||
102 | +++ b/hw/riscv/sifive_e.c | ||
103 | @@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine) | ||
104 | memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory); | ||
105 | |||
106 | if (machine->kernel_filename) { | ||
107 | - riscv_load_kernel(machine, memmap[SIFIVE_E_DEV_DTIM].base, NULL); | ||
108 | + riscv_load_kernel(machine, &s->soc.cpus, | ||
109 | + memmap[SIFIVE_E_DEV_DTIM].base, NULL); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c | ||
114 | index XXXXXXX..XXXXXXX 100644 | ||
115 | --- a/hw/riscv/sifive_u.c | ||
116 | +++ b/hw/riscv/sifive_u.c | ||
117 | @@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine) | ||
118 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus, | ||
119 | firmware_end_addr); | ||
120 | |||
121 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); | ||
122 | + kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus, | ||
123 | + kernel_start_addr, NULL); | ||
124 | |||
125 | if (machine->initrd_filename) { | ||
126 | riscv_load_initrd(machine, kernel_entry); | ||
127 | diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c | ||
128 | index XXXXXXX..XXXXXXX 100644 | ||
129 | --- a/hw/riscv/spike.c | ||
130 | +++ b/hw/riscv/spike.c | ||
131 | @@ -XXX,XX +XXX,XX @@ static void spike_board_init(MachineState *machine) | ||
132 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], | ||
133 | firmware_end_addr); | ||
134 | |||
135 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, | ||
136 | + kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
137 | + kernel_start_addr, | ||
138 | htif_symbol_callback); | ||
139 | |||
140 | if (machine->initrd_filename) { | ||
141 | diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c | ||
142 | index XXXXXXX..XXXXXXX 100644 | ||
143 | --- a/hw/riscv/virt.c | ||
144 | +++ b/hw/riscv/virt.c | ||
145 | @@ -XXX,XX +XXX,XX @@ static void virt_machine_done(Notifier *notifier, void *data) | ||
146 | kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], | ||
147 | firmware_end_addr); | ||
148 | |||
149 | - kernel_entry = riscv_load_kernel(machine, kernel_start_addr, NULL); | ||
150 | + kernel_entry = riscv_load_kernel(machine, &s->soc[0], | ||
151 | + kernel_start_addr, NULL); | ||
152 | |||
153 | if (machine->initrd_filename) { | ||
154 | riscv_load_initrd(machine, kernel_entry); | ||
155 | diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h | ||
156 | index XXXXXXX..XXXXXXX 100644 | ||
157 | --- a/include/hw/riscv/boot.h | ||
158 | +++ b/include/hw/riscv/boot.h | ||
159 | @@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename, | ||
160 | hwaddr firmware_load_addr, | ||
161 | symbol_fn_t sym_cb); | ||
162 | target_ulong riscv_load_kernel(MachineState *machine, | ||
163 | + RISCVHartArrayState *harts, | ||
164 | target_ulong firmware_end_addr, | ||
165 | symbol_fn_t sym_cb); | ||
166 | void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry); | ||
167 | -- | ||
168 | 2.39.1 | diff view generated by jsdifflib |