lkml.org 
[lkml]   [2000]   [Feb]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] vc_screen once more
Hi Linus,
during reading through code I found that when code was converted from
old put_user to new in-kernel buffer, it started to try to store unaligned
shorts and it is fatal on some architectures, AFAIK. So there is patch.
For vcs_write, I added simple get_unaligned, as I did not found any
reasonable way to fix it except splitting loop for attributed and
non-attributed (vcsa & vcs) paths completely.
For vcs_read, I rewrite inside loop so that now always character
+ attribute is copied into buffer - code is shorter, gets rid of
ifdef __BIG_ENDIAN and I believe that it is more readable. I also
changed logic for computing buffer sizes for HEADER_SIZE data,
original code had some problems with writting beyond buffer when
pos was in range 1..HEADER_SIZE-1.
Patch was created on 2.3.46.
Thanks,
Petr Vandrovec
vandrove@vc.cvut.cz

diff -urdN linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- linux/drivers/char/vc_screen.c Wed Feb 16 23:42:05 2000
+++ linux/drivers/char/vc_screen.c Thu Feb 17 12:44:41 2000
@@ -37,6 +37,7 @@
#include <linux/console.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>

#undef attr
#undef org
@@ -175,71 +176,58 @@
con_buf0[1] = (char) video_num_columns;
getconsxy(currcons, con_buf0 + 2);

- tmp_count = HEADER_SIZE - p;
+ con_buf_start += p;
+ this_round += p;
+ if (this_round > CON_BUF_SIZE) {
+ this_round = CON_BUF_SIZE;
+ orig_count = this_round - p;
+ }
+
+ tmp_count = HEADER_SIZE;
if (tmp_count > this_round)
tmp_count = this_round;

/* Advance state pointers and move on. */
this_round -= tmp_count;
- con_buf_start += p;
- orig_count -= p;
- p += tmp_count;
- con_buf0 = con_buf + p;
+ p = HEADER_SIZE;
+ con_buf0 = con_buf + HEADER_SIZE;
+ /* If this_round >= 0, then p is even... */
+ } else if (p & 1) {
+ /* Skip first byte for output if start address is odd
+ * Update region sizes up/down depending on free
+ * space in buffer.
+ */
+ con_buf_start++;
+ if (this_round < CON_BUF_SIZE)
+ this_round++;
+ else
+ orig_count--;
}
- p -= HEADER_SIZE;
- col = (p/2) % maxcol;
if (this_round > 0) {
- char tmp_byte;
-
- org = screen_pos(currcons, p/2, viewed);
- if ((p & 1) && this_round > 0) {
-#ifdef __BIG_ENDIAN
- tmp_byte = vcs_scr_readw(currcons, org++) & 0xff;
-#else
- tmp_byte = vcs_scr_readw(currcons, org++) >> 8;
-#endif
-
- *con_buf0++ = tmp_byte;
+ unsigned short *tmp_buf = (unsigned short *)con_buf0;

- this_round--;
- p++;
- if (++col == maxcol) {
- org = screen_pos(currcons, p/2, viewed);
- col = 0;
- }
- }
+ p -= HEADER_SIZE;
p /= 2;
+ col = p % maxcol;
+
+ org = screen_pos(currcons, p, viewed);
p += maxcol - col;
- }

- if (this_round > 1) {
- size_t tmp_count = this_round;
- unsigned short *tmp_buf = (unsigned short *)con_buf0;
+ /* Buffer has even length, so we can always copy
+ * character + attribute. We do not copy last byte
+ * to userspace if this_round is odd.
+ */
+ this_round = (this_round + 1) >> 1;

- while (tmp_count > 1) {
+ while (this_round) {
*tmp_buf++ = vcs_scr_readw(currcons, org++);
- tmp_count -= 2;
+ this_round --;
if (++col == maxcol) {
org = screen_pos(currcons, p, viewed);
col = 0;
p += maxcol;
}
}
-
- /* Advance pointers, and move on. */
- this_round = tmp_count;
- con_buf0 = (char*)tmp_buf;
- }
- if (this_round > 0) {
- char tmp_byte;
-
-#ifdef __BIG_ENDIAN
- tmp_byte = vcs_scr_readw(currcons, org) >> 8;
-#else
- tmp_byte = vcs_scr_readw(currcons, org) & 0xff;
-#endif
-
- *con_buf0++ = tmp_byte;
}
}

@@ -415,7 +403,7 @@
while (this_round > 1) {
unsigned short w;

- w = *((const unsigned short *)con_buf0);
+ w = get_unaligned(((const unsigned short *)con_buf0));
vcs_scr_writew(currcons, w, org++);
con_buf0 += 2;
this_round -= 2;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:56    [W:1.635 / U:0.028 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site