merge with xen-unstable.hg

This commit is contained in:
awilliam@xenbuild.aw committed 2006-09-10 14:52:57 -06:00
commit fc81946a2c
21 files changed
+339 -193

No files matched your search

+4 -3
View File
@@ -432,7 +432,6 @@ bug report.
Sample xen domain info looks as follows (lines wrapped manually to
make the man page more readable):
system : Linux
host : talon
release : 2.6.12.6-xen0
version : #1 Mon Nov 14 14:26:26 EST 2005
@@ -444,13 +443,14 @@ make the man page more readable):
threads_per_core : 1
cpu_mhz : 696
hw_caps : 0383fbff:00000000:00000000:00000040
memory : 767
total_memory : 767
free_memory : 37
xen_major : 3
xen_minor : 0
xen_extra : -devel
xen_caps : xen-3.0-x86_32
xen_params : virt_start=0xfc000000
xen_pagesize : 4096
platform_params : virt_start=0xfc000000
xen_changeset : Mon Nov 14 18:13:38 2005 +0100
7793:090e44133d40
cc_compiler : gcc version 3.4.3 (Mandrakelinux
@@ -458,6 +458,7 @@ make the man page more readable):
cc_compile_by : sdague
cc_compile_domain : (none)
cc_compile_date : Mon Nov 14 14:16:48 EST 2005
xend_config_format : 2
B<FIELDS>
+44 -12
View File
@@ -1654,26 +1654,58 @@ Now unmount (this is important!):
In the configuration file set:
\begin{quote}
\verb_disk = ['file:/full/path/to/vm1disk,sda1,w']_
\verb_disk = ['tap:aio:/full/path/to/vm1disk,sda1,w']_
\end{quote}
As the virtual machine writes to its `disk', the sparse file will be
filled in and consume more space up to the original 2GB.
{\bf Note that file-backed VBDs may not be appropriate for backing
I/O-intensive domains.} File-backed VBDs are known to experience
{\em{Note:}} Users that have worked with file-backed VBDs on Xen in previous
versions will be interested to know that this support is now provided through
the blktap driver instead of the loopback driver. This change results in
file-based block devices that are higher-performance, more scalable, and which
provide better safety properties for VBD data. All that is required to update
your existing file-backed VM configurations is to change VBD configuration
lines from:
\begin{quote}
\verb_disk = ['file:/full/path/to/vm1disk,sda1,w']_
\end{quote}
to:
\begin{quote}
\verb_disk = ['tap:aio:/full/path/to/vm1disk,sda1,w']_
\end{quote}
\subsection{Loopback-mounted file-backed VBDs (deprecated)}
{\em{{\bf{Note:}} Loopback mounted VBDs have now been replaced with
blktap-based support for raw image files, as described above. This
section remains to detail a configuration that was used by older Xen
versions.}}
Raw image file-backed VBDs amy also be attached to VMs using the
Linux loopback driver. The only required change to the raw file
instructions above are to specify the configuration entry as:
\begin{quote}
\verb_disk = ['file:/full/path/to/vm1disk,sda1,w']_
\end{quote}
{\bf Note that loopback file-backed VBDs may not be appropriate for backing
I/O-intensive domains.} This approach is known to experience
substantial slowdowns under heavy I/O workloads, due to the I/O
handling by the loopback block device used to support file-backed VBDs
in dom0. Better I/O performance can be achieved by using either
LVM-backed VBDs (Section~\ref{s:using-lvm-backed-vbds}) or physical
devices as VBDs (Section~\ref{s:exporting-physical-devices-as-vbds}).
in dom0. Loopbach support remains for old Xen installations, and users
are strongly encouraged to use the blktap-based file support (using
``{\tt{tap:aio}}'' as described above).
Linux supports a maximum of eight file-backed VBDs across all domains
by default. This limit can be statically increased by using the
\emph{max\_loop} module parameter if CONFIG\_BLK\_DEV\_LOOP is
compiled as a module in the dom0 kernel, or by using the
\emph{max\_loop=n} boot option if CONFIG\_BLK\_DEV\_LOOP is compiled
directly into the dom0 kernel.
Additionally, Linux supports a maximum of eight loopback file-backed
VBDs across all domains by default. This limit can be statically
increased by using the \emph{max\_loop} module parameter if
CONFIG\_BLK\_DEV\_LOOP is compiled as a module in the dom0 kernel, or
by using the \emph{max\_loop=n} boot option if CONFIG\_BLK\_DEV\_LOOP
is compiled directly into the dom0 kernel. Again, users are encouraged
to use the blktap-based file support described above which scales to much
larger number of active VBDs.
\section{Using LVM-backed VBDs}
@@ -182,17 +182,18 @@ static struct console kcons_info = {
.index = -1,
};
#define __RETCODE 0
static int __init xen_console_init(void)
{
if (!is_running_on_xen())
return __RETCODE;
goto out;
if (is_initial_xendomain()) {
if (xc_mode == XC_DEFAULT)
xc_mode = XC_SERIAL;
kcons_info.write = kcons_write_dom0;
} else {
if (!xen_start_info->console.domU.evtchn)
goto out;
if (xc_mode == XC_DEFAULT)
xc_mode = XC_TTY;
kcons_info.write = kcons_write;
@@ -212,14 +213,15 @@ static int __init xen_console_init(void)
break;
default:
return __RETCODE;
goto out;
}
wbuf = alloc_bootmem(wbuf_size);
register_console(&kcons_info);
return __RETCODE;
out:
return 0;
}
console_initcall(xen_console_init);
@@ -247,7 +249,9 @@ void xencons_force_flush(void)
int sz;
/* Emergency console is synchronous, so there's nothing to flush. */
if (is_initial_xendomain())
if (!is_running_on_xen() ||
is_initial_xendomain() ||
!xen_start_info->console.domU.evtchn)
return;
/* Spin until console data is flushed through to the daemon. */
@@ -582,7 +586,11 @@ static int __init xencons_init(void)
if (xc_mode == XC_OFF)
return 0;
xencons_ring_init();
if (!is_initial_xendomain()) {
rc = xencons_ring_init();
if (rc)
return rc;
}
xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
1 : MAX_NR_CONSOLES);
@@ -110,24 +110,26 @@ static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
int xencons_ring_init(void)
{
int err;
int irq;
if (xencons_irq)
unbind_from_irqhandler(xencons_irq, NULL);
xencons_irq = 0;
if (!xen_start_info->console.domU.evtchn)
return 0;
if (!is_running_on_xen() ||
is_initial_xendomain() ||
!xen_start_info->console.domU.evtchn)
return -ENODEV;
err = bind_evtchn_to_irqhandler(
irq = bind_evtchn_to_irqhandler(
xen_start_info->console.domU.evtchn,
handle_input, 0, "xencons", NULL);
if (err <= 0) {
printk(KERN_ERR "XEN console request irq failed %i\n", err);
return err;
if (irq < 0) {
printk(KERN_ERR "XEN console request irq failed %i\n", irq);
return irq;
}
xencons_irq = err;
xencons_irq = irq;
/* In case we have in-flight data after save/restore... */
notify_daemon();
@@ -427,6 +427,14 @@ static int connect_rings(struct backend_info *be)
be->netif->dev->features |= NETIF_F_TSO;
}
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
"%d", &val) < 0)
val = 0;
if (val) {
be->netif->features &= ~NETIF_F_IP_CSUM;
be->netif->dev->features &= ~NETIF_F_IP_CSUM;
}
/* Map the shared frame, irq etc. */
err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
if (err) {
+25 -4
View File
@@ -237,6 +237,25 @@ static uint32_t gen_cksum(char *ptr, int len)
return ret;
}
static int get_filesize(char *filename, uint64_t *size, struct stat *st)
{
int blockfd;
/*Set to the backing file size*/
if(S_ISBLK(st->st_mode)) {
blockfd = open(filename, O_RDONLY);
if (blockfd < 0)
return -1;
if (ioctl(blockfd,BLKGETSIZE,size)!=0) {
printf("Unable to get Block device size\n");
close(blockfd);
return -1;
}
close(blockfd);
} else *size = (st->st_size >> SECTOR_SHIFT);
return 0;
}
static int qcow_set_key(struct td_state *bs, const char *key)
{
struct tdqcow_state *s = (struct tdqcow_state *)bs->private;
@@ -1204,12 +1223,14 @@ int qcow_create(const char *filename, uint64_t total_size,
header_size += backing_filename_len;
/*Set to the backing file size*/
size = (st.st_size >> SECTOR_SHIFT);
if(get_filesize(backing_filename, &size, &st)) {
return -1;
}
DPRINTF("Backing file size detected: %lld sectors"
"(total %lld [%lld MB])\n",
(long long)total_size,
(long long)(total_size << SECTOR_SHIFT),
(long long)(total_size >> 11));
(long long)size,
(long long)(size << SECTOR_SHIFT),
(long long)(size >> 11));
} else {
backing_file = NULL;
DPRINTF("Setting file size: %lld (total %lld)\n",
+9 -14
View File
@@ -127,18 +127,15 @@ void sig_handler(int sig)
static inline int LOCAL_FD_SET(fd_set *readfds)
{
fd_list_entry_t *ptr;
int i;
ptr = fd_start;
while (ptr != NULL) {
if (ptr->tap_fd) {
FD_SET(ptr->tap_fd, readfds);
for (i = 0; i < MAX_IOFD; i++) {
if (ptr->io_fd[i])
FD_SET(ptr->io_fd[i], readfds);
maxfds = (ptr->io_fd[i] > maxfds ?
ptr->io_fd[i]: maxfds);
}
if (ptr->io_fd[READ])
FD_SET(ptr->io_fd[READ], readfds);
maxfds = (ptr->io_fd[READ] > maxfds ?
ptr->io_fd[READ]: maxfds);
maxfds = (ptr->tap_fd > maxfds ? ptr->tap_fd: maxfds);
}
ptr = ptr->next;
@@ -580,7 +577,7 @@ static void get_io_request(struct td_state *s)
int main(int argc, char *argv[])
{
int len, msglen, ret, i;
int len, msglen, ret;
char *p, *buf;
fd_set readfds, writefds;
struct timeval timeout;
@@ -633,16 +630,14 @@ int main(int argc, char *argv[])
(fd_set *) 0, &timeout);
if (ret > 0)
{
{
ptr = fd_start;
while (ptr != NULL) {
if (FD_ISSET(ptr->tap_fd, &readfds))
get_io_request(ptr->s);
for (i = 0; i < MAX_IOFD; i++) {
if (ptr->io_fd[i] &&
FD_ISSET(ptr->io_fd[i], &readfds))
io_done(ptr->s, i);
}
if (ptr->io_fd[READ] &&
FD_ISSET(ptr->io_fd[READ], &readfds))
io_done(ptr->s, READ);
ptr = ptr->next;
}
+2 -1
View File
@@ -220,7 +220,8 @@ int main(int argc, char **argv)
user friendly, we'll bail out here since no data will ever show
up on domain-0. */
if (domid == 0) {
err(errno, "Could not read tty from store");
fprintf(stderr, "Can't specify Domain-0\n");
exit(EINVAL);
}
/* Wait a little bit for tty to appear. There is a race
+5
View File
@@ -48,6 +48,9 @@ else
function vtpm_migrate() {
echo "Error: vTPM migration accross machines not implemented."
}
function vtpm_migrate_local() {
echo "Error: local vTPM migration not supported"
}
function vtpm_migrate_recover() {
true
}
@@ -353,6 +356,8 @@ function vtpm_migration_step() {
local res=$(vtpm_isLocalAddress $1)
if [ "$res" == "0" ]; then
vtpm_migrate $1 $2 $3
else
vtpm_migrate_local
fi
}
+3
View File
@@ -184,3 +184,6 @@ function vtpm_migrate_recover() {
echo "Error: Recovery not supported yet"
}
function vtpm_migrate_local() {
echo "Error: local vTPM migration not supported"
}
+4
View File
@@ -420,6 +420,10 @@ class XendDomain:
""" The following call may raise a XendError exception """
dominfo.testMigrateDevices(True, dst)
if live:
""" Make sure there's memory free for enabling shadow mode """
dominfo.checkLiveMigrateMemory()
if port == 0:
port = xroot.get_xend_relocation_port()
try:
+46 -14
View File
@@ -49,6 +49,7 @@ from xen.xend.xenstore.xstransact import xstransact, complete
from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
from xen.xend.xenstore.xswatch import xswatch
from xen.xend import arch
"""Shutdown code for poweroff."""
DOMAIN_POWEROFF = 0
@@ -1087,6 +1088,15 @@ class XendDomainInfo:
## public:
def destroyDevice(self, deviceClass, devid):
if type(devid) is str:
devicePath = '%s/device/%s' % (self.dompath, deviceClass)
for entry in xstransact.List(devicePath):
backend = xstransact.Read('%s/%s' % (devicePath, entry), "backend")
devName = xstransact.Read(backend, "dev")
if devName == devid:
# We found the integer matching our devid, use it instead
devid = entry
break
return self.getDeviceController(deviceClass).destroyDevice(devid)
@@ -1285,28 +1295,37 @@ class XendDomainInfo:
for v in range(0, self.info['max_vcpu_id']+1):
xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
# Use architecture- and image-specific calculations to determine
# the various headrooms necessary, given the raw configured
# values.
# reservation, maxmem, memory, and shadow are all in KiB.
reservation = self.image.getRequiredInitialReservation(
self.info['memory'] * 1024)
maxmem = self.image.getRequiredAvailableMemory(
self.info['maxmem'] * 1024)
memory = self.image.getRequiredAvailableMemory(
self.info['memory'] * 1024)
shadow = self.image.getRequiredShadowMemory(
self.info['shadow_memory'] * 1024,
self.info['maxmem'] * 1024)
# Round shadow up to a multiple of a MiB, as shadow_mem_control
# takes MiB and we must not round down and end up under-providing.
shadow = ((shadow + 1023) / 1024) * 1024
# set memory limit
maxmem = self.image.getRequiredMemory(self.info['maxmem'] * 1024)
xc.domain_setmaxmem(self.domid, maxmem)
mem_kb = self.image.getRequiredMemory(self.info['memory'] * 1024)
# get the domain's shadow memory requirement
shadow_kb = self.image.getRequiredShadowMemory(mem_kb)
shadow_kb_req = self.info['shadow_memory'] * 1024
if shadow_kb_req > shadow_kb:
shadow_kb = shadow_kb_req
shadow_mb = (shadow_kb + 1023) / 1024
# Make sure there's enough RAM available for the domain
balloon.free(mem_kb + shadow_mb * 1024)
balloon.free(memory + shadow)
# Set up the shadow memory
shadow_cur = xc.shadow_mem_control(self.domid, shadow_mb)
shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024)
self.info['shadow_memory'] = shadow_cur
# initial memory allocation
xc.domain_memory_increase_reservation(self.domid, mem_kb, 0, 0)
# initial memory reservation
xc.domain_memory_increase_reservation(self.domid, reservation, 0,
0)
self.createChannels()
@@ -1485,6 +1504,19 @@ class XendDomainInfo:
## public:
def checkLiveMigrateMemory(self):
""" Make sure there's enough memory to migrate this domain """
overhead_kb = 0
if arch.type == "x86":
# 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
# the minimum that Xen would allocate if no value were given.
overhead_kb = self.info['vcpus'] * 1024 + self.info['maxmem'] * 4
overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
# The domain might already have some shadow memory
overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
if overhead_kb > 0:
balloon.free(overhead_kb)
def testMigrateDevices(self, network, dst):
""" Notify all device about intention of migration
@raise: XendError for a device that cannot be migrated
+35 -10
View File
@@ -143,12 +143,27 @@ class ImageHandler:
raise VmError('Building domain failed: ostype=%s dom=%d err=%s'
% (self.ostype, self.vm.getDomid(), str(result)))
def getRequiredMemory(self, mem_kb):
def getRequiredAvailableMemory(self, mem_kb):
"""@param mem_kb The configured maxmem or memory, in KiB.
@return The corresponding required amount of memory for the domain,
also in KiB. This is normally the given mem_kb, but architecture- or
image-specific code may override this to add headroom where
necessary."""
return mem_kb
def getRequiredShadowMemory(self, mem_kb):
"""@return The minimum shadow memory required, in KiB, for a domain
with mem_kb KiB of RAM."""
def getRequiredInitialReservation(self, mem_kb):
"""@param mem_kb The configured memory, in KiB.
@return The corresponding required amount of memory to be free, also
in KiB. This is normally the same as getRequiredAvailableMemory, but
architecture- or image-specific code may override this to
add headroom where necessary."""
return self.getRequiredAvailableMemory(mem_kb)
def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
"""@param shadow_mem_kb The configured shadow memory, in KiB.
@param maxmem_kb The configured maxmem, in KiB.
@return The corresponding required amount of shadow memory, also in
KiB."""
# PV domains don't need any shadow memory
return 0
@@ -418,7 +433,7 @@ class IA64_HVM_ImageHandler(HVMImageHandler):
ostype = "hvm"
def getRequiredMemory(self, mem_kb):
def getRequiredAvailableMemory(self, mem_kb):
page_kb = 16
# ROM size for guest firmware, ioreq page and xenstore page
extra_pages = 1024 + 2
@@ -432,19 +447,29 @@ class X86_HVM_ImageHandler(HVMImageHandler):
ostype = "hvm"
def getRequiredMemory(self, mem_kb):
def getRequiredAvailableMemory(self, mem_kb):
# Add 8 MiB overhead for QEMU's video RAM.
return self.getRequiredInitialReservation(mem_kb) + 8192
def getRequiredInitialReservation(self, mem_kb):
page_kb = 4
# This was derived emperically:
# 2.4 MB overhead per 1024 MB RAM + 8 MB constant
# 2.4 MB overhead per 1024 MB RAM
# + 4 to avoid low-memory condition
extra_mb = (2.4/1024) * (mem_kb/1024.0) + 12;
extra_mb = (2.4/1024) * (mem_kb/1024.0) + 4;
extra_pages = int( math.ceil( extra_mb*1024 / page_kb ))
return mem_kb + extra_pages * page_kb
def getRequiredShadowMemory(self, mem_kb):
def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
# The given value is the configured value -- we need to include the
# overhead due to getRequiredInitialReservation.
maxmem_kb = self.getRequiredInitialReservation(maxmem_kb)
# 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than
# the minimum that Xen would allocate if no value were given.
return 1024 * self.vm.getVCpuCount() + mem_kb / 256
return max(1024 * self.vm.getVCpuCount() + maxmem_kb / 256,
shadow_mem_kb)
_handlers = {
"powerpc": {
+1 -1
View File
@@ -1,5 +1,5 @@
from xen.xend.XendLogging import log
from xen.xend.XendError import XendError
from xen.xend.XendError import XendError, VmError
import sys
import os.path
from xen.xend.sxp import *
+3
View File
@@ -1169,6 +1169,9 @@ def main(argv):
if not opts:
return
if type(config) == str:
config = sxp.parse(file(config))[0]
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
else:
+4
View File
@@ -51,6 +51,7 @@ class test_create(unittest.TestCase):
'path' : '.:/etc/xen',
'builder' : 'linux',
'nics' : -1,
'vncunused' : 1,
'xauthority': xen.xm.create.get_xauthority(),
})
@@ -101,6 +102,7 @@ on_crash = 'destroy'
'path' : '.:/etc/xen',
'builder' : 'linux',
'vncunused' : 1,
'xauthority' : xen.xm.create.get_xauthority(),
})
@@ -140,6 +142,7 @@ cpu_weight = 0.75
'builder' : 'linux',
'nics' : -1,
'vncunused' : 1,
'xauthority' : xen.xm.create.get_xauthority(),
})
@@ -182,6 +185,7 @@ ne2000=0
xen.xm.create.VNC_BASE_PORT +
xen.xm.create.choose_vnc_display())),
'vnc' : 1,
'vncunused' : 1,
'vncviewer' : 1,
'xm_file' : fname,
+3
View File
@@ -672,6 +672,9 @@ def main():
parser = setup_cmdline_parser()
(options, args) = parser.parse_args()
if options.mspersample < 0:
parser.error("option --ms_per_sample: invalid negative value: '%d'" %
options.mspersample)
start_xenbaked()
if options.live:
@@ -17,6 +17,7 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -25,6 +26,8 @@
#include <linux/init.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -47,7 +50,6 @@ MODULE_AUTHOR("ssmith@xensource.com");
MODULE_DESCRIPTION("Xen platform PCI device");
MODULE_LICENSE("GPL");
unsigned long *phys_to_machine_mapping;
EXPORT_SYMBOL(phys_to_machine_mapping);
@@ -118,7 +120,7 @@ unsigned long alloc_xen_mmio(unsigned long len)
/* Lifted from hvmloader.c */
static int get_hypercall_stubs(void)
{
uint32_t eax, ebx, ecx, edx, pages, msr, order, i;
uint32_t eax, ebx, ecx, edx, pages, msr, i;
char signature[13];
cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
@@ -141,22 +143,22 @@ static int get_hypercall_stubs(void)
cpuid(0x40000002, &pages, &msr, &ecx, &edx);
i = pages - 1;
for (order = 0; i != 0; order++)
i >>= 1;
printk(KERN_INFO "Hypercall area is %u pages.\n", pages);
printk(KERN_INFO "Hypercall area is %u pages (order %u allocation)\n",
pages, order);
hypercall_stubs = (void *)__get_free_pages(GFP_KERNEL, order);
/* Use __vmalloc() because vmalloc_exec() is not an exported symbol. */
/* PAGE_KERNEL_EXEC also is not exported, hence we use PAGE_KERNEL. */
/* hypercall_stubs = vmalloc_exec(pages * PAGE_SIZE); */
hypercall_stubs = __vmalloc(pages * PAGE_SIZE,
GFP_KERNEL | __GFP_HIGHMEM,
__pgprot(__PAGE_KERNEL & ~_PAGE_NX));
if (hypercall_stubs == NULL)
return -ENOMEM;
for (i = 0; i < pages; i++)
wrmsrl(ebx,
virt_to_phys(hypercall_stubs) + /* base address */
(i << PAGE_SHIFT) + /* offset of page @i */
i); /* request page @i */
for (i = 0; i < pages; i++) {
unsigned long pfn;
pfn = vmalloc_to_pfn((char *)hypercall_stubs + i*PAGE_SIZE);
wrmsrl(msr, ((u64)pfn << PAGE_SHIFT) + i);
}
return 0;
}
+4 -2
View File
@@ -1792,8 +1792,10 @@ void sh_install_xen_entries_in_l2h(struct vcpu *v,
for ( i = 0; i < MACHPHYS_MBYTES>>1; i++ )
{
sl2e[shadow_l2_table_offset(RO_MPT_VIRT_START) + i] =
shadow_l2e_from_mfn(_mfn(l3e_get_pfn(p2m[i])),
__PAGE_HYPERVISOR);
(l3e_get_flags(p2m[i]) & _PAGE_PRESENT)
? shadow_l2e_from_mfn(_mfn(l3e_get_pfn(p2m[i])),
__PAGE_HYPERVISOR)
: shadow_l2e_empty();
}
sh_unmap_domain_page(p2m);
}
+71 -75
View File
@@ -90,11 +90,8 @@ __gnttab_map_grant_ref(
unsigned long frame = 0;
int rc = GNTST_okay;
struct active_grant_entry *act;
/* Entry details from @rd's shared grant table. */
grant_entry_t *sha;
domid_t sdom;
u16 sflags;
union grant_combo scombo, prev_scombo, new_scombo;
/*
* We bound the number of times we retry CMPXCHG on memory locations that
@@ -159,7 +156,10 @@ __gnttab_map_grant_ref(
memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order);
for ( i = lgt->maptrack_limit; i < (lgt->maptrack_limit << 1); i++ )
{
new_mt[i].ref = i+1;
new_mt[i].flags = 0;
}
free_xenheap_pages(lgt->maptrack, lgt->maptrack_order);
lgt->maptrack = new_mt;
@@ -175,12 +175,19 @@ __gnttab_map_grant_ref(
spin_lock(&rd->grant_table->lock);
/* If already pinned, check the active domid and avoid refcnt overflow. */
if ( act->pin &&
((act->domid != ld->domain_id) ||
(act->pin & 0x80808080U) != 0) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad domain (%d != %d), or risk of counter overflow %08x\n",
act->domid, ld->domain_id, act->pin);
if ( !act->pin ||
(!(op->flags & GNTMAP_readonly) &&
!(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask))) )
{
sflags = sha->flags;
sdom = sha->domid;
scombo.word = *(u32 *)&sha->flags;
/*
* This loop attempts to set the access (reading/writing) flags
@@ -190,33 +197,29 @@ __gnttab_map_grant_ref(
*/
for ( ; ; )
{
union grant_combo scombo, prev_scombo, new_scombo;
/* If not already pinned, check the grant domid and type. */
if ( !act->pin &&
(((scombo.shorts.flags & GTF_type_mask) !=
GTF_permit_access) ||
(scombo.shorts.domid != ld->domain_id)) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad flags (%x) or dom (%d). (expected dom %d)\n",
scombo.shorts.flags, scombo.shorts.domid,
ld->domain_id);
if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
unlikely(sdom != led->domain->domain_id) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
sflags, sdom, led->domain->domain_id);
/* Merge two 16-bit values into a 32-bit combined update. */
scombo.shorts.flags = sflags;
scombo.shorts.domid = sdom;
new_scombo = scombo;
new_scombo.shorts.flags |= GTF_reading;
if ( !(op->flags & GNTMAP_readonly) )
{
new_scombo.shorts.flags |= GTF_writing;
if ( unlikely(sflags & GTF_readonly) )
if ( unlikely(scombo.shorts.flags & GTF_readonly) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a r/o grant entry.\n");
}
prev_scombo.word = cmpxchg((u32 *)&sha->flags,
scombo.word, new_scombo.word);
/* Did the combined update work (did we see what we expected?). */
if ( likely(prev_scombo.word == scombo.word) )
break;
@@ -224,20 +227,15 @@ __gnttab_map_grant_ref(
PIN_FAIL(unlock_out, GNTST_general_error,
"Shared grant entry is unstable.\n");
/* Didn't see what we expected. Split out the seen flags & dom. */
sflags = prev_scombo.shorts.flags;
sdom = prev_scombo.shorts.domid;
scombo = prev_scombo;
}
if ( !act->pin )
{
act->domid = sdom;
act->domid = scombo.shorts.domid;
act->frame = gmfn_to_mfn(rd, sha->frame);
}
}
else if ( (act->pin & 0x80808080U) != 0 )
PIN_FAIL(unlock_out, ENOSPC,
"Risk of counter overflow %08x\n", act->pin);
if ( op->flags & GNTMAP_device_map )
act->pin += (op->flags & GNTMAP_readonly) ?
@@ -545,9 +543,7 @@ gnttab_prepare_for_transfer(
{
struct grant_table *rgt;
struct grant_entry *sha;
domid_t sdom;
u16 sflags;
union grant_combo scombo, prev_scombo, tmp_scombo;
union grant_combo scombo, prev_scombo, new_scombo;
int retries = 0;
if ( unlikely((rgt = rd->grant_table) == NULL) ||
@@ -562,29 +558,24 @@ gnttab_prepare_for_transfer(
sha = &rgt->shared[ref];
sflags = sha->flags;
sdom = sha->domid;
scombo.word = *(u32 *)&sha->flags;
for ( ; ; )
{
if ( unlikely(sflags != GTF_accept_transfer) ||
unlikely(sdom != ld->domain_id) )
if ( unlikely(scombo.shorts.flags != GTF_accept_transfer) ||
unlikely(scombo.shorts.domid != ld->domain_id) )
{
DPRINTK("Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
sflags, sdom, ld->domain_id);
scombo.shorts.flags, scombo.shorts.domid,
ld->domain_id);
goto fail;
}
/* Merge two 16-bit values into a 32-bit combined update. */
scombo.shorts.flags = sflags;
scombo.shorts.domid = sdom;
new_scombo = scombo;
new_scombo.shorts.flags |= GTF_transfer_committed;
tmp_scombo = scombo;
tmp_scombo.shorts.flags |= GTF_transfer_committed;
prev_scombo.word = cmpxchg((u32 *)&sha->flags,
scombo.word, tmp_scombo.word);
/* Did the combined update work (did we see what we expected?). */
scombo.word, new_scombo.word);
if ( likely(prev_scombo.word == scombo.word) )
break;
@@ -594,9 +585,7 @@ gnttab_prepare_for_transfer(
goto fail;
}
/* Didn't see what we expected. Split out the seen flags & dom. */
sflags = prev_scombo.shorts.flags;
sdom = prev_scombo.shorts.domid;
scombo = prev_scombo;
}
spin_unlock(&rgt->lock);
@@ -734,16 +723,21 @@ __release_grant_for_copy(
gnttab_mark_dirty(rd, r_frame);
spin_lock(&rd->grant_table->lock);
if ( readonly )
act->pin -= GNTPIN_hstr_inc;
else
act->pin -= GNTPIN_hstw_inc;
if ( !(act->pin & GNTPIN_hstw_mask) && !readonly )
gnttab_clear_flag(_GTF_writing, &sha->flags);
if ( readonly )
{
act->pin -= GNTPIN_hstr_inc;
}
else
{
act->pin -= GNTPIN_hstw_inc;
if ( !(act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) )
gnttab_clear_flag(_GTF_writing, &sha->flags);
}
if ( !act->pin )
gnttab_clear_flag(_GTF_reading, &sha->flags);
spin_unlock(&rd->grant_table->lock);
}
@@ -759,8 +753,7 @@ __acquire_grant_for_copy(
struct active_grant_entry *act;
s16 rc = GNTST_okay;
int retries = 0;
u16 sflags;
domid_t sdom;
union grant_combo scombo, prev_scombo, new_scombo;
if ( unlikely(gref >= NR_GRANT_ENTRIES) )
PIN_FAIL(error_out, GNTST_bad_gntref,
@@ -771,36 +764,42 @@ __acquire_grant_for_copy(
spin_lock(&rd->grant_table->lock);
/* If already pinned, check the active domid and avoid refcnt overflow. */
if ( act->pin &&
((act->domid != current->domain->domain_id) ||
(act->pin & 0x80808080U) != 0) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad domain (%d != %d), or risk of counter overflow %08x\n",
act->domid, current->domain->domain_id, act->pin);
if ( !act->pin ||
(!readonly && !(act->pin & GNTPIN_hstw_mask)) )
(!readonly && !(act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask))) )
{
sflags = sha->flags;
sdom = sha->domid;
scombo.word = *(u32 *)&sha->flags;
for ( ; ; )
{
union grant_combo scombo, prev_scombo, new_scombo;
/* If not already pinned, check the grant domid and type. */
if ( !act->pin &&
(((scombo.shorts.flags & GTF_type_mask) !=
GTF_permit_access) ||
(scombo.shorts.domid != current->domain->domain_id)) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad flags (%x) or dom (%d). (expected dom %d)\n",
scombo.shorts.flags, scombo.shorts.domid,
current->domain->domain_id);
if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access ||
sdom != current->domain->domain_id ) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
sflags, sdom, current->domain->domain_id);
/* Merge two 16-bit values into a 32-bit combined update. */
scombo.shorts.flags = sflags;
scombo.shorts.domid = sdom;
new_scombo = scombo;
new_scombo.shorts.flags |= GTF_reading;
if ( !readonly )
{
new_scombo.shorts.flags |= GTF_writing;
if ( unlikely(sflags & GTF_readonly) )
if ( unlikely(scombo.shorts.flags & GTF_readonly) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Attempt to write-pin a r/o grant entry.\n");
}
prev_scombo.word = cmpxchg((u32 *)&sha->flags,
scombo.word, new_scombo.word);
if ( likely(prev_scombo.word == scombo.word) )
@@ -809,19 +808,16 @@ __acquire_grant_for_copy(
if ( retries++ == 4 )
PIN_FAIL(unlock_out, GNTST_general_error,
"Shared grant entry is unstable.\n");
sflags = prev_scombo.shorts.flags;
sdom = prev_scombo.shorts.flags;
scombo = prev_scombo;
}
if ( !act->pin )
{
act->domid = sdom;
act->domid = scombo.shorts.domid;
act->frame = gmfn_to_mfn(rd, sha->frame);
}
}
else if ( (act->pin & 0x80808080U) != 0 )
PIN_FAIL(unlock_out, ENOSPC,
"Risk of counter overflow %08x\n", act->pin);
act->pin += readonly ? GNTPIN_hstr_inc : GNTPIN_hstw_inc;
+28 -29
View File
@@ -7,20 +7,19 @@
#include <xen/config.h>
/*
* These have to be done with inline assembly: that way the bit-setting
* is guaranteed to be atomic. All bit operations return 0 if the bit
* was cleared before the operation and != 0 if it was not.
*
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
*/
#ifdef CONFIG_SMP
#define LOCK_PREFIX "lock ; "
#else
#define LOCK_PREFIX ""
#endif
/*
* We use the "+m" constraint because the memory operand is both read from
* and written to. Since the operand is in fact a word array, we also
* specify "memory" in the clobbers list to indicate that words other than
* the one directly addressed by the memory operand may be modified.
*/
#define ADDR (*(volatile long *) addr)
/**
@@ -37,8 +36,8 @@ static __inline__ void set_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
:"=m" (ADDR)
:"dIr" (nr));
:"+m" (ADDR)
:"dIr" (nr) : "memory");
}
/**
@@ -54,8 +53,8 @@ static __inline__ void __set_bit(int nr, volatile void * addr)
{
__asm__(
"btsl %1,%0"
:"=m" (ADDR)
:"dIr" (nr));
:"+m" (ADDR)
:"dIr" (nr) : "memory");
}
/**
@@ -72,8 +71,8 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
:"=m" (ADDR)
:"dIr" (nr));
:"+m" (ADDR)
:"dIr" (nr) : "memory");
}
/**
@@ -89,8 +88,8 @@ static __inline__ void __clear_bit(int nr, volatile void * addr)
{
__asm__(
"btrl %1,%0"
:"=m" (ADDR)
:"dIr" (nr));
:"+m" (ADDR)
:"dIr" (nr) : "memory");
}
#define smp_mb__before_clear_bit() barrier()
@@ -109,8 +108,8 @@ static __inline__ void __change_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
"btcl %1,%0"
:"=m" (ADDR)
:"dIr" (nr));
:"+m" (ADDR)
:"dIr" (nr) : "memory");
}
/**
@@ -126,8 +125,8 @@ static __inline__ void change_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
:"=m" (ADDR)
:"dIr" (nr));
:"+m" (ADDR)
:"dIr" (nr) : "memory");
}
/**
@@ -144,7 +143,7 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -164,8 +163,8 @@ static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
__asm__(
"btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"dIr" (nr));
:"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -183,7 +182,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -203,8 +202,8 @@ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
__asm__(
"btrl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"dIr" (nr));
:"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -215,7 +214,7 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__(
"btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -234,7 +233,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (ADDR)
:"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -242,7 +241,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
{
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
return ((1U << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
}
static __inline__ int variable_test_bit(int nr, volatile void * addr)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.