Skip to content

Commit cb320a0

Browse files
committed
Merge remote-tracking branch 'remotes/stsquad/tags/pull-fixes-for-rc2-270720-1' into staging
Various fixes for rc2: - get shippable working again - semihosting bug fixes - tweak tb-size handling for low memory machines - i386 compound literal float fix - linux-user MAP_FIXED->MAP_NOREPLACE on fallback - docker binfmt_misc fixes - linux-user nanosleep fix - tests/vm drain console fixes # gpg: Signature made Mon 27 Jul 2020 09:45:31 BST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <[email protected]>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-fixes-for-rc2-270720-1: tests/vm: add shutdown timeout in basevm.py python/qemu: Change ConsoleSocket to optionally drain socket. python/qemu: Cleanup changes to ConsoleSocket linux-user, ppc: fix clock_nanosleep() for linux-user-ppc linux-user: fix clock_nanosleep() tests/docker: add support for DEB_KEYRING tests/docker: fix binfmt_misc image building tests/docker: fix update command due to python3 str/bytes distinction linux-user: don't use MAP_FIXED in pgd_find_hole_fallback target/i386: floatx80: avoid compound literals in static initializers accel/tcg: better handle memory constrained systems util/oslib-win32: add qemu_get_host_physmem implementation util: add qemu_get_host_physmem utility function semihosting: don't send the trailing '\0' semihosting: defer connect_chardevs a little more to use serialx shippable: add one more qemu to registry url Signed-off-by: Peter Maydell <[email protected]>
2 parents 4215d34 + 4a70232 commit cb320a0

File tree

18 files changed

+390
-311
lines changed

18 files changed

+390
-311
lines changed

.shippable.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ env:
2727
TARGET_LIST=ppc64-softmmu,ppc64-linux-user,ppc64abi32-linux-user
2828
build:
2929
pre_ci_boot:
30-
image_name: registry.gitlab.com/qemu-project/qemu/${IMAGE}
30+
image_name: registry.gitlab.com/qemu-project/qemu/qemu/${IMAGE}
3131
image_tag: latest
3232
pull: true
3333
options: "-e HOME=/root"

accel/tcg/translate-all.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,12 @@ static inline size_t size_code_gen_buffer(size_t tb_size)
976976
{
977977
/* Size the buffer. */
978978
if (tb_size == 0) {
979-
tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
979+
size_t phys_mem = qemu_get_host_physmem();
980+
if (phys_mem == 0) {
981+
tb_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
982+
} else {
983+
tb_size = MIN(DEFAULT_CODE_GEN_BUFFER_SIZE, phys_mem / 8);
984+
}
980985
}
981986
if (tb_size < MIN_CODE_GEN_BUFFER_SIZE) {
982987
tb_size = MIN_CODE_GEN_BUFFER_SIZE;

hw/semihosting/console.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ static GString *copy_user_string(CPUArchState *env, target_ulong addr)
5252

5353
do {
5454
if (cpu_memory_rw_debug(cpu, addr++, &c, 1, 0) == 0) {
55-
s = g_string_append_c(s, c);
55+
if (c) {
56+
s = g_string_append_c(s, c);
57+
}
5658
} else {
5759
qemu_log_mask(LOG_GUEST_ERROR,
5860
"%s: passed inaccessible address " TARGET_FMT_lx,

include/fpu/softfloat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ static inline bool floatx80_invalid_encoding(floatx80 a)
822822
}
823823

824824
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
825+
#define floatx80_zero_init make_floatx80_init(0x0000, 0x0000000000000000LL)
825826
#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
826827
#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
827828
#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)

include/qemu/osdep.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ extern int daemon(int, int);
173173
#ifndef MAP_ANONYMOUS
174174
#define MAP_ANONYMOUS MAP_ANON
175175
#endif
176+
#ifndef MAP_FIXED_NOREPLACE
177+
#define MAP_FIXED_NOREPLACE 0
178+
#endif
176179
#ifndef ENOMEDIUM
177180
#define ENOMEDIUM ENODEV
178181
#endif
@@ -668,4 +671,16 @@ static inline void qemu_reset_optind(void)
668671
*/
669672
char *qemu_get_host_name(Error **errp);
670673

674+
/**
675+
* qemu_get_host_physmem:
676+
*
677+
* Operating system agnostic way of querying host memory.
678+
*
679+
* Returns amount of physical memory on the system. This is purely
680+
* advisery and may return 0 if we can't work it out. At the other
681+
* end we saturate to SIZE_MAX if you are lucky enough to have that
682+
* much memory.
683+
*/
684+
size_t qemu_get_host_physmem(void);
685+
671686
#endif

linux-user/elfload.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,12 +2134,15 @@ static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk,
21342134
/* we have run out of space */
21352135
return -1;
21362136
} else {
2137-
int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE | MAP_FIXED;
2137+
int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE |
2138+
MAP_FIXED_NOREPLACE;
21382139
void * mmap_start = mmap((void *) align_start, guest_size,
21392140
PROT_NONE, flags, -1, 0);
21402141
if (mmap_start != MAP_FAILED) {
21412142
munmap((void *) align_start, guest_size);
2142-
return (uintptr_t) mmap_start + offset;
2143+
if (MAP_FIXED_NOREPLACE || mmap_start == (void *) align_start) {
2144+
return (uintptr_t) mmap_start + offset;
2145+
}
21432146
}
21442147
base += qemu_host_page_size;
21452148
}
@@ -2307,9 +2310,8 @@ static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr,
23072310
/* Widen the "image" to the entire reserved address space. */
23082311
pgb_static(image_name, 0, reserved_va, align);
23092312

2310-
#ifdef MAP_FIXED_NOREPLACE
2313+
/* osdep.h defines this as 0 if it's missing */
23112314
flags |= MAP_FIXED_NOREPLACE;
2312-
#endif
23132315

23142316
/* Reserve the memory on the host. */
23152317
assert(guest_base != 0);

linux-user/syscall.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11831,16 +11831,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
1183111831
target_to_host_timespec(&ts, arg3);
1183211832
ret = get_errno(safe_clock_nanosleep(arg1, arg2,
1183311833
&ts, arg4 ? &ts : NULL));
11834-
if (arg4)
11834+
/*
11835+
* if the call is interrupted by a signal handler, it fails
11836+
* with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
11837+
* TIMER_ABSTIME, it returns the remaining unslept time in arg4.
11838+
*/
11839+
if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME) {
1183511840
host_to_target_timespec(arg4, &ts);
11836-
11837-
#if defined(TARGET_PPC)
11838-
/* clock_nanosleep is odd in that it returns positive errno values.
11839-
* On PPC, CR0 bit 3 should be set in such a situation. */
11840-
if (ret && ret != -TARGET_ERESTARTSYS) {
11841-
((CPUPPCState *)cpu_env)->crf[0] |= 1;
1184211841
}
11843-
#endif
11842+
1184411843
return ret;
1184511844
}
1184611845
#endif

python/qemu/console_socket.py

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
#!/usr/bin/env python3
2-
#
3-
# This python module implements a ConsoleSocket object which is
4-
# designed always drain the socket itself, and place
5-
# the bytes into a in memory buffer for later processing.
6-
#
7-
# Optionally a file path can be passed in and we will also
8-
# dump the characters to this file for debug.
9-
#
1+
"""
2+
QEMU Console Socket Module:
3+
4+
This python module implements a ConsoleSocket object,
5+
which can drain a socket and optionally dump the bytes to file.
6+
"""
107
# Copyright 2020 Linaro
118
#
129
# Authors:
@@ -15,96 +12,118 @@
1512
# This code is licensed under the GPL version 2 or later. See
1613
# the COPYING file in the top-level directory.
1714
#
18-
import asyncore
15+
1916
import socket
2017
import threading
21-
import io
22-
import os
23-
import sys
2418
from collections import deque
2519
import time
26-
import traceback
2720

28-
class ConsoleSocket(asyncore.dispatcher):
2921

30-
def __init__(self, address, file=None):
22+
class ConsoleSocket(socket.socket):
23+
"""
24+
ConsoleSocket represents a socket attached to a char device.
25+
26+
Optionally (if drain==True), drains the socket and places the bytes
27+
into an in memory buffer for later processing.
28+
29+
Optionally a file path can be passed in and we will also
30+
dump the characters to this file for debugging purposes.
31+
"""
32+
def __init__(self, address, file=None, drain=False):
3133
self._recv_timeout_sec = 300
34+
self._sleep_time = 0.5
3235
self._buffer = deque()
33-
self._asyncore_thread = None
34-
self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
35-
self._sock.connect(address)
36+
socket.socket.__init__(self, socket.AF_UNIX, socket.SOCK_STREAM)
37+
self.connect(address)
3638
self._logfile = None
3739
if file:
3840
self._logfile = open(file, "w")
39-
asyncore.dispatcher.__init__(self, sock=self._sock)
4041
self._open = True
41-
self._thread_start()
42+
if drain:
43+
self._drain_thread = self._thread_start()
44+
else:
45+
self._drain_thread = None
4246

43-
def _thread_start(self):
44-
"""Kick off a thread to wait on the asyncore.loop"""
45-
if self._asyncore_thread is not None:
46-
return
47-
self._asyncore_thread = threading.Thread(target=asyncore.loop,
48-
kwargs={'timeout':1})
49-
self._asyncore_thread.daemon = True
50-
self._asyncore_thread.start()
47+
def _drain_fn(self):
48+
"""Drains the socket and runs while the socket is open."""
49+
while self._open:
50+
try:
51+
self._drain_socket()
52+
except socket.timeout:
53+
# The socket is expected to timeout since we set a
54+
# short timeout to allow the thread to exit when
55+
# self._open is set to False.
56+
time.sleep(self._sleep_time)
5157

52-
def handle_close(self):
53-
"""redirect close to base class"""
54-
# Call the base class close, but not self.close() since
55-
# handle_close() occurs in the context of the thread which
56-
# self.close() attempts to join.
57-
asyncore.dispatcher.close(self)
58+
def _thread_start(self):
59+
"""Kick off a thread to drain the socket."""
60+
# Configure socket to not block and timeout.
61+
# This allows our drain thread to not block
62+
# on recieve and exit smoothly.
63+
socket.socket.setblocking(self, False)
64+
socket.socket.settimeout(self, 1)
65+
drain_thread = threading.Thread(target=self._drain_fn)
66+
drain_thread.daemon = True
67+
drain_thread.start()
68+
return drain_thread
5869

5970
def close(self):
6071
"""Close the base object and wait for the thread to terminate"""
6172
if self._open:
6273
self._open = False
63-
asyncore.dispatcher.close(self)
64-
if self._asyncore_thread is not None:
65-
thread, self._asyncore_thread = self._asyncore_thread, None
74+
if self._drain_thread is not None:
75+
thread, self._drain_thread = self._drain_thread, None
6676
thread.join()
77+
socket.socket.close(self)
6778
if self._logfile:
6879
self._logfile.close()
6980
self._logfile = None
7081

71-
def handle_read(self):
82+
def _drain_socket(self):
7283
"""process arriving characters into in memory _buffer"""
73-
try:
74-
data = asyncore.dispatcher.recv(self, 1)
75-
# latin1 is needed since there are some chars
76-
# we are receiving that cannot be encoded to utf-8
77-
# such as 0xe2, 0x80, 0xA6.
78-
string = data.decode("latin1")
79-
except:
80-
print("Exception seen.")
81-
traceback.print_exc()
82-
return
84+
data = socket.socket.recv(self, 1)
85+
# latin1 is needed since there are some chars
86+
# we are receiving that cannot be encoded to utf-8
87+
# such as 0xe2, 0x80, 0xA6.
88+
string = data.decode("latin1")
8389
if self._logfile:
8490
self._logfile.write("{}".format(string))
8591
self._logfile.flush()
8692
for c in string:
8793
self._buffer.extend(c)
8894

89-
def recv(self, n=1, sleep_delay_s=0.1):
90-
"""Return chars from in memory buffer"""
95+
def recv(self, bufsize=1):
96+
"""Return chars from in memory buffer.
97+
Maintains the same API as socket.socket.recv.
98+
"""
99+
if self._drain_thread is None:
100+
# Not buffering the socket, pass thru to socket.
101+
return socket.socket.recv(self, bufsize)
91102
start_time = time.time()
92-
while len(self._buffer) < n:
93-
time.sleep(sleep_delay_s)
103+
while len(self._buffer) < bufsize:
104+
time.sleep(self._sleep_time)
94105
elapsed_sec = time.time() - start_time
95106
if elapsed_sec > self._recv_timeout_sec:
96107
raise socket.timeout
97-
chars = ''.join([self._buffer.popleft() for i in range(n)])
108+
chars = ''.join([self._buffer.popleft() for i in range(bufsize)])
98109
# We choose to use latin1 to remain consistent with
99110
# handle_read() and give back the same data as the user would
100111
# receive if they were reading directly from the
101112
# socket w/o our intervention.
102113
return chars.encode("latin1")
103114

104-
def set_blocking(self):
105-
"""Maintain compatibility with socket API"""
106-
pass
115+
def setblocking(self, value):
116+
"""When not draining we pass thru to the socket,
117+
since when draining we control socket blocking.
118+
"""
119+
if self._drain_thread is None:
120+
socket.socket.setblocking(self, value)
107121

108122
def settimeout(self, seconds):
109-
"""Set current timeout on recv"""
110-
self._recv_timeout_sec = seconds
123+
"""When not draining we pass thru to the socket,
124+
since when draining we control the timeout.
125+
"""
126+
if seconds is not None:
127+
self._recv_timeout_sec = seconds
128+
if self._drain_thread is None:
129+
socket.socket.settimeout(self, seconds)

python/qemu/machine.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,10 @@
2323
import subprocess
2424
import shutil
2525
import signal
26-
import socket
2726
import tempfile
2827
from typing import Optional, Type
2928
from types import TracebackType
30-
from qemu.console_socket import ConsoleSocket
29+
from . import console_socket
3130

3231
from . import qmp
3332

@@ -673,11 +672,8 @@ def console_socket(self):
673672
Returns a socket connected to the console
674673
"""
675674
if self._console_socket is None:
676-
if self._drain_console:
677-
self._console_socket = ConsoleSocket(self._console_address,
678-
file=self._console_log_path)
679-
else:
680-
self._console_socket = socket.socket(socket.AF_UNIX,
681-
socket.SOCK_STREAM)
682-
self._console_socket.connect(self._console_address)
675+
self._console_socket = console_socket.ConsoleSocket(
676+
self._console_address,
677+
file=self._console_log_path,
678+
drain=self._drain_console)
683679
return self._console_socket

python/qemu/pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ good-names=i,
3333
Run,
3434
_,
3535
fd,
36-
36+
c,
3737
[VARIABLES]
3838

3939
[STRING]

0 commit comments

Comments
 (0)