I am sponsoring this case for Henry Zhao of the x86 Platform group. The timeout is set for Wednesday, July 28, 2010.
Since this only adds new interfaces a release binding of Patch is requested, though no patch release is planned at this time. -Alan Coopersmith- alan.coopersm...@oracle.com Oracle Solaris Platform Engineering: X Window System Template Version: @(#)sac_nextcase 1.70 03/30/10 SMI This information is Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 1. Introduction 1.1. Project/Component Working Name: VGA arbitration kernel driver 1.2. Name of Document Author/Supplier: Author: Henry Zhao 1.3 Date of This Document: 20 July, 2010 4. Technical Description 4.1. Summary X server/driver's access to a VGA device falls into two categories: legacy accesses and non-legacy accesses. Legacy accesses are accesses whose addresses are hardcoded and shared with different VGA devices, such as framebuffer (legacy MEM access) and VGA ports (legacy IO access). Non-legacy accesses are accesses whose address are distinct in the address space of different VGA devices, such as memory mapping. In a system with multiple server instances running, there is a risk that a legacy access may apply to all VGA devices so that a VGA device may decode data that was not intended for it. To solve this problem, a kernel driver is needed that controls and arbiters all the accesses such that during a legacy access, only the intended device decodes. The kernel driver receives MEM/IO access requests from X server/driver, and resolves these requests using lock/unlock mechanism to ensure that during a legacy access, MEM/IO access is enabled (for decoding) only on the intended device. Enabling/disabling MEM/IO access of a VGA device is done by enabling/disabling MEM/IO bits of its PCI config space, along with the VGA forwarding bit on any bridges on the path to the device. A program needs to acquire a lock on the target VGA device before it can access it, and releases the lock after access completion. To improve performance, two different locks, legacy locks and non-legacy locks, are arranged in the new design. A request for a non-legacy lock is blocked only when some other device already has a legacy lock (on the same resources). A request for a legacy lock is blocked when some other device already has a legacy or non-legacy lock (on the same resource). This means a request for non-legacy lock should not be blocked just because some other device already has a non-legacy lock (on the same resources). Since the accesses of most graphics operations after initialization are non-legacy, this reduces chances of locking hence improves performance. Potential deadlock may occur when a program holds a non-legacy lock while requesting a legacy lock. The problem is prevented by releasing non-legacy lock resources the same program has acquired before going to sleep, and restoring them after wakeup when the requesting legacy lock is acquired. 4.2. Interfaces Both userland and kernel interfaces are provided. The userland interfaces include open, close, read and write system calls. read() returns the status of the target device. write() commands are further divided into operations to set target device, lock/trylock target device, unlock target device, and set decoding attributes to target device. Kernel interfaces, in addition to acquiring/releasing lock and setting decoding attributes, also allow a client to register callback functions to a VGA to device. The callback functions include resetting decoding attributes when there is a change in configuration, and/or doing IRQ related processing when a device's MEM/IO enable/disable status changes. The latter is needed because when MEM access is disabled, any interrupts, if generated, would not be processed. Exported Interfaces ------------------- Interface Classification Comment /devices/vga_arbiter:vga_arbiter Uncommitted device /platform/kernel/drv/<amd64>/vga_arbiter Uncommitted driver /platform/kernel/drv/vga_arbiter.conf Uncommitted config file Userland -------- Use the standard open, close, read, write system calls to access the device, with string format of read/write commands defined as follows: "target <card_ID>" uncommitted write to device to set target "lock <io_state>" uncommitted write to device to set lock (wait) "trylock <io_state>" uncommitted write to device to set lock (no wait) "unlock <io_state>" uncommitted write to device to unlock "unlock all" uncommitted write to device to unlock "decodes <io_state>" uncommitted write to device to set decoding attr "count:<num>,card_ID,decodes=<io_state>,owns=<io_state>,legalocks=<io_state>(lic:lmc),normlocks=<io_state>(nic:nmc)" uncommitted read from device <card_ID> is in a format of "PCI:domain:bus:dev.fn" <io_state> is a string "io+mem+IO+MEM" or a part of it Kernel ------ void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes) uncommitted set decoding attributes int vga_get(struct pci_dev *pdev, unsigned int rsrc, unsigned int io_norm_cnt, unsigned int mem_norm_cnt, int interruptible); uncommitted acquire a lock (wait) int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) uncommitted acquire a lock (no wait) void vga_put(struct pci_dev *pdev, unsigned int rsrc) uncommitted release a lock int vga_client_register(struct pci_dev *pdev, void *cookie, void (*irq_set_state)(void *cookie, bool state), unsigned int (*set_vga_decode)(void *cookie, bool state)) uncommitted register callback functions 4.3. Implementation * The original code (using one lock) resides in linux kernel tree: drivers/gpr/vga/vgaarb.c drivers/include/linux/vgaarb.h * Code is modified to add an additional lock (non legacy lock) to improve performance when ported to Solaris. * Hot-plugging (to dynamically handle adding/removing vga devices) will be implemented in second phase. 6. Resources and Schedule 6.4. Steering Committee requested information 6.4.1. Consolidation C-team Name: ON 6.5. ARC review type: FastTrack 6.6. ARC Exposure: open _______________________________________________ opensolaris-arc mailing list opensolaris-arc@opensolaris.org