From 4226bdfec74751fb997da27be5d540ca5ff4e595 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Thu, 2 Sep 2004 15:35:56 +0000 Subject: [PATCH 01/22] bitkeeper revision 1.1159.68.1 (41373ddcTLdrlPC1j7y6wwqeJNMnzw) Get xend to start xfrd. Remove some dead code. --- tools/python/xen/xend/server/SrvDaemon.py | 270 ++++++++-------------- tools/python/xen/xend/server/params.py | 8 +- tools/xfrd/xfrd.c | 5 + 3 files changed, 112 insertions(+), 171 deletions(-) diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index 851b72198b..20569c74b4 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -23,7 +23,6 @@ from twisted.internet import reactor from twisted.internet import protocol from twisted.internet import abstract from twisted.internet import defer -#defer.Deferred.debug = 1 from xen.lowlevel import xu @@ -45,127 +44,6 @@ from params import * DEBUG = 1 -class MgmtProtocol(protocol.DatagramProtocol): - """Handler for the management socket (unix-domain). - """ - - def __init__(self, daemon): - #protocol.DatagramProtocol.__init__(self) - self.daemon = daemon - - def write(self, data, addr): - return self.transport.write(data, addr) - - def datagramReceived(self, data, addr): - if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data - io = StringIO.StringIO(data) - try: - vals = sxp.parse(io) - res = self.dispatch(vals[0]) - self.send_result(addr, res) - except SystemExit: - raise - except: - if DEBUG: - raise - else: - self.send_error(addr) - - def send_reply(self, addr, sxpr): - io = StringIO.StringIO() - sxp.show(sxpr, out=io) - io.seek(0) - self.write(io.getvalue(), addr) - - def send_result(self, addr, res): - - def fn(res, self=self, addr=addr): - self.send_reply(addr, ['ok', res]) - - if isinstance(res, defer.Deferred): - res.addCallback(fn) - else: - fn(res) - - def send_error(self, addr): - (extype, exval) = sys.exc_info()[:2] - self.send_reply(addr, ['err', - ['type', str(extype) ], - ['value', str(exval) ] ] ) - - def opname(self, name): - """Get the name of the method for an operation. - """ - return 'op_' + name.replace('.', '_') - - def operror(self, name, v): - """Default operation handler - signals an error. - """ - raise NotImplementedError('Invalid operation: ' +name) - - def dispatch(self, req): - """Dispatch a request to its handler. - """ - op_name = sxp.name(req) - op_method_name = self.opname(op_name) - op_method = getattr(self, op_method_name, self.operror) - return op_method(op_name, req) - - def op_console_create(self, name, req): - """Create a new control interface - console for a domain. - """ - print name, req - dom = sxp.child_value(req, 'domain') - if not dom: raise XendError('Missing domain') - dom = int(dom) - console_port = sxp.child_value(req, 'console_port') - if console_port: - console_port = int(console_port) - resp = self.daemon.console_create(dom, console_port).sxpr() - print name, resp - return resp - - def op_consoles(self, name, req): - """Get a list of the consoles. - """ - return self.daemon.consoles() - - def op_console_disconnect(self, name, req): - id = sxp.child_value(req, 'id') - if not id: - raise XendError('Missing console id') - id = int(id) - console = self.daemon.get_console(id) - if not console: - raise XendError('Invalid console id') - if console.conn: - console.conn.loseConnection() - return ['ok'] - - def op_blkifs(self, name, req): - pass - - def op_blkif_devs(self, name, req): - pass - - def op_blkif_create(self, name, req): - pass - - def op_blkif_dev_create(self, name, req): - pass - - def op_netifs(self, name, req): - pass - - def op_netif_devs(self, name, req): - pass - - def op_netif_create(self, name, req): - pass - - def op_netif_dev_create(self, name, req): - pass - class NotifierProtocol(protocol.Protocol): """Asynchronous handler for i/o on the notifier (event channel). """ @@ -245,17 +123,14 @@ class NotifierPort(abstract.FileDescriptor): del self.d def doRead(self): - #print 'NotifierPort>doRead>', self count = 0 while 1: - #print 'NotifierPort>doRead>', count notification = self.notifier.read() if not notification: break self.protocol.notificationReceived(notification) self.notifier.unmask(notification) count += 1 - #print 'NotifierPort>doRead<' class EventProtocol(protocol.Protocol): """Asynchronous handler for a connected event socket. @@ -481,25 +356,69 @@ class Daemon: err = 1 print "Daemon already running: ", pids return err - - def cleanup(self, kill=False): - # No cleanup to do if PID_FILE is empty. - if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE): - return 0 - # Read the pid of the previous invocation and search active process list. - pid = open(PID_FILE, 'r').read() - lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines() - for line in lines: - if re.search('^ *' + pid + '.+xend', line): - if not kill: - print "Daemon is already running (pid %d)" % int(pid) - return 1 - # Old daemon is still active: terminate it. - os.kill(int(pid), 1) - # Delete the stale PID_FILE. - os.remove(PID_FILE) - return 0 + def read_pid(self, pidfile): + """Read process id from a file. + + @param pidfile: file to read + @return pid or 0 + """ + pid = 0 + if os.path.isfile(pidfile) and os.path.getsize(pidfile): + try: + pid = open(pidfile, 'r').read() + pid = int(pid) + except: + pid = 0 + return pid + + def find_process(self, pid, name): + """Search for a process. + + @param pid: process id + @param name: process name + @return: pid if found, 0 otherwise + """ + running = 0 + if pid: + lines = os.popen('ps %d 2>/dev/null' % pid).readlines() + exp = '^ *%d.+%s' % (pid, name) + for line in lines: + if re.search(exp, line): + running = pid + break + return running + + def cleanup_process(self, pidfile, name, kill): + """Clean up the pidfile for a process. + If a running process is found, kills it if 'kill' is true. + + @param pidfile: pid file + @param name: process name + @param kill: whether to kill the process + @return running process id or 0 + """ + running = 0 + pid = self.read_pid(pidfile) + if self.find_process(pid, name): + if kill: + os.kill(pid, 1) + else: + running = pid + if running == 0 and os.path.isfile(pidfile): + os.remove(pidfile) + return running + + def cleanup_xend(self, kill=False): + return self.cleanup_process(XEND_PID_FILE, "xend", kill) + + def cleanup_xfrd(self, kill=False): + return self.cleanup_process(XFRD_PID_FILE, "xfrd", kill) + + def cleanup(self, kill=False): + self.cleanup_xend(kill=kill) + self.cleanup_xfrd(kill=kill) + def install_child_reaper(self): #signal.signal(signal.SIGCHLD, self.onSIGCHLD) # Ensure that zombie children are automatically reaped. @@ -510,42 +429,65 @@ class Daemon: while code > 0: code = os.waitpid(-1, os.WNOHANG) + def fork_pid(self, pidfile): + """Fork and write the pid of the child to 'pidfile'. + + @param pidfile: pid file + @return: pid of child in parent, 0 in child + """ + pid = os.fork() + if pid: + # Parent + pidfile = open(pidfile, 'w') + pidfile.write(str(pid)) + pidfile.close() + return pid + + def start_xfrd(self): + """Fork and exec xfrd, writing its pid to XFRD_PID_FILE. + """ + if self.fork_pid(XFRD_PID_FILE): + # Parent + pass + else: + # Child + self.set_user() + os.execl("/usr/sbin/xfrd", "xfrd") + def start(self, trace=0): - if self.cleanup(kill=False): + xend_pid = self.cleanup_xend() + xfrd_pid = self.cleanup_xfrd() + if xfrd_pid == 0: + self.start_xfrd() + if xend_pid > 0: return 1 # Detach from TTY. if not DEBUG: os.setsid() - if self.set_user(): return 1 - self.install_child_reaper() - # Fork -- parent writes PID_FILE and exits. - pid = os.fork() - if pid: - # Parent - pidfile = open(PID_FILE, 'w') - pidfile.write(str(pid)) - pidfile.close() - return 0 - # Child - self.tracing(trace) - self.run() + if self.fork_pid(XEND_PID_FILE): + #Parent + pass + else: + # Child + self.tracing(trace) + self.run() return 0 def tracing(self, traceon): """Turn tracing on or off. - traceon tracing flag + @param traceon: tracing flag """ if traceon == self.traceon: return self.traceon = traceon if traceon: - self.tracefile = open('/var/log/xend.trace', 'w+', 1) + self.tracefile = open(XEND_TRACE_FILE, 'w+', 1) self.traceindent = 0 sys.settrace(self.trace) try: @@ -620,7 +562,6 @@ class Daemon: xroot = XendRoot.instance() log.info("Xend Daemon started") self.createFactories() - self.listenMgmt() self.listenEvent() self.listenNotifier() self.listenVirq() @@ -634,13 +575,6 @@ class Daemon: self.netifCF = netif.NetifControllerFactory() self.consoleCF = console.ConsoleControllerFactory() - def listenMgmt(self): - protocol = MgmtProtocol(self) - s = os.path.join(CONTROL_DIR, MGMT_SOCK) - if os.path.exists(s): - os.unlink(s) - return reactor.listenUNIXDatagram(s, protocol) - def listenEvent(self): protocol = EventFactory(self) return reactor.listenTCP(EVENT_PORT, protocol) @@ -656,7 +590,7 @@ class Daemon: virqChan.registerClient(VirqClient(self)) def exit(self): - reactor.diconnectAll() + reactor.disconnectAll() sys.exit(0) def getDomChannel(self, dom): diff --git a/tools/python/xen/xend/server/params.py b/tools/python/xen/xend/server/params.py index fa3cee9b14..bb5277aecd 100644 --- a/tools/python/xen/xend/server/params.py +++ b/tools/python/xen/xend/server/params.py @@ -1,8 +1,10 @@ # The following parameters could be placed in a configuration file. -PID_FILE = '/var/run/xend.pid' +XEND_PID_FILE = '/var/run/xend.pid' +XFRD_PID_FILE = '/var/run/xfrd.pid' +XEND_TRACE_FILE = '/var/log/xend.trace' + USER = 'root' -CONTROL_DIR = '/var/run/xend' -MGMT_SOCK = 'xendsock' # relative to CONTROL_DIR + EVENT_PORT = 8001 CONSOLE_PORT_BASE = 9600 diff --git a/tools/xfrd/xfrd.c b/tools/xfrd/xfrd.c index 05c942f5a5..f84e29e6a2 100644 --- a/tools/xfrd/xfrd.c +++ b/tools/xfrd/xfrd.c @@ -50,6 +50,7 @@ #define MODULE_NAME "XFRD" #define DEBUG 0 +#undef DEBUG #include "debug.h" /* @@ -1142,7 +1143,11 @@ int main(int argc, char *argv[]){ int err = 0; int key = 0; int long_index = 0; + static const char * LOGFILE = "/var/log/xfrd.log"; + freopen(LOGFILE, "w+", stdout); + fclose(stderr); + stderr = stdout; dprintf(">\n"); set_defaults(args); while(1){ From 032af4d9468312380d14b8e9ebf569bffe0cd7e8 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Fri, 3 Sep 2004 09:43:59 +0000 Subject: [PATCH 02/22] bitkeeper revision 1.1159.68.2 (41383cdfHn8bdXUvTO9mrnc7pCTLGA) Send a fake ARP packet when a vif comes up, to let switches see the MAC address. --- .../drivers/xen/netfront/netfront.c | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c index 71105776b2..85e29d4d25 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c @@ -26,6 +26,9 @@ #include #include +#include +#include + #if 0 #define DPRINTK(fmt, args...) \ printk(KERN_INFO "[XEN] %s" fmt, __FUNCTION__, ##args) @@ -171,6 +174,32 @@ static int netctrl_connected_count(void) return connected; } +/** Send a packet on a net device to encourage switches to learn the + * MAC. We send a fake ARP request. + * + * @param dev device + * @return 0 on success, error code otherwise + */ +static int vif_wake(struct net_device *dev){ + int err = 0; + struct sk_buff *skb; + u32 src_ip; + u32 dst_ip = INADDR_BROADCAST; + unsigned char dst_hw[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK); + skb = arp_create(ARPOP_REQUEST, ETH_P_ARP, + dst_ip, dev, src_ip, + dst_hw, dev->dev_addr, NULL); + if(skb == NULL){ + err = -ENOMEM; + goto exit; + } + err = dev_queue_xmit(skb); + exit: + return err; +} + static inline struct sk_buff *alloc_skb_page(void) { struct sk_buff *skb; @@ -739,6 +768,7 @@ static void netif_status_change(netif_fe_interface_status_changed_t *status) (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, dev->name, dev); netctrl_connected_count(); + vif_wake(dev); break; default: From 254692941de24e2c73f61d337c738c1445bf4dc2 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Fri, 3 Sep 2004 11:09:53 +0000 Subject: [PATCH 03/22] bitkeeper revision 1.1159.68.3 (41385101Grb5mmJcQ0YiLdCY2dOnCg) Notify device controllers when devices are added or removed so that they can probe for the devices. --- .../drivers/xen/blkfront/blkfront.c | 6 ++ .../drivers/xen/netfront/netfront.c | 6 ++ tools/python/xen/xend/XendClient.py | 2 +- tools/python/xen/xend/XendDomainInfo.py | 25 ++++++-- tools/python/xen/xend/server/blkif.py | 57 +++++++++++++------ tools/python/xen/xend/server/messages.py | 2 + tools/python/xen/xend/server/netif.py | 25 ++++++-- tools/python/xen/xm/main.py | 22 ++++--- .../hypervisor-ifs/io/domain_controller.h | 2 + 9 files changed, 111 insertions(+), 36 deletions(-) diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c index 930e469103..259275ebd1 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -1148,6 +1148,12 @@ static void blkif_status_change(blkif_fe_interface_status_changed_t *status) break; + case BLKIF_INTERFACE_STATUS_CHANGED: + /* The domain controller is notifying us that a device has been + * added or removed. + */ + break; + default: printk(KERN_WARNING "Status change to unknown value %d\n", status->status); diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c index 85e29d4d25..44aa8e9dde 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c @@ -771,6 +771,12 @@ static void netif_status_change(netif_fe_interface_status_changed_t *status) vif_wake(dev); break; + case NETIF_INTERFACE_STATUS_CHANGED: + /* The domain controller is notifying us that a device has been + * added or removed. + */ + break; + default: printk(KERN_WARNING "Status change to unknown value %d\n", status->status); diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 5041e06cb7..01d6d3df3c 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -548,7 +548,7 @@ class Xend: return self.xendPost(self.domainurl(id), {'op' : 'device_destroy', 'type' : type, - 'index' : idx }) + 'idx' : idx }) def xend_consoles(self): return self.xendGet(self.consoleurl()) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index b86167143b..f582a51145 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -576,6 +576,16 @@ class XendDomainInfo: dl.append(dev) self.devices[type] = dl + def remove_device(self, type, dev): + """Remove a device from a virtual machine. + + @param type: device type + @param dev: device + """ + dl = self.devices.get(type, []) + if dev in dl: + dl.remove(dev) + def get_devices(self, type): """Get a list of the devices of a given type. @@ -812,7 +822,7 @@ class XendDomainInfo: devs = self.get_devices(dev_name) dev_index = len(devs) self.config.append(['device', dev_config]) - d = dev_handler(self, dev_config, dev_index) + d = dev_handler(self, dev_config, dev_index, change=1) return d def device_destroy(self, type, idx): @@ -829,7 +839,8 @@ class XendDomainInfo: dev_config = self.config_device(type, index) if dev_config: self.config.remove(['device', dev_config]) - dev.destroy() + dev.destroy(change=1) + self.remove_device(type, dev) def configure_memory(self): """Configure vm memory limit. @@ -1053,7 +1064,7 @@ def vm_image_netbsd(vm, image): return vm -def vm_dev_vif(vm, val, index): +def vm_dev_vif(vm, val, index, change=0): """Create a virtual network interface (vif). @param vm: virtual machine @@ -1069,11 +1080,13 @@ def vm_dev_vif(vm, val, index): def cbok(dev): dev.vifctl('up', vmname=vm.name) vm.add_device('vif', dev) + if change: + dev.interfaceChanged() return dev defer.addCallback(cbok) return defer -def vm_dev_vbd(vm, val, index): +def vm_dev_vbd(vm, val, index, change=0): """Create a virtual block device (vbd). @param vm: virtual machine @@ -1094,6 +1107,8 @@ def vm_dev_vbd(vm, val, index): vbd.dev = dev vbd.uname = uname vm.add_device('vbd', vbd) + if change: + vbd.interfaceChanged() return vbd defer.addCallback(fn) return defer @@ -1110,7 +1125,7 @@ def parse_pci(val): v = val return v -def vm_dev_pci(vm, val, index): +def vm_dev_pci(vm, val, index, change=0): """Add a pci device. @param vm: virtual machine diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index c3c3eb2de3..60708e24a9 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -3,7 +3,6 @@ """ from twisted.internet import defer -#defer.Deferred.debug = 1 from xen.xend import sxp from xen.xend.XendLogging import log @@ -88,14 +87,12 @@ class BlkifBackendInterface(controller.BackendInterface): self.send_be_disconnect(response=d) def send_be_disconnect(self, response=None): - log.debug('>BlkifBackendController>send_be_disconnect> %s', str(self)) msg = packMsg('blkif_be_disconnect_t', { 'domid' : self.controller.dom, 'blkif_handle' : self.handle }) self.writeRequest(msg, response=response) def send_be_destroy(self, response=None): - log.debug('>BlkifBackendController>send_be_destroy> %s', str(self)) msg = packMsg('blkif_be_destroy_t', { 'domid' : self.controller.dom, 'blkif_handle' : self.handle }) @@ -127,9 +124,28 @@ class BlkifBackendInterface(controller.BackendInterface): msg = packMsg('blkif_fe_interface_status_changed_t', { 'handle' : self.handle, 'status' : BLKIF_INTERFACE_STATUS_CONNECTED, - 'domid' : 0, ## FIXME: should be domid of backend + 'domid' : self.dom, 'evtchn' : self.evtchn['port2'] }) self.controller.writeRequest(msg, response=response) + + def interfaceDisconnected(self): + msg = packMsg('blkif_fe_interface_status_changed_t', + { 'handle' : self.handle, + 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED, + 'domid' : self.dom, + 'evtchn' : 0 }) + self.controller.writeRequest(msg) + + def interfaceChanged(self): + """Notify the front-end that devices have been added or removed. + The front-end should then probe for devices. + """ + msg = packMsg('blkif_fe_interface_status_changed_t', + { 'handle' : self.handle, + 'status' : BLKIF_INTERFACE_STATUS_CHANGED, + 'domid' : self.dom, + 'evtchn' : 0 }) + self.controller.writeRequest(msg) class BlkifControllerFactory(controller.SplitControllerFactory): """Factory for creating block device interface controllers. @@ -230,9 +246,21 @@ class BlkDev(controller.SplitDev): val.append(['uname', self.uname]) return val - def destroy(self): + def destroy(self, change=0): + """Destroy the device. If 'change' is true notify the front-end interface. + + @param change: change flag + """ log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev) - self.send_be_vbd_destroy() + d = self.send_be_vbd_destroy() + if change: + d.addCallback(lambda val: self.interfaceChanged()) + + def interfaceChanged(self): + """Tell the back-end to notify the front-end that a device has been + added or removed. + """ + self.getBackendInterface().interfaceChanged() def attach(self): """Attach the device to its controller. @@ -295,16 +323,16 @@ class BlkDev(controller.SplitDev): % (self.vdev, status)) return self - def send_be_vbd_destroy(self, response=None): - log.debug('>BlkDev>send_be_vbd_destroy> dom=%d vdev=%d', - self.controller.dom, self.vdev) + def send_be_vbd_destroy(self): + d = defer.Deferred() backend = self.getBackendInterface() msg = packMsg('blkif_be_vbd_destroy_t', { 'domid' : self.controller.dom, 'blkif_handle' : backend.handle, 'vdevice' : self.vdev }) self.controller.delDevice(self.vdev) - backend.writeRequest(msg, response=response) + backend.writeRequest(msg, response=d) + return d class BlkifController(controller.SplitController): @@ -399,13 +427,8 @@ class BlkifController(controller.SplitController): def recv_fe_driver_status_changed(self, msg, req): val = unpackMsg('blkif_fe_driver_status_changed_t', msg) - # For each backend? - msg = packMsg('blkif_fe_interface_status_changed_t', - { 'handle' : 0, - 'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED, - 'domid' : 0, ## FIXME: should be domid of backend - 'evtchn' : 0 }) - self.writeRequest(msg) + for backend in self.getBackendInterfaces(): + backend.interfaceDisconnected() def recv_fe_interface_connect(self, msg, req): val = unpackMsg('blkif_fe_interface_connect_t', msg) diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py index 8d68d95887..fb94214a64 100644 --- a/tools/python/xen/xend/server/messages.py +++ b/tools/python/xen/xend/server/messages.py @@ -50,6 +50,7 @@ BLKIF_DRIVER_STATUS_UP = 1 BLKIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */ BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */ BLKIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */ +BLKIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */ BLKIF_BE_STATUS_OKAY = 0 BLKIF_BE_STATUS_ERROR = 1 @@ -117,6 +118,7 @@ CMSG_NETIF_BE_DRIVER_STATUS_CHANGED = 32 NETIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */ NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */ NETIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */ +NETIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */ NETIF_DRIVER_STATUS_DOWN = 0 NETIF_DRIVER_STATUS_UP = 1 diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index 3b4dc25339..3c07333a84 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -5,7 +5,6 @@ import random from twisted.internet import defer -#defer.Deferred.debug = 1 from xen.xend import sxp from xen.xend import Vifctl @@ -208,13 +207,17 @@ class NetDev(controller.SplitDev): val = unpackMsg('netif_be_create_t', msg) return self - def destroy(self): + def destroy(self, change=0): """Destroy the device's resources and disconnect from the back-end - device controller. + device controller. If 'change' is true notify the front-end interface. + + @param change: change flag """ def cb_destroy(val): self.send_be_destroy() self.getBackendInterface().close() + if change: + self.interfaceChanged() log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif) self.vifctl('down') d = self.send_be_disconnect() @@ -256,7 +259,7 @@ class NetDev(controller.SplitDev): { 'handle' : self.vif, 'status' : NETIF_INTERFACE_STATUS_CONNECTED, 'evtchn' : self.evtchn['port2'], - 'domid' : 0, ## FIXME: should be domid of backend + 'domid' : self.backendDomain, 'mac' : self.mac }) self.controller.writeRequest(msg) @@ -265,7 +268,19 @@ class NetDev(controller.SplitDev): { 'handle' : self.vif, 'status' : NETIF_INTERFACE_STATUS_DISCONNECTED, 'evtchn' : 0, - 'domid' : 0, ## FIXME: should be domid of backend + 'domid' : self.backendDomain, + 'mac' : self.mac }) + self.controller.writeRequest(msg) + + def interfaceChanged(self): + """Notify the font-end that a device has been added or removed. + The front-end should then probe the devices. + """ + msg = packMsg('netif_fe_interface_status_changed_t', + { 'handle' : self.vif, + 'status' : NETIF_INTERFACE_STATUS_CHANGED, + 'evtchn' : 0, + 'domid' : self.backendDomain, 'mac' : self.mac }) self.controller.writeRequest(msg) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 2d77bd5ca6..d8c70e75fe 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -737,22 +737,26 @@ class ProgVbdCreate(Prog): info = """Create a new virtual block device for a domain""" def help(self, args): - print args[0], "DOM UNAME DEV MODE" + print args[0], "DOM UNAME DEV MODE [BACKEND]" print """ Create a virtual block device for a domain. - UNAME - device to export, e.g. phys:hda2 - DEV - device name in the domain, e.g. xda1 - MODE - access mode: r for read, w for read-write + UNAME - device to export, e.g. phy:hda2 + DEV - device name in the domain, e.g. xda1 + MODE - access mode: r for read, w for read-write + BACKEND - backend driver domain """ def main(self, args): - if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0]) + n = len(args) + if n < 5 or n > 6: self.err("%s: Invalid argument(s)" % args[0]) dom = args[1] vbd = ['vbd', ['uname', args[2]], ['dev', args[3]], ['mode', args[4]]] + if n == 6: + vbd.append(['backend', args[5]]) server.xend_domain_device_create(dom, vbd) xm.prog(ProgVbdCreate) @@ -766,13 +770,15 @@ class ProgVbdDestroy(Prog): print args[0], "DOM DEV" print """ Destroy vbd DEV attached to domain DOM. Detaches the device -from the domain, but does not destroy the device contents.""" +from the domain, but does not destroy the device contents. +The device indentifier DEV is the idx field in the device +information. This is visible in 'xm vbd-list'.""" def main(self, args): - if len(args!=3): self.err("%s: Invalid argument(s)" % args[0]) + if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0]) dom = args[1] dev = args[2] - sever.xend_domain_device_destroy(dom, "vbd", dev) + server.xend_domain_device_destroy(dom, "vbd", dev) xm.prog(ProgVbdDestroy) diff --git a/xen/include/hypervisor-ifs/io/domain_controller.h b/xen/include/hypervisor-ifs/io/domain_controller.h index 45090aca0f..5de3c2d673 100644 --- a/xen/include/hypervisor-ifs/io/domain_controller.h +++ b/xen/include/hypervisor-ifs/io/domain_controller.h @@ -93,6 +93,7 @@ typedef struct { #define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */ #define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */ #define BLKIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */ +#define BLKIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */ typedef struct { u32 handle; /* 0 */ u32 status; /* 4 */ @@ -357,6 +358,7 @@ typedef struct { #define NETIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */ #define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */ #define NETIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */ +#define NETIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */ typedef struct { u32 handle; /* 0 */ u32 status; /* 4 */ From 454fe96660d1b0a9026fa61e2189f924cde3d4ec Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Fri, 3 Sep 2004 11:10:54 +0000 Subject: [PATCH 04/22] bitkeeper revision 1.1159.68.4 (4138513ej82nxKggDAvxAH3haoMXLA) Turn off debug. --- tools/xfrd/xen_domain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/xfrd/xen_domain.c b/tools/xfrd/xen_domain.c index 5f4dcda506..fe63e73a3d 100644 --- a/tools/xfrd/xen_domain.c +++ b/tools/xfrd/xen_domain.c @@ -16,6 +16,7 @@ typedef unsigned long u32; #define MODULE_NAME "XFRD" #define DEBUG 1 +#undef DEBUG #include "debug.h" From 353cb77788560d9516fe0d0dd14efec6d92f25f3 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Fri, 3 Sep 2004 16:43:14 +0000 Subject: [PATCH 05/22] bitkeeper revision 1.1159.70.3 (41389f22BlnxYbup7d6jcZXvICR6qg) Fix problem with domain shutdown events. --- tools/python/xen/xend/XendDomain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 2111a166bd..afe2a4601b 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -243,12 +243,12 @@ class XendDomain: if d['shutdown']: reason = XendDomainInfo.shutdown_reason(d['shutdown_reason']) log.debug('XendDomain>reap> shutdown id=%s reason=%s', id, reason) + dominfo = self.domain_by_id.get(id) + name = (dominfo and dominfo.name) or '??' if reason in ['suspend']: - dominfo = self.domain_by_id.get(id) if dominfo.is_terminated(): log.debug('XendDomain>reap> Suspended domain died id=%s', id) else: - name = (dominfo and dominfo.name) or '??' eserver.inject('xend.domain.suspended', [name, id]) continue if reason in ['poweroff', 'reboot']: From b9ef5137a5bff3017c73a1c575b67ba58f1cfa87 Mon Sep 17 00:00:00 2001 From: "iap10@labyrinth.cl.cam.ac.uk" Date: Fri, 3 Sep 2004 20:44:22 +0000 Subject: [PATCH 06/22] bitkeeper revision 1.1159.69.3 (4138d7a65FvXU3lh0Vx8Nsl4KhPxGw) Fix potential security hole in writeable pagetable implementation: We wern't ensuring that that L1 pages' VA backpointer is immutable after the backpointer is initialised when the page first becomes linked into a pagetable. The backpointer can only be released after the type count drops to zero (or 1 if the page is pinned). In summary: We now ensure that if an L1 page is used in multiple pagetables it must be at the same virtual address in all of them, and that L1 pages can only be used once in any given pagetable. None of these extra rules should be a problem for any OS. --- xen/arch/x86/domain.c | 3 ++ xen/arch/x86/memory.c | 97 +++++++++++++++------------------------- xen/arch/x86/traps.c | 4 +- xen/include/asm-x86/mm.h | 83 +++++++++++++++++++++++++++++++--- 4 files changed, 119 insertions(+), 68 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 3031d5de69..478daea09a 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -745,6 +745,9 @@ int construct_dom0(struct domain *p, { page->u.inuse.type_info &= ~PGT_type_mask; page->u.inuse.type_info |= PGT_l1_page_table; + page->u.inuse.type_info |= + ((v_start>>L2_PAGETABLE_SHIFT)+(count-1))<u.inuse.type_info &= ~PGT_va_mask; - page->u.inuse.type_info |= va_idx << PGT_va_shift; -} - - /* * We allow an L2 tables to map each other (a.k.a. linear page tables). It * needs some special care with reference counst and access permissions: @@ -463,8 +455,10 @@ get_page_from_l1e( /* NB. Virtual address 'l2e' maps to a machine address within frame 'pfn'. */ static int get_page_from_l2e( - l2_pgentry_t l2e, unsigned long pfn, struct domain *d) + l2_pgentry_t l2e, unsigned long pfn, struct domain *d, unsigned long va_idx) { + int rc; + if ( !(l2_pgentry_val(l2e) & _PAGE_PRESENT) ) return 1; @@ -475,8 +469,11 @@ get_page_from_l2e( return 0; } - if ( unlikely(!get_page_and_type_from_pagenr( - l2_pgentry_to_pagenr(l2e), PGT_l1_page_table, d)) ) + rc = get_page_and_type_from_pagenr( + l2_pgentry_to_pagenr(l2e), + PGT_l1_page_table | (va_idx<> PAGE_SHIFT, i); } #if defined(__i386__) @@ -674,11 +670,10 @@ static int mod_l2_entry(l2_pgentry_t *pl2e, if ( ((l2_pgentry_val(ol2e) ^ l2_pgentry_val(nl2e)) & ~0xffe) == 0 ) return update_l2e(pl2e, ol2e, nl2e); - if ( unlikely(!get_page_from_l2e(nl2e, pfn, current)) ) + if ( unlikely(!get_page_from_l2e(nl2e, pfn, current, + ((unsigned long) + pl2e & ~PAGE_MASK) >> 2 )) ) return 0; - - set_l1_page_va(l2_pgentry_val(nl2e) >> PAGE_SHIFT, - ((unsigned long)pl2e & (PAGE_SIZE-1)) >> 2); if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) ) { @@ -833,10 +828,20 @@ static int do_extended_command(unsigned long ptr, unsigned long val) { case MMUEXT_PIN_L1_TABLE: case MMUEXT_PIN_L2_TABLE: + + /* When we pin an L1 page we now insist that the va + backpointer (used for writable page tables) must still be + mutable. This is an additional restriction even for guests + that don't use writable page tables, but I don't think it + will break anything as guests typically pin pages before + they are used, hence they'll still be mutable. */ + okay = get_page_and_type_from_pagenr( pfn, - (cmd==MMUEXT_PIN_L2_TABLE) ? PGT_l2_page_table : PGT_l1_page_table, + ((cmd==MMUEXT_PIN_L2_TABLE) ? + PGT_l2_page_table : (PGT_l1_page_table | PGT_va_mutable) ) , FOREIGNDOM); + if ( unlikely(!okay) ) { MEM_LOG("Error while pinning pfn %08lx", pfn); @@ -894,8 +899,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val) /* * Note that we tick the clock /after/ dropping the old base's * reference count. If the page tables got freed then this will - * avoid unnecessary TLB flushes when the pages are reused. - */ + * avoid unnecessary TLB flushes when the pages are reused. */ tlb_clocktick(); } else @@ -1230,7 +1234,7 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) switch ( (page->u.inuse.type_info & PGT_type_mask) ) { case PGT_l1_page_table: - if ( likely(get_page_type(page, PGT_l1_page_table)) ) + if ( likely(passive_get_page_type(page, PGT_l1_page_table)) ) { okay = mod_l1_entry((l1_pgentry_t *)va, mk_l1_pgentry(req.val)); @@ -1623,9 +1627,11 @@ int ptwr_do_page_fault(unsigned long addr) PTWR_PRINTK(("get user %p for va %08lx\n", &linear_pg_table[addr>>PAGE_SHIFT], addr)); #endif + + /* Testing for page_present in the L2 avoids lots of unncessary fixups */ if ( (l2_pgentry_val(linear_l2_table[addr >> L2_PAGETABLE_SHIFT]) & - _PAGE_PRESENT) && - (__get_user(pte, (unsigned long *) + _PAGE_PRESENT) && + (__get_user(pte, (unsigned long *) &linear_pg_table[addr >> PAGE_SHIFT]) == 0) ) { pfn = pte >> PAGE_SHIFT; @@ -1650,6 +1656,7 @@ int ptwr_do_page_fault(unsigned long addr) if ( l2_pgentry_val(*pl2e) >> PAGE_SHIFT != pfn ) { + /* this L1 is not in the current address space */ l1_pgentry_t *pl1e; PTWR_PRINTK(("[I] freeing l1 page %p taf %08x/%08x\n", page, page->u.inuse.type_info, @@ -1715,36 +1722,6 @@ int ptwr_do_page_fault(unsigned long addr) return 0; } -static void ptwr_init_backpointers(void) -{ - struct pfn_info *page; - unsigned long pde; - int va_idx; - - for ( va_idx = 0; va_idx < DOMAIN_ENTRIES_PER_L2_PAGETABLE; va_idx++ ) - { - /* check if entry valid */ - pde = l2_pgentry_val(linear_l2_table[va_idx]); - if ( (pde & _PAGE_PRESENT) == 0 ) - continue; - - page = &frame_table[pde >> PAGE_SHIFT]; - /* assert that page is an l1_page_table XXXcl maybe l2? */ - if ( (page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table ) { - MEM_LOG("ptwr: Inconsistent pagetable: pde %lx not an l1 page\n", - pde >> PAGE_SHIFT); - domain_crash(); - } - page->u.inuse.type_info &= ~PGT_va_mask; - page->u.inuse.type_info |= va_idx << PGT_va_shift; - } -} - -static void ptwr_disable(void) -{ - __cleanup_writable_pagetable(PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE); -} - #ifndef NDEBUG void ptwr_status(void) { diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 24f1d401d2..d488a252f2 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -330,9 +330,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) return; /* successfully copied the mapping */ } - if ( unlikely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) ) + if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) ) { - if ( (addr >> L2_PAGETABLE_SHIFT) == ptwr_info[cpu].disconnected ) + if ( unlikely((addr >> L2_PAGETABLE_SHIFT) == ptwr_info[cpu].disconnected )) { ptwr_reconnect_disconnected(addr); return; diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 7bbe5fe06d..05813d64b7 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -74,6 +74,7 @@ struct pfn_info /* 10-bit most significant bits of va address if used as l1 page table */ #define PGT_va_shift 18 #define PGT_va_mask (((1<<10)-1)<count_info)) ) + { + /* if the page is pinned, but we're dropping the last reference + then make the va backpointer mutable again */ + nx |= PGT_va_mutable; + } } while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) ); } @@ -217,22 +225,35 @@ static inline int get_page_type(struct pfn_info *page, u32 type) } else if ( unlikely((x & PGT_count_mask) == 0) ) { - if ( (x & PGT_type_mask) != type ) + if ( (x & (PGT_type_mask|PGT_va_mask)) != type ) { - nx &= ~(PGT_type_mask | PGT_validated); + nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); nx |= type; /* No extra validation needed for writable pages. */ - if ( type == PGT_writable_page ) + if ( (type & PGT_type_mask) == PGT_writable_page ) nx |= PGT_validated; } } - else if ( unlikely((x & PGT_type_mask) != type) ) + else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) { DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", x & PGT_type_mask, type, page_to_pfn(page)); return 0; } - else if ( unlikely(!(x & PGT_validated)) ) + else if ( (x & PGT_va_mask) == PGT_va_mutable ) + { + /* The va_backpointer is currently mutable, hence we update it. */ + nx &= ~PGT_va_mask; + nx |= type; /* we know the actual type is correct */ + } + else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask) ) ) + { + /* The va backpointer wasn't mutable, and is different :-( */ + DPRINTK("Unexpected va backpointer (saw %08x != exp %08x) for pfn %08lx\n", + x, type, page_to_pfn(page)); + return 0; + } + else if ( unlikely(!(x & PGT_validated)) ) { /* Someone else is updating validation of this page. Wait... */ while ( (y = page->u.inuse.type_info) != x ) @@ -248,7 +269,7 @@ static inline int get_page_type(struct pfn_info *page, u32 type) if ( unlikely(!(nx & PGT_validated)) ) { /* Try to validate page type; drop the new reference on failure. */ - if ( unlikely(!alloc_page_type(page, type)) ) + if ( unlikely(!alloc_page_type(page, type & PGT_type_mask)) ) { DPRINTK("Error while validating pfn %08lx for type %08x." " caf=%08x taf=%08x\n", @@ -258,12 +279,62 @@ static inline int get_page_type(struct pfn_info *page, u32 type) put_page_type(page); return 0; } + set_bit(_PGT_validated, &page->u.inuse.type_info); } return 1; } +/* This 'passive' version of get_page_type doesn't attempt to validate +the page, but just checks the type and increments the type count. The +function is called while doing a NORMAL_PT_UPDATE of an entry in an L1 +page table: We want to 'lock' the page for the brief beriod while +we're doing the update, but we're not actually linking it in to a +pagetable. */ + +static inline int passive_get_page_type(struct pfn_info *page, u32 type) +{ + u32 nx, x, y = page->u.inuse.type_info; + again: + do { + x = y; + nx = x + 1; + if ( unlikely((nx & PGT_count_mask) == 0) ) + { + DPRINTK("Type count overflow on pfn %08lx\n", page_to_pfn(page)); + return 0; + } + else if ( unlikely((x & PGT_count_mask) == 0) ) + { + if ( (x & (PGT_type_mask|PGT_va_mask)) != type ) + { + nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); + nx |= type; + } + } + else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) + { + DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", + x & PGT_type_mask, type, page_to_pfn(page)); + return 0; + } + else if ( unlikely(!(x & PGT_validated)) ) + { + /* Someone else is updating validation of this page. Wait... */ + while ( (y = page->u.inuse.type_info) != x ) + { + rep_nop(); + barrier(); + } + goto again; + } + } + while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) ); + + return 1; +} + static inline void put_page_and_type(struct pfn_info *page) { From efd9ae8aa1916d49462a63e55617316c8a6521ff Mon Sep 17 00:00:00 2001 From: "iap10@labyrinth.cl.cam.ac.uk" Date: Fri, 3 Sep 2004 21:56:18 +0000 Subject: [PATCH 07/22] bitkeeper revision 1.1159.69.5 (4138e882jA1YaR_OfTfNHe_uT4PDIg) trivial --- xen/arch/x86/shadow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 672f48ef9f..d909d64085 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -262,7 +262,7 @@ void __shadow_mode_disable(struct domain *d) __free_shadow_table(m); m->shadow_mode = 0; - SH_LOG("freed tables count=%d l1=%d l2=%d", + SH_VLOG("freed tables count=%d l1=%d l2=%d", m->shadow_page_count, perfc_value(shadow_l1_pages), perfc_value(shadow_l2_pages)); From 9f6b2232e170261fac275db18870212fa5b01a9f Mon Sep 17 00:00:00 2001 From: "kaf24@camelot.eng.3leafnetworks.com" Date: Fri, 3 Sep 2004 22:26:02 +0000 Subject: [PATCH 08/22] bitkeeper revision 1.1159.71.1 (4138ef7arWNBBMfQRCJaRyf93H0eqw) Remove L1 PT pinning from Xen. Clean up the fixes for writable page tables. --- BitKeeper/etc/logging_ok | 1 + .../include/asm-xen/pgalloc.h | 2 - .../arch/xen/i386/mm/hypervisor.c | 50 +----------- .../include/asm-xen/hypervisor.h | 12 --- tools/libxc/xc_linux_build.c | 2 +- tools/libxc/xc_linux_restore.c | 30 +++---- tools/libxc/xc_netbsd_build.c | 2 +- xen/arch/x86/memory.c | 45 +++++------ xen/common/schedule.c | 14 ---- xen/include/asm-x86/mm.h | 81 ++----------------- xen/include/hypervisor-ifs/hypervisor-if.h | 11 +-- 11 files changed, 42 insertions(+), 208 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 35d2bada8d..9332c02f2b 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -19,6 +19,7 @@ iap10@striker.cl.cam.ac.uk iap10@tetris.cl.cam.ac.uk jws22@gauntlet.cl.cam.ac.uk jws@cairnwell.research +kaf24@camelot.eng.3leafnetworks.com kaf24@freefall.cl.cam.ac.uk kaf24@labyrinth.cl.cam.ac.uk kaf24@penguin.local diff --git a/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h b/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h index f6bee4d689..be678385f3 100644 --- a/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h +++ b/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h @@ -134,7 +134,6 @@ static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) { clear_page(pte); __make_page_readonly(pte); - queue_pte_pin(__pa(pte)); } return pte; @@ -153,7 +152,6 @@ static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, static __inline__ void pte_free_slow(pte_t *pte) { - queue_pte_unpin(__pa(pte)); __make_page_writable(pte); free_page((unsigned long)pte); } diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c index a57eabcd8c..03158c3ee4 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c @@ -85,8 +85,6 @@ static void DEBUG_disallow_pt_read(unsigned long va) #undef queue_invlpg #undef queue_pgd_pin #undef queue_pgd_unpin -#undef queue_pte_pin -#undef queue_pte_unpin #undef queue_set_ldt #endif @@ -219,7 +217,7 @@ void queue_pgd_pin(unsigned long ptr) spin_lock_irqsave(&update_lock, flags); update_queue[idx].ptr = phys_to_machine(ptr); update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_PIN_L2_TABLE; + update_queue[idx].val = MMUEXT_PIN_TABLE; increment_index(); spin_unlock_irqrestore(&update_lock, flags); } @@ -235,28 +233,6 @@ void queue_pgd_unpin(unsigned long ptr) spin_unlock_irqrestore(&update_lock, flags); } -void queue_pte_pin(unsigned long ptr) -{ - unsigned long flags; - spin_lock_irqsave(&update_lock, flags); - update_queue[idx].ptr = phys_to_machine(ptr); - update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_PIN_L1_TABLE; - increment_index(); - spin_unlock_irqrestore(&update_lock, flags); -} - -void queue_pte_unpin(unsigned long ptr) -{ - unsigned long flags; - spin_lock_irqsave(&update_lock, flags); - update_queue[idx].ptr = phys_to_machine(ptr); - update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_UNPIN_TABLE; - increment_index(); - spin_unlock_irqrestore(&update_lock, flags); -} - void queue_set_ldt(unsigned long ptr, unsigned long len) { unsigned long flags; @@ -339,7 +315,7 @@ void xen_pgd_pin(unsigned long ptr) spin_lock_irqsave(&update_lock, flags); update_queue[idx].ptr = phys_to_machine(ptr); update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_PIN_L2_TABLE; + update_queue[idx].val = MMUEXT_PIN_TABLE; increment_index_and_flush(); spin_unlock_irqrestore(&update_lock, flags); } @@ -355,28 +331,6 @@ void xen_pgd_unpin(unsigned long ptr) spin_unlock_irqrestore(&update_lock, flags); } -void xen_pte_pin(unsigned long ptr) -{ - unsigned long flags; - spin_lock_irqsave(&update_lock, flags); - update_queue[idx].ptr = phys_to_machine(ptr); - update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_PIN_L1_TABLE; - increment_index_and_flush(); - spin_unlock_irqrestore(&update_lock, flags); -} - -void xen_pte_unpin(unsigned long ptr) -{ - unsigned long flags; - spin_lock_irqsave(&update_lock, flags); - update_queue[idx].ptr = phys_to_machine(ptr); - update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_UNPIN_TABLE; - increment_index_and_flush(); - spin_unlock_irqrestore(&update_lock, flags); -} - void xen_set_ldt(unsigned long ptr, unsigned long len) { unsigned long flags; diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h index 4d7ddc55a7..0de4075b28 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h @@ -54,8 +54,6 @@ void queue_tlb_flush(void); void queue_invlpg(unsigned long ptr); void queue_pgd_pin(unsigned long ptr); void queue_pgd_unpin(unsigned long ptr); -void queue_pte_pin(unsigned long ptr); -void queue_pte_unpin(unsigned long ptr); void queue_set_ldt(unsigned long ptr, unsigned long bytes); void queue_machphys_update(unsigned long mfn, unsigned long pfn); void xen_l1_entry_update(pte_t *ptr, unsigned long val); @@ -65,8 +63,6 @@ void xen_tlb_flush(void); void xen_invlpg(unsigned long ptr); void xen_pgd_pin(unsigned long ptr); void xen_pgd_unpin(unsigned long ptr); -void xen_pte_pin(unsigned long ptr); -void xen_pte_unpin(unsigned long ptr); void xen_set_ldt(unsigned long ptr, unsigned long bytes); void xen_machphys_update(unsigned long mfn, unsigned long pfn); #define MMU_UPDATE_DEBUG 0 @@ -141,14 +137,6 @@ extern page_update_debug_t update_debug_queue[]; printk("PGD UNPIN %s %d: %08lx\n", __FILE__, __LINE__, (_p)); \ queue_pgd_unpin(_p); \ }) -#define queue_pte_pin(_p) ({ \ - printk("PTE PIN %s %d: %08lx\n", __FILE__, __LINE__, (_p)); \ - queue_pte_pin(_p); \ -}) -#define queue_pte_unpin(_p) ({ \ - printk("PTE UNPIN %s %d: %08lx\n", __FILE__, __LINE__, (_p)); \ - queue_pte_unpin(_p); \ -}) #define queue_set_ldt(_p,_l) ({ \ printk("SETL LDT %s %d: %08lx %d\n", __FILE__, __LINE__, (_p), (_l)); \ queue_set_ldt((_p), (_l)); \ diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 41569b8057..1242334dad 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -270,7 +270,7 @@ static int setup_guestos(int xc_handle, * correct protection for the page */ if ( add_mmu_update(xc_handle, mmu, - l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) ) + l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_TABLE) ) goto error_out; start_info = map_pfn_writeable( diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index fe7522e1ed..5e4739f84b 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -473,28 +473,16 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) */ for ( i = 0; i < nr_pfns; i++ ) { - if ( pfn_type[i] == (L1TAB|LPINTAB) ) + if ( pfn_type[i] != (L2TAB|LPINTAB) ) + continue; + if ( add_mmu_update(xc_handle, mmu, + (pfn_to_mfn_table[i]<> 2 )) ) + ((unsigned long)pl2e & + ~PAGE_MASK) >> 2)) ) return 0; if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) ) @@ -826,21 +827,9 @@ static int do_extended_command(unsigned long ptr, unsigned long val) switch ( cmd ) { - case MMUEXT_PIN_L1_TABLE: - case MMUEXT_PIN_L2_TABLE: - - /* When we pin an L1 page we now insist that the va - backpointer (used for writable page tables) must still be - mutable. This is an additional restriction even for guests - that don't use writable page tables, but I don't think it - will break anything as guests typically pin pages before - they are used, hence they'll still be mutable. */ - + case MMUEXT_PIN_TABLE: okay = get_page_and_type_from_pagenr( - pfn, - ((cmd==MMUEXT_PIN_L2_TABLE) ? - PGT_l2_page_table : (PGT_l1_page_table | PGT_va_mutable) ) , - FOREIGNDOM); + pfn, PGT_l2_page_table, FOREIGNDOM); if ( unlikely(!okay) ) { @@ -1183,6 +1172,7 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) unsigned long prev_spfn = 0; l1_pgentry_t *prev_spl1e = 0; struct domain *d = current; + u32 type_info; perfc_incrc(calls_to_mmu_update); perfc_addc(num_page_updates, count); @@ -1231,10 +1221,11 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) } page = &frame_table[pfn]; - switch ( (page->u.inuse.type_info & PGT_type_mask) ) + switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask ) { case PGT_l1_page_table: - if ( likely(passive_get_page_type(page, PGT_l1_page_table)) ) + if ( likely(get_page_type( + page, type_info & (PGT_type_mask|PGT_va_mask))) ) { okay = mod_l1_entry((l1_pgentry_t *)va, mk_l1_pgentry(req.val)); @@ -1484,11 +1475,11 @@ void ptwr_reconnect_disconnected(unsigned long addr) [ptwr_info[cpu].writable_l1>>PAGE_SHIFT]; #ifdef PTWR_TRACK_DOMAIN - if (ptwr_domain[cpu] != get_current()->domain) + if (ptwr_domain[cpu] != current->domain) printk("ptwr_reconnect_disconnected domain mismatch %d != %d\n", - ptwr_domain[cpu], get_current()->domain); + ptwr_domain[cpu], current->domain); #endif - PTWR_PRINTK(("[A] page fault in disconnected space: addr %08lx space %08lx\n", + PTWR_PRINTK(("[A] page fault in disconn space: addr %08lx space %08lx\n", addr, ptwr_info[cpu].disconnected << L2_PAGETABLE_SHIFT)); pl2e = &linear_l2_table[ptwr_info[cpu].disconnected]; @@ -1560,9 +1551,9 @@ void ptwr_flush_inactive(void) int i, idx; #ifdef PTWR_TRACK_DOMAIN - if (ptwr_info[cpu].domain != get_current()->domain) + if (ptwr_info[cpu].domain != current->domain) printk("ptwr_flush_inactive domain mismatch %d != %d\n", - ptwr_info[cpu].domain, get_current()->domain); + ptwr_info[cpu].domain, current->domain); #endif #if 0 { @@ -1643,9 +1634,9 @@ int ptwr_do_page_fault(unsigned long addr) if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table ) { #ifdef PTWR_TRACK_DOMAIN - if ( ptwr_info[cpu].domain != get_current()->domain ) + if ( ptwr_info[cpu].domain != current->domain ) printk("ptwr_do_page_fault domain mismatch %d != %d\n", - ptwr_info[cpu].domain, get_current()->domain); + ptwr_info[cpu].domain, current->domain); #endif pl2e = &linear_l2_table[(page->u.inuse.type_info & PGT_va_mask) >> PGT_va_shift]; diff --git a/xen/common/schedule.c b/xen/common/schedule.c index cc06d3c085..a986ee06a1 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -374,20 +374,6 @@ void __enter_scheduler(void) cleanup_writable_pagetable( prev, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE); -#ifdef PTWR_TRACK_DOMAIN - { - extern domid_t ptwr_domain[]; - int cpu = smp_processor_id(); - if (ptwr_domain[cpu] != prev->domain) - printk("switch_to domain mismatch %d != %d\n", - ptwr_domain[cpu], prev->domain); - ptwr_domain[cpu] = next->domain; - if (ptwr_disconnected[cpu] != ENTRIES_PER_L2_PAGETABLE || - ptwr_writable_idx[cpu]) - printk("switch_to ptwr dirty!!!\n"); - } -#endif - perfc_incrc(sched_ctx); #if defined(WAKE_HISTO) diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 05813d64b7..b60e2e5f42 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -71,10 +71,9 @@ struct pfn_info /* Has this page been validated for use as its current type? */ #define _PGT_validated 28 #define PGT_validated (1<<_PGT_validated) - /* 10-bit most significant bits of va address if used as l1 page table */ + /* The 10 most significant bits of virt address if this is a L1 page table. */ #define PGT_va_shift 18 #define PGT_va_mask (((1<<10)-1)<count_info)) ) - { - /* if the page is pinned, but we're dropping the last reference - then make the va backpointer mutable again */ - nx |= PGT_va_mutable; - } } while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) ); } @@ -230,27 +222,15 @@ static inline int get_page_type(struct pfn_info *page, u32 type) nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); nx |= type; /* No extra validation needed for writable pages. */ - if ( (type & PGT_type_mask) == PGT_writable_page ) + if ( type == PGT_writable_page ) nx |= PGT_validated; } } - else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) + else if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != type) ) { - DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", - x & PGT_type_mask, type, page_to_pfn(page)); - return 0; - } - else if ( (x & PGT_va_mask) == PGT_va_mutable ) - { - /* The va_backpointer is currently mutable, hence we update it. */ - nx &= ~PGT_va_mask; - nx |= type; /* we know the actual type is correct */ - } - else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask) ) ) - { - /* The va backpointer wasn't mutable, and is different :-( */ - DPRINTK("Unexpected va backpointer (saw %08x != exp %08x) for pfn %08lx\n", - x, type, page_to_pfn(page)); + DPRINTK("Unexpected type or va backptr (saw %08x != exp %08x) " + "for pfn %08lx\n", + x & (PGT_type_mask|PGT_va_mask), type, page_to_pfn(page)); return 0; } else if ( unlikely(!(x & PGT_validated)) ) @@ -286,55 +266,6 @@ static inline int get_page_type(struct pfn_info *page, u32 type) return 1; } -/* This 'passive' version of get_page_type doesn't attempt to validate -the page, but just checks the type and increments the type count. The -function is called while doing a NORMAL_PT_UPDATE of an entry in an L1 -page table: We want to 'lock' the page for the brief beriod while -we're doing the update, but we're not actually linking it in to a -pagetable. */ - -static inline int passive_get_page_type(struct pfn_info *page, u32 type) -{ - u32 nx, x, y = page->u.inuse.type_info; - again: - do { - x = y; - nx = x + 1; - if ( unlikely((nx & PGT_count_mask) == 0) ) - { - DPRINTK("Type count overflow on pfn %08lx\n", page_to_pfn(page)); - return 0; - } - else if ( unlikely((x & PGT_count_mask) == 0) ) - { - if ( (x & (PGT_type_mask|PGT_va_mask)) != type ) - { - nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); - nx |= type; - } - } - else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) - { - DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", - x & PGT_type_mask, type, page_to_pfn(page)); - return 0; - } - else if ( unlikely(!(x & PGT_validated)) ) - { - /* Someone else is updating validation of this page. Wait... */ - while ( (y = page->u.inuse.type_info) != x ) - { - rep_nop(); - barrier(); - } - goto again; - } - } - while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) ); - - return 1; -} - static inline void put_page_and_type(struct pfn_info *page) { diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 3a0189a655..36528bfda4 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -104,9 +104,9 @@ * ptr[1:0] == MMU_EXTENDED_COMMAND: * val[7:0] -- MMUEXT_* command. * - * val[7:0] == MMUEXT_(UN)PIN_*_TABLE: - * ptr[:2] -- Machine address of frame to be (un)pinned as a p.t. page. - * The frame must belong to the FD, if one is specified. + * val[7:0] == MMUEXT_[UN]PIN_TABLE: + * ptr[:2] -- Machine address of frame to be (un)pinned as a top-level p.t. + * page. The frame must belong to the FD, if one is specified. * * val[7:0] == MMUEXT_NEW_BASEPTR: * ptr[:2] -- Machine address of new page-table base to install in MMU. @@ -142,10 +142,7 @@ #define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ #define MMU_MACHPHYS_UPDATE 2 /* ptr = MA of frame to modify entry for */ #define MMU_EXTENDED_COMMAND 3 /* least 8 bits of val demux further */ -#define MMUEXT_PIN_L1_TABLE 0 /* ptr = MA of frame to pin */ -#define MMUEXT_PIN_L2_TABLE 1 /* ptr = MA of frame to pin */ -#define MMUEXT_PIN_L3_TABLE 2 /* ptr = MA of frame to pin */ -#define MMUEXT_PIN_L4_TABLE 3 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_TABLE 0 /* ptr = MA of frame to pin */ #define MMUEXT_UNPIN_TABLE 4 /* ptr = MA of frame to unpin */ #define MMUEXT_NEW_BASEPTR 5 /* ptr = MA of new pagetable base */ #define MMUEXT_TLB_FLUSH 6 /* ptr = NULL */ From 8e90e37e6db85211de890d8a6c26b35454107aec Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sat, 4 Sep 2004 04:36:41 +0000 Subject: [PATCH 09/22] bitkeeper revision 1.1159.69.7 (41394659gzch_AlptZgctoWrGnWAGw) Fix WBINVD by adding a new hypercall. Various drivers still use wbinvd directly rather than using the helper macro in system.h. They should be fixed by sending patches to the appropriate maintainers (e.g., DRM, AGP, ...). --- .../include/asm-xen/asm-i386/system.h | 10 +++++++--- xen/arch/x86/memory.c | 12 +++++++++++ xen/include/hypervisor-ifs/dom0_ops.h | 2 +- xen/include/hypervisor-ifs/hypervisor-if.h | 20 +++++++++++-------- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h index 822c57f29a..133f1eaf49 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h @@ -122,9 +122,13 @@ static inline unsigned long _get_base(char * addr) #endif /* __KERNEL__ */ -#define wbinvd() \ - BUG(); -// __asm__ __volatile__ ("wbinvd": : :"memory"); +static inline void wbinvd(void) +{ + mmu_update_t u; + u.ptr = MMU_EXTENDED_COMMAND; + u.val = MMUEXT_FLUSH_CACHE; + (void)HYPERVISOR_mmu_update(&u, 1, NULL); +} static inline unsigned long get_limit(unsigned long segment) { diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index 5d95bea71e..35a248a50d 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -905,6 +905,18 @@ static int do_extended_command(unsigned long ptr, unsigned long val) __flush_tlb_one(ptr); break; + case MMUEXT_FLUSH_CACHE: + if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) ) + { + MEM_LOG("Non-physdev domain tried to FLUSH_CACHE.\n"); + okay = 0; + } + else + { + wbinvd(); + } + break; + case MMUEXT_SET_LDT: { unsigned long ents = val >> MMUEXT_CMD_SHIFT; diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index 7dec0af739..ebac7397bd 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -19,7 +19,7 @@ * This makes sure that old versions of dom0 tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define DOM0_INTERFACE_VERSION 0xAAAA0012 +#define DOM0_INTERFACE_VERSION 0xAAAA0013 #define MAX_DOMAIN_NAME 16 diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 36528bfda4..2b9f8c7166 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -117,6 +117,9 @@ * val[7:0] == MMUEXT_INVLPG: * ptr[:2] -- Linear address to be flushed from the TLB. * + * val[7:0] == MMUEXT_FLUSH_CACHE: + * No additional arguments. Writes back and flushes cache contents. + * * val[7:0] == MMUEXT_SET_LDT: * ptr[:2] -- Linear address of LDT base (NB. must be page-aligned). * val[:8] -- Number of entries in LDT. @@ -143,15 +146,16 @@ #define MMU_MACHPHYS_UPDATE 2 /* ptr = MA of frame to modify entry for */ #define MMU_EXTENDED_COMMAND 3 /* least 8 bits of val demux further */ #define MMUEXT_PIN_TABLE 0 /* ptr = MA of frame to pin */ -#define MMUEXT_UNPIN_TABLE 4 /* ptr = MA of frame to unpin */ -#define MMUEXT_NEW_BASEPTR 5 /* ptr = MA of new pagetable base */ -#define MMUEXT_TLB_FLUSH 6 /* ptr = NULL */ -#define MMUEXT_INVLPG 7 /* ptr = VA to invalidate */ -#define MMUEXT_SET_LDT 8 /* ptr = VA of table; val = # entries */ +#define MMUEXT_UNPIN_TABLE 1 /* ptr = MA of frame to unpin */ +#define MMUEXT_NEW_BASEPTR 2 /* ptr = MA of new pagetable base */ +#define MMUEXT_TLB_FLUSH 3 /* ptr = NULL */ +#define MMUEXT_INVLPG 4 /* ptr = VA to invalidate */ +#define MMUEXT_FLUSH_CACHE 5 +#define MMUEXT_SET_LDT 6 /* ptr = VA of table; val = # entries */ +#define MMUEXT_SET_FOREIGNDOM 7 /* val[31:16] = dom */ +#define MMUEXT_CLEAR_FOREIGNDOM 8 #define MMUEXT_TRANSFER_PAGE 9 /* ptr = MA of frame; val[31:16] = dom */ -#define MMUEXT_SET_FOREIGNDOM 10 /* val[31:16] = dom */ -#define MMUEXT_CLEAR_FOREIGNDOM 11 -#define MMUEXT_REASSIGN_PAGE 12 +#define MMUEXT_REASSIGN_PAGE 10 #define MMUEXT_CMD_MASK 255 #define MMUEXT_CMD_SHIFT 8 From e6863321667c6344fc3203e18b9ceef251645cb0 Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Sat, 4 Sep 2004 06:28:25 +0000 Subject: [PATCH 10/22] bitkeeper revision 1.1159.69.8 (413960891Us2H0wgOni9gC4Dvk3uCw) Fix I/O mapping in Xen/Linux. --- linux-2.6.8.1-xen-sparse/arch/xen/Kconfig | 3 +- .../arch/xen/i386/mm/ioremap.c | 32 +++++++++++++++---- .../include/asm-xen/asm-i386/io.h | 6 ++-- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig index 9f4c1d8002..5beabc830d 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig +++ b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig @@ -26,13 +26,12 @@ menu "XEN" config XEN_PRIVILEGED_GUEST bool "Privileged Guest (domain 0)" default n + select XEN_PHYSDEV_ACCESS help Support for privileged operation (domain 0) config XEN_PHYSDEV_ACCESS bool "Device-driver domain (physical device access)" - default y if XEN_PRIVILEGED_GUEST - default n help Device-driver domain (physical device access) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c index eed6379821..1efdacd8c2 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -17,6 +17,25 @@ #include #include +#ifndef CONFIG_XEN_PHYSDEV_ACCESS + +void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +{ return NULL; } + +void *ioremap_nocache (unsigned long phys_addr, unsigned long size) +{ return NULL; } + +void iounmap(void *addr) +{ } + +void __init *bt_ioremap(unsigned long phys_addr, unsigned long size) +{ return NULL; } + +void __init bt_iounmap(void *addr, unsigned long size) +{ } + +#else + static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, unsigned long phys_addr, unsigned long flags) { @@ -133,11 +152,11 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag /* * Don't allow anybody to remap normal RAM that we're using.. */ - if (phys_addr < virt_to_phys(high_memory)) { + if (machine_to_phys(phys_addr) < virt_to_phys(high_memory)) { char *t_addr, *t_end; struct page *page; - t_addr = __va(phys_addr); + t_addr = bus_to_virt(phys_addr); t_end = t_addr + (size - 1); for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) @@ -200,8 +219,8 @@ void *ioremap_nocache (unsigned long phys_addr, unsigned long size) /* Guaranteed to be > phys_addr, as per __ioremap() */ last_addr = phys_addr + size - 1; - if (last_addr < virt_to_phys(high_memory)) { - struct page *ppage = virt_to_page(__va(phys_addr)); + if (machine_to_phys(last_addr) < virt_to_phys(high_memory)) { + struct page *ppage = virt_to_page(bus_to_virt(phys_addr)); unsigned long npages; phys_addr &= PAGE_MASK; @@ -237,8 +256,8 @@ void iounmap(void *addr) return; } - if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { - change_page_attr(virt_to_page(__va(p->phys_addr)), + if (p->flags && machine_to_phys(p->phys_addr) < virt_to_phys(high_memory)) { + change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)), p->size >> PAGE_SHIFT, PAGE_KERNEL); global_flush_tlb(); @@ -316,6 +335,7 @@ void __init bt_iounmap(void *addr, unsigned long size) } } +#endif /* CONFIG_XEN_PHYSDEV_ACCESS */ #if defined(CONFIG_XEN_PRIVILEGED_GUEST) diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h index 81de51c1b5..db076b4370 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h @@ -128,12 +128,12 @@ extern void bt_iounmap(void *addr, unsigned long size); /* * ISA I/O bus memory addresses are 1:1 with the physical address. */ -#define isa_virt_to_bus(_x) BUG() // should be (void *)((FIX_ISAMAP_BEGIN - __virt_to_fix((_x))) << PAGE_SHIFT) -#define isa_page_to_bus(_x) BUG() // page_to_phys(_x) +#define isa_virt_to_bus(_x) isa_virt_to_bus_is_UNSUPPORTED->x +#define isa_page_to_bus(_x) isa_page_to_bus_is_UNSUPPORTED->x #ifdef CONFIG_XEN_PRIVILEGED_GUEST #define isa_bus_to_virt(_x) (void *)__fix_to_virt(FIX_ISAMAP_BEGIN - ((_x) >> PAGE_SHIFT)) #else -#define isa_bus_to_virt(_x) (void *)0L /* XXXcl */ +#define isa_bus_to_virt(_x) isa_bus_to_virt_needs_PRIVILEGED_BUILD #endif /* From a5ab702e1c8f3003122196080ececfe39ace15a1 Mon Sep 17 00:00:00 2001 From: "kaf24@camelot.eng.3leafnetworks.com" Date: Sat, 4 Sep 2004 18:32:45 +0000 Subject: [PATCH 11/22] bitkeeper revision 1.1159.69.9 (413a0a4d7ODoJ_4kti38jM2_4EooQA) Cset exclude: kaf24@camelot.eng.3leafnetworks.com|ChangeSet|20040903222602|39015 --- .../include/asm-xen/pgalloc.h | 2 + .../arch/xen/i386/mm/hypervisor.c | 50 +++++++++++- .../include/asm-xen/hypervisor.h | 12 +++ tools/libxc/xc_linux_build.c | 2 +- tools/libxc/xc_linux_restore.c | 30 ++++--- tools/libxc/xc_netbsd_build.c | 2 +- xen/arch/x86/memory.c | 45 ++++++----- xen/common/schedule.c | 14 ++++ xen/include/asm-x86/mm.h | 81 +++++++++++++++++-- xen/include/hypervisor-ifs/hypervisor-if.h | 11 ++- 10 files changed, 208 insertions(+), 41 deletions(-) diff --git a/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h b/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h index be678385f3..f6bee4d689 100644 --- a/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h +++ b/linux-2.4.27-xen-sparse/include/asm-xen/pgalloc.h @@ -134,6 +134,7 @@ static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address) { clear_page(pte); __make_page_readonly(pte); + queue_pte_pin(__pa(pte)); } return pte; @@ -152,6 +153,7 @@ static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, static __inline__ void pte_free_slow(pte_t *pte) { + queue_pte_unpin(__pa(pte)); __make_page_writable(pte); free_page((unsigned long)pte); } diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c index 03158c3ee4..a57eabcd8c 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c @@ -85,6 +85,8 @@ static void DEBUG_disallow_pt_read(unsigned long va) #undef queue_invlpg #undef queue_pgd_pin #undef queue_pgd_unpin +#undef queue_pte_pin +#undef queue_pte_unpin #undef queue_set_ldt #endif @@ -217,7 +219,7 @@ void queue_pgd_pin(unsigned long ptr) spin_lock_irqsave(&update_lock, flags); update_queue[idx].ptr = phys_to_machine(ptr); update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_PIN_TABLE; + update_queue[idx].val = MMUEXT_PIN_L2_TABLE; increment_index(); spin_unlock_irqrestore(&update_lock, flags); } @@ -233,6 +235,28 @@ void queue_pgd_unpin(unsigned long ptr) spin_unlock_irqrestore(&update_lock, flags); } +void queue_pte_pin(unsigned long ptr) +{ + unsigned long flags; + spin_lock_irqsave(&update_lock, flags); + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; + update_queue[idx].val = MMUEXT_PIN_L1_TABLE; + increment_index(); + spin_unlock_irqrestore(&update_lock, flags); +} + +void queue_pte_unpin(unsigned long ptr) +{ + unsigned long flags; + spin_lock_irqsave(&update_lock, flags); + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; + update_queue[idx].val = MMUEXT_UNPIN_TABLE; + increment_index(); + spin_unlock_irqrestore(&update_lock, flags); +} + void queue_set_ldt(unsigned long ptr, unsigned long len) { unsigned long flags; @@ -315,7 +339,7 @@ void xen_pgd_pin(unsigned long ptr) spin_lock_irqsave(&update_lock, flags); update_queue[idx].ptr = phys_to_machine(ptr); update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; - update_queue[idx].val = MMUEXT_PIN_TABLE; + update_queue[idx].val = MMUEXT_PIN_L2_TABLE; increment_index_and_flush(); spin_unlock_irqrestore(&update_lock, flags); } @@ -331,6 +355,28 @@ void xen_pgd_unpin(unsigned long ptr) spin_unlock_irqrestore(&update_lock, flags); } +void xen_pte_pin(unsigned long ptr) +{ + unsigned long flags; + spin_lock_irqsave(&update_lock, flags); + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; + update_queue[idx].val = MMUEXT_PIN_L1_TABLE; + increment_index_and_flush(); + spin_unlock_irqrestore(&update_lock, flags); +} + +void xen_pte_unpin(unsigned long ptr) +{ + unsigned long flags; + spin_lock_irqsave(&update_lock, flags); + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= MMU_EXTENDED_COMMAND; + update_queue[idx].val = MMUEXT_UNPIN_TABLE; + increment_index_and_flush(); + spin_unlock_irqrestore(&update_lock, flags); +} + void xen_set_ldt(unsigned long ptr, unsigned long len) { unsigned long flags; diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h index 0de4075b28..4d7ddc55a7 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h @@ -54,6 +54,8 @@ void queue_tlb_flush(void); void queue_invlpg(unsigned long ptr); void queue_pgd_pin(unsigned long ptr); void queue_pgd_unpin(unsigned long ptr); +void queue_pte_pin(unsigned long ptr); +void queue_pte_unpin(unsigned long ptr); void queue_set_ldt(unsigned long ptr, unsigned long bytes); void queue_machphys_update(unsigned long mfn, unsigned long pfn); void xen_l1_entry_update(pte_t *ptr, unsigned long val); @@ -63,6 +65,8 @@ void xen_tlb_flush(void); void xen_invlpg(unsigned long ptr); void xen_pgd_pin(unsigned long ptr); void xen_pgd_unpin(unsigned long ptr); +void xen_pte_pin(unsigned long ptr); +void xen_pte_unpin(unsigned long ptr); void xen_set_ldt(unsigned long ptr, unsigned long bytes); void xen_machphys_update(unsigned long mfn, unsigned long pfn); #define MMU_UPDATE_DEBUG 0 @@ -137,6 +141,14 @@ extern page_update_debug_t update_debug_queue[]; printk("PGD UNPIN %s %d: %08lx\n", __FILE__, __LINE__, (_p)); \ queue_pgd_unpin(_p); \ }) +#define queue_pte_pin(_p) ({ \ + printk("PTE PIN %s %d: %08lx\n", __FILE__, __LINE__, (_p)); \ + queue_pte_pin(_p); \ +}) +#define queue_pte_unpin(_p) ({ \ + printk("PTE UNPIN %s %d: %08lx\n", __FILE__, __LINE__, (_p)); \ + queue_pte_unpin(_p); \ +}) #define queue_set_ldt(_p,_l) ({ \ printk("SETL LDT %s %d: %08lx %d\n", __FILE__, __LINE__, (_p), (_l)); \ queue_set_ldt((_p), (_l)); \ diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 1242334dad..41569b8057 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -270,7 +270,7 @@ static int setup_guestos(int xc_handle, * correct protection for the page */ if ( add_mmu_update(xc_handle, mmu, - l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_TABLE) ) + l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) ) goto error_out; start_info = map_pfn_writeable( diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 5e4739f84b..fe7522e1ed 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -473,16 +473,28 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) */ for ( i = 0; i < nr_pfns; i++ ) { - if ( pfn_type[i] != (L2TAB|LPINTAB) ) - continue; - if ( add_mmu_update(xc_handle, mmu, - (pfn_to_mfn_table[i]<> 2)) ) + ((unsigned long) + pl2e & ~PAGE_MASK) >> 2 )) ) return 0; if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) ) @@ -827,9 +826,21 @@ static int do_extended_command(unsigned long ptr, unsigned long val) switch ( cmd ) { - case MMUEXT_PIN_TABLE: + case MMUEXT_PIN_L1_TABLE: + case MMUEXT_PIN_L2_TABLE: + + /* When we pin an L1 page we now insist that the va + backpointer (used for writable page tables) must still be + mutable. This is an additional restriction even for guests + that don't use writable page tables, but I don't think it + will break anything as guests typically pin pages before + they are used, hence they'll still be mutable. */ + okay = get_page_and_type_from_pagenr( - pfn, PGT_l2_page_table, FOREIGNDOM); + pfn, + ((cmd==MMUEXT_PIN_L2_TABLE) ? + PGT_l2_page_table : (PGT_l1_page_table | PGT_va_mutable) ) , + FOREIGNDOM); if ( unlikely(!okay) ) { @@ -1184,7 +1195,6 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) unsigned long prev_spfn = 0; l1_pgentry_t *prev_spl1e = 0; struct domain *d = current; - u32 type_info; perfc_incrc(calls_to_mmu_update); perfc_addc(num_page_updates, count); @@ -1233,11 +1243,10 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) } page = &frame_table[pfn]; - switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask ) + switch ( (page->u.inuse.type_info & PGT_type_mask) ) { case PGT_l1_page_table: - if ( likely(get_page_type( - page, type_info & (PGT_type_mask|PGT_va_mask))) ) + if ( likely(passive_get_page_type(page, PGT_l1_page_table)) ) { okay = mod_l1_entry((l1_pgentry_t *)va, mk_l1_pgentry(req.val)); @@ -1487,11 +1496,11 @@ void ptwr_reconnect_disconnected(unsigned long addr) [ptwr_info[cpu].writable_l1>>PAGE_SHIFT]; #ifdef PTWR_TRACK_DOMAIN - if (ptwr_domain[cpu] != current->domain) + if (ptwr_domain[cpu] != get_current()->domain) printk("ptwr_reconnect_disconnected domain mismatch %d != %d\n", - ptwr_domain[cpu], current->domain); + ptwr_domain[cpu], get_current()->domain); #endif - PTWR_PRINTK(("[A] page fault in disconn space: addr %08lx space %08lx\n", + PTWR_PRINTK(("[A] page fault in disconnected space: addr %08lx space %08lx\n", addr, ptwr_info[cpu].disconnected << L2_PAGETABLE_SHIFT)); pl2e = &linear_l2_table[ptwr_info[cpu].disconnected]; @@ -1563,9 +1572,9 @@ void ptwr_flush_inactive(void) int i, idx; #ifdef PTWR_TRACK_DOMAIN - if (ptwr_info[cpu].domain != current->domain) + if (ptwr_info[cpu].domain != get_current()->domain) printk("ptwr_flush_inactive domain mismatch %d != %d\n", - ptwr_info[cpu].domain, current->domain); + ptwr_info[cpu].domain, get_current()->domain); #endif #if 0 { @@ -1646,9 +1655,9 @@ int ptwr_do_page_fault(unsigned long addr) if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table ) { #ifdef PTWR_TRACK_DOMAIN - if ( ptwr_info[cpu].domain != current->domain ) + if ( ptwr_info[cpu].domain != get_current()->domain ) printk("ptwr_do_page_fault domain mismatch %d != %d\n", - ptwr_info[cpu].domain, current->domain); + ptwr_info[cpu].domain, get_current()->domain); #endif pl2e = &linear_l2_table[(page->u.inuse.type_info & PGT_va_mask) >> PGT_va_shift]; diff --git a/xen/common/schedule.c b/xen/common/schedule.c index a986ee06a1..cc06d3c085 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -374,6 +374,20 @@ void __enter_scheduler(void) cleanup_writable_pagetable( prev, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE); +#ifdef PTWR_TRACK_DOMAIN + { + extern domid_t ptwr_domain[]; + int cpu = smp_processor_id(); + if (ptwr_domain[cpu] != prev->domain) + printk("switch_to domain mismatch %d != %d\n", + ptwr_domain[cpu], prev->domain); + ptwr_domain[cpu] = next->domain; + if (ptwr_disconnected[cpu] != ENTRIES_PER_L2_PAGETABLE || + ptwr_writable_idx[cpu]) + printk("switch_to ptwr dirty!!!\n"); + } +#endif + perfc_incrc(sched_ctx); #if defined(WAKE_HISTO) diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index b60e2e5f42..05813d64b7 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -71,9 +71,10 @@ struct pfn_info /* Has this page been validated for use as its current type? */ #define _PGT_validated 28 #define PGT_validated (1<<_PGT_validated) - /* The 10 most significant bits of virt address if this is a L1 page table. */ + /* 10-bit most significant bits of va address if used as l1 page table */ #define PGT_va_shift 18 #define PGT_va_mask (((1<<10)-1)<count_info)) ) + { + /* if the page is pinned, but we're dropping the last reference + then make the va backpointer mutable again */ + nx |= PGT_va_mutable; + } } while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) ); } @@ -222,15 +230,27 @@ static inline int get_page_type(struct pfn_info *page, u32 type) nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); nx |= type; /* No extra validation needed for writable pages. */ - if ( type == PGT_writable_page ) + if ( (type & PGT_type_mask) == PGT_writable_page ) nx |= PGT_validated; } } - else if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != type) ) + else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) { - DPRINTK("Unexpected type or va backptr (saw %08x != exp %08x) " - "for pfn %08lx\n", - x & (PGT_type_mask|PGT_va_mask), type, page_to_pfn(page)); + DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", + x & PGT_type_mask, type, page_to_pfn(page)); + return 0; + } + else if ( (x & PGT_va_mask) == PGT_va_mutable ) + { + /* The va_backpointer is currently mutable, hence we update it. */ + nx &= ~PGT_va_mask; + nx |= type; /* we know the actual type is correct */ + } + else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask) ) ) + { + /* The va backpointer wasn't mutable, and is different :-( */ + DPRINTK("Unexpected va backpointer (saw %08x != exp %08x) for pfn %08lx\n", + x, type, page_to_pfn(page)); return 0; } else if ( unlikely(!(x & PGT_validated)) ) @@ -266,6 +286,55 @@ static inline int get_page_type(struct pfn_info *page, u32 type) return 1; } +/* This 'passive' version of get_page_type doesn't attempt to validate +the page, but just checks the type and increments the type count. The +function is called while doing a NORMAL_PT_UPDATE of an entry in an L1 +page table: We want to 'lock' the page for the brief beriod while +we're doing the update, but we're not actually linking it in to a +pagetable. */ + +static inline int passive_get_page_type(struct pfn_info *page, u32 type) +{ + u32 nx, x, y = page->u.inuse.type_info; + again: + do { + x = y; + nx = x + 1; + if ( unlikely((nx & PGT_count_mask) == 0) ) + { + DPRINTK("Type count overflow on pfn %08lx\n", page_to_pfn(page)); + return 0; + } + else if ( unlikely((x & PGT_count_mask) == 0) ) + { + if ( (x & (PGT_type_mask|PGT_va_mask)) != type ) + { + nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); + nx |= type; + } + } + else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) + { + DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", + x & PGT_type_mask, type, page_to_pfn(page)); + return 0; + } + else if ( unlikely(!(x & PGT_validated)) ) + { + /* Someone else is updating validation of this page. Wait... */ + while ( (y = page->u.inuse.type_info) != x ) + { + rep_nop(); + barrier(); + } + goto again; + } + } + while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) ); + + return 1; +} + static inline void put_page_and_type(struct pfn_info *page) { diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 2b9f8c7166..49cc4c46a3 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -104,9 +104,9 @@ * ptr[1:0] == MMU_EXTENDED_COMMAND: * val[7:0] -- MMUEXT_* command. * - * val[7:0] == MMUEXT_[UN]PIN_TABLE: - * ptr[:2] -- Machine address of frame to be (un)pinned as a top-level p.t. - * page. The frame must belong to the FD, if one is specified. + * val[7:0] == MMUEXT_(UN)PIN_*_TABLE: + * ptr[:2] -- Machine address of frame to be (un)pinned as a p.t. page. + * The frame must belong to the FD, if one is specified. * * val[7:0] == MMUEXT_NEW_BASEPTR: * ptr[:2] -- Machine address of new page-table base to install in MMU. @@ -145,7 +145,10 @@ #define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ #define MMU_MACHPHYS_UPDATE 2 /* ptr = MA of frame to modify entry for */ #define MMU_EXTENDED_COMMAND 3 /* least 8 bits of val demux further */ -#define MMUEXT_PIN_TABLE 0 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L1_TABLE 0 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L2_TABLE 1 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L3_TABLE 2 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L4_TABLE 3 /* ptr = MA of frame to pin */ #define MMUEXT_UNPIN_TABLE 1 /* ptr = MA of frame to unpin */ #define MMUEXT_NEW_BASEPTR 2 /* ptr = MA of new pagetable base */ #define MMUEXT_TLB_FLUSH 3 /* ptr = NULL */ From 5e2bad938a65bd8ad4fcb40234771ddfefadd778 Mon Sep 17 00:00:00 2001 From: "kaf24@camelot.eng.3leafnetworks.com" Date: Sat, 4 Sep 2004 19:58:36 +0000 Subject: [PATCH 12/22] bitkeeper revision 1.1159.69.10 (413a1e6ckNNgvyiZ6JU5_vjN5ITSuA) Add pinning of L1 table sback in, as it helps 2.4 performance. At the same time I've fixed the 'mutable backptr' support in Xen. --- xen/arch/x86/domain.c | 134 ++++++++++++++------- xen/arch/x86/memory.c | 63 +++++----- xen/common/dom0_ops.c | 2 +- xen/common/dom_mem_ops.c | 2 +- xen/common/page_alloc.c | 6 +- xen/common/schedule.c | 14 --- xen/include/asm-x86/mm.h | 121 ++++++------------- xen/include/hypervisor-ifs/dom0_ops.h | 2 +- xen/include/hypervisor-ifs/hypervisor-if.h | 20 +-- 9 files changed, 177 insertions(+), 187 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 478daea09a..fc8b4847dc 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -449,12 +449,94 @@ long do_iopl(domid_t domain, unsigned int new_io_pl) #endif -void domain_relinquish_memory(struct domain *d) + +static void relinquish_list(struct domain *d, struct list_head *list) { - struct list_head *ent, *tmp; + struct list_head *ent; struct pfn_info *page; unsigned long x, y; + /* Use a recursive lock, as we may enter 'free_domheap_page'. */ + spin_lock_recursive(&d->page_alloc_lock); + + /* + * Careful! Any time we might decrement a page's reference count we + * might invalidate our page pointer or our pointer into the page list. + * In such cases we have to exit the current iteration of the loop and + * start back at the beginning of the list. We are guaranteed to make + * forward progress because nothign will get added to the list (the domain + * is dying) and no pages will become pinned after we unpin them. + */ + ent = list->next; + while ( ent != list ) + { + page = list_entry(ent, struct pfn_info, list); + + if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) + { + /* NB. Check the allocation pin /before/ put_page_and_type()! */ + if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) + put_page(page); + put_page_and_type(page); + /* May have lost our place in the list - start over. */ + ent = list->next; + continue; + } + + if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) + { + put_page(page); + /* May have lost our place in the list - start over. */ + ent = list->next; + continue; + } + + /* + * Forcibly invalidate base page tables at this point to break circular + * 'linear page table' references. This is okay because MMU structures + * are not shared across domains and this domain is now dead. Thus base + * tables are not in use so a non-zero count means circular reference. + */ + y = page->u.inuse.type_info; + do { + x = y; + if ( likely((x & (PGT_type_mask|PGT_validated)) != + (PGT_base_page_table|PGT_validated)) ) + { + /* + * We have done no work on this iteration, so it is safe + * to move on to the next page in the list. + */ + ent = ent->next; + break; + } + y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated); + if ( likely(y == x) ) + { + free_page_type(page, PGT_base_page_table); + /* May have lost our place in the list - start over. */ + ent = list->next; + } + } + while ( unlikely(y != x) ); + } + + spin_unlock_recursive(&d->page_alloc_lock); + + /* + * Another CPU may have raced us to free some pages. Wait for those + * to trickle out now that we have released the lock. + */ + while ( !list_empty(list) ) + { + smp_mb(); + cpu_relax(); + } +} + + +void domain_relinquish_memory(struct domain *d) +{ /* Ensure that noone is running over the dead domain's page tables. */ synchronise_pagetables(~0UL); @@ -472,49 +554,9 @@ void domain_relinquish_memory(struct domain *d) */ destroy_gdt(d); - /* Use a recursive lock, as we may enter 'free_domheap_page'. */ - spin_lock_recursive(&d->page_alloc_lock); - - /* Relinquish Xen-heap pages. */ - list_for_each_safe ( ent, tmp, &d->xenpage_list ) - { - page = list_entry(ent, struct pfn_info, list); - - if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) - put_page(page); - } - - /* Relinquish all pages on the domain's allocation list. */ - list_for_each_safe ( ent, tmp, &d->page_list ) - { - page = list_entry(ent, struct pfn_info, list); - - if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_info) ) - put_page_and_type(page); - - if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) - put_page(page); - - /* - * Forcibly invalidate base page tables at this point to break circular - * 'linear page table' references. This is okay because MMU structures - * are not shared across domains and this domain is now dead. Thus base - * tables are not in use so a non-zero count means circular reference. - */ - y = page->u.inuse.type_info; - do { - x = y; - if ( likely((x & (PGT_type_mask|PGT_validated)) != - (PGT_base_page_table|PGT_validated)) ) - break; - y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated); - if ( likely(y == x) ) - free_page_type(page, PGT_base_page_table); - } - while ( unlikely(y != x) ); - } - - spin_unlock_recursive(&d->page_alloc_lock); + /* Relinquish every page of memory. */ + relinquish_list(d, &d->xenpage_list); + relinquish_list(d, &d->page_list); } @@ -739,7 +781,7 @@ int construct_dom0(struct domain *p, /* Get another ref to L2 page so that it can be pinned. */ if ( !get_page_and_type(page, p, PGT_l2_page_table) ) BUG(); - set_bit(_PGC_guest_pinned, &page->count_info); + set_bit(_PGT_pinned, &page->u.inuse.type_info); } else { diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index baeadbe310..509e8346fc 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -455,7 +455,8 @@ get_page_from_l1e( /* NB. Virtual address 'l2e' maps to a machine address within frame 'pfn'. */ static int get_page_from_l2e( - l2_pgentry_t l2e, unsigned long pfn, struct domain *d, unsigned long va_idx) + l2_pgentry_t l2e, unsigned long pfn, + struct domain *d, unsigned long va_idx) { int rc; @@ -471,7 +472,7 @@ get_page_from_l2e( rc = get_page_and_type_from_pagenr( l2_pgentry_to_pagenr(l2e), - PGT_l1_page_table | (va_idx<> 2 )) ) + ((unsigned long)pl2e & + ~PAGE_MASK) >> 2)) ) return 0; if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) ) @@ -828,18 +829,15 @@ static int do_extended_command(unsigned long ptr, unsigned long val) { case MMUEXT_PIN_L1_TABLE: case MMUEXT_PIN_L2_TABLE: - - /* When we pin an L1 page we now insist that the va - backpointer (used for writable page tables) must still be - mutable. This is an additional restriction even for guests - that don't use writable page tables, but I don't think it - will break anything as guests typically pin pages before - they are used, hence they'll still be mutable. */ - + /* + * We insist that, if you pin an L1 page, it's the first thing that + * you do to it. This is because we require the backptr to still be + * mutable. This assumption seems safe. + */ okay = get_page_and_type_from_pagenr( pfn, ((cmd==MMUEXT_PIN_L2_TABLE) ? - PGT_l2_page_table : (PGT_l1_page_table | PGT_va_mutable) ) , + PGT_l2_page_table : (PGT_l1_page_table|PGT_va_mutable)), FOREIGNDOM); if ( unlikely(!okay) ) @@ -849,8 +847,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val) break; } - if ( unlikely(test_and_set_bit(_PGC_guest_pinned, - &page->count_info)) ) + if ( unlikely(test_and_set_bit(_PGT_pinned, + &page->u.inuse.type_info)) ) { MEM_LOG("Pfn %08lx already pinned", pfn); put_page_and_type(page); @@ -866,8 +864,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val) MEM_LOG("Page %08lx bad domain (dom=%p)", ptr, page->u.inuse.domain); } - else if ( likely(test_and_clear_bit(_PGC_guest_pinned, - &page->count_info)) ) + else if ( likely(test_and_clear_bit(_PGT_pinned, + &page->u.inuse.type_info)) ) { put_page_and_type(page); put_page(page); @@ -1053,13 +1051,18 @@ static int do_extended_command(unsigned long ptr, unsigned long val) spin_lock(&e->page_alloc_lock); - /* Check that 'e' will accept the page and has reservation headroom. */ + /* + * Check that 'e' will accept the page and has reservation headroom. + * Also, a domain mustn't have PGC_allocated pages when it is dying. + */ ASSERT(e->tot_pages <= e->max_pages); - if ( unlikely(e->tot_pages == e->max_pages) || + if ( unlikely(test_bit(DF_DYING, &e->flags)) || + unlikely(e->tot_pages == e->max_pages) || unlikely(!gnttab_prepare_for_transfer(e, d, gntref)) ) { MEM_LOG("Transferee has no reservation headroom (%d,%d), or " - "provided a bad grant ref.\n", e->tot_pages, e->max_pages); + "provided a bad grant ref, or is dying (%08x).\n", + e->tot_pages, e->max_pages, e->flags); spin_unlock(&e->page_alloc_lock); put_domain(e); okay = 0; @@ -1195,6 +1198,7 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) unsigned long prev_spfn = 0; l1_pgentry_t *prev_spl1e = 0; struct domain *d = current; + u32 type_info; perfc_incrc(calls_to_mmu_update); perfc_addc(num_page_updates, count); @@ -1243,10 +1247,11 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) } page = &frame_table[pfn]; - switch ( (page->u.inuse.type_info & PGT_type_mask) ) + switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask ) { case PGT_l1_page_table: - if ( likely(passive_get_page_type(page, PGT_l1_page_table)) ) + if ( likely(get_page_type( + page, type_info & (PGT_type_mask|PGT_va_mask))) ) { okay = mod_l1_entry((l1_pgentry_t *)va, mk_l1_pgentry(req.val)); @@ -1496,11 +1501,11 @@ void ptwr_reconnect_disconnected(unsigned long addr) [ptwr_info[cpu].writable_l1>>PAGE_SHIFT]; #ifdef PTWR_TRACK_DOMAIN - if (ptwr_domain[cpu] != get_current()->domain) + if (ptwr_domain[cpu] != current->domain) printk("ptwr_reconnect_disconnected domain mismatch %d != %d\n", - ptwr_domain[cpu], get_current()->domain); + ptwr_domain[cpu], current->domain); #endif - PTWR_PRINTK(("[A] page fault in disconnected space: addr %08lx space %08lx\n", + PTWR_PRINTK(("[A] page fault in disconn space: addr %08lx space %08lx\n", addr, ptwr_info[cpu].disconnected << L2_PAGETABLE_SHIFT)); pl2e = &linear_l2_table[ptwr_info[cpu].disconnected]; @@ -1572,9 +1577,9 @@ void ptwr_flush_inactive(void) int i, idx; #ifdef PTWR_TRACK_DOMAIN - if (ptwr_info[cpu].domain != get_current()->domain) + if (ptwr_info[cpu].domain != current->domain) printk("ptwr_flush_inactive domain mismatch %d != %d\n", - ptwr_info[cpu].domain, get_current()->domain); + ptwr_info[cpu].domain, current->domain); #endif #if 0 { @@ -1655,9 +1660,9 @@ int ptwr_do_page_fault(unsigned long addr) if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table ) { #ifdef PTWR_TRACK_DOMAIN - if ( ptwr_info[cpu].domain != get_current()->domain ) + if ( ptwr_info[cpu].domain != current->domain ) printk("ptwr_do_page_fault domain mismatch %d != %d\n", - ptwr_info[cpu].domain, get_current()->domain); + ptwr_info[cpu].domain, current->domain); #endif pl2e = &linear_l2_table[(page->u.inuse.type_info & PGT_va_mask) >> PGT_va_shift]; diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 5ae8924143..5d95cdf184 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -628,7 +628,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) break; } - if ( page->count_info & PGC_guest_pinned ) + if ( page->u.inuse.type_info & PGT_pinned ) type |= LPINTAB; l_arr[j] |= type; put_page(page); diff --git a/xen/common/dom_mem_ops.c b/xen/common/dom_mem_ops.c index ba570d91f7..a4ce55bbc0 100644 --- a/xen/common/dom_mem_ops.c +++ b/xen/common/dom_mem_ops.c @@ -82,7 +82,7 @@ static long free_dom_mem(struct domain *d, return i; } - if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_info) ) + if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) put_page_and_type(page); if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index faa3b6ec3a..02a46bf1c3 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -393,10 +393,13 @@ struct pfn_info *alloc_domheap_pages(struct domain *d, int order) spin_lock(&d->page_alloc_lock); - if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) ) + if ( unlikely(test_bit(DF_DYING, &d->flags)) || + unlikely((d->tot_pages + (1 << order)) > d->max_pages) ) { DPRINTK("Over-allocation for domain %u: %u > %u\n", d->domain, d->tot_pages + (1 << order), d->max_pages); + DPRINTK("...or the domain is dying (%d)\n", + !!test_bit(DF_DYING, &d->flags)); spin_unlock(&d->page_alloc_lock); free_heap_pages(MEMZONE_DOM, pg, order); return NULL; @@ -427,6 +430,7 @@ void free_domheap_pages(struct pfn_info *pg, int order) if ( unlikely(IS_XEN_HEAP_FRAME(pg)) ) { + /* NB. May recursively lock from domain_relinquish_memory(). */ spin_lock_recursive(&d->page_alloc_lock); for ( i = 0; i < (1 << order); i++ ) diff --git a/xen/common/schedule.c b/xen/common/schedule.c index cc06d3c085..a986ee06a1 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -374,20 +374,6 @@ void __enter_scheduler(void) cleanup_writable_pagetable( prev, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE); -#ifdef PTWR_TRACK_DOMAIN - { - extern domid_t ptwr_domain[]; - int cpu = smp_processor_id(); - if (ptwr_domain[cpu] != prev->domain) - printk("switch_to domain mismatch %d != %d\n", - ptwr_domain[cpu], prev->domain); - ptwr_domain[cpu] = next->domain; - if (ptwr_disconnected[cpu] != ENTRIES_PER_L2_PAGETABLE || - ptwr_writable_idx[cpu]) - printk("switch_to ptwr dirty!!!\n"); - } -#endif - perfc_incrc(sched_ctx); #if defined(WAKE_HISTO) diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 05813d64b7..944e5c3177 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -71,27 +71,27 @@ struct pfn_info /* Has this page been validated for use as its current type? */ #define _PGT_validated 28 #define PGT_validated (1<<_PGT_validated) - /* 10-bit most significant bits of va address if used as l1 page table */ -#define PGT_va_shift 18 + /* Owning guest has pinned this page to its current type? */ +#define _PGT_pinned 27 +#define PGT_pinned (1<<_PGT_pinned) + /* The 10 most significant bits of virt address if this is a page table. */ +#define PGT_va_shift 17 #define PGT_va_mask (((1<<10)-1)<count_info)) ) + else if ( unlikely((nx & (PGT_pinned | PGT_count_mask)) == + (PGT_pinned | 1)) ) { - /* if the page is pinned, but we're dropping the last reference - then make the va backpointer mutable again */ + /* Page is now only pinned. Make the back pointer mutable again. */ nx |= PGT_va_mutable; } } @@ -230,33 +229,36 @@ static inline int get_page_type(struct pfn_info *page, u32 type) nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); nx |= type; /* No extra validation needed for writable pages. */ - if ( (type & PGT_type_mask) == PGT_writable_page ) + if ( type == PGT_writable_page ) nx |= PGT_validated; } } - else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) + else if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != type) ) { - DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", - x & PGT_type_mask, type, page_to_pfn(page)); - return 0; - } - else if ( (x & PGT_va_mask) == PGT_va_mutable ) - { - /* The va_backpointer is currently mutable, hence we update it. */ - nx &= ~PGT_va_mask; - nx |= type; /* we know the actual type is correct */ - } - else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask) ) ) - { - /* The va backpointer wasn't mutable, and is different :-( */ - DPRINTK("Unexpected va backpointer (saw %08x != exp %08x) for pfn %08lx\n", - x, type, page_to_pfn(page)); - return 0; + if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) + { + DPRINTK("Bad type (saw %08x != exp %08x) for pfn %08lx\n", + x & PGT_type_mask, type, page_to_pfn(page)); + return 0; + } + else if ( (x & PGT_va_mask) == PGT_va_mutable ) + { + /* The va backpointer is mutable, hence we update it. */ + nx &= ~PGT_va_mask; + nx |= type; /* we know the actual type is correct */ + } + else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask)) ) + { + /* The va backpointer wasn't mutable, and is different. */ + DPRINTK("Unexpected va backpointer (saw %08x != exp %08x)" + " for pfn %08lx\n", x, type, page_to_pfn(page)); + return 0; + } } else if ( unlikely(!(x & PGT_validated)) ) { /* Someone else is updating validation of this page. Wait... */ - while ( (y = page->u.inuse.type_info) != x ) + while ( (y = page->u.inuse.type_info) == x ) { rep_nop(); barrier(); @@ -286,55 +288,6 @@ static inline int get_page_type(struct pfn_info *page, u32 type) return 1; } -/* This 'passive' version of get_page_type doesn't attempt to validate -the page, but just checks the type and increments the type count. The -function is called while doing a NORMAL_PT_UPDATE of an entry in an L1 -page table: We want to 'lock' the page for the brief beriod while -we're doing the update, but we're not actually linking it in to a -pagetable. */ - -static inline int passive_get_page_type(struct pfn_info *page, u32 type) -{ - u32 nx, x, y = page->u.inuse.type_info; - again: - do { - x = y; - nx = x + 1; - if ( unlikely((nx & PGT_count_mask) == 0) ) - { - DPRINTK("Type count overflow on pfn %08lx\n", page_to_pfn(page)); - return 0; - } - else if ( unlikely((x & PGT_count_mask) == 0) ) - { - if ( (x & (PGT_type_mask|PGT_va_mask)) != type ) - { - nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated); - nx |= type; - } - } - else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) ) - { - DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n", - x & PGT_type_mask, type, page_to_pfn(page)); - return 0; - } - else if ( unlikely(!(x & PGT_validated)) ) - { - /* Someone else is updating validation of this page. Wait... */ - while ( (y = page->u.inuse.type_info) != x ) - { - rep_nop(); - barrier(); - } - goto again; - } - } - while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) ); - - return 1; -} - static inline void put_page_and_type(struct pfn_info *page) { diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index ebac7397bd..2bae662d12 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -19,7 +19,7 @@ * This makes sure that old versions of dom0 tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define DOM0_INTERFACE_VERSION 0xAAAA0013 +#define DOM0_INTERFACE_VERSION 0xAAAA0014 #define MAX_DOMAIN_NAME 16 diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 49cc4c46a3..c7874bd708 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -149,16 +149,16 @@ #define MMUEXT_PIN_L2_TABLE 1 /* ptr = MA of frame to pin */ #define MMUEXT_PIN_L3_TABLE 2 /* ptr = MA of frame to pin */ #define MMUEXT_PIN_L4_TABLE 3 /* ptr = MA of frame to pin */ -#define MMUEXT_UNPIN_TABLE 1 /* ptr = MA of frame to unpin */ -#define MMUEXT_NEW_BASEPTR 2 /* ptr = MA of new pagetable base */ -#define MMUEXT_TLB_FLUSH 3 /* ptr = NULL */ -#define MMUEXT_INVLPG 4 /* ptr = VA to invalidate */ -#define MMUEXT_FLUSH_CACHE 5 -#define MMUEXT_SET_LDT 6 /* ptr = VA of table; val = # entries */ -#define MMUEXT_SET_FOREIGNDOM 7 /* val[31:16] = dom */ -#define MMUEXT_CLEAR_FOREIGNDOM 8 -#define MMUEXT_TRANSFER_PAGE 9 /* ptr = MA of frame; val[31:16] = dom */ -#define MMUEXT_REASSIGN_PAGE 10 +#define MMUEXT_UNPIN_TABLE 4 /* ptr = MA of frame to unpin */ +#define MMUEXT_NEW_BASEPTR 5 /* ptr = MA of new pagetable base */ +#define MMUEXT_TLB_FLUSH 6 /* ptr = NULL */ +#define MMUEXT_INVLPG 7 /* ptr = VA to invalidate */ +#define MMUEXT_FLUSH_CACHE 8 +#define MMUEXT_SET_LDT 9 /* ptr = VA of table; val = # entries */ +#define MMUEXT_SET_FOREIGNDOM 10 /* val[31:16] = dom */ +#define MMUEXT_CLEAR_FOREIGNDOM 11 +#define MMUEXT_TRANSFER_PAGE 12 /* ptr = MA of frame; val[31:16] = dom */ +#define MMUEXT_REASSIGN_PAGE 13 #define MMUEXT_CMD_MASK 255 #define MMUEXT_CMD_SHIFT 8 From 36602816237266d61d024793871faf02146db6fd Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sat, 4 Sep 2004 21:37:22 +0000 Subject: [PATCH 13/22] bitkeeper revision 1.1159.69.11 (413a3592ceCfqW4DvqOdKq04_bXOig) Fix our freeing of domain memory when a domain dies. --- xen/arch/x86/domain.c | 56 ++++++++++++------------------------------- 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index fc8b4847dc..868a3c97ad 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -459,37 +459,24 @@ static void relinquish_list(struct domain *d, struct list_head *list) /* Use a recursive lock, as we may enter 'free_domheap_page'. */ spin_lock_recursive(&d->page_alloc_lock); - /* - * Careful! Any time we might decrement a page's reference count we - * might invalidate our page pointer or our pointer into the page list. - * In such cases we have to exit the current iteration of the loop and - * start back at the beginning of the list. We are guaranteed to make - * forward progress because nothign will get added to the list (the domain - * is dying) and no pages will become pinned after we unpin them. - */ ent = list->next; while ( ent != list ) { page = list_entry(ent, struct pfn_info, list); - if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) + /* Grab a reference to the page so it won't disappear from under us. */ + if ( unlikely(!get_page(page, d)) ) { - /* NB. Check the allocation pin /before/ put_page_and_type()! */ - if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) - put_page(page); - put_page_and_type(page); - /* May have lost our place in the list - start over. */ - ent = list->next; + /* Couldn't get a reference -- someone is freeing this page. */ + ent = ent->next; continue; } + if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) + put_page_and_type(page); + if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) - { put_page(page); - /* May have lost our place in the list - start over. */ - ent = list->next; - continue; - } /* * Forcibly invalidate base page tables at this point to break circular @@ -498,40 +485,27 @@ static void relinquish_list(struct domain *d, struct list_head *list) * tables are not in use so a non-zero count means circular reference. */ y = page->u.inuse.type_info; - do { + for ( ; ; ) + { x = y; if ( likely((x & (PGT_type_mask|PGT_validated)) != (PGT_base_page_table|PGT_validated)) ) - { - /* - * We have done no work on this iteration, so it is safe - * to move on to the next page in the list. - */ - ent = ent->next; break; - } + y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated); if ( likely(y == x) ) { free_page_type(page, PGT_base_page_table); - /* May have lost our place in the list - start over. */ - ent = list->next; + break; } } - while ( unlikely(y != x) ); + + /* Follow the list chain and /then/ potentially free the page. */ + ent = ent->next; + put_page(page); } spin_unlock_recursive(&d->page_alloc_lock); - - /* - * Another CPU may have raced us to free some pages. Wait for those - * to trickle out now that we have released the lock. - */ - while ( !list_empty(list) ) - { - smp_mb(); - cpu_relax(); - } } From 42fd3b74608ed6e9d35021ca5cfdffe2d0d6b8d1 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sat, 4 Sep 2004 23:04:53 +0000 Subject: [PATCH 14/22] bitkeeper revision 1.1159.69.12 (413a4a15Z23E3TdWcslHMKLH4O-Gww) Fix timestamp-scaling calculations in Linux 2.4. Time now progresses at the correct rate! --- linux-2.4.27-xen-sparse/arch/xen/kernel/time.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c b/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c index a2ffce3039..924a4a8efe 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c +++ b/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c @@ -604,12 +604,15 @@ static struct irqaction dbg_time = { void __init time_init(void) { unsigned long long alarm; - u64 __cpu_khz, cpu_freq, scale, scale2; + u64 __cpu_khz, __cpu_ghz, cpu_freq, scale, scale2; unsigned int cpu_ghz; - __cpu_khz = HYPERVISOR_shared_info->cpu_freq; - do_div(__cpu_khz, 1000); + __cpu_khz = __cpu_ghz = cpu_freq = HYPERVISOR_shared_info->cpu_freq; + do_div(__cpu_khz, 1000UL); cpu_khz = (u32)__cpu_khz; + do_div(__cpu_ghz, 1000000000UL); + cpu_ghz = (unsigned int)__cpu_ghz; + printk("Xen reported: %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); @@ -617,9 +620,6 @@ void __init time_init(void) xtime.tv_usec = HYPERVISOR_shared_info->wc_usec; processed_system_time = shadow_system_time; - cpu_freq = HYPERVISOR_shared_info->cpu_freq; - - cpu_ghz = do_div(cpu_freq, 1000000000UL); for ( rdtsc_bitshift = 0; cpu_ghz != 0; rdtsc_bitshift++, cpu_ghz >>= 1 ) continue; From 34a5c2ef0aa91c1df951c79aa1494508c9c32c26 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sun, 5 Sep 2004 00:08:14 +0000 Subject: [PATCH 15/22] bitkeeper revision 1.1159.69.13 (413a58ee74ENA9qdHnGab6iTYgHQRA) Fix formatting in debug message --- xen/arch/x86/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index 509e8346fc..65ee976872 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1061,7 +1061,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val) unlikely(!gnttab_prepare_for_transfer(e, d, gntref)) ) { MEM_LOG("Transferee has no reservation headroom (%d,%d), or " - "provided a bad grant ref, or is dying (%08x).\n", + "provided a bad grant ref, or is dying (%08lx).\n", e->tot_pages, e->max_pages, e->flags); spin_unlock(&e->page_alloc_lock); put_domain(e); From 8476b9f4c6eb09605eb818bdab3072cddd4e53b0 Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Sun, 5 Sep 2004 00:51:20 +0000 Subject: [PATCH 16/22] bitkeeper revision 1.1159.69.14 (413a6308LJJj1t5B4TsyMIFyWP356w) Ensure that unsupported features don't creep into the cpu_caps array. --- .rootkeys | 1 + .../include/asm-xen/asm-i386/bugs.h | 215 ++++++++++++++++++ .../asm-i386/mach-xen/setup_arch_post.h | 15 +- 3 files changed, 226 insertions(+), 5 deletions(-) create mode 100644 linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h diff --git a/.rootkeys b/.rootkeys index 698764dd14..2d8b4d0fcb 100644 --- a/.rootkeys +++ b/.rootkeys @@ -204,6 +204,7 @@ 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.8.1-xen-sparse/drivers/xen/privcmd/Makefile 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.8.1-xen-sparse/drivers/xen/privcmd/privcmd.c 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.8.1-xen-sparse/include/asm-generic/pgtable.h +413a6306kzex7seHlfTzg2SYiU50Dw linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/desc.h 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h 40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/e820.h diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h new file mode 100644 index 0000000000..6ca98964f6 --- /dev/null +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h @@ -0,0 +1,215 @@ +/* + * include/asm-i386/bugs.h + * + * Copyright (C) 1994 Linus Torvalds + * + * Cyrix stuff, June 1998 by: + * - Rafael R. Reilova (moved everything from head.S), + * + * - Channing Corn (tests & fixes), + * - Andrew D. Balsa (code cleanup). + * + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 + */ + +/* + * This is included by init/main.c to check for architecture-dependent bugs. + * + * Needs: + * void check_bugs(void); + */ + +#include +#include +#include +#include +#include + +static int __init no_halt(char *s) +{ + boot_cpu_data.hlt_works_ok = 0; + return 1; +} + +__setup("no-hlt", no_halt); + +static int __init mca_pentium(char *s) +{ + mca_pentium_flag = 1; + return 1; +} + +__setup("mca-pentium", mca_pentium); + +static int __init no_387(char *s) +{ + boot_cpu_data.hard_math = 0; + write_cr0(0xE | read_cr0()); + return 1; +} + +__setup("no387", no_387); + +static double __initdata x = 4195835.0; +static double __initdata y = 3145727.0; + +/* + * This used to check for exceptions.. + * However, it turns out that to support that, + * the XMM trap handlers basically had to + * be buggy. So let's have a correct XMM trap + * handler, and forget about printing out + * some status at boot. + * + * We should really only care about bugs here + * anyway. Not features. + */ +static void __init check_fpu(void) +{ + if (!boot_cpu_data.hard_math) { +#ifndef CONFIG_MATH_EMULATION + printk(KERN_EMERG "No coprocessor found and no math emulation present.\n"); + printk(KERN_EMERG "Giving up.\n"); + for (;;) ; +#endif + return; + } + +/* Enable FXSR and company _before_ testing for FP problems. */ + /* + * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. + */ + if (offsetof(struct task_struct, thread.i387.fxsave) & 15) { + extern void __buggy_fxsr_alignment(void); + __buggy_fxsr_alignment(); + } + if (cpu_has_fxsr) { + printk(KERN_INFO "Enabling fast FPU save and restore... "); + set_in_cr4(X86_CR4_OSFXSR); + printk("done.\n"); + } + if (cpu_has_xmm) { + printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... "); + set_in_cr4(X86_CR4_OSXMMEXCPT); + printk("done.\n"); + } + + /* Test for the divl bug.. */ + __asm__("fninit\n\t" + "fldl %1\n\t" + "fdivl %2\n\t" + "fmull %2\n\t" + "fldl %1\n\t" + "fsubp %%st,%%st(1)\n\t" + "fistpl %0\n\t" + "fwait\n\t" + "fninit" + : "=m" (*&boot_cpu_data.fdiv_bug) + : "m" (*&x), "m" (*&y)); + if (boot_cpu_data.fdiv_bug) + printk("Hmm, FPU with FDIV bug.\n"); +} + +static void __init check_hlt(void) +{ + printk(KERN_INFO "Checking 'hlt' instruction... "); + if (!boot_cpu_data.hlt_works_ok) { + printk("disabled\n"); + return; + } + __asm__ __volatile__("hlt ; hlt ; hlt ; hlt"); + printk("OK.\n"); +} + +/* + * Most 386 processors have a bug where a POPAD can lock the + * machine even from user space. + */ + +static void __init check_popad(void) +{ +#ifndef CONFIG_X86_POPAD_OK + int res, inp = (int) &res; + + printk(KERN_INFO "Checking for popad bug... "); + __asm__ __volatile__( + "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx " + : "=&a" (res) + : "d" (inp) + : "ecx", "edi" ); + /* If this fails, it means that any user program may lock the CPU hard. Too bad. */ + if (res != 12345678) printk( "Buggy.\n" ); + else printk( "OK.\n" ); +#endif +} + +/* + * Check whether we are able to run this kernel safely on SMP. + * + * - In order to run on a i386, we need to be compiled for i386 + * (for due to lack of "invlpg" and working WP on a i386) + * - In order to run on anything without a TSC, we need to be + * compiled for a i486. + * - In order to support the local APIC on a buggy Pentium machine, + * we need to be compiled with CONFIG_X86_GOOD_APIC disabled, + * which happens implicitly if compiled for a Pentium or lower + * (unless an advanced selection of CPU features is used) as an + * otherwise config implies a properly working local APIC without + * the need to do extra reads from the APIC. +*/ + +static void __init check_config(void) +{ +/* + * We'd better not be a i386 if we're configured to use some + * i486+ only features! (WP works in supervisor mode and the + * new "invlpg" and "bswap" instructions) + */ +#if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_BSWAP) + if (boot_cpu_data.x86 == 3) + panic("Kernel requires i486+ for 'invlpg' and other features"); +#endif + +/* + * If we configured ourselves for a TSC, we'd better have one! + */ +#ifdef CONFIG_X86_TSC + if (!cpu_has_tsc) + panic("Kernel compiled for Pentium+, requires TSC feature!"); +#endif + +/* + * If we were told we had a good local APIC, check for buggy Pentia, + * i.e. all B steppings and the C2 stepping of P54C when using their + * integrated APIC (see 11AP erratum in "Pentium Processor + * Specification Update"). + */ +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC) + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL + && cpu_has_apic + && boot_cpu_data.x86 == 5 + && boot_cpu_data.x86_model == 2 + && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11)) + panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!"); +#endif +} + +extern void alternative_instructions(void); +extern void machine_specific_modify_cpu_capabilities(void); + +static void __init check_bugs(void) +{ + identify_cpu(&boot_cpu_data); + machine_specific_modify_cpu_capabilities(); +#ifndef CONFIG_SMP + printk("CPU: "); + print_cpu_info(&boot_cpu_data); +#endif + check_config(); + check_fpu(); + check_hlt(); + check_popad(); + system_utsname.machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); + alternative_instructions(); +} diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h index e4daac8ed3..cf04b96b30 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h @@ -25,12 +25,8 @@ static char * __init machine_specific_memory_setup(void) extern void hypervisor_callback(void); extern void failsafe_callback(void); -static void __init machine_specific_arch_setup(void) +void __init machine_specific_modify_cpu_capabilities(void) { - HYPERVISOR_set_callbacks( - __KERNEL_CS, (unsigned long)hypervisor_callback, - __KERNEL_CS, (unsigned long)failsafe_callback); - clear_bit(X86_FEATURE_VME, boot_cpu_data.x86_capability); clear_bit(X86_FEATURE_DE, boot_cpu_data.x86_capability); clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability); @@ -39,3 +35,12 @@ static void __init machine_specific_arch_setup(void) clear_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability); clear_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability); } + +static void __init machine_specific_arch_setup(void) +{ + HYPERVISOR_set_callbacks( + __KERNEL_CS, (unsigned long)hypervisor_callback, + __KERNEL_CS, (unsigned long)failsafe_callback); + + machine_specific_modify_cpu_capabilities(); +} From a73326ecce294db0b938b72217ef9bb9a822a2f3 Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Sun, 5 Sep 2004 03:57:12 +0000 Subject: [PATCH 17/22] bitkeeper revision 1.1159.69.15 (413a8e98X2LuwKBOkOzn7uAjeL2KWA) Add full driver configurability for device-capable Linux. --- .../arch/xen/Kconfig.drivers | 98 +++----- .../arch/xen/configs/xen0_defconfig | 229 ++++++++++++------ .../arch/xen/configs/xenU_defconfig | 25 +- 3 files changed, 197 insertions(+), 155 deletions(-) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers index 508bc7a174..93db5f9df6 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers +++ b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers @@ -4,84 +4,52 @@ menu "Device Drivers" source "drivers/base/Kconfig" -source "drivers/scsi/Kconfig" -source "drivers/block/Kconfig" -source "drivers/md/Kconfig" +if XEN_PHYSDEV_ACCESS +source "drivers/mtd/Kconfig" +source "drivers/parport/Kconfig" +source "drivers/pnp/Kconfig" +endif -# Always include scsi and block to enable iscsi, loop0 etc. +source "drivers/block/Kconfig" if XEN_PHYSDEV_ACCESS source "drivers/ide/Kconfig" +endif + +source "drivers/scsi/Kconfig" + +if XEN_PHYSDEV_ACCESS source "drivers/cdrom/Kconfig" endif +source "drivers/md/Kconfig" + +if XEN_PHYSDEV_ACCESS +source "drivers/message/fusion/Kconfig" +source "drivers/ieee1394/Kconfig" +source "drivers/message/i2o/Kconfig" +endif + source "net/Kconfig" -if XEN_PRIVILEGED_GUEST -source "drivers/input/Kconfig" -endif - -config INPUT - tristate "Input devices (needed for keyboard, mouse, ...)" if EMBEDDED - default y - ---help--- - Say Y here if you have any input device (mouse, keyboard, tablet, - joystick, steering wheel ...) connected to your system and want - it to be available to applications. This includes standard PS/2 - keyboard and mouse. - - Say N here if you have a headless (no monitor, no keyboard) system. - - More information is available: - - If unsure, say Y. - - To compile this driver as a module, choose M here: the - module will be called input. - -if XEN_PRIVILEGED_GUEST -source "drivers/char/Kconfig" -endif - -config UNIX98_PTYS - bool "Unix98 PTY support" if EMBEDDED - default y - ---help--- - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx for - masters and /dev/ttyxx for slaves of pseudo terminals. This scheme - has a number of problems. The GNU C library glibc 2.1 and later, - however, supports the Unix98 naming standard: in order to acquire a - pseudo terminal, a process opens /dev/ptmx; the number of the pseudo - terminal is then made available to the process and the pseudo - terminal slave can be accessed as /dev/pts/. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - All modern Linux systems use the Unix98 ptys. Say Y unless - you're on an embedded system and want to conserve memory. - - if XEN_PHYSDEV_ACCESS +source "drivers/isdn/Kconfig" +source "drivers/telephony/Kconfig" +source "drivers/input/Kconfig" +source "drivers/char/Kconfig" source "drivers/i2c/Kconfig" +source "drivers/w1/Kconfig" +source "drivers/misc/Kconfig" +source "drivers/media/Kconfig" source "drivers/video/Kconfig" +source "sound/Kconfig" +source "drivers/usb/Kconfig" endif -#config XEN_EVTCHN -# bool "Xen Event Channel" -# depends on XEN -# default Y -# -#config XEN_CONSOLE -# bool "Xen Console" -# depends on XEN && XEN_EVTCHN -# default Y -# help -# Say Y to build a console driver for Xen. +if !XEN_PHYSDEV_ACCESS +config UNIX98_PTYS + bool + default y +endif endmenu diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig index 960c332306..75fac7e487 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig +++ b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig @@ -175,6 +175,105 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_CMD640 is not set +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_ATIIXP is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +CONFIG_BLK_DEV_SVWKS=y +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + # # SCSI device support # @@ -295,22 +394,9 @@ CONFIG_SCSI_QLA2XXX=y # CONFIG_PCMCIA_SYM53C500 is not set # -# Block devices +# Old CD-ROM drivers (not SCSI, not IDE) # -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=y -# CONFIG_BLK_DEV_SX8 is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_LBD is not set +# CONFIG_CD_NO_IDESCSI is not set # # Multi-device support (RAID and LVM) @@ -330,75 +416,19 @@ CONFIG_DM_MIRROR=y # CONFIG_DM_ZERO is not set # -# ATA/ATAPI/MFM/RLL support +# Fusion MPT device support # -CONFIG_IDE=y -CONFIG_BLK_DEV_IDE=y +# CONFIG_FUSION is not set # -# Please see Documentation/ide.txt for help/info on IDE drives +# IEEE 1394 (FireWire) support # -# CONFIG_BLK_DEV_IDE_SATA is not set -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS is not set -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IDE_TASKFILE_IO is not set +# CONFIG_IEEE1394 is not set # -# IDE chipset support/bugfixes +# I2O device support # -CONFIG_IDE_GENERIC=y -# CONFIG_BLK_DEV_CMD640 is not set -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_IDEPCI_SHARE_IRQ is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -CONFIG_BLK_DEV_GENERIC=y -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_ADMA=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_ATIIXP is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -CONFIG_BLK_DEV_PIIX=y -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -CONFIG_BLK_DEV_SVWKS=y -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_ARM is not set -# CONFIG_IDE_CHIPSETS is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_BLK_DEV_HD is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_I2O is not set # # Networking support @@ -645,6 +675,16 @@ CONFIG_TIGON3=y # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + # # Input device support # @@ -752,6 +792,26 @@ CONFIG_LEGACY_PTY_COUNT=256 # # CONFIG_I2C is not set +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# +# CONFIG_IBM_ASM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + # # Graphics support # @@ -765,6 +825,21 @@ CONFIG_VGA_CONSOLE=y # CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + # # File systems # diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig index 09bfb25851..70e8811692 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig +++ b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig @@ -131,6 +131,18 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + # # SCSI device support # @@ -167,18 +179,6 @@ CONFIG_BLK_DEV_SD=m # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_DEBUG is not set -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_LBD is not set - # # Multi-device support (RAID and LVM) # @@ -283,7 +283,6 @@ CONFIG_NETDEVICES=y # CONFIG_SLIP is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set -CONFIG_INPUT=y CONFIG_UNIX98_PTYS=y # From c3565a2b1d77b78bc66479009442ed9e89fc6e46 Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Sun, 5 Sep 2004 05:19:12 +0000 Subject: [PATCH 18/22] bitkeeper revision 1.1159.69.16 (413aa1d0GpVAPcEe9OlMHIT6xiUM_w) Patch AGP and DRM video drivers to be (hopefully) safe for Xen. These patches must be applied manually for now: cd linux-2.6.8.1-xen0 ; patch -p1 <../linux-2.6.8.1-patches/*.patch --- .rootkeys | 2 + linux-2.6.8.1-patches/agpgart.patch | 328 ++++++++++++++++++++++++++++ linux-2.6.8.1-patches/drm.patch | 11 + 3 files changed, 341 insertions(+) create mode 100644 linux-2.6.8.1-patches/agpgart.patch create mode 100644 linux-2.6.8.1-patches/drm.patch diff --git a/.rootkeys b/.rootkeys index 2d8b4d0fcb..78e1b4f5ca 100644 --- a/.rootkeys +++ b/.rootkeys @@ -126,6 +126,8 @@ 409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4.27-xen-sparse/mm/page_alloc.c 3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.27-xen-sparse/mm/swapfile.c 41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.27-xen-sparse/mm/vmalloc.c +413aa1d0oNP8HXLvfPuMe6cSroUfSA linux-2.6.8.1-patches/agpgart.patch +413aa1d0ewvSv-ohnNnQQNGsbPTTNA linux-2.6.8.1-patches/drm.patch 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.8.1-xen-sparse/arch/xen/Kconfig 40f56237utH41NPukqHksuNf29IC9A linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.8.1-xen-sparse/arch/xen/Makefile diff --git a/linux-2.6.8.1-patches/agpgart.patch b/linux-2.6.8.1-patches/agpgart.patch new file mode 100644 index 0000000000..f5d2ad9f17 --- /dev/null +++ b/linux-2.6.8.1-patches/agpgart.patch @@ -0,0 +1,328 @@ +--- linux-2.6.8.1/drivers/char/agp/ali-agp.c 2004-08-14 11:55:35.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/ali-agp.c 2004-09-05 05:55:58.876495340 +0100 +@@ -150,7 +150,7 @@ + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | +- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN )); ++ virt_to_bus(addr)) | ALI_CACHE_FLUSH_EN )); + return addr; + } + +@@ -174,7 +174,7 @@ + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | +- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN)); ++ virt_to_bus(addr)) | ALI_CACHE_FLUSH_EN)); + agp_generic_destroy_page(addr); + } + +--- linux-2.6.8.1/drivers/char/agp/amd-k7-agp.c 2004-08-14 11:56:24.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/amd-k7-agp.c 2004-09-05 05:55:58.877495108 +0100 +@@ -43,7 +43,7 @@ + + SetPageReserved(virt_to_page(page_map->real)); + global_cache_flush(); +- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), ++ page_map->remapped = ioremap_nocache(virt_to_bus(page_map->real), + PAGE_SIZE); + if (page_map->remapped == NULL) { + ClearPageReserved(virt_to_page(page_map->real)); +@@ -152,7 +152,7 @@ + + agp_bridge->gatt_table_real = (u32 *)page_dir.real; + agp_bridge->gatt_table = (u32 *)page_dir.remapped; +- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); ++ agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real); + + /* Get the address for the gart region. + * This is a bus address even on the alpha, b/c its +@@ -166,7 +166,7 @@ + /* Calculate the agp offset */ + for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = +- virt_to_phys(amd_irongate_private.gatt_pages[i]->real); ++ virt_to_bus(amd_irongate_private.gatt_pages[i]->real); + page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; + } + +--- linux-2.6.8.1/drivers/char/agp/amd64-agp.c 2004-08-14 11:55:47.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/amd64-agp.c 2004-09-05 05:55:58.877495108 +0100 +@@ -212,7 +212,7 @@ + + static int amd_8151_configure(void) + { +- unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); ++ unsigned long gatt_bus = virt_to_bus(agp_bridge->gatt_table_real); + + /* Configure AGP regs in each x86-64 host bridge. */ + for_each_nb() { +@@ -521,7 +521,7 @@ + { + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + +- release_mem_region(virt_to_phys(bridge->gatt_table_real), ++ release_mem_region(virt_to_bus(bridge->gatt_table_real), + amd64_aperture_sizes[bridge->aperture_size_idx].size); + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +--- linux-2.6.8.1/drivers/char/agp/ati-agp.c 2004-08-14 11:55:48.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/ati-agp.c 2004-09-05 05:55:58.877495108 +0100 +@@ -64,7 +64,7 @@ + + /* CACHE_FLUSH(); */ + global_cache_flush(); +- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), ++ page_map->remapped = ioremap_nocache(virt_to_bus(page_map->real), + PAGE_SIZE); + if (page_map->remapped == NULL || err) { + ClearPageReserved(virt_to_page(page_map->real)); +--- linux-2.6.8.1/drivers/char/agp/backend.c 2004-08-14 11:55:47.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/backend.c 2004-09-05 05:55:58.878494876 +0100 +@@ -142,7 +142,7 @@ + return -ENOMEM; + } + +- bridge->scratch_page_real = virt_to_phys(addr); ++ bridge->scratch_page_real = virt_to_bus(addr); + bridge->scratch_page = + bridge->driver->mask_memory(bridge->scratch_page_real, 0); + } +@@ -186,7 +186,7 @@ + err_out: + if (bridge->driver->needs_scratch_page) + bridge->driver->agp_destroy_page( +- phys_to_virt(bridge->scratch_page_real)); ++ bus_to_virt(bridge->scratch_page_real)); + if (got_gatt) + bridge->driver->free_gatt_table(); + if (got_keylist) { +@@ -211,7 +211,7 @@ + if (bridge->driver->agp_destroy_page && + bridge->driver->needs_scratch_page) + bridge->driver->agp_destroy_page( +- phys_to_virt(bridge->scratch_page_real)); ++ bus_to_virt(bridge->scratch_page_real)); + } + + static const drm_agp_t drm_agp = { +--- linux-2.6.8.1/drivers/char/agp/generic.c 2004-08-14 11:55:10.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/generic.c 2004-09-05 05:55:58.879494644 +0100 +@@ -127,7 +127,7 @@ + } + if (curr->page_count != 0) { + for (i = 0; i < curr->page_count; i++) { +- agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i])); ++ agp_bridge->driver->agp_destroy_page(bus_to_virt(curr->memory[i])); + } + } + agp_free_key(curr->key); +@@ -181,7 +181,7 @@ + return NULL; + } + new->memory[i] = +- agp_bridge->driver->mask_memory(virt_to_phys(addr), type); ++ agp_bridge->driver->mask_memory(virt_to_bus(addr), type); + new->page_count++; + } + +@@ -636,6 +636,7 @@ + int i; + void *temp; + struct page *page; ++ dma_addr_t dma; + + /* The generic routines can't handle 2 level gatt's */ + if (agp_bridge->driver->size_type == LVL2_APER_SIZE) +@@ -674,8 +675,10 @@ + break; + } + +- table = (char *) __get_free_pages(GFP_KERNEL, +- page_order); ++ table = dma_alloc_coherent( ++ &agp_bridge->dev->dev, ++ PAGE_SIZE << page_order, &dma, ++ GFP_KERNEL); + + if (table == NULL) { + i++; +@@ -706,7 +709,9 @@ + size = ((struct aper_size_info_fixed *) temp)->size; + page_order = ((struct aper_size_info_fixed *) temp)->page_order; + num_entries = ((struct aper_size_info_fixed *) temp)->num_entries; +- table = (char *) __get_free_pages(GFP_KERNEL, page_order); ++ table = dma_alloc_coherent( ++ &agp_bridge->dev->dev, ++ PAGE_SIZE << page_order, &dma, GFP_KERNEL); + } + + if (table == NULL) +@@ -721,7 +726,7 @@ + agp_gatt_table = (void *)table; + + agp_bridge->driver->cache_flush(); +- agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table), ++ agp_bridge->gatt_table = ioremap_nocache(virt_to_bus(table), + (PAGE_SIZE * (1 << page_order))); + agp_bridge->driver->cache_flush(); + +@@ -729,11 +734,12 @@ + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) + ClearPageReserved(page); + +- free_pages((unsigned long) table, page_order); ++ dma_free_coherent(&agp_bridge->dev->dev, PAGE_SIZE<gatt_bus_addr = virt_to_phys(agp_bridge->gatt_table_real); ++ agp_bridge->gatt_bus_addr = virt_to_bus(table); + + /* AK: bogus, should encode addresses > 4GB */ + for (i = 0; i < num_entries; i++) +@@ -785,7 +791,8 @@ + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) + ClearPageReserved(page); + +- free_pages((unsigned long) agp_bridge->gatt_table_real, page_order); ++ dma_free_coherent(&agp_bridge->dev->dev, PAGE_SIZE<gatt_table_real, agp_bridge->gatt_bus_addr); + + agp_gatt_table = NULL; + agp_bridge->gatt_table = NULL; +--- linux-2.6.8.1/drivers/char/agp/hp-agp.c 2004-08-14 11:55:59.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/hp-agp.c 2004-09-05 05:55:58.879494644 +0100 +@@ -110,7 +110,7 @@ + hp->gart_size = HP_ZX1_GART_SIZE; + hp->gatt_entries = hp->gart_size / hp->io_page_size; + +- hp->io_pdir = phys_to_virt(INREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE)); ++ hp->io_pdir = bus_to_virt(INREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE)); + hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; + + if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { +@@ -248,7 +248,7 @@ + agp_bridge->mode = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS); + + if (hp->io_pdir_owner) { +- OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_phys(hp->io_pdir)); ++ OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_bus(hp->io_pdir)); + OUTREG64(hp->ioc_regs, HP_ZX1_TCNFG, hp->io_tlb_ps); + OUTREG64(hp->ioc_regs, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1)); + OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, hp->iova_base | 0x1); +--- linux-2.6.8.1/drivers/char/agp/i460-agp.c 2004-08-14 11:55:34.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/i460-agp.c 2004-09-05 05:55:58.879494644 +0100 +@@ -371,7 +371,7 @@ + } + memset(lp->alloced_map, 0, map_size); + +- lp->paddr = virt_to_phys(lpage); ++ lp->paddr = virt_to_bus(lpage); + lp->refcount = 0; + atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); + return 0; +@@ -382,7 +382,7 @@ + kfree(lp->alloced_map); + lp->alloced_map = NULL; + +- free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); ++ free_pages((unsigned long) bus_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); + atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); + } + +--- linux-2.6.8.1/drivers/char/agp/intel-agp.c 2004-08-14 11:55:32.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/intel-agp.c 2004-09-05 05:55:58.880494412 +0100 +@@ -285,7 +285,7 @@ + if (new == NULL) + return NULL; + +- new->memory[0] = virt_to_phys(addr); ++ new->memory[0] = virt_to_bus(addr); + if (pg_count == 4) { + /* kludge to get 4 physical pages for ARGB cursor */ + new->memory[1] = new->memory[0] + PAGE_SIZE; +@@ -328,10 +328,10 @@ + agp_free_key(curr->key); + if(curr->type == AGP_PHYS_MEMORY) { + if (curr->page_count == 4) +- i8xx_destroy_pages(phys_to_virt(curr->memory[0])); ++ i8xx_destroy_pages(bus_to_virt(curr->memory[0])); + else + agp_bridge->driver->agp_destroy_page( +- phys_to_virt(curr->memory[0])); ++ bus_to_virt(curr->memory[0])); + vfree(curr->memory); + } + kfree(curr); +--- linux-2.6.8.1/drivers/char/agp/intel-mch-agp.c 2004-08-14 11:54:49.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/intel-mch-agp.c 2004-09-05 05:55:58.880494412 +0100 +@@ -51,7 +51,7 @@ + if (new == NULL) + return NULL; + +- new->memory[0] = agp_bridge->driver->mask_memory(virt_to_phys(addr), type); ++ new->memory[0] = agp_bridge->driver->mask_memory(virt_to_bus(addr), type); + new->page_count = 1; + new->num_scratch_pages = 1; + new->type = AGP_PHYS_MEMORY; +@@ -63,7 +63,7 @@ + { + agp_free_key(curr->key); + if(curr->type == AGP_PHYS_MEMORY) { +- agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0])); ++ agp_bridge->driver->agp_destroy_page(bus_to_virt(curr->memory[0])); + vfree(curr->memory); + } + kfree(curr); +--- linux-2.6.8.1/drivers/char/agp/sworks-agp.c 2004-08-14 11:55:10.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/sworks-agp.c 2004-09-05 05:55:58.881494180 +0100 +@@ -51,7 +51,7 @@ + } + SetPageReserved(virt_to_page(page_map->real)); + global_cache_flush(); +- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), ++ page_map->remapped = ioremap_nocache(virt_to_bus(page_map->real), + PAGE_SIZE); + if (page_map->remapped == NULL) { + ClearPageReserved(virt_to_page(page_map->real)); +@@ -164,7 +164,7 @@ + for(i = 0; i < 1024; i++) { + serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge->scratch_page; + page_dir.remapped[i] = +- virt_to_phys(serverworks_private.scratch_dir.real); ++ virt_to_bus(serverworks_private.scratch_dir.real); + page_dir.remapped[i] |= 0x00000001; + } + +@@ -177,7 +177,7 @@ + + agp_bridge->gatt_table_real = (u32 *)page_dir.real; + agp_bridge->gatt_table = (u32 *)page_dir.remapped; +- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); ++ agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real); + + /* Get the address for the gart region. + * This is a bus address even on the alpha, b/c its +@@ -191,7 +191,7 @@ + + for(i = 0; i < value->num_entries / 1024; i++) { + page_dir.remapped[i] = +- virt_to_phys(serverworks_private.gatt_pages[i]->real); ++ virt_to_bus(serverworks_private.gatt_pages[i]->real); + page_dir.remapped[i] |= 0x00000001; + } + +--- linux-2.6.8.1/drivers/char/agp/uninorth-agp.c 2004-08-14 11:55:32.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/agp/uninorth-agp.c 2004-09-05 05:55:58.881494180 +0100 +@@ -200,7 +200,7 @@ + + agp_bridge->gatt_table_real = (u32 *) table; + agp_bridge->gatt_table = (u32 *)table; +- agp_bridge->gatt_bus_addr = virt_to_phys(table); ++ agp_bridge->gatt_bus_addr = virt_to_bus(table); + + for (i = 0; i < num_entries; i++) { + agp_bridge->gatt_table[i] = diff --git a/linux-2.6.8.1-patches/drm.patch b/linux-2.6.8.1-patches/drm.patch new file mode 100644 index 0000000000..3412ce6203 --- /dev/null +++ b/linux-2.6.8.1-patches/drm.patch @@ -0,0 +1,11 @@ +--- linux-2.6.8.1/drivers/char/drm/ati_pcigart.h 2004-08-14 11:56:14.000000000 +0100 ++++ linux-2.6.8.1-xen0/drivers/char/drm/ati_pcigart.h 2004-09-05 06:14:51.751782846 +0100 +@@ -158,7 +158,7 @@ + ret = 1; + + #if defined(__i386__) || defined(__x86_64__) +- asm volatile ( "wbinvd" ::: "memory" ); ++ wbinvd(); + #else + mb(); + #endif From 40e8096b2d59185566928a24064b6f6cceb58840 Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Sun, 5 Sep 2004 18:28:08 +0000 Subject: [PATCH 19/22] bitkeeper revision 1.1159.69.17 (413b5ab8tE2tTd_Ht7wxKU0Uktv2_w) Fix WBINVD uses. --- .rootkeys | 1 + linux-2.6.8.1-patches/agpgart.patch | 18 ++ .../arch/xen/i386/mm/Makefile | 4 +- .../arch/xen/i386/mm/pageattr.c | 215 ++++++++++++++++++ 4 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c diff --git a/.rootkeys b/.rootkeys index 78e1b4f5ca..2597b013de 100644 --- a/.rootkeys +++ b/.rootkeys @@ -163,6 +163,7 @@ 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c +413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c 40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c 4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.8.1-xen-sparse/arch/xen/i386/pci/Makefile 4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.8.1-xen-sparse/arch/xen/i386/pci/direct.c diff --git a/linux-2.6.8.1-patches/agpgart.patch b/linux-2.6.8.1-patches/agpgart.patch index f5d2ad9f17..aba8b200b1 100644 --- a/linux-2.6.8.1-patches/agpgart.patch +++ b/linux-2.6.8.1-patches/agpgart.patch @@ -326,3 +326,21 @@ for (i = 0; i < num_entries; i++) { agp_bridge->gatt_table[i] = +--- linux-2.6.8.1/include/asm-i386/agp.h 2004-08-14 11:54:47.000000000 +0100 ++++ linux-2.6.8.1-xen0/include/asm-i386/agp.h 2004-09-05 05:57:26.040268956 +0100 +@@ -3,6 +3,7 @@ + + #include + #include ++#include + + /* + * Functions to keep the agpgart mappings coherent with the MMU. +@@ -19,6 +20,6 @@ + /* Could use CLFLUSH here if the cpu supports it. But then it would + need to be called for each cacheline of the whole page so it may not be + worth it. Would need a page for it. */ +-#define flush_agp_cache() asm volatile("wbinvd":::"memory") ++#define flush_agp_cache() wbinvd() + + #endif diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile index 55063591f0..50c97507c2 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile @@ -6,8 +6,8 @@ XENARCH := $(subst ",,$(CONFIG_XENARCH)) CFLAGS += -Iarch/$(XENARCH)/mm -obj-y := init.o fault.o ioremap.o pgtable.o hypervisor.o -c-obj-y := extable.o pageattr.o +obj-y := init.o fault.o ioremap.o pgtable.o hypervisor.o pageattr.o +c-obj-y := extable.o c-obj-$(CONFIG_DISCONTIGMEM) += discontig.o c-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c new file mode 100644 index 0000000000..57341454ed --- /dev/null +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c @@ -0,0 +1,215 @@ +/* + * Copyright 2002 Andi Kleen, SuSE Labs. + * Thanks to Ben LaHaise for precious feedback. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static spinlock_t cpa_lock = SPIN_LOCK_UNLOCKED; +static struct list_head df_list = LIST_HEAD_INIT(df_list); + + +pte_t *lookup_address(unsigned long address) +{ + pgd_t *pgd = pgd_offset_k(address); + pmd_t *pmd; + if (pgd_none(*pgd)) + return NULL; + pmd = pmd_offset(pgd, address); + if (pmd_none(*pmd)) + return NULL; + if (pmd_large(*pmd)) + return (pte_t *)pmd; + return pte_offset_kernel(pmd, address); +} + +static struct page *split_large_page(unsigned long address, pgprot_t prot) +{ + int i; + unsigned long addr; + struct page *base; + pte_t *pbase; + + spin_unlock_irq(&cpa_lock); + base = alloc_pages(GFP_KERNEL, 0); + spin_lock_irq(&cpa_lock); + if (!base) + return NULL; + + address = __pa(address); + addr = address & LARGE_PAGE_MASK; + pbase = (pte_t *)page_address(base); + for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { + pbase[i] = pfn_pte(addr >> PAGE_SHIFT, + addr == address ? prot : PAGE_KERNEL); + } + return base; +} + +static void flush_kernel_map(void *dummy) +{ + /* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */ + if (boot_cpu_data.x86_model >= 4) + wbinvd(); + /* Flush all to work around Errata in early athlons regarding + * large page flushing. + */ + __flush_tlb_all(); +} + +static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) +{ + struct page *page; + unsigned long flags; + + set_pte_atomic(kpte, pte); /* change init_mm */ + if (PTRS_PER_PMD > 1) + return; + + spin_lock_irqsave(&pgd_lock, flags); + for (page = pgd_list; page; page = (struct page *)page->index) { + pgd_t *pgd; + pmd_t *pmd; + pgd = (pgd_t *)page_address(page) + pgd_index(address); + pmd = pmd_offset(pgd, address); + set_pte_atomic((pte_t *)pmd, pte); + } + spin_unlock_irqrestore(&pgd_lock, flags); +} + +/* + * No more special protections in this 2/4MB area - revert to a + * large page again. + */ +static inline void revert_page(struct page *kpte_page, unsigned long address) +{ + pte_t *linear = (pte_t *) + pmd_offset(pgd_offset(&init_mm, address), address); + set_pmd_pte(linear, address, + pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT, + PAGE_KERNEL_LARGE)); +} + +static int +__change_page_attr(struct page *page, pgprot_t prot) +{ + pte_t *kpte; + unsigned long address; + struct page *kpte_page; + +#ifdef CONFIG_HIGHMEM + if (page >= highmem_start_page) + BUG(); +#endif + address = (unsigned long)page_address(page); + + kpte = lookup_address(address); + if (!kpte) + return -EINVAL; + kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); + if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { + if ((pte_val(*kpte) & _PAGE_PSE) == 0) { + pte_t old = *kpte; + pte_t standard = mk_pte(page, PAGE_KERNEL); + set_pte_atomic(kpte, mk_pte(page, prot)); + if (pte_same(old,standard)) + get_page(kpte_page); + } else { + struct page *split = split_large_page(address, prot); + if (!split) + return -ENOMEM; + get_page(kpte_page); + set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL)); + } + } else if ((pte_val(*kpte) & _PAGE_PSE) == 0) { + set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL)); + __put_page(kpte_page); + } + + if (cpu_has_pse && (page_count(kpte_page) == 1)) { + list_add(&kpte_page->lru, &df_list); + revert_page(kpte_page, address); + } + return 0; +} + +static inline void flush_map(void) +{ + on_each_cpu(flush_kernel_map, NULL, 1, 1); +} + +/* + * Change the page attributes of an page in the linear mapping. + * + * This should be used when a page is mapped with a different caching policy + * than write-back somewhere - some CPUs do not like it when mappings with + * different caching policies exist. This changes the page attributes of the + * in kernel linear mapping too. + * + * The caller needs to ensure that there are no conflicting mappings elsewhere. + * This function only deals with the kernel linear map. + * + * Caller must call global_flush_tlb() after this. + */ +int change_page_attr(struct page *page, int numpages, pgprot_t prot) +{ + int err = 0; + int i; + unsigned long flags; + + spin_lock_irqsave(&cpa_lock, flags); + for (i = 0; i < numpages; i++, page++) { + err = __change_page_attr(page, prot); + if (err) + break; + } + spin_unlock_irqrestore(&cpa_lock, flags); + return err; +} + +void global_flush_tlb(void) +{ + LIST_HEAD(l); + struct list_head* n; + + BUG_ON(irqs_disabled()); + + spin_lock_irq(&cpa_lock); + list_splice_init(&df_list, &l); + spin_unlock_irq(&cpa_lock); + flush_map(); + n = l.next; + while (n != &l) { + struct page *pg = list_entry(n, struct page, lru); + n = n->next; + __free_page(pg); + } +} + +#ifdef CONFIG_DEBUG_PAGEALLOC +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + if (PageHighMem(page)) + return; + /* the return value is ignored - the calls cannot fail, + * large pages are disabled at boot time. + */ + change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); + /* we should perform an IPI and flush all tlbs, + * but that can deadlock->flush only current cpu. + */ + __flush_tlb_all(); +} +EXPORT_SYMBOL(kernel_map_pages); +#endif + +EXPORT_SYMBOL(change_page_attr); +EXPORT_SYMBOL(global_flush_tlb); From a63aa1bc354313c85061bacf00bd64a87a681b11 Mon Sep 17 00:00:00 2001 From: "kaf24@freefall.cl.cam.ac.uk" Date: Mon, 6 Sep 2004 00:06:51 +0000 Subject: [PATCH 20/22] bitkeeper revision 1.1159.69.18 (413baa1bXGfcJkRulx6s9wKLDL1Kkg) Clean up pagetable bootstrap in Linux 2.6. Write-protecting the two pagetables is now clearer, and we properly deallocate the old pagetables when we are done with them. --- .../arch/xen/i386/kernel/cpu/common.c | 2 +- .../arch/xen/i386/mm/init.c | 67 +++++++------------ .../include/asm-xen/hypervisor.h | 6 +- xen/common/domain.c | 6 +- 4 files changed, 35 insertions(+), 46 deletions(-) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c index 6620406951..465759bcfe 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c @@ -504,7 +504,7 @@ void __init cpu_gdt_init(struct Xgt_desc_struct *gdt_descr) va < gdt_descr->address + gdt_descr->size; va += PAGE_SIZE, f++) { frames[f] = virt_to_machine(va) >> PAGE_SHIFT; - wrprotect_bootpt(swapper_pg_dir, (void *)va, 1); + protect_page(swapper_pg_dir, (void *)va, PROT_ON); } flush_page_update_queue(); if (HYPERVISOR_set_gdt(frames, gdt_descr->size / 8)) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c index 0b2706b055..7886cd64c7 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c @@ -76,11 +76,9 @@ static pte_t * __init one_page_table_init(pmd_t *pmd) if (pmd_none(*pmd)) { pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); - flush_page_update_queue(); if (page_table != pte_offset_kernel(pmd, 0)) BUG(); - wrprotect_bootpt((pgd_t *)start_info.pt_base, page_table, 1); return page_table; } @@ -125,8 +123,7 @@ static void __init page_table_range_init (unsigned long start, unsigned long end } } -/* NOTE: caller must call flush_page_update_queue() */ -void __init wrprotect_bootpt(pgd_t *pgd, void *page, int set) +void __init protect_page(pgd_t *pgd, void *page, int mode) { pmd_t *pmd; pte_t *pte; @@ -138,31 +135,25 @@ void __init wrprotect_bootpt(pgd_t *pgd, void *page, int set) pte = pte_offset_kernel(pmd, addr); if (!pte_present(*pte)) return; - queue_l1_entry_update(pte, set ? pte_val_ma(*pte) & ~_PAGE_RW : - pte_val_ma(*pte) | _PAGE_RW); + queue_l1_entry_update(pte, mode ? pte_val_ma(*pte) & ~_PAGE_RW : + pte_val_ma(*pte) | _PAGE_RW); } -/* NOTE: caller must call flush_page_update_queue() */ -static void __init protect_bootpt_entries(pgd_t *spgd, pgd_t *dpgd, int set, - int pmdupdate, int pmdset) +void __init protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode) { pmd_t *pmd; pte_t *pte; int pgd_idx, pmd_idx; + protect_page(dpgd, spgd, mode); + for (pgd_idx = 0; pgd_idx < PTRS_PER_PGD_NO_HV; spgd++, pgd_idx++) { pmd = pmd_offset(spgd, 0); if (pmd_none(*pmd)) continue; - if (pmdupdate) - wrprotect_bootpt(dpgd, pmd, pmdset); for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) { - if (cpu_has_pse) { - /* XXX */ - } else { - pte = pte_offset_kernel(pmd, 0); - wrprotect_bootpt(dpgd, pte, set); - } + pte = pte_offset_kernel(pmd, 0); + protect_page(dpgd, pte, mode); } } } @@ -536,18 +527,6 @@ out: #endif -/* - * - write protect new L1 pages in old pgd - * - write protect new pgd page in old pgd - * - write protect new pgd page in new pgd - * - write protect new L1 pages in new pgd - * - write protect old L1 pages in new pgd and write protect old pgd in - * new pgd - * - pin new pgd - * - switch to new pgd - * - unpin old pgd - * - make old L1 pages and old pgd page writeable in new pgd - */ /* * paging_init() sets up the page tables - note that the first 8MB are * already mapped by head.S. @@ -557,6 +536,8 @@ out: */ void __init paging_init(void) { + pgd_t *old_pgd = (pgd_t *)start_info.pt_base; + pgd_t *new_pgd = swapper_pg_dir; #ifdef CONFIG_XEN_PHYSDEV_ACCESS int i; #endif @@ -569,21 +550,25 @@ void __init paging_init(void) pagetable_init(); - wrprotect_bootpt((pgd_t *)start_info.pt_base, swapper_pg_dir, 1); - wrprotect_bootpt(swapper_pg_dir, swapper_pg_dir, 1); - flush_page_update_queue(); - protect_bootpt_entries(swapper_pg_dir, swapper_pg_dir, 1, 0, 0); - protect_bootpt_entries((pgd_t *)start_info.pt_base, swapper_pg_dir, - 1, 1, 1); - queue_pgd_pin(__pa(swapper_pg_dir)); - load_cr3(swapper_pg_dir); + /* + * Write-protect both page tables within both page tables. + * That's three ops, as the old p.t. is already protected + * within the old p.t. Then pin the new table, switch tables, + * and unprotect the old table. + */ + protect_pagetable(new_pgd, old_pgd, PROT_ON); + protect_pagetable(new_pgd, new_pgd, PROT_ON); + protect_pagetable(old_pgd, new_pgd, PROT_ON); + queue_pgd_pin(__pa(new_pgd)); + load_cr3(new_pgd); + queue_pgd_unpin(__pa(old_pgd)); __flush_tlb_all(); /* implicit flush */ - queue_pgd_unpin(__pa(start_info.pt_base)); - protect_bootpt_entries((pgd_t *)start_info.pt_base, swapper_pg_dir, - 0, 1, 0); - wrprotect_bootpt((pgd_t *)start_info.pt_base, swapper_pg_dir, 0); + protect_pagetable(new_pgd, old_pgd, PROT_OFF); flush_page_update_queue(); + /* Completely detached from old tables, so free them. */ + free_bootmem(__pa(old_pgd), start_info.nr_pt_frames << PAGE_SHIFT); + #ifdef CONFIG_X86_PAE /* * We will bail out later - printk doesn't work right now so diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h index 4d7ddc55a7..e1ee44a014 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h @@ -34,7 +34,11 @@ void xen_cpu_idle (void); void do_hypervisor_callback(struct pt_regs *regs); /* arch/xen/i386/mm/init.c */ -void wrprotect_bootpt(pgd_t *, void *, int); +/* NOTE: caller must call flush_page_update_queue() */ +#define PROT_ON 1 +#define PROT_OFF 0 +void /* __init */ protect_page(pgd_t *dpgd, void *page, int mode); +void /* __init */ protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode); /* arch/xen/i386/kernel/head.S */ void lgdt_finish(void); diff --git a/xen/common/domain.c b/xen/common/domain.c index 314f875511..f64d21e711 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -65,7 +65,7 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) strncpy(d->name, buf, MAX_DOMAIN_NAME); d->name[MAX_DOMAIN_NAME-1] = '\0'; - arch_do_createdomain(d); + arch_do_createdomain(d); sched_add_domain(d); @@ -152,8 +152,8 @@ void domain_crash(void) { struct domain *d; - if (current->domain == 0) - BUG(); + if ( current->domain == 0 ) + BUG(); set_bit(DF_CRASHED, ¤t->flags); From 1f11b350266e19d75cb92fb91ab507e5bcdf86ea Mon Sep 17 00:00:00 2001 From: "cl349@freefall.cl.cam.ac.uk" Date: Mon, 6 Sep 2004 09:32:48 +0000 Subject: [PATCH 21/22] bitkeeper revision 1.1159.69.19 (413c2ec0U4csp-bDtIykYOqnQQWb7A) Ensure that unsupported features don't creep into the cpu_caps array. (without increasing the number of changed files) --- .rootkeys | 1 - .../arch/xen/i386/kernel/cpu/common.c | 4 + .../include/asm-xen/asm-i386/bugs.h | 215 ------------------ .../asm-i386/mach-xen/setup_arch_post.h | 24 +- 4 files changed, 16 insertions(+), 228 deletions(-) delete mode 100644 linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h diff --git a/.rootkeys b/.rootkeys index 2597b013de..ed597156b3 100644 --- a/.rootkeys +++ b/.rootkeys @@ -207,7 +207,6 @@ 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.8.1-xen-sparse/drivers/xen/privcmd/Makefile 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.8.1-xen-sparse/drivers/xen/privcmd/privcmd.c 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.8.1-xen-sparse/include/asm-generic/pgtable.h -413a6306kzex7seHlfTzg2SYiU50Dw linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/desc.h 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h 40f5623anSzpuEHgiNmQ56fIRfCoaQ linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/e820.h diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c index 465759bcfe..07ced337a2 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c @@ -20,6 +20,8 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; extern void mcheck_init(struct cpuinfo_x86 *c); +extern void machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c); + extern int disable_pse; static void default_init(struct cpuinfo_x86 * c) @@ -392,6 +394,8 @@ void __init identify_cpu(struct cpuinfo_x86 *c) c->x86_vendor, c->x86_model); } + machine_specific_modify_cpu_capabilities(c); + /* Now the feature flags better reflect actual CPU features! */ printk(KERN_DEBUG "CPU: After all inits, caps: %08lx %08lx %08lx %08lx\n", diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h deleted file mode 100644 index 6ca98964f6..0000000000 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/bugs.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * include/asm-i386/bugs.h - * - * Copyright (C) 1994 Linus Torvalds - * - * Cyrix stuff, June 1998 by: - * - Rafael R. Reilova (moved everything from head.S), - * - * - Channing Corn (tests & fixes), - * - Andrew D. Balsa (code cleanup). - * - * Pentium III FXSR, SSE support - * Gareth Hughes , May 2000 - */ - -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -#include -#include -#include -#include -#include - -static int __init no_halt(char *s) -{ - boot_cpu_data.hlt_works_ok = 0; - return 1; -} - -__setup("no-hlt", no_halt); - -static int __init mca_pentium(char *s) -{ - mca_pentium_flag = 1; - return 1; -} - -__setup("mca-pentium", mca_pentium); - -static int __init no_387(char *s) -{ - boot_cpu_data.hard_math = 0; - write_cr0(0xE | read_cr0()); - return 1; -} - -__setup("no387", no_387); - -static double __initdata x = 4195835.0; -static double __initdata y = 3145727.0; - -/* - * This used to check for exceptions.. - * However, it turns out that to support that, - * the XMM trap handlers basically had to - * be buggy. So let's have a correct XMM trap - * handler, and forget about printing out - * some status at boot. - * - * We should really only care about bugs here - * anyway. Not features. - */ -static void __init check_fpu(void) -{ - if (!boot_cpu_data.hard_math) { -#ifndef CONFIG_MATH_EMULATION - printk(KERN_EMERG "No coprocessor found and no math emulation present.\n"); - printk(KERN_EMERG "Giving up.\n"); - for (;;) ; -#endif - return; - } - -/* Enable FXSR and company _before_ testing for FP problems. */ - /* - * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. - */ - if (offsetof(struct task_struct, thread.i387.fxsave) & 15) { - extern void __buggy_fxsr_alignment(void); - __buggy_fxsr_alignment(); - } - if (cpu_has_fxsr) { - printk(KERN_INFO "Enabling fast FPU save and restore... "); - set_in_cr4(X86_CR4_OSFXSR); - printk("done.\n"); - } - if (cpu_has_xmm) { - printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... "); - set_in_cr4(X86_CR4_OSXMMEXCPT); - printk("done.\n"); - } - - /* Test for the divl bug.. */ - __asm__("fninit\n\t" - "fldl %1\n\t" - "fdivl %2\n\t" - "fmull %2\n\t" - "fldl %1\n\t" - "fsubp %%st,%%st(1)\n\t" - "fistpl %0\n\t" - "fwait\n\t" - "fninit" - : "=m" (*&boot_cpu_data.fdiv_bug) - : "m" (*&x), "m" (*&y)); - if (boot_cpu_data.fdiv_bug) - printk("Hmm, FPU with FDIV bug.\n"); -} - -static void __init check_hlt(void) -{ - printk(KERN_INFO "Checking 'hlt' instruction... "); - if (!boot_cpu_data.hlt_works_ok) { - printk("disabled\n"); - return; - } - __asm__ __volatile__("hlt ; hlt ; hlt ; hlt"); - printk("OK.\n"); -} - -/* - * Most 386 processors have a bug where a POPAD can lock the - * machine even from user space. - */ - -static void __init check_popad(void) -{ -#ifndef CONFIG_X86_POPAD_OK - int res, inp = (int) &res; - - printk(KERN_INFO "Checking for popad bug... "); - __asm__ __volatile__( - "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx " - : "=&a" (res) - : "d" (inp) - : "ecx", "edi" ); - /* If this fails, it means that any user program may lock the CPU hard. Too bad. */ - if (res != 12345678) printk( "Buggy.\n" ); - else printk( "OK.\n" ); -#endif -} - -/* - * Check whether we are able to run this kernel safely on SMP. - * - * - In order to run on a i386, we need to be compiled for i386 - * (for due to lack of "invlpg" and working WP on a i386) - * - In order to run on anything without a TSC, we need to be - * compiled for a i486. - * - In order to support the local APIC on a buggy Pentium machine, - * we need to be compiled with CONFIG_X86_GOOD_APIC disabled, - * which happens implicitly if compiled for a Pentium or lower - * (unless an advanced selection of CPU features is used) as an - * otherwise config implies a properly working local APIC without - * the need to do extra reads from the APIC. -*/ - -static void __init check_config(void) -{ -/* - * We'd better not be a i386 if we're configured to use some - * i486+ only features! (WP works in supervisor mode and the - * new "invlpg" and "bswap" instructions) - */ -#if defined(CONFIG_X86_WP_WORKS_OK) || defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_BSWAP) - if (boot_cpu_data.x86 == 3) - panic("Kernel requires i486+ for 'invlpg' and other features"); -#endif - -/* - * If we configured ourselves for a TSC, we'd better have one! - */ -#ifdef CONFIG_X86_TSC - if (!cpu_has_tsc) - panic("Kernel compiled for Pentium+, requires TSC feature!"); -#endif - -/* - * If we were told we had a good local APIC, check for buggy Pentia, - * i.e. all B steppings and the C2 stepping of P54C when using their - * integrated APIC (see 11AP erratum in "Pentium Processor - * Specification Update"). - */ -#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC) - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL - && cpu_has_apic - && boot_cpu_data.x86 == 5 - && boot_cpu_data.x86_model == 2 - && (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11)) - panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!"); -#endif -} - -extern void alternative_instructions(void); -extern void machine_specific_modify_cpu_capabilities(void); - -static void __init check_bugs(void) -{ - identify_cpu(&boot_cpu_data); - machine_specific_modify_cpu_capabilities(); -#ifndef CONFIG_SMP - printk("CPU: "); - print_cpu_info(&boot_cpu_data); -#endif - check_config(); - check_fpu(); - check_hlt(); - check_popad(); - system_utsname.machine[1] = '0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86); - alternative_instructions(); -} diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h index cf04b96b30..68889ad832 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h @@ -22,25 +22,25 @@ static char * __init machine_specific_memory_setup(void) return who; } +void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) +{ + clear_bit(X86_FEATURE_VME, c->x86_capability); + clear_bit(X86_FEATURE_DE, c->x86_capability); + clear_bit(X86_FEATURE_PSE, c->x86_capability); + clear_bit(X86_FEATURE_TSC, c->x86_capability); + clear_bit(X86_FEATURE_PGE, c->x86_capability); + clear_bit(X86_FEATURE_MTRR, c->x86_capability); + clear_bit(X86_FEATURE_FXSR, c->x86_capability); +} + extern void hypervisor_callback(void); extern void failsafe_callback(void); -void __init machine_specific_modify_cpu_capabilities(void) -{ - clear_bit(X86_FEATURE_VME, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_DE, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability); - clear_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability); -} - static void __init machine_specific_arch_setup(void) { HYPERVISOR_set_callbacks( __KERNEL_CS, (unsigned long)hypervisor_callback, __KERNEL_CS, (unsigned long)failsafe_callback); - machine_specific_modify_cpu_capabilities(); + machine_specific_modify_cpu_capabilities(&boot_cpu_data); } From fb505bc4b00c69d8609b12d9900bf98e1b2e5ed1 Mon Sep 17 00:00:00 2001 From: "cl349@freefall.cl.cam.ac.uk" Date: Mon, 6 Sep 2004 14:46:01 +0000 Subject: [PATCH 22/22] bitkeeper revision 1.1159.69.20 (413c7829P-RU1PkUqzwGG3rQ_fI5Qg) Manage L1 pagetables in a kmem_cache, which allows us to keep the pages pinned while they are not used. --- .../arch/xen/i386/mm/init.c | 9 ++++ .../arch/xen/i386/mm/pgtable.c | 50 ++++++++++++------- .../include/asm-xen/asm-i386/pgalloc.h | 15 +++--- .../include/asm-xen/asm-i386/pgtable.h | 5 +- 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c index 7886cd64c7..2e80b31c76 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c @@ -726,9 +726,18 @@ void __init mem_init(void) kmem_cache_t *pgd_cache; kmem_cache_t *pmd_cache; +kmem_cache_t *pte_cache; void __init pgtable_cache_init(void) { + pte_cache = kmem_cache_create("pte", + PTRS_PER_PTE*sizeof(pte_t), + PTRS_PER_PTE*sizeof(pte_t), + 0, + pte_ctor, + pte_dtor); + if (!pte_cache) + panic("pgtable_cache_init(): Cannot create pte cache"); if (PTRS_PER_PMD > 1) { pmd_cache = kmem_cache_create("pmd", PTRS_PER_PMD*sizeof(pmd_t), diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c index b6182d9961..bebd04f92d 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c @@ -185,32 +185,44 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) return pte; } +void pte_ctor(void *pte, kmem_cache_t *cache, unsigned long unused) +{ + + clear_page(pte); + __make_page_readonly(pte); + queue_pte_pin(virt_to_phys(pte)); + flush_page_update_queue(); +} + +void pte_dtor(void *pte, kmem_cache_t *cache, unsigned long unused) +{ + + queue_pte_unpin(virt_to_phys(pte)); + __make_page_writable(pte); + flush_page_update_queue(); +} + struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) { - struct page *pte; + pte_t *ptep; #ifdef CONFIG_HIGHPTE + struct page *pte; + pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0); -#else - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); -#endif - if (pte) { -#ifdef CONFIG_HIGHPTE - void *kaddr = kmap_atomic(pte, KM_USER0); - clear_page(kaddr); - kunmap_atomic_force(kaddr, KM_USER0); -#else + if (pte == NULL) + return pte; + if (pte >= highmem_start_page) { clear_highpage(pte); -#endif -#ifdef CONFIG_HIGHPTE - if (pte < highmem_start_page) -#endif - { - __make_page_readonly(phys_to_virt(page_to_pseudophys(pte))); - flush_page_update_queue(); - } + return pte; } - return pte; + /* not a highmem page -- free page and grab one from the cache */ + __free_page(pte); +#endif + ptep = kmem_cache_alloc(pte_cache, GFP_KERNEL); + if (ptep) + return virt_to_page(ptep); + return NULL; } void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags) diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h index 0ba1e5a542..3d36223eca 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h @@ -41,19 +41,16 @@ static inline void pte_free(struct page *pte) #ifdef CONFIG_HIGHPTE if (pte < highmem_start_page) #endif - { - __make_page_writable(phys_to_virt(page_to_pseudophys(pte))); + kmem_cache_free(pte_cache, + phys_to_virt(page_to_pseudophys(pte))); +#ifdef CONFIG_HIGHPTE + else __free_page(pte); - flush_page_update_queue(); - } +#endif } -#define __pte_free_tlb(tlb,pte) do { \ - tlb_remove_page((tlb),(pte)); \ - flush_page_update_queue(); \ - /* XXXcl queue */ \ -} while (0) +#define __pte_free_tlb(tlb,pte) pte_free(pte) /* * allocating and freeing a pmd is trivial: the 1-entry pmd is diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h index a84b1a2308..20dda455dc 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -35,9 +35,12 @@ extern unsigned long empty_zero_page[1024]; extern pgd_t swapper_pg_dir[1024]; extern kmem_cache_t *pgd_cache; extern kmem_cache_t *pmd_cache; +extern kmem_cache_t *pte_cache; extern spinlock_t pgd_lock; extern struct page *pgd_list; +void pte_ctor(void *, kmem_cache_t *, unsigned long); +void pte_dtor(void *, kmem_cache_t *, unsigned long); void pmd_ctor(void *, kmem_cache_t *, unsigned long); void pgd_ctor(void *, kmem_cache_t *, unsigned long); void pgd_dtor(void *, kmem_cache_t *, unsigned long); @@ -315,9 +318,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) #define pmd_clear(xp) do { \ - pmd_t p = *(xp); \ set_pmd(xp, __pmd(0)); \ - __make_page_writable((void *)pmd_page_kernel(p)); \ xen_flush_page_update_queue(); \ } while (0)