1
From: Sameeh Jubran <sjubran@redhat.com>
1
Hi,
2
2
3
This series fixes qemu-ga's behaviour upon facing a missing serial/serial
3
This new version removed the translate_fn() from patch 1 because it
4
driver by listening to the serial device's events.
4
wasn't removing the sign-extension for pentry as we thought it would.
5
A more detailed explanation is given in the commit msg of patch 1.
5
6
6
For more info on why this series is needed checkout the commit message
7
We're now retrieving the 'lowaddr' value from load_elf_ram_sym() and
7
of the third patch and the following bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=990629.
8
using it when we're running a 32-bit CPU. This worked with 32 bit
9
'virt' machine booting with the -kernel option.
8
10
9
Sameeh Jubran (3):
11
If this approach doesn't work for the Xvisor use case, IMO we should
10
qga: Channel: Add functions for checking serial status
12
just filter kernel_load_addr bits directly as we were doing a handful of
11
qga: main: make qga config and socket activation global
13
versions ago.
12
qga: Prevent qemu-ga exit if serial doesn't exist
13
14
14
Makefile | 4 +
15
Patches are based on current riscv-to-apply.next.
15
qga/channel-posix.c | 54 ++++++++++
16
16
qga/channel-win32.c | 60 +++++++++++
17
Changes from v9:
17
qga/channel.h | 9 ++
18
- patch 1:
18
qga/main.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++------
19
- removed the translate_fn() callback
19
qga/service-win32.h | 4 +
20
- return 'kernel_low' when running a 32-bit CPU
20
6 files changed, 385 insertions(+), 30 deletions(-)
21
- v9 link: https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg04509.html
22
23
Daniel Henrique Barboza (3):
24
hw/riscv: handle 32 bit CPUs kernel_addr in riscv_load_kernel()
25
hw/riscv/boot.c: consolidate all kernel init in riscv_load_kernel()
26
hw/riscv/boot.c: make riscv_load_initrd() static
27
28
hw/riscv/boot.c | 96 +++++++++++++++++++++++---------------
29
hw/riscv/microchip_pfsoc.c | 12 +----
30
hw/riscv/opentitan.c | 4 +-
31
hw/riscv/sifive_e.c | 4 +-
32
hw/riscv/sifive_u.c | 12 +----
33
hw/riscv/spike.c | 14 ++----
34
hw/riscv/virt.c | 12 +----
35
include/hw/riscv/boot.h | 3 +-
36
8 files changed, 76 insertions(+), 81 deletions(-)
21
37
22
--
38
--
23
2.9.4
39
2.39.1
24
25
diff view generated by jsdifflib
1
From: Sameeh Jubran <sjubran@redhat.com>
1
load_elf_ram_sym() will sign-extend 32 bit addresses. If a 32 bit QEMU
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].
2
5
3
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
6
Using a translate_fn() callback in load_elf_ram_sym() to filter the
7
padding from the address doesn't work. A more detailed explanation can
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
15
Let's instead use a kernel_low var to capture the 'lowaddr' value from
16
load_elf_ram_sim(), and return it when we're dealing with 32 bit CPUs.
17
18
[1] https://lists.gnu.org/archive/html/qemu-devel/2023-01/msg02281.html
19
[2] https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg00099.html
20
21
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
4
---
22
---
5
qga/main.c | 44 +++++++++++++++++++++++---------------------
23
hw/riscv/boot.c | 15 +++++++++++----
6
1 file changed, 23 insertions(+), 21 deletions(-)
24
hw/riscv/microchip_pfsoc.c | 3 ++-
25
hw/riscv/opentitan.c | 3 ++-
26
hw/riscv/sifive_e.c | 3 ++-
27
hw/riscv/sifive_u.c | 3 ++-
28
hw/riscv/spike.c | 3 ++-
29
hw/riscv/virt.c | 3 ++-
30
include/hw/riscv/boot.h | 1 +
31
8 files changed, 24 insertions(+), 10 deletions(-)
7
32
8
diff --git a/qga/main.c b/qga/main.c
33
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
9
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
10
--- a/qga/main.c
35
--- a/hw/riscv/boot.c
11
+++ b/qga/main.c
36
+++ b/hw/riscv/boot.c
12
@@ -XXX,XX +XXX,XX @@ struct GAState {
37
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename,
13
GAPersistentState pstate;
38
}
14
};
39
15
40
target_ulong riscv_load_kernel(MachineState *machine,
16
+typedef struct GAConfig {
41
+ RISCVHartArrayState *harts,
17
+ char *channel_path;
42
target_ulong kernel_start_addr,
18
+ char *method;
43
symbol_fn_t sym_cb)
19
+ char *log_filepath;
44
{
20
+ char *pid_filepath;
45
const char *kernel_filename = machine->kernel_filename;
21
+#ifdef CONFIG_FSFREEZE
46
- uint64_t kernel_load_base, kernel_entry;
22
+ char *fsfreeze_hook;
47
+ uint64_t kernel_load_base, kernel_entry, kernel_low;
23
+#endif
48
24
+ char *state_dir;
49
g_assert(kernel_filename != NULL);
25
+#ifdef _WIN32
50
26
+ const char *service;
51
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine,
27
+#endif
52
* the (expected) load address load address. This allows kernels to have
28
+ gchar *bliststr; /* blacklist may point to this string */
53
* separate SBI and ELF entry points (used by FreeBSD, for example).
29
+ GList *blacklist;
54
*/
30
+ int daemonize;
55
- if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL,
31
+ GLogLevelFlags log_level;
56
- NULL, &kernel_load_base, NULL, NULL, 0,
32
+ int dumpconf;
57
+ if (load_elf_ram_sym(kernel_filename, NULL, NULL, NULL, NULL,
33
+} GAConfig;
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;
34
+
62
+
35
struct GAState *ga_state;
63
+ if (riscv_is_32bit(harts)) {
36
+struct GAConfig *ga_config;
64
+ kernel_entry = kernel_low;
37
+int ga_socket_activation;
65
+ }
38
QmpCommandList ga_commands;
66
+
39
67
+ return kernel_entry;
40
/* commands that are safe to issue while filesystems are frozen */
68
}
41
@@ -XXX,XX +XXX,XX @@ static GList *split_list(const gchar *str, const gchar *delim)
69
42
return list;
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
}
43
}
97
}
44
98
45
-typedef struct GAConfig {
99
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
46
- char *channel_path;
100
index XXXXXXX..XXXXXXX 100644
47
- char *method;
101
--- a/hw/riscv/sifive_e.c
48
- char *log_filepath;
102
+++ b/hw/riscv/sifive_e.c
49
- char *pid_filepath;
103
@@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine)
50
-#ifdef CONFIG_FSFREEZE
104
memmap[SIFIVE_E_DEV_MROM].base, &address_space_memory);
51
- char *fsfreeze_hook;
105
52
-#endif
106
if (machine->kernel_filename) {
53
- char *state_dir;
107
- riscv_load_kernel(machine, memmap[SIFIVE_E_DEV_DTIM].base, NULL);
54
-#ifdef _WIN32
108
+ riscv_load_kernel(machine, &s->soc.cpus,
55
- const char *service;
109
+ memmap[SIFIVE_E_DEV_DTIM].base, NULL);
56
-#endif
57
- gchar *bliststr; /* blacklist may point to this string */
58
- GList *blacklist;
59
- int daemonize;
60
- GLogLevelFlags log_level;
61
- int dumpconf;
62
-} GAConfig;
63
-
64
static void config_load(GAConfig *config)
65
{
66
GError *gerr = NULL;
67
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
68
{
69
int ret = EXIT_SUCCESS;
70
GAState *s = g_new0(GAState, 1);
71
- GAConfig *config = g_new0(GAConfig, 1);
72
+ GAConfig *config = ga_config = g_new0(GAConfig, 1);
73
int socket_activation;
74
75
config->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
76
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
77
config->method = g_strdup("virtio-serial");
78
}
110
}
79
111
}
80
- socket_activation = check_socket_activation();
112
81
+ ga_socket_activation = socket_activation = check_socket_activation();
113
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
82
if (socket_activation > 1) {
114
index XXXXXXX..XXXXXXX 100644
83
g_critical("qemu-ga only supports listening on one socket");
115
--- a/hw/riscv/sifive_u.c
84
ret = EXIT_FAILURE;
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);
85
--
167
--
86
2.9.4
168
2.39.1
87
88
diff view generated by jsdifflib
1
From: Sameeh Jubran <sjubran@redhat.com>
1
The microchip_icicle_kit, sifive_u, spike and virt boards are now doing
2
2
the same steps when '-kernel' is used:
3
This commit adds functions to check if the serial is
3
4
connected/disconnected or else if it has been attached or detached.
4
- execute load_kernel()
5
5
- load init_rd()
6
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
6
- write kernel_cmdline
7
8
Let's fold everything inside riscv_load_kernel() to avoid code
9
repetition. To not change the behavior of boards that aren't calling
10
riscv_load_init(), add an 'load_initrd' flag to riscv_load_kernel() and
11
allow these boards to opt out from initrd loading.
12
13
Cc: Palmer Dabbelt <palmer@dabbelt.com>
14
Reviewed-by: Bin Meng <bmeng@tinylab.org>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
7
---
17
---
8
qga/channel-posix.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
18
hw/riscv/boot.c | 21 ++++++++++++++++++---
9
qga/channel-win32.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++
19
hw/riscv/microchip_pfsoc.c | 11 +----------
10
qga/channel.h | 9 ++++++++
20
hw/riscv/opentitan.c | 3 ++-
11
3 files changed, 123 insertions(+)
21
hw/riscv/sifive_e.c | 3 ++-
12
22
hw/riscv/sifive_u.c | 11 +----------
13
diff --git a/qga/channel-posix.c b/qga/channel-posix.c
23
hw/riscv/spike.c | 11 +----------
14
index XXXXXXX..XXXXXXX 100644
24
hw/riscv/virt.c | 11 +----------
15
--- a/qga/channel-posix.c
25
include/hw/riscv/boot.h | 1 +
16
+++ b/qga/channel-posix.c
26
8 files changed, 27 insertions(+), 45 deletions(-)
17
@@ -XXX,XX +XXX,XX @@ void ga_channel_free(GAChannel *c)
27
18
}
28
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
19
g_free(c);
29
index XXXXXXX..XXXXXXX 100644
20
}
30
--- a/hw/riscv/boot.c
31
+++ b/hw/riscv/boot.c
32
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename,
33
target_ulong riscv_load_kernel(MachineState *machine,
34
RISCVHartArrayState *harts,
35
target_ulong kernel_start_addr,
36
+ bool load_initrd,
37
symbol_fn_t sym_cb)
38
{
39
const char *kernel_filename = machine->kernel_filename;
40
uint64_t kernel_load_base, kernel_entry, kernel_low;
41
+ void *fdt = machine->fdt;
42
43
g_assert(kernel_filename != NULL);
44
45
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine,
46
kernel_entry = kernel_low;
47
}
48
49
- return kernel_entry;
50
+ goto out;
51
}
52
53
if (load_uimage_as(kernel_filename, &kernel_entry, NULL, NULL,
54
NULL, NULL, NULL) > 0) {
55
- return kernel_entry;
56
+ goto out;
57
}
58
59
if (load_image_targphys_as(kernel_filename, kernel_start_addr,
60
current_machine->ram_size, NULL) > 0) {
61
- return kernel_start_addr;
62
+ kernel_entry = kernel_start_addr;
63
+ goto out;
64
}
65
66
error_report("could not load kernel '%s'", kernel_filename);
67
exit(1);
21
+
68
+
22
+static bool is_serial_present(GAChannelMethod method, const gchar *path,
69
+out:
23
+ int *error_code)
70
+ if (load_initrd && machine->initrd_filename) {
24
+{
71
+ riscv_load_initrd(machine, kernel_entry);
25
+ int fd = -1;
26
+ bool ret = true;
27
+
28
+ assert(error_code);
29
+ *error_code = 0;
30
+
31
+ switch (method) {
32
+ case GA_CHANNEL_VIRTIO_SERIAL:
33
+ fd = qemu_open(path, O_RDWR | O_NONBLOCK
34
+#ifndef CONFIG_SOLARIS
35
+ | O_ASYNC
36
+#endif
37
+ );
38
+ break;
39
+ case GA_CHANNEL_ISA_SERIAL:
40
+ fd = qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK);
41
+ break;
42
+ default:
43
+ ret = false;
44
+ }
45
+ if (fd < 0) {
46
+ *error_code = errno;
47
+ ret = false;
48
+ } else {
49
+ close(fd);
50
+ }
51
+ return ret;
52
+}
53
+
54
+bool ga_channel_serial_is_present(GAChannelMethod method, const gchar *path)
55
+{
56
+ int error_code = 0;
57
+ return is_serial_present(method, path, &error_code) ||
58
+ error_code == EBUSY;
59
+}
60
+
61
+bool ga_channel_was_serial_attached(GAChannelMethod method, const gchar *path,
62
+ bool is_serial_attached)
63
+{
64
+ int error_code = 0;
65
+ return !is_serial_attached &&
66
+ is_serial_present(method, path, &error_code);
67
+}
68
+bool ga_channel_was_serial_detached(GAChannelMethod method, const gchar *path,
69
+ bool is_serial_attached)
70
+{
71
+ int error_code = 0;
72
+ return is_serial_attached && !is_serial_present(method, path, &error_code)
73
+ && error_code == ENOENT;
74
+}
75
diff --git a/qga/channel-win32.c b/qga/channel-win32.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/qga/channel-win32.c
78
+++ b/qga/channel-win32.c
79
@@ -XXX,XX +XXX,XX @@ void ga_channel_free(GAChannel *c)
80
g_free(c->rstate.buf);
81
g_free(c);
82
}
83
+
84
+static bool is_serial_present(GAChannelMethod method, const gchar *path,
85
+ DWORD *err)
86
+{
87
+ gchar newpath[MAXPATHLEN] = { 0 };
88
+ bool ret = false;
89
+
90
+ assert(err);
91
+
92
+ if (method != GA_CHANNEL_VIRTIO_SERIAL && method != GA_CHANNEL_ISA_SERIAL) {
93
+ g_critical("unsupported communication method");
94
+ return false;
95
+ }
72
+ }
96
+
73
+
97
+ if (method == GA_CHANNEL_ISA_SERIAL) {
74
+ if (fdt && machine->kernel_cmdline && *machine->kernel_cmdline) {
98
+ snprintf(newpath, sizeof(newpath), "\\\\.\\%s", path);
75
+ qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
99
+ } else {
76
+ machine->kernel_cmdline);
100
+ g_strlcpy(newpath, path, sizeof(newpath));
101
+ }
77
+ }
102
+
78
+
103
+ HANDLE handle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE, 0, NULL,
79
+ return kernel_entry;
104
+ OPEN_EXISTING,
80
}
105
+ FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
81
106
+
82
void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
107
+ if (handle == INVALID_HANDLE_VALUE) {
83
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
108
+ *err = GetLastError();
84
index XXXXXXX..XXXXXXX 100644
109
+ ret = false;
85
--- a/hw/riscv/microchip_pfsoc.c
110
+ } else {
86
+++ b/hw/riscv/microchip_pfsoc.c
111
+ ret = true;
87
@@ -XXX,XX +XXX,XX @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
112
+ }
88
firmware_end_addr);
113
+
89
114
+ CloseHandle(handle);
90
kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus,
115
+ return ret;
91
- kernel_start_addr, NULL);
116
+}
92
-
117
+
93
- if (machine->initrd_filename) {
118
+bool ga_channel_serial_is_present(GAChannelMethod method, const gchar *path)
94
- riscv_load_initrd(machine, kernel_entry);
119
+{
95
- }
120
+ DWORD err_code;
96
-
121
+ return is_serial_present(method, path, &err_code) ||
97
- if (machine->kernel_cmdline && *machine->kernel_cmdline) {
122
+ err_code == ERROR_ACCESS_DENIED;
98
- qemu_fdt_setprop_string(machine->fdt, "/chosen",
123
+}
99
- "bootargs", machine->kernel_cmdline);
124
+
100
- }
125
+bool ga_channel_was_serial_attached(GAChannelMethod method, const gchar *path,
101
+ kernel_start_addr, true, NULL);
126
+ bool is_serial_attached)
102
127
+{
103
/* Compute the fdt load address in dram */
128
+ DWORD err_code;
104
fdt_load_addr = riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base,
129
+ return !is_serial_attached && is_serial_present(method, path, &err_code);
105
diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
130
+}
106
index XXXXXXX..XXXXXXX 100644
131
+
107
--- a/hw/riscv/opentitan.c
132
+bool ga_channel_was_serial_detached(GAChannelMethod method, const gchar *path,
108
+++ b/hw/riscv/opentitan.c
133
+ bool is_serial_attached)
109
@@ -XXX,XX +XXX,XX @@ static void opentitan_board_init(MachineState *machine)
134
+{
110
135
+ DWORD err_code = NO_ERROR;
111
if (machine->kernel_filename) {
136
+ /* In order to make sure the serial that qemu-ga uses is the one that
112
riscv_load_kernel(machine, &s->soc.cpus,
137
+ * was detached. We'll get the error ERROR_FILE_NOT_FOUND when
113
- memmap[IBEX_DEV_RAM].base, NULL);
138
+ * attempting to call CreateFile with the serial path.
114
+ memmap[IBEX_DEV_RAM].base,
139
+ */
115
+ false, NULL);
140
+ return is_serial_attached && !is_serial_present(method, path, &err_code)
116
}
141
+ && err_code == ERROR_FILE_NOT_FOUND;
117
}
142
+}
118
143
diff --git a/qga/channel.h b/qga/channel.h
119
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
144
index XXXXXXX..XXXXXXX 100644
120
index XXXXXXX..XXXXXXX 100644
145
--- a/qga/channel.h
121
--- a/hw/riscv/sifive_e.c
146
+++ b/qga/channel.h
122
+++ b/hw/riscv/sifive_e.c
147
@@ -XXX,XX +XXX,XX @@
123
@@ -XXX,XX +XXX,XX @@ static void sifive_e_machine_init(MachineState *machine)
148
#ifndef QGA_CHANNEL_H
124
149
#define QGA_CHANNEL_H
125
if (machine->kernel_filename) {
150
126
riscv_load_kernel(machine, &s->soc.cpus,
151
+#ifndef _WIN32
127
- memmap[SIFIVE_E_DEV_DTIM].base, NULL);
152
+#define SUBSYSTEM_VIRTIO_SERIAL "virtio-ports";
128
+ memmap[SIFIVE_E_DEV_DTIM].base,
153
+#define SUBSYSTEM_ISA_SERIAL "isa-serial";
129
+ false, NULL);
154
+#endif
130
}
155
131
}
156
typedef struct GAChannel GAChannel;
132
157
133
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
158
@@ -XXX,XX +XXX,XX @@ GAChannel *ga_channel_new(GAChannelMethod method, const gchar *path,
134
index XXXXXXX..XXXXXXX 100644
159
void ga_channel_free(GAChannel *c);
135
--- a/hw/riscv/sifive_u.c
160
GIOStatus ga_channel_read(GAChannel *c, gchar *buf, gsize size, gsize *count);
136
+++ b/hw/riscv/sifive_u.c
161
GIOStatus ga_channel_write_all(GAChannel *c, const gchar *buf, gsize size);
137
@@ -XXX,XX +XXX,XX @@ static void sifive_u_machine_init(MachineState *machine)
162
+bool ga_channel_serial_is_present(GAChannelMethod method, const gchar *path);
138
firmware_end_addr);
163
+bool ga_channel_was_serial_attached(GAChannelMethod method, const gchar *path,
139
164
+ bool is_serial_attached);
140
kernel_entry = riscv_load_kernel(machine, &s->soc.u_cpus,
165
+bool ga_channel_was_serial_detached(GAChannelMethod method, const gchar *path,
141
- kernel_start_addr, NULL);
166
+ bool is_serial_attached);
142
-
167
143
- if (machine->initrd_filename) {
168
#endif
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,
169
--
211
--
170
2.9.4
212
2.39.1
171
172
diff view generated by jsdifflib
1
From: Sameeh Jubran <sjubran@redhat.com>
1
The only remaining caller is riscv_load_kernel_and_initrd() which
2
belongs to the same file.
2
3
3
Currently whenever the qemu-ga's service doesn't find the virtio-serial
4
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
4
it terminates. This commit addresses this issue by listening to the serial events
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
by registering for notifications for the chosen serial and it handles channel
6
Reviewed-by: Bin Meng <bmeng@tinylab.org>
6
initialization accordingily.
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
---
9
hw/riscv/boot.c | 80 ++++++++++++++++++++---------------------
10
include/hw/riscv/boot.h | 1 -
11
2 files changed, 40 insertions(+), 41 deletions(-)
7
12
8
A list of possible scenarios of which could lead to this behavour:
13
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
9
10
* qemu-ga's service is started while the virtio-serial driver hasn't been installed yet
11
* hotplug/ unplug of the virtio-serial device
12
* upgrading the virtio-serial driver
13
14
Note: This problem is much more common on Windows as the virtio-serial
15
driver should be installed by the user and isn't shipped with the Windows OS.
16
17
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
18
---
19
Makefile | 4 +
20
qga/main.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++--
21
qga/service-win32.h | 4 +
22
3 files changed, 239 insertions(+), 9 deletions(-)
23
24
diff --git a/Makefile b/Makefile
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/Makefile
15
--- a/hw/riscv/boot.c
27
+++ b/Makefile
16
+++ b/hw/riscv/boot.c
28
@@ -XXX,XX +XXX,XX @@ $(call set-vpath, $(SRC_PATH))
17
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_firmware(const char *firmware_filename,
29
18
exit(1);
30
LIBS+=-lz $(LIBS_TOOLS)
19
}
31
20
32
+ifndef CONFIG_WIN32
21
+static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
33
+LIBS_QGA+=-ludev
22
+{
34
+endif
23
+ const char *filename = machine->initrd_filename;
24
+ uint64_t mem_size = machine->ram_size;
25
+ void *fdt = machine->fdt;
26
+ hwaddr start, end;
27
+ ssize_t size;
35
+
28
+
36
HELPERS-$(CONFIG_LINUX) = qemu-bridge-helper$(EXESUF)
29
+ g_assert(filename != NULL);
37
38
ifdef BUILD_DOCS
39
diff --git a/qga/main.c b/qga/main.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/qga/main.c
42
+++ b/qga/main.c
43
@@ -XXX,XX +XXX,XX @@
44
#ifndef _WIN32
45
#include <syslog.h>
46
#include <sys/wait.h>
47
+#include <libudev.h>
48
+#include <sys/types.h>
49
#endif
50
#include "qapi/qmp/json-streamer.h"
51
#include "qapi/qmp/json-parser.h"
52
@@ -XXX,XX +XXX,XX @@
53
#include "qemu/sockets.h"
54
#include "qemu/systemd.h"
55
#ifdef _WIN32
56
+#include <dbt.h>
57
#include "qga/service-win32.h"
58
#include "qga/vss-win32.h"
59
#endif
60
@@ -XXX,XX +XXX,XX @@ struct GAState {
61
GLogLevelFlags log_level;
62
FILE *log_file;
63
bool logging_enabled;
64
+ bool serial_connected;
65
+#ifndef _WIN32
66
+ struct udev_monitor *udev_monitor;
67
+#endif
68
#ifdef _WIN32
69
GAService service;
70
#endif
71
@@ -XXX,XX +XXX,XX @@ static const char *ga_freeze_whitelist[] = {
72
#ifdef _WIN32
73
DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data,
74
LPVOID ctx);
75
+DWORD WINAPI handle_serial_device_events(DWORD type, LPVOID data);
76
VOID WINAPI service_main(DWORD argc, TCHAR *argv[]);
77
#endif
78
79
+static bool get_channel_method(GAChannelMethod *channel_method,
80
+ const gchar *method, GAState *s);
81
+static gboolean channel_init(GAState *s, const gchar *method, const gchar *path,
82
+ int listen_fd, bool *serial_connected);
83
+
30
+
84
static void
31
+ /*
85
init_dfl_pathnames(void)
32
+ * We want to put the initrd far enough into RAM that when the
86
{
33
+ * kernel is uncompressed it will not clobber the initrd. However
87
@@ -XXX,XX +XXX,XX @@ static void quit_handler(int sig)
34
+ * on boards without much RAM we must ensure that we still leave
88
}
35
+ * enough room for a decent sized initrd, and on boards with large
89
36
+ * amounts of RAM we must avoid the initrd being so far up in RAM
90
#ifndef _WIN32
37
+ * that it is outside lowmem and inaccessible to the kernel.
91
+static int get_method_udev_subsystem(const char **serial_subsystem)
38
+ * So for boards with less than 256MB of RAM we put the initrd
92
+{
39
+ * halfway into RAM, and for boards with 256MB of RAM or more we put
93
+ if (strcmp(ga_config->method, "virtio-serial") == 0) {
40
+ * the initrd at 128MB.
94
+ *serial_subsystem = SUBSYSTEM_VIRTIO_SERIAL;
41
+ */
95
+ } else if (strcmp(ga_config->method, "isa-serial") == 0) {
42
+ start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
96
+ /* try the default path for the serial port - COM1 */
97
+ *serial_subsystem = SUBSYSTEM_ISA_SERIAL;
98
+ } else {
99
+ serial_subsystem = NULL;
100
+ return -1;
101
+ }
102
+ return 0;
103
+}
104
+
43
+
105
+static gboolean serial_event_callback(GIOChannel *source,
44
+ size = load_ramdisk(filename, start, mem_size - start);
106
+ GIOCondition condition, gpointer data)
45
+ if (size == -1) {
107
+{
46
+ size = load_image_targphys(filename, start, mem_size - start);
108
+ struct udev_monitor *mon = ga_state->udev_monitor;
47
+ if (size == -1) {
109
+ const char *serial_subsystem = NULL;
48
+ error_report("could not load ramdisk '%s'", filename);
110
+ struct udev_device *dev;
49
+ exit(1);
111
+
112
+ if (get_method_udev_subsystem(&serial_subsystem) == -1) {
113
+ return false;
114
+ }
115
+ dev = udev_monitor_receive_device(mon);
116
+
117
+ if (dev && serial_subsystem && strcmp(udev_device_get_subsystem(dev),
118
+ serial_subsystem) == 0) {
119
+
120
+ GAChannelMethod channel_method;
121
+ get_channel_method(&channel_method, ga_config->method, ga_state);
122
+ if (ga_channel_was_serial_attached(channel_method,
123
+ ga_config->channel_path, ga_state->serial_connected)) {
124
+ ga_state->serial_connected = true;
125
+ if (!channel_init(ga_state,
126
+ ga_config->method, ga_config->channel_path,
127
+ ga_socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1,
128
+ &ga_state->serial_connected)) {
129
+ g_critical("failed to initialize guest agent channel");
130
+ }
131
+ }
50
+ }
132
+
133
+ if (ga_channel_was_serial_detached(channel_method,
134
+ ga_config->channel_path, ga_state->serial_connected)) {
135
+ ga_state->serial_connected = false;
136
+ ga_channel_free(ga_state->channel);
137
+ }
138
+ udev_device_unref(dev);
139
+ }
140
+ return true;
141
+}
142
+
143
+static int monitor_serial_events(void)
144
+{
145
+ int ret = 0;
146
+ const char *serial_subsystem = NULL;
147
+ struct udev *udev = NULL;
148
+ ga_state->udev_monitor = NULL;
149
+ GIOChannel *channel = NULL;
150
+ GSource *watch_source = NULL;
151
+ if (get_method_udev_subsystem(&serial_subsystem) == -1) {
152
+ ret = -1;
153
+ goto out;
154
+ }
51
+ }
155
+
52
+
156
+ udev = udev_new();
53
+ /* Some RISC-V machines (e.g. opentitan) don't have a fdt. */
157
+ if (!udev) {
54
+ if (fdt) {
158
+ g_error("Couldn't create udev\n");
55
+ end = start + size;
159
+ ret = -1;
56
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
160
+ goto out;
57
+ qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
161
+ }
162
+
163
+ ga_state->udev_monitor =
164
+ udev_monitor_new_from_netlink(udev, "udev");
165
+ if (!ga_state->udev_monitor) {
166
+ ret = -1;
167
+ goto out;
168
+ } else {
169
+ /* We don't want the udev_monitor to be freed on out, so increase
170
+ * ref count
171
+ */
172
+ udev_monitor_ref(ga_state->udev_monitor);
173
+ }
174
+
175
+ if (udev_monitor_filter_add_match_subsystem_devtype(ga_state->udev_monitor,
176
+ serial_subsystem, NULL) < 0 ||
177
+ udev_monitor_enable_receiving(ga_state->udev_monitor) < 0) {
178
+ ret = -1;
179
+ goto out;
180
+ }
181
+
182
+ channel =
183
+ g_io_channel_unix_new(udev_monitor_get_fd(ga_state->udev_monitor));
184
+ if (!channel) {
185
+ ret = -1;
186
+ goto out;
187
+ }
188
+ watch_source = g_io_create_watch(channel, G_IO_IN);
189
+ if (!watch_source) {
190
+ ret = -1;
191
+ goto out;
192
+ }
193
+ g_source_set_callback(watch_source, (GSourceFunc)serial_event_callback,
194
+ ga_state->udev_monitor, NULL);
195
+ g_source_attach(watch_source, g_main_loop_get_context(ga_state->main_loop));
196
+
197
+out:
198
+ if (udev) {
199
+ udev_unref(udev);
200
+ }
201
+ if (ga_state->udev_monitor) {
202
+ udev_monitor_unref(ga_state->udev_monitor);
203
+ }
204
+ if (channel) {
205
+ g_io_channel_unref(channel);
206
+ }
207
+ if (watch_source) {
208
+ g_source_unref(watch_source);
209
+ }
210
+
211
+ return ret;
212
+}
213
+
214
+static void free_monitor_resources(void)
215
+{
216
+ if (ga_state->udev_monitor) {
217
+ udev_monitor_unref(ga_state->udev_monitor);
218
+ }
58
+ }
219
+}
59
+}
220
+
60
+
221
static gboolean register_signal_handlers(void)
61
target_ulong riscv_load_kernel(MachineState *machine,
222
{
62
RISCVHartArrayState *harts,
223
struct sigaction sigact;
63
target_ulong kernel_start_addr,
224
@@ -XXX,XX +XXX,XX @@ static gboolean channel_event_cb(GIOCondition condition, gpointer data)
64
@@ -XXX,XX +XXX,XX @@ out:
225
return true;
65
return kernel_entry;
226
}
66
}
227
67
228
-static gboolean channel_init(GAState *s, const gchar *method, const gchar *path,
68
-void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
229
- int listen_fd)
69
-{
230
+static bool get_channel_method(GAChannelMethod *channel_method,
70
- const char *filename = machine->initrd_filename;
231
+ const gchar *method, GAState *s)
71
- uint64_t mem_size = machine->ram_size;
232
{
72
- void *fdt = machine->fdt;
233
- GAChannelMethod channel_method;
73
- hwaddr start, end;
234
+ assert(channel_method);
74
- ssize_t size;
235
+ assert(method);
236
237
if (strcmp(method, "virtio-serial") == 0) {
238
+ assert(s);
239
s->virtio = true; /* virtio requires special handling in some cases */
240
- channel_method = GA_CHANNEL_VIRTIO_SERIAL;
241
+ *channel_method = GA_CHANNEL_VIRTIO_SERIAL;
242
} else if (strcmp(method, "isa-serial") == 0) {
243
- channel_method = GA_CHANNEL_ISA_SERIAL;
244
+ *channel_method = GA_CHANNEL_ISA_SERIAL;
245
} else if (strcmp(method, "unix-listen") == 0) {
246
- channel_method = GA_CHANNEL_UNIX_LISTEN;
247
+ *channel_method = GA_CHANNEL_UNIX_LISTEN;
248
} else if (strcmp(method, "vsock-listen") == 0) {
249
- channel_method = GA_CHANNEL_VSOCK_LISTEN;
250
+ *channel_method = GA_CHANNEL_VSOCK_LISTEN;
251
} else {
252
g_critical("unsupported channel method/type: %s", method);
253
return false;
254
}
255
+ return true;
256
+}
257
+
258
+static gboolean channel_init(GAState *s, const gchar *method, const gchar *path,
259
+ int listen_fd, bool *serial_connected)
260
+{
261
+ assert(serial_connected);
262
+ GAChannelMethod channel_method;
263
+ if (!get_channel_method(&channel_method, method, s)) {
264
+ return false;
265
+ }
266
+ *serial_connected = ga_channel_serial_is_present(channel_method, path);
267
268
s->channel = ga_channel_new(channel_method, path, listen_fd,
269
channel_event_cb, s);
270
@@ -XXX,XX +XXX,XX @@ static gboolean channel_init(GAState *s, const gchar *method, const gchar *path,
271
}
272
273
#ifdef _WIN32
274
+DWORD WINAPI handle_serial_device_events(DWORD type, LPVOID data)
275
+{
276
+ DWORD ret = NO_ERROR;
277
+ PDEV_BROADCAST_HDR broadcast_header = (PDEV_BROADCAST_HDR)data;
278
+ GAChannelMethod channel_method;
279
+
280
+ if (broadcast_header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
281
+ get_channel_method(&channel_method, ga_config->method, ga_state);
282
+ switch (type) {
283
+ /* Device inserted */
284
+ case DBT_DEVICEARRIVAL:
285
+ /* Start QEMU-ga's service */
286
+ if (ga_channel_was_serial_attached(channel_method,
287
+ ga_config->channel_path, ga_state->serial_connected)) {
288
+ if (!channel_init(ga_state,
289
+ ga_config->method, ga_config->channel_path,
290
+ ga_socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1,
291
+ &ga_state->serial_connected)) {
292
+ g_critical("failed to initialize guest agent channel");
293
+ ret = EXIT_FAILURE;
294
+ }
295
+ }
296
+ break;
297
+ /* Device removed */
298
+ case DBT_DEVICEQUERYREMOVE:
299
+ case DBT_DEVICEREMOVEPENDING:
300
+ case DBT_DEVICEREMOVECOMPLETE:
301
+
302
+ /* Stop QEMU-ga's service */
303
+ if (ga_channel_was_serial_detached(channel_method,
304
+ ga_config->channel_path, ga_state->serial_connected)) {
305
+ ga_state->serial_connected = false;
306
+ ga_channel_free(ga_state->channel);
307
+ }
308
+ break;
309
+ default:
310
+ ret = ERROR_CALL_NOT_IMPLEMENTED;
311
+ }
312
+ }
313
+ return ret;
314
+}
315
+
316
DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data,
317
LPVOID ctx)
318
{
319
@@ -XXX,XX +XXX,XX @@ DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD type, LPVOID data,
320
service->status.dwCurrentState = SERVICE_STOP_PENDING;
321
SetServiceStatus(service->status_handle, &service->status);
322
break;
323
+ case SERVICE_CONTROL_DEVICEEVENT:
324
+ handle_serial_device_events(type, data);
325
+ break;
326
327
default:
328
ret = ERROR_CALL_NOT_IMPLEMENTED;
329
@@ -XXX,XX +XXX,XX @@ VOID WINAPI service_main(DWORD argc, TCHAR *argv[])
330
service->status.dwServiceSpecificExitCode = NO_ERROR;
331
service->status.dwCheckPoint = 0;
332
service->status.dwWaitHint = 0;
333
+ DEV_BROADCAST_DEVICEINTERFACE notification_filter;
334
+ ZeroMemory(&notification_filter, sizeof(notification_filter));
335
+ notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
336
+ notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
337
+ notification_filter.dbcc_classguid = GUID_VIOSERIAL_PORT;
338
+
339
+ service->device_notification_handle =
340
+ RegisterDeviceNotification(service->status_handle,
341
+ &notification_filter, DEVICE_NOTIFY_SERVICE_HANDLE);
342
+ if (!service->device_notification_handle) {
343
+ g_critical("Failed to register device notification handle!\n");
344
+ return;
345
+ }
346
SetServiceStatus(service->status_handle, &service->status);
347
348
g_main_loop_run(ga_state->main_loop);
349
350
+ UnregisterDeviceNotification(service->device_notification_handle);
351
service->status.dwCurrentState = SERVICE_STOPPED;
352
SetServiceStatus(service->status_handle, &service->status);
353
}
354
@@ -XXX,XX +XXX,XX @@ static int run_agent(GAState *s, GAConfig *config, int socket_activation)
355
#endif
356
357
s->main_loop = g_main_loop_new(NULL, false);
358
-
75
-
359
if (!channel_init(ga_state, config->method, config->channel_path,
76
- g_assert(filename != NULL);
360
- socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1)) {
77
-
361
+ socket_activation ? FIRST_SOCKET_ACTIVATION_FD : -1,
78
- /*
362
+ &ga_state->serial_connected) &&
79
- * We want to put the initrd far enough into RAM that when the
363
+ ga_state->serial_connected) {
80
- * kernel is uncompressed it will not clobber the initrd. However
364
g_critical("failed to initialize guest agent channel");
81
- * on boards without much RAM we must ensure that we still leave
365
return EXIT_FAILURE;
82
- * enough room for a decent sized initrd, and on boards with large
366
}
83
- * amounts of RAM we must avoid the initrd being so far up in RAM
367
#ifndef _WIN32
84
- * that it is outside lowmem and inaccessible to the kernel.
368
+ monitor_serial_events();
85
- * So for boards with less than 256MB of RAM we put the initrd
369
g_main_loop_run(ga_state->main_loop);
86
- * halfway into RAM, and for boards with 256MB of RAM or more we put
370
+ free_monitor_resources();
87
- * the initrd at 128MB.
371
#else
88
- */
372
if (config->daemonize) {
89
- start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
373
SERVICE_TABLE_ENTRY service_table[] = {
90
-
374
{ (char *)QGA_SERVICE_NAME, service_main }, { NULL, NULL } };
91
- size = load_ramdisk(filename, start, mem_size - start);
375
StartServiceCtrlDispatcher(service_table);
92
- if (size == -1) {
376
} else {
93
- size = load_image_targphys(filename, start, mem_size - start);
377
+ if (!ga_state->serial_connected) {
94
- if (size == -1) {
378
+ return EXIT_FAILURE;
95
- error_report("could not load ramdisk '%s'", filename);
379
+ }
96
- exit(1);
380
g_main_loop_run(ga_state->main_loop);
97
- }
381
}
98
- }
382
#endif
99
-
383
diff --git a/qga/service-win32.h b/qga/service-win32.h
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
/*
109
* This function makes an assumption that the DRAM interval
110
* 'dram_base' + 'dram_size' is contiguous.
111
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
384
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
385
--- a/qga/service-win32.h
113
--- a/include/hw/riscv/boot.h
386
+++ b/qga/service-win32.h
114
+++ b/include/hw/riscv/boot.h
387
@@ -XXX,XX +XXX,XX @@
115
@@ -XXX,XX +XXX,XX @@ target_ulong riscv_load_kernel(MachineState *machine,
388
#define QGA_SERVICE_NAME "qemu-ga"
116
target_ulong firmware_end_addr,
389
#define QGA_SERVICE_DESCRIPTION "Enables integration with QEMU machine emulator and virtualizer."
117
bool load_initrd,
390
118
symbol_fn_t sym_cb);
391
+static const GUID GUID_VIOSERIAL_PORT = { 0x6fde7521, 0x1b65, 0x48ae,
119
-void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry);
392
+{ 0xb6, 0x28, 0x80, 0xbe, 0x62, 0x1, 0x60, 0x26 } };
120
uint64_t riscv_compute_fdt_addr(hwaddr dram_start, uint64_t dram_size,
393
+
121
MachineState *ms);
394
typedef struct GAService {
122
void riscv_load_fdt(hwaddr fdt_addr, void *fdt);
395
SERVICE_STATUS status;
396
SERVICE_STATUS_HANDLE status_handle;
397
+ HDEVNOTIFY device_notification_handle;
398
} GAService;
399
400
int ga_install_service(const char *path, const char *logfile,
401
--
123
--
402
2.9.4
124
2.39.1
403
125
404
126
diff view generated by jsdifflib